Author: Richard Plangger <r...@pasra.at>
Branch: vecopt-merge
Changeset: r79040:4c2ccf278516
Date: 2015-08-18 17:08 +0200
http://bitbucket.org/pypy/pypy/changeset/4c2ccf278516/

Log:    added two tests ensuring that paths are constructed correctly, Path
        was not copied ensured that paths are not cyclic

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
@@ -26,8 +26,10 @@
 
 LOAD_COMPLEX_OBJ = [ (rop.GETARRAYITEM_GC, 0, 1)
                    , (rop.GETARRAYITEM_RAW, 0, 1)
+                   , (rop.RAW_LOAD, 0, 1)
                    , (rop.GETINTERIORFIELD_GC, 0, 1)
-                   , (rop.RAW_LOAD, 0, 1)
+                   , (rop.GETFIELD_GC, 0, -1)
+                   , (rop.GETFIELD_RAW, 0, -1)
                    ]
 
 class Path(object):
@@ -44,7 +46,7 @@
             return None
         return self.path[len(self.path)-2]
 
-    def has_no_side_effects(self, exclude_first=False, exclude_last=False):
+    def is_always_pure(self, exclude_first=False, exclude_last=False):
         last = len(self.path)-1
         count = len(self.path)
         i = 0
@@ -81,10 +83,15 @@
                 assert 0, "segment %s was already seen. this makes the path 
cyclic!" % segment
             else:
                 seen.add(segment)
+        return True
 
     def clone(self):
         return Path(self.path[:])
 
+    def as_str(self):
+        """ NOT_RPYTHON """
+        return ' -> '.join([str(p) for p in self.path])
+
 class Node(object):
     def __init__(self, op, opidx):
         self.op = op
@@ -120,8 +127,6 @@
     def edge_to(self, to, arg=None, failarg=False, label=None):
         if self is to:
             return
-        if self.getindex() > to.getindex():
-            import pdb; pdb.set_trace()
         dep = self.depends_on(to)
         if not dep:
             #if force or self.independent(idx_from, idx_to):
@@ -161,7 +166,7 @@
         return self.op.getopnum() == rop.GUARD_EARLY_EXIT
 
     def loads_from_complex_object(self):
-        return rop._ALWAYS_PURE_LAST <= self.op.getopnum() <= 
rop.GETINTERIORFIELD_GC
+        return rop._ALWAYS_PURE_LAST <= self.op.getopnum() < rop._MALLOC_FIRST
 
     def modifies_complex_object(self):
         return rop.SETARRAYITEM_GC <= self.op.getopnum() <= rop.UNICODESETITEM
@@ -183,18 +188,17 @@
                         args.append((op.getarg(i), op.getarg(j), True))
                         for x in range(j+1,len(op_args)):
                             args.append((op.getarg(x), None, False))
-                    break
-        else:
-            # assume this destroys every argument... can be enhanced by looking
-            # at the effect info of a call for instance
-            for arg in op.getarglist():
-                # if it is a constant argument it cannot be destroyed.
-                # neither can a box float be destroyed. BoxInt can
-                # contain a reference thus it is assumed to be destroyed
-                if isinstance(arg, Const) or isinstance(arg, BoxFloat):
-                    args.append((arg, None, False))
-                else:
-                    args.append((arg, None,True))
+                    return args
+        # assume this destroys every argument... can be enhanced by looking
+        # at the effect info of a call for instance
+        for arg in op.getarglist():
+            # if it is a constant argument it cannot be destroyed.
+            # neither can a box float be destroyed. BoxInt can
+            # contain a reference thus it is assumed to be destroyed
+            if isinstance(arg, Const) or isinstance(arg, BoxFloat):
+                args.append((arg, None, False))
+            else:
+                args.append((arg, None, True))
         return args
 
     def provides_count(self):
@@ -259,7 +263,7 @@
 
     def iterate_paths(self, to, backwards=False, path_max_len=-1):
         """ yield all nodes from self leading to 'to' """
-        if self == to:
+        if self is to:
             return
         path = Path([self])
         worklist = [(0, self, 1)]
@@ -282,7 +286,7 @@
                 pathlen += 1
 
                 if next_node is to or (path_max_len > 0 and pathlen >= 
path_max_len):
-                    yield path
+                    yield Path(path.path[:])
                 else:
                     worklist.append((0, next_node, pathlen))
 
@@ -586,7 +590,6 @@
                 # i = int_and(j, 255)
                 # guard_true(i) [...]
                 pass
-
         elif guard_op.is_foldable_guard():
             # these guards carry their protected variables directly as a 
parameter
             for arg in guard_node.getoperation().getarglist():
@@ -669,9 +672,12 @@
             for opnum, i, j in unrolling_iterable(LOAD_COMPLEX_OBJ):
                 if opnum == op.getopnum():
                     cobj = op.getarg(i)
-                    index_var = op.getarg(j)
-                    tracker.depends_on_arg(cobj, node, index_var)
-                    tracker.depends_on_arg(index_var, node)
+                    if j != -1:
+                        index_var = op.getarg(j)
+                        tracker.depends_on_arg(cobj, node, index_var)
+                        tracker.depends_on_arg(index_var, node)
+                    else:
+                        tracker.depends_on_arg(cobj, node)
         else:
             for arg, argcell, destroyed in node.side_effect_arguments():
                 if argcell is not None:
@@ -722,6 +728,8 @@
             dot = "digraph dep_graph {\n"
             for node in self.nodes:
                 op = node.getoperation()
