Author: Richard Plangger <planri...@gmail.com>
Branch: zarch-simd-support
Changeset: r87072:1ea1c6504c10
Date: 2016-09-13 15:56 +0200
http://bitbucket.org/pypy/pypy/changeset/1ea1c6504c10/

Log:    do not generate a new operation for index calc if it can be
        expressed as a single operation

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
@@ -993,6 +993,23 @@
         self.next_nonconst = None
         self.current_end = None
 
+    def calculated_by(self, op):
+        # quick check to indicate if this operation is not directly 
expressable using
+        # the operation in the op parameter.
+        if op.getopnum() == rop.INT_ADD:
+            a0 = op.getarg(0)
+            a1 = op.getarg(1)
+            if a0 is self.var and a1.is_constant() and a1.getint() == 
self.constant:
+                return True
+            if a1 is self.var and a0.is_constant() and a0.getint() == 
self.constant:
+                return True
+        if op.getopnum() == rop.INT_SUB:
+            a0 = op.getarg(0)
+            a1 = op.getarg(1)
+            if a0 is self.var and a1.is_constant() and a1.getint() == 
self.constant:
+                return True
+        return False
+
     def stride_const(self):
         return self.next_nonconst is None
 
diff --git a/rpython/jit/metainterp/optimizeopt/schedule.py 
b/rpython/jit/metainterp/optimizeopt/schedule.py
--- a/rpython/jit/metainterp/optimizeopt/schedule.py
+++ b/rpython/jit/metainterp/optimizeopt/schedule.py
@@ -49,7 +49,8 @@
             if arg.is_constant() or arg.is_inputarg():
                 continue
             if arg not in self.seen:
-                needs_resolving[arg] = None
+                box = self.renamer.rename_box(arg)
+                needs_resolving[box] = None
 
         indexvars = self.graph.index_vars
         i = len(delayed)-1
@@ -60,18 +61,32 @@
                 # either it is a normal operation, or we know that there is a 
linear combination
                 del needs_resolving[op]
                 if op in indexvars:
-                    indexvar = indexvars[op]
-                    last = None
-                    for operation in indexvar.get_operations():
-                        self.append_to_oplist(operation)
-                        last = operation
-                    if last:
-                        indexvars[last] = indexvar
-                        self.renamer.start_renaming(op, last)
+                    opindexvar = indexvars[op]
+                    # there might be a variable already, that
+                    # calculated the index variable, thus just reuse it
+                    for var, indexvar in indexvars.items(): 
+                        if indexvar == opindexvar and var in self.seen:
+                            self.renamer.start_renaming(op, var)
+                            break
+                    else:
+                        if opindexvar.calculated_by(op):
+                            # just append this operation
+                            self.seen[op] = None
+                            self.append_to_oplist(op)
+                        else:
+                            # here is an easier way to calculate just this 
operation
+                            last = op
+                            for operation in opindexvar.get_operations():
+                                self.append_to_oplist(operation)
+                                last = operation
+                            indexvars[last] = opindexvar
+                            self.renamer.start_renaming(op, last)
+                            self.seen[op] = None
+                            self.seen[last] = None
                 else: 
                     self.resolve_delayed(needs_resolving, delayed, op)
                     self.append_to_oplist(op)
-                self.seen[op] = None
+                    self.seen[op] = None
                 if len(delayed) > i:
                     del delayed[i]
             i -= 1
@@ -84,14 +99,20 @@
         self.renamer.rename(op)
         self.oplist.append(op)
 
+    def schedule(self):
+        self.prepare()
+        Scheduler().walk_and_emit(self)
+        self.post_schedule()
+
     def post_schedule(self):
         loop = self.graph.loop
+        jump = loop.jump
         if self.delayed:
             # some operations can be delayed until the jump instruction,
             # handle them here
-            self.resolve_delayed({}, self.delayed, loop.jump)
+            self.resolve_delayed({}, self.delayed, jump)
+        self.renamer.rename(jump)
         loop.operations = self.oplist
-        self.renamer.rename(loop.jump)
 
     def profitable(self):
         return True
@@ -120,8 +141,10 @@
         delayed.append(node)
         node.delayed = None
         provides = node.provides()
+        op = node.getoperation()
         if len(provides) == 0:
-            self.delayed.append(node)
+            for n in delayed:
+                self.delayed.append(n)
         else:
             for to in node.provides():
                 tnode = to.target_node()
@@ -187,13 +210,14 @@
     def post_emit(self, node):
         pass
 
-    def pre_emit(self, node, pack_first=True):
-        delayed = node.delayed
+    def pre_emit(self, orignode, pack_first=True):
+        delayed = orignode.delayed
         if delayed:
             # there are some nodes that have been delayed just for this 
operation
             if pack_first:
-                op = node.getoperation()
+                op = orignode.getoperation()
                 self.resolve_delayed({}, delayed, op)
+
             for node in delayed:
                 op = node.getoperation()
                 if op in self.seen:
@@ -208,7 +232,7 @@
                         for to in node.provides():
                             tnode = to.target_node()
                             self.delegate_delay(tnode, [node])
-                        node.delayed = None
+            orignode.delayed = None
 
 class Scheduler(object):
     """ Create an instance of this class to (re)schedule a vector trace. """
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_schedule.py 
b/rpython/jit/metainterp/optimizeopt/test/test_schedule.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_schedule.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_schedule.py
@@ -5,7 +5,7 @@
 from rpython.jit.metainterp.optimizeopt.renamer import Renamer
 from rpython.jit.metainterp.optimizeopt.vector import (VecScheduleState,
         Pack, Pair, NotAProfitableLoop, VectorizingOptimizer, GenericCostModel,
-        PackSet)
+        PackSet, SchedulerState)
 from rpython.jit.backend.llsupport.vector_ext import VectorExt
 from rpython.jit.metainterp.optimizeopt.dependency import Node, DependencyGraph
 from rpython.jit.metainterp.optimizeopt.schedule import Scheduler
@@ -460,5 +460,18 @@
         state.expand(['d','d','c'], 'ddc')
         assert state.find_expanded(['d','d','c']) == 'ddc'
 
-
-
+    def test_delayed_schedule(self):
+        loop = self.parse("""
+        [i0]
+        i1 = int_add(i0,1)
+        i2 = int_add(i0,1)
+        jump(i2)
+        """)
+        loop.prefix_label = None
+        loop.label = ResOperation(rop.LABEL, loop.inputargs)
+        ops = loop.operations
+        loop.operations = ops[:-1]
+        loop.jump = ops[-1]
+        state = SchedulerState(self.cpu, DependencyGraph(loop))
+        state.schedule()
+        assert len(loop.operations) == 1
diff --git a/rpython/jit/metainterp/optimizeopt/vector.py 
b/rpython/jit/metainterp/optimizeopt/vector.py
--- a/rpython/jit/metainterp/optimizeopt/vector.py
+++ b/rpython/jit/metainterp/optimizeopt/vector.py
@@ -262,11 +262,8 @@
 
         # re-schedule the trace -> removes many pure operations
         graph = DependencyGraph(loop)
-        costmodel = GenericCostModel(self.cpu, self.cost_threshold)
         state = SchedulerState(self.cpu, graph)
-        state.prepare()
-        Scheduler().walk_and_emit(state)
-        state.post_schedule()
+        state.schedule()
 
         return loop.finaloplist(jitcell_token=jitcell_token, 
reset_label_token=False)
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to