Author: Richard Plangger <r...@pasra.at>
Branch: vecopt-merge
Changeset: r79052:8fa916fbce20
Date: 2015-08-19 13:19 +0200
http://bitbucket.org/pypy/pypy/changeset/8fa916fbce20/

Log:    further cut down the search space to move guards to an earlier
        position, at the same time it seems that I have made it weaker. some
        guards are not moved anymore (need investigation)

diff --git a/rpython/jit/metainterp/compile.py 
b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -674,6 +674,9 @@
         cloned.copy_all_attributes_from(self)
         return cloned
 
+    def exits_early(self):
+        return True
+
 class ResumeGuardNonnullDescr(ResumeGuardDescr):
     guard_opnum = rop.GUARD_NONNULL
 
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
@@ -4,6 +4,7 @@
 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from rpython.jit.metainterp.resoperation import (rop, GuardResOp, ResOperation)
 from rpython.jit.metainterp.resume import Snapshot
+from rpython.jit.metainterp.compile import ResumeGuardDescr
 from rpython.jit.codewriter.effectinfo import EffectInfo
 from rpython.jit.metainterp.history import (BoxPtr, ConstPtr, ConstInt, BoxInt,
     Box, Const, BoxFloat, AbstractValue)
@@ -61,8 +62,13 @@
             count -= 1
         while i < count: 
             op = self.path[i].getoperation()
-            if op.getopnum() != rop.GUARD_EARLY_EXIT and not 
op.is_always_pure():
+            if not op.is_always_pure():
                 return False
+            if op.is_guard():
+                descr = op.getdescr()
+                assert isinstance(descr, ResumeGuardDescr)
+                if not descr or not descr.exits_early():
+                    return False
             i += 1
         return True
 
@@ -286,9 +292,8 @@
             else:
                 iterdir = node.provides()
             if index >= len(iterdir):
-                #if blacklist:
-                    #blacklist_visit[node] = None
-                #    print "blacklisting 1", node, "path", 
'->'.join([str(p.opidx) for p in path.path])
+                if blacklist:
+                    blacklist_visit[node] = None
                 continue
             else:
                 next_dep = iterdir[index]
@@ -297,7 +302,6 @@
                 if index < len(iterdir):
                     worklist.append((index, node, pathlen))
                 else:
-                    print "blacklisting 2", node, "path", 
'->'.join([str(p.opidx) for p in path.path])
                     blacklist_visit[node] = None
                 path.cut_off_at(pathlen)
                 path.walk(next_node)
@@ -385,9 +389,6 @@
         return self.to == to
     def points_at(self, at):
         return self.at == at
-    def i_points_at(self, idx):
-        # REM
-        return self.at.opidx == idx
 
     def add_dependency(self, at, to, arg):
         self.args.append((at,arg))
@@ -576,17 +577,16 @@
         # pass 2 correct guard dependencies
         for guard_node in self.guards:
             self.build_guard_dependencies(guard_node, tracker)
-        # pass 3 find schedulable nodes
-        jump_node = self.nodes[jump_pos]
-        label_node = self.nodes[label_pos]
+
+    def prepare_for_scheduling(self):
+        jump_node = self.nodes[len(self.nodes)-1]
+        jump_node.emitted = True
+        label_node = self.nodes[0]
         for node in self.nodes:
-            if node != jump_node:
-                if node.depends_count() == 0:
-                    self.schedulable_nodes.insert(0, node)
-                # every leaf instruction points to the jump_op. in theory 
every instruction
-                # points to jump_op. this forces the jump/finish op to be the 
last operation
-                if node.provides_count() == 0:
-                    node.edge_to(jump_node, None, label='jump')
+            if node.depends_count() == 0:
+                self.schedulable_nodes.insert(0, node)
+        if not we_are_translated():
+            assert self.schedulable_nodes[-1] == label_node
 
     def guard_argument_protection(self, guard_node, tracker):
         """ the parameters the guard protects are an indicator for
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
@@ -98,6 +98,11 @@
 
             raise AssertionError("schedule failed cannot continue. possible 
reason: cycle")
 
+        jump_node = self.graph.nodes[-1]
+        assert jump_node.getopnum() == rop.JUMP
+        self.sched_data.unpack_from_vector(jump_node.getoperation(), self)
+        oplist.append(jump_node.getoperation())
+
 def vectorbox_outof_box(box, count=-1, size=-1, type='-'):
     if box.type not in (FLOAT, INT):
         raise AssertionError("cannot create vector box of type %s" % 
(box.type))
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py 
b/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_vectorize.py
@@ -97,6 +97,7 @@
             if cycle is not None:
                 print "CYCLE found %s" % cycle
             self.show_dot_graph(opt.dependency_graph, "early_exit_" + 
self.test_name)
+            assert cycle is None
             opt.schedule(False)
         opt.unroll_loop_iterations(loop, unroll_factor)
         opt.loop.operations = opt.get_newoperations()
@@ -1348,7 +1349,6 @@
         guard_true(i22, descr=<ResumeGuardTrueDescr object at 0x7fc657d7bdc0>) 
[p1, p0, p5, p6, p7, p12, p13, i14]
         jump(p0, p1, p5, p6, p7, p12, p13, i31, i15, i16, i17, i18, i19, i20)
         """
