[pypy-commit] pypy vecopt2: extended memory ref analysis to consider division as well, added some tests

plan_rich noreply at buildbot.pypy.org
Tue May 5 09:45:26 CEST 2015


Author: Richard Plangger <rich at pasra.at>
Branch: vecopt2
Changeset: r77078:a1985466b222
Date: 2015-03-13 16:13 +0100
http://bitbucket.org/pypy/pypy/changeset/a1985466b222/

Log:	extended memory ref analysis to consider division as well, added
	some tests added a simple test to test the whole optimizer on a very
	basic loop

diff --git a/rpython/jit/metainterp/optimizeopt/dependency.py b/rpython/jit/metainterp/optimizeopt/dependency.py
--- a/rpython/jit/metainterp/optimizeopt/dependency.py
+++ b/rpython/jit/metainterp/optimizeopt/dependency.py
@@ -18,13 +18,13 @@
         Representation is an adjacent list. The number of edges between the
         vertices is expected to be small.
     """
-    def __init__(self, optimizer, loop):
-        self.loop = loop
-        self.operations = loop.operations
+    def __init__(self, optimizer):
+        self.loop = optimizer.loop
+        self.operations = self.loop.operations
         self.optimizer = optimizer
         self.adjacent_list = [ [] for i in range(len(self.operations)) ]
 
-        self.build_dependencies(loop.operations)
+        self.build_dependencies(self.operations)
 
     def build_dependencies(self, operations):
         """ This is basically building the definition-use chain and saving this
diff --git a/rpython/jit/metainterp/optimizeopt/vectorize.py b/rpython/jit/metainterp/optimizeopt/vectorize.py
--- a/rpython/jit/metainterp/optimizeopt/vectorize.py
+++ b/rpython/jit/metainterp/optimizeopt/vectorize.py
@@ -14,28 +14,30 @@
         return 'NotAVectorizeableLoop()'
 
 def optimize_vector(metainterp_sd, jitdriver_sd, loop, optimizations):
-    opt = OptVectorize(metainterp_sd, jitdriver_sd, loop, optimizations)
+    opt = VectorizingOptimizer(metainterp_sd, jitdriver_sd, loop, optimizations)
     try:
         opt.propagate_all_forward()
+        # TODO
+        def_opt = Optimizer(metainterp_sd, jitdriver_sd, loop, optimizations)
+        def_opt.propagate_all_forward()
     except NotAVectorizeableLoop:
         # vectorization is not possible, propagate only normal optimizations
         def_opt = Optimizer(metainterp_sd, jitdriver_sd, loop, optimizations)
         def_opt.propagate_all_forward()
 
-class VectorizeOptimizer(Optimizer):
-    def setup(self):
-        pass
-
-class OptVectorize(Optimization):
+class VectorizingOptimizer(Optimizer):
     """ Try to unroll the loop and find instructions to group """
 
     def __init__(self, metainterp_sd, jitdriver_sd, loop, optimizations):
-        self.optimizer = VectorizeOptimizer(metainterp_sd, jitdriver_sd,
-                                             loop, optimizations)
+        Optimizer.__init__(self, metainterp_sd, jitdriver_sd, loop, optimizations)
         self.vec_info = LoopVectorizeInfo()
         self.memory_refs = []
         self.dependency_graph = None
 
+    def emit_unrolled_operation(self, op):
+        self._last_emitted_op = op
+        self._newoperations.append(op)
+
     def _rename_arguments_ssa(self, rename_map, label_args, jump_args):
         # fill the map with the renaming boxes. keys are boxes from the label
         # values are the target boxes.
@@ -58,15 +60,14 @@
         iterations = [operations]
         label_op_args = [self.getvalue(box).get_key_box() for box in label_op.getarglist()]
         values = [self.getvalue(box) for box in label_op.getarglist()]
-        #values[0].make_nonnull(self.optimizer)
 
         jump_op_args = jump_op.getarglist()
 
         rename_map = {}
+        self.emit_unrolled_operation(label_op)
         for unroll_i in range(2, unroll_factor+1):
             # for each unrolling factor the boxes are renamed.
             self._rename_arguments_ssa(rename_map, label_op_args, jump_op_args)
-            iteration_ops = []
             for op in operations:
                 copied_op = op.clone()
 
@@ -86,7 +87,7 @@
                         pass
 
                 self.vec_info._op_index = op_index
-                iteration_ops.append(copied_op)
+                self.emit_unrolled_operation(copied_op)
                 op_index += 1
                 self.vec_info.inspect_operation(copied_op)
 
