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