[pypy-commit] pypy vecopt-merge: path iteration on a dependecy graph can enable blacklisting nodes that have already been visited.this cuts down the search space. this is only valid if a property must hold along all the paths and once for one path proven, any subpath must not be checked anymore (is the case in guard early exit
plan_rich
noreply at buildbot.pypy.org
Tue Aug 18 17:49:26 CEST 2015
Author: Richard Plangger <rich at pasra.at>
Branch: vecopt-merge
Changeset: r79042:4886c173125a
Date: 2015-08-18 17:49 +0200
http://bitbucket.org/pypy/pypy/changeset/4886c173125a/
Log: path iteration on a dependecy graph can enable blacklisting nodes
that have already been visited.this cuts down the search space. this
is only valid if a property must hold along all the paths and once
for one path proven, any subpath must not be checked anymore (is the
case in guard early exit
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
@@ -44,7 +44,12 @@
def last_but_one(self):
if len(self.path) < 2:
return None
- return self.path[len(self.path)-2]
+ return self.path[-2]
+
+ def last(self):
+ if len(self.path) < 1:
+ return None
+ return self.path[-1]
def is_always_pure(self, exclude_first=False, exclude_last=False):
last = len(self.path)-1
@@ -261,10 +266,16 @@
worklist.append(dep.to)
return True
- def iterate_paths(self, to, backwards=False, path_max_len=-1):
- """ yield all nodes from self leading to 'to' """
+ def iterate_paths(self, to, backwards=False, path_max_len=-1, blacklist=False):
+ """ yield all nodes from self leading to 'to'. backwards determines
+ the iteration direction and blacklist marks nodes that have already been visited.
+ blacklist comes in handy if a property must hold for every path. not *every* possible
+ instance must be iterated, but trees that have already been visited can be ignored
+ after the have been visited
+ """
if self is to:
return
+ blacklist_visit = {}
path = Path([self])
worklist = [(0, self, 1)]
while len(worklist) > 0:
@@ -274,19 +285,28 @@
else:
iterdir = node.provides()
if index >= len(iterdir):
+ if blacklist:
+ blacklist_visit[node] = None
continue
else:
next_dep = iterdir[index]
next_node = next_dep.to
index += 1
+ if blacklist and next_node in blacklist_visit:
+ yield Path(path.path[:])
+ continue
if index < len(iterdir):
worklist.append((index, node, pathlen))
+ else:
+ blacklist_visit[node] = None
path.cut_off_at(pathlen)
path.walk(next_node)
pathlen += 1
if next_node is to or (path_max_len > 0 and pathlen >= path_max_len):
yield Path(path.path[:])
+ if blacklist:
+ blacklist_visit[next_node] = None
else:
worklist.append((0, next_node, pathlen))
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
@@ -434,5 +434,35 @@
for i in r:
assert paths[i].as_str() == "n0 -> %s -> n%d" % (nodes[i], len(r)+1)
+ def test_iterate_paths_blacklist_diamond(self):
+ blacklist = {}
+ n1,n2,n3,n4 = [FakeNode(i+1) for i in range(4)]
+ # n1 -> n2 -> n4
+ # +---> n3 --^
+ n1.edge_to(n2); n2.edge_to(n4);
+ n1.edge_to(n3); n3.edge_to(n4);
+
+ paths = list(n1.iterate_paths(n4, blacklist=True))
+ assert len(paths) == 2
+ assert paths[0].as_str() == "n1 -> n2 -> n4"
+ assert paths[1].as_str() == "n1 -> n3"
+
+ def test_iterate_paths_blacklist_double_diamond(self):
+ blacklist = {}
+ n1,n2,n3,n4,n5,n6,n7,n8 = [FakeNode(i+1) for i in range(8)]
+ # n1 -> n2 -> n4 -> n5 -> n6 --> n8
+ # +---> n3 --^ +---> n7 --^
+ n1.edge_to(n2); n2.edge_to(n4);
+ n1.edge_to(n3); n3.edge_to(n4);
+ n4.edge_to(n5)
+ n5.edge_to(n6); n6.edge_to(n8);
+ n5.edge_to(n7); n7.edge_to(n8);
+
+ paths = list(n1.iterate_paths(n8, blacklist=True))
+ assert len(paths) == 3
+ assert paths[0].as_str() == "n1 -> n2 -> n4 -> n5 -> n6 -> n8"
+ assert paths[1].as_str() == "n1 -> n2 -> n4 -> n5 -> n7"
+ assert paths[2].as_str() == "n1 -> n3"
+
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
@@ -521,7 +521,7 @@
modify_later = []
last_prev_node = None
i = 0
- for path in guard_node.iterate_paths(ee_guard_node, True):
+ for path in guard_node.iterate_paths(ee_guard_node, backwards=True, blacklist=True):
if not we_are_translated():
path.check_acyclic()
print "loop", i
@@ -545,7 +545,8 @@
else:
if path.is_always_pure(exclude_first=True, exclude_last=True):
path.set_schedule_priority(10)
- modify_later.append((path.last_but_one(), None))
+ 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!
More information about the pypy-commit
mailing list