@@ -104,14 +105,7 @@
             # map will be rebuilt, the jump operation has been updated already
             rename_map.clear()
 
-            iterations.append(iteration_ops)
-
-        # unwrap the loop nesting.
-        loop.operations.append(label_op)
-        for iteration in iterations:
-            for op in iteration:
-                loop.operations.append(op)
-        loop.operations.append(jump_op)
+        self.emit_unrolled_operation(jump_op)
 
     def _gather_trace_information(self, loop):
         for i,op in enumerate(loop.operations):
@@ -132,10 +126,9 @@
 
     def propagate_all_forward(self):
 
-        loop = self.optimizer.loop
-        self.optimizer.clear_newoperations()
+        self.clear_newoperations()
 
-        self._gather_trace_information(loop)
+        self._gather_trace_information(self.loop)
 
         byte_count = self.vec_info.smallest_type_bytes
         if byte_count == 0:
@@ -144,22 +137,25 @@
 
         unroll_factor = self.get_estimated_unroll_factor()
 
-        self.unroll_loop_iterations(loop, unroll_factor)
+        self.unroll_loop_iterations(self.loop, unroll_factor)
 
-        self.build_dependencies()
+        self.loop.operations = self.get_newoperations();
+        self.clear_newoperations();
+
+        self.build_dependency_graph()
+        self.find_adjacent_memory_refs()
 
     def build_dependency_graph(self):
-        self.dependency_graph = DependencyGraph(self.optimizer,
-                                                self.optimizer.loop)
+        self.dependency_graph = DependencyGraph(self)
 
     def find_adjacent_memory_refs(self):
         """ the pre pass already builds a hash of memory references and the
         operations. Since it is in SSA form there is no array index. Indices
         are flattend. If there are two array accesses in the unrolled loop
         i0,i1 and i1 = int_add(i0,c), then i0 = i0 + 0, i1 = i0 + 1 """
-        loop = self.optimizer.loop
+        loop = self.loop
         operations = loop.operations
-        integral_mod = IntegralMod(self.optimizer)
+        integral_mod = IntegralMod(self)
         for opidx,memref in self.vec_info.memory_refs.items():
             integral_mod.reset()
             while True:
diff --git a/rpython/jit/metainterp/test/test_vectorize.py b/rpython/jit/metainterp/test/test_vectorize.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/metainterp/test/test_vectorize.py
@@ -0,0 +1,51 @@
+import py
+
+from rpython.jit.metainterp.warmspot import ll_meta_interp, get_stats
+from rpython.jit.metainterp.test.support import LLJitMixin
+from rpython.jit.codewriter.policy import StopAtXPolicy
+from rpython.jit.metainterp.resoperation import rop
+from rpython.jit.metainterp import history
+from rpython.rlib.jit import JitDriver, hint, set_param
+from rpython.rlib.objectmodel import compute_hash
+from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib.rarithmetic import r_uint
+from rpython.rlib.rawstorage import (alloc_raw_storage, raw_storage_setitem,
+                                     free_raw_storage, raw_storage_getitem)
+
+class VectorizeTest(object):
+    enable_opts = ''
+
+    automatic_promotion_result = {
+        'int_add' : 6, 'int_gt' : 1, 'guard_false' : 1, 'jump' : 1,
+        'guard_value' : 3
+    }
+
+    def meta_interp(self, f, args, policy=None):
+        return ll_meta_interp(f, args, enable_opts=self.enable_opts,
+                              policy=policy,
+                              CPUClass=self.CPUClass,
+                              type_system=self.type_system)
+
+    def test_simple_raw_load(self):
+        myjitdriver = JitDriver(greens = [],
+                                reds = ['i', 'res', 'va'],
+                                vectorize=True)
+        def f():
+            res = r_uint(0)
+            va = alloc_raw_storage(32, zero=True)
+            for i in range(32):
+                raw_storage_setitem(va, i, rffi.cast(rffi.UCHAR,i))
+            i = 0
+            while i < 32:
+                myjitdriver.can_enter_jit(i=i, res=res,  va=va)
+                myjitdriver.jit_merge_point(i=i, res=res, va=va)
+                res += raw_storage_getitem(rffi.UCHAR,va,i)
+                i += 1
+            free_raw_storage(va)
+            return res
+        res = self.meta_interp(f, [])
+        assert res == sum(range(32))
+        self.check_trace_count(1)
+
+class TestLLtype(VectorizeTest, LLJitMixin):
+    pass


More information about the pypy-commit mailing list