+                if op.getopnum() == rop.DEBUG_MERGE_POINT:
+                    continue
                 op_str = str(op)
                 if op.is_guard():
                     op_str += " " + ','.join([str(arg) for arg in 
op.getfailargs()])
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_dependency.py 
b/rpython/jit/metainterp/optimizeopt/test/test_dependency.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_dependency.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_dependency.py
@@ -5,10 +5,18 @@
     LLtypeMixin, BaseTest, FakeMetaInterpStaticData, 
convert_old_style_to_targets)
 from rpython.jit.metainterp.history import TargetToken, JitCellToken, TreeLoop
 from rpython.jit.metainterp.optimizeopt.dependency import (DependencyGraph, 
Dependency,
-        IndexVar, MemoryRef)
+        IndexVar, MemoryRef, Node)
 from rpython.jit.metainterp.resoperation import rop, ResOperation
 from rpython.conftest import option
 
+class FakeNode(Node):
+    def __init__(self, i):
+        Node.__init__(self, None, i)
+        pass
+
+    def __repr__(self):
+        return "n%d" % self.opidx
+
 class DependencyBaseTest(BaseTest):
 
     def setup_method(self, method):
@@ -356,19 +364,75 @@
         self.assert_dependencies(ops, full_check=False)
         self.assert_dependent(2,12)
 
+    def test_getfield(self):
+        pass 
+        trace = """
+        [p0, p1] # 0: 1,2,5
+        p2 = getfield_gc(p0) # 1: 3,5
+        p3 = getfield_gc(p0) # 2: 4
+        guard_nonnull(p2) [p2] # 3: 4,5
+        guard_nonnull(p3) [p3] # 4: 5
+        jump(p0,p2) # 5:
+        """
+        self.assert_dependencies(trace, full_check=True)
+
     def test_cyclic(self):
         pass 
         trace = """
         [p0, p1, p5, p6, p7, p9, p11, p12] # 0: 1,6
-        guard_early_exit() [] # 1: 2,6,7
-        p13 = getfield_gc(p9) # 2: 3,4,5,6
-        guard_nonnull(p13) [] # 3: 4,5,6
-        i14 = getfield_gc(p9) # 4: 5,6,7
+        guard_early_exit() [] # 1: 2,4,6,7
+        p13 = getfield_gc(p9) # 2: 3,5,6
+        guard_nonnull(p13) [] # 3: 5,6
+        i14 = getfield_gc(p9) # 4: 6
         p15 = getfield_gc(p13) # 5: 6
         guard_class(p15, 140737326900656) [p1, p0, p9, i14, p15, p13, p5, p6, 
p7] # 6: 7
         jump(p0,p1,p5,p6,p7,p9,p11,p12) # 7:
         """
         self.assert_dependencies(trace, full_check=True)
 
+
+    def test_iterate_paths(self):
+        n1,n2,n3,n4,n5 = [FakeNode(i+1) for i in range(5)]
+        # n1 -> n2 -> n4 -> n5
+        #  +---> n3 --^
+        n1.edge_to(n2); n2.edge_to(n4); n4.edge_to(n5)
+        n1.edge_to(n3); n3.edge_to(n4);
+
+        paths = list(n5.iterate_paths(n1, backwards=True))
+        assert all([path.check_acyclic() for path in paths])
+        assert len(paths) == 2
+        assert paths[0].as_str() == "n5 -> n4 -> n2 -> n1"
+        assert paths[1].as_str() == "n5 -> n4 -> n3 -> n1"
+        paths = list(n1.iterate_paths(n5))
+        assert all([path.check_acyclic() for path in paths])
+        assert len(paths) == 2
+        assert paths[0].as_str() == "n1 -> n2 -> n4 -> n5"
+        assert paths[1].as_str() == "n1 -> n3 -> n4 -> n5"
+
+
+    def test_iterate_one_many_one(self):
+        r = range(19)
+        n0 = FakeNode(0)
+        nodes = [FakeNode(i+1) for i in r]
+        nend = FakeNode(len(r)+1)
+
+        assert len(list(n0.iterate_paths(nodes[0], backwards=True))) == 0
+
+        for i in r:
+            n0.edge_to(nodes[i])
+            nodes[i].edge_to(nend)
+
+        paths = list(nend.iterate_paths(n0, backwards=True))
+        assert all([path.check_acyclic() for path in paths])
+        assert len(paths) == len(r)
+        for i in r:
+            assert paths[i].as_str() == "n%d -> %s -> n0" % (len(r)+1, 
nodes[i])
+        # forward
+        paths = list(n0.iterate_paths(nend))
+        assert all([path.check_acyclic() for path in paths])
+        assert len(paths) == len(r)
+        for i in r:
+            assert paths[i].as_str() == "n0 -> %s -> n%d" % (nodes[i], 
len(r)+1)
+
 class TestLLtype(BaseTestDependencyGraph, LLtypeMixin):
     pass
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
@@ -520,9 +520,12 @@
                 continue
             modify_later = []
             last_prev_node = None
+            i = 0
             for path in guard_node.iterate_paths(ee_guard_node, True):
                 if not we_are_translated():
                     path.check_acyclic()
+                print "loop", i
+                i+=1
                 prev_node = path.second()
                 dep = prev_node.depends_on(guard_node)
                 if dep.is_failarg():
@@ -540,7 +543,7 @@
                         continue
                     modify_later.append((prev_node, guard_node))
                 else:
-                    if path.has_no_side_effects(exclude_first=True, 
exclude_last=True):
+                    if path.is_always_pure(exclude_first=True, 
exclude_last=True):
                         path.set_schedule_priority(10)
                         modify_later.append((path.last_but_one(), None))
                     else:
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to