-        # schedule 885 -> ptype is non for raw_load?
         opt = self.vectorize(self.parse_loop(trace))
         self.debug_print_operations(opt.loop)
 
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
@@ -469,6 +469,7 @@
         if sched_data is None:
             sched_data = VecScheduleData(self.cpu.vector_register_size,
                                          self.costmodel, self.orig_label_args)
+        self.dependency_graph.prepare_for_scheduling()
         scheduler = Scheduler(self.dependency_graph, sched_data)
         renamer = Renamer()
         #
@@ -515,49 +516,34 @@
         label_node = graph.getnode(0)
         ee_guard_node = graph.getnode(ee_pos)
         guards = graph.guards
-        unique = set()
         for guard_node in guards:
             if guard_node is ee_guard_node:
                 continue
             modify_later = []
             last_prev_node = None
-            for path in guard_node.iterate_paths(ee_guard_node, 
backwards=True, blacklist=True):
-                p = '->'.join([str(p.opidx) for p in path.path])
-                if p in unique:
-                    assert 0
+            valid = True
+            for prev_dep in guard_node.depends():
+                prev_node = prev_dep.to
+                if prev_dep.is_failarg():
+                    # remove this edge later.
+                    # 1) only because of failing, this dependency exists
+                    # 2) non pure operation points to this guard.
+                    #    but if this guard only depends on pure operations, it 
can be checked
+                    #    at an earlier position, the non pure op can execute 
later!
+                    modify_later.append((prev_node, guard_node))
                 else:
-                    unique.add(p)
-                print "PATH:", p
-                if not we_are_translated():
-                    path.check_acyclic()
-                prev_node = path.second()
-                dep = prev_node.depends_on(guard_node)
-                if dep.is_failarg():
-                    # this dependency we are able to break because it is soley
-                    # relevant due to one or multiple fail args
-                    if prev_node is not last_prev_node:
-                        #  ...
-                        #  o  o
-                        #  \ /
-                        #  (a)
-                        #   |
-                        #  (g)
-                        # this graph yields 2 paths from (g), thus (a) is
-                        # remembered and skipped the second time visited
-                        modify_later.append((prev_node, guard_node))
-                        print "  => remove guard -> second"
-                    last_prev_node = prev_node
-                    continue
-                if path.is_always_pure(exclude_first=True, exclude_last=True):
-                    path.set_schedule_priority(10)
-                    if path.last() is ee_guard_node:
-                        modify_later.append((path.last_but_one(), None))
-                        print "  => always pure"
-                else:
-                    # transformation is invalid.
-                    # exit and do not enter else branch!
-                    break
-            else:
+                    for path in prev_node.iterate_paths(ee_guard_node, 
backwards=True, blacklist=True):
+                        if path.is_always_pure(exclude_first=True, 
exclude_last=True):
+                            path.set_schedule_priority(10)
+                            if path.last() is ee_guard_node:
+                                modify_later.append((path.last_but_one(), 
None))
+                        else:
+                            # transformation is invalid.
+                            # exit and do not enter else branch!
+                            valid = False
+                    if not valid:
+                        break
+            if valid:
                 # transformation is valid, modify the graph and execute
                 # this guard earlier
                 for a,b in modify_later:
@@ -568,7 +554,8 @@
                         if last_but_one is ee_guard_node:
                             continue
                         ee_guard_node.remove_edge_to(last_but_one)
-                        label_node.edge_to(last_but_one, label='pullup')
+                        #label_node.edge_to(last_but_one, label='pullup')
+                print "guard", guard_node, "moved earlier"
                 # only the last guard needs a connection
                 guard_node.edge_to(ee_guard_node, label='pullup-last-guard')
                 self.relax_guard_to(guard_node, ee_guard_node)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to