Author: Richard Plangger <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit