[pypy-commit] pypy vecopt2: enhanced dependency test. no boiler plate code to define dependencies (but annotate in the code instead)
plan_rich
noreply at buildbot.pypy.org
Tue May 5 09:45:50 CEST 2015
Author: Richard Plangger <rich at pasra.at>
Branch: vecopt2
Changeset: r77100:4f501c0da147
Date: 2015-03-31 12:15 +0200
http://bitbucket.org/pypy/pypy/changeset/4f501c0da147/
Log: enhanced dependency test. no boiler plate code to define
dependencies (but annotate in the code instead) leaf nodes now have
a dep. edge to jump op correctly redefining variables if they are
destroyed by a call
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
@@ -75,7 +75,7 @@
i -= 1
except KeyError:
# when a key error is raised, this means
- # no information is available, assume the worst
+ # no information is available, safe default
pass
return def_chain[-1][0]
@@ -102,9 +102,9 @@
self.adjacent_list = [ [] for i in range(len(self.operations)) ]
self.integral_mod = IntegralMod()
self.schedulable_nodes = [0] # label is always scheduleable
- self.build_dependencies(self.operations)
+ self.build_dependencies()
- def build_dependencies(self, operations):
+ def build_dependencies(self):
""" This is basically building the definition-use chain and saving this
information in a graph structure. This is the same as calculating
the reaching definitions and the 'looking back' whenever it is used.
@@ -113,99 +113,120 @@
the operations are in SSA form
"""
tracker = DefTracker(self.memory_refs)
-
+ #
guards = []
# pass 1
- for i,op in enumerate(operations):
+ for i,op in enumerate(self.operations):
# the label operation defines all operations at the
# beginning of the loop
if op.getopnum() == rop.LABEL:
for arg in op.getarglist():
tracker.define(arg, 0)
continue # prevent adding edge to the label itself
-
# definition of a new variable
if op.result is not None:
# In SSA form. Modifications get a new variable
tracker.define(op.result, i)
-
# usage of defined variables
if op.is_always_pure() or op.is_final():
# normal case every arguments definition is set
for arg in op.getarglist():
self._def_use(arg, i, tracker)
+ elif op.is_guard():
+ guards.append(i)
else:
- self.put_edges_for_complex_objects(op, i, tracker)
-
- # guard specifics
- if op.is_guard():
- guards.append(i)
- # TODO
- #if i > 0:
- # self._guard_dependency(op, i, operations, tracker)
-
+ self._build_non_pure_dependencies(op, i, tracker)
+ #
# pass 2 correct guard dependencies
for guard_idx in guards:
- variables = []
- for dep in self.depends(guard_idx):
- idx = dep.idx_from
- op = operations[idx]
- for arg in op.getarglist():
- if isinstance(arg, Box):
- variables.append(arg)
- if op.result:
- variables.append(op.result)
- print "\ntesting", variables
- for var in variables:
- try:
- def_idx = tracker.definition_index(var)
- print "guard", guard_idx, def_idx, "var", var, "aaa", [d.idx_to for d in self.get_uses(def_idx)]
- for dep in self.provides(def_idx):
- if var in dep.args and dep.idx_to > guard_idx:
- self._put_edge(guard_idx, dep.idx_to, var)
- print "put edge", guard_idx, dep.idx_to, var, dep.args
- except KeyError:
- pass
- op = operations[guard_idx]
- for arg in op.getfailargs():
- try:
- def_idx = tracker.definition_index(arg)
- self._put_edge(def_idx, i, arg)
- except KeyError:
- pass
-
+ self._build_guard_dependencies(guard_idx, op.getopnum(), tracker)
# pass 3 find schedulable nodes
- for i,op in enumerate(operations):
+ jump_pos = len(self.operations)-1
+ for i,op in enumerate(self.operations):
if len(self.adjacent_list[i]) == 0:
self.schedulable_nodes.append(i)
+ # every leaf instruction points to the jump_op. in theory
+ # every instruction points to jump_op, this is an optimization
+ # to prevent the scheduling of ops before the jump operation
+ if i != jump_pos:
+ for dep in self.adjacent_list[i]:
+ if dep.idx_to > i:
+ break
+ else:
+ self._put_edge(i, jump_pos, None)
+ def _build_guard_dependencies(self, guard_idx, guard_opnum, tracker):
+ if guard_opnum >= rop.GUARD_NOT_INVALIDATED:
+ # ignure invalidated & future condition guard
+ return
+ # 'GUARD_TRUE/1d',
+ # 'GUARD_FALSE/1d',
+ # 'GUARD_VALUE/2d',
+ # 'GUARD_CLASS/2d',
+ # 'GUARD_NONNULL/1d',
+ # 'GUARD_ISNULL/1d',
+ # 'GUARD_NONNULL_CLASS/2d',
+ guard_op = self.operations[guard_idx]
+ for arg in guard_op.getarglist():
+ self._def_use(arg, guard_idx, tracker)
- def update_memory_ref(self, op, index, tracker):
- if index not in self.memory_refs:
- return
- memref = self.memory_refs[index]
- self.integral_mod.reset()
- try:
- curidx = tracker.definition_index(memref.origin)
- except KeyError:
- return
- curop = self.operations[curidx]
- while True:
- self.integral_mod.inspect_operation(curop)
- if self.integral_mod.is_const_mod:
- self.integral_mod.update_memory_ref(memref)
+ variables = []
+ for dep in self.depends(guard_idx):
+ idx = dep.idx_from
+ op = self.operations[idx]
+ for arg in op.getarglist():
+ if isinstance(arg, Box):
+ variables.append(arg)
+ if op.result:
+ variables.append(op.result)
+ #
+ for var in variables:
+ try:
+ def_idx = tracker.definition_index(var)
+ print "guard", guard_idx, def_idx, "var", var, "aaa", [d.idx_to for d in self.get_uses(def_idx)]
+ for dep in self.provides(def_idx):
+ if var in dep.args and dep.idx_to > guard_idx:
+ self._put_edge(guard_idx, dep.idx_to, var)
+ print "put edge", guard_idx, dep.idx_to, var, dep.args
+ except KeyError:
+ pass
+ # handle fail args
+ op = self.operations[guard_idx]
+ for arg in op.getfailargs():
+ try:
+ def_idx = tracker.definition_index(arg)
+ self._put_edge(def_idx, guard_idx, arg)
+ except KeyError:
+ assert False
+ #
+ # guards check overflow or raise are directly dependent
+ # find the first non guard operation
+ prev_op_idx = guard_idx - 1
+ while prev_op_idx > 0:
+ prev_op = self.operations[prev_op_idx]
+ if prev_op.is_guard():
+ prev_op_idx -= 1
else:
- break # an operation that is not tractable
- for dep in self.depends(curidx):
- curop = self.operations[dep.idx_from]
- if curop.result == memref.origin:
- curidx = dep.idx_from
- break
- else:
- break # cannot go further, this might be the label, or a constant
+ break
+ prev_op = self.operations[prev_op_idx]
+ #
+ if op.is_guard_exception() and prev_op.can_raise():
+ self._guard_inhert(prev_op_idx, guard_idx)
+ elif op.is_guard_overflow() and prev_op.is_ovf():
+ self._guard_inhert(prev_op_idx, guard_idx)
+ elif op.getopnum() == rop.GUARD_NOT_FORCED and prev_op.can_raise():
+ self._guard_inhert(prev_op_idx, guard_idx)
+ elif op.getopnum() == rop.GUARD_NOT_FORCED_2 and prev_op.can_raise():
+ self._guard_inhert(prev_op_idx, guard_idx)
- def put_edges_for_complex_objects(self, op, index, tracker):
- self.update_memory_ref(op, index, tracker)
+ def _guard_inhert(self, idx, guard_idx):
+ self._put_edge(idx, guard_idx, None)
+ for dep in self.provides(idx):
+ if dep.idx_to > guard_idx:
+ self._put_edge(guard_idx, dep.idx_to, None)
+
+ def _build_non_pure_dependencies(self, op, index, tracker):
+ self._update_memory_ref(op, index, tracker)
if self.loads_from_complex_object(op):
# If this complex object load operation loads an index that has been
# modified, the last modification should be used to put a def-use edge.
@@ -221,15 +242,13 @@
# tracks the exact cell that is modified
self._def_use(arg, index, tracker, argcell=argcell)
self._def_use(argcell, index, tracker)
- if destroyed:
- tracker.define(arg, index, argcell=argcell)
else:
if destroyed:
- # we cannot be sure that only a one cell is modified
- # assume the worst, this is a complete redefintion
+ # cannot be sure that only a one cell is modified
+ # assume all cells are (equivalent to a redefinition)
try:
- # A trace is not in SSA form, but this complex object
- # modification introduces a WAR/WAW dependency
+ # A trace is not entirely in SSA form. complex object
+ # modification introduces WAR/WAW dependencies
def_idx = tracker.definition_index(arg)
for dep in self.provides(def_idx):
if dep.idx_to >= index:
@@ -241,6 +260,8 @@
else:
# not destroyed, just a normal use of arg
self._def_use(arg, index, tracker)
+ if destroyed:
+ tracker.define(arg, index, argcell=argcell)
def _def_use(self, arg, index, tracker, argcell=None):
try:
@@ -274,46 +295,34 @@
return args
- def _guard_dependency(self, op, i, operations, defining_indices):
- # respect a guard after a statement that can raise!
- assert i > 0
-
- j = i - 1
- while j > 0:
- prev_op = operations[j]
- if prev_op.is_guard():
- j -= 1
+ def _update_memory_ref(self, op, index, tracker):
+ if index not in self.memory_refs:
+ return
+ memref = self.memory_refs[index]
+ self.integral_mod.reset()
+ try:
+ curidx = tracker.definition_index(memref.origin)
+ except KeyError:
+ return
+ curop = self.operations[curidx]
+ while True:
+ self.integral_mod.inspect_operation(curop)
+ if self.integral_mod.is_const_mod:
+ self.integral_mod.update_memory_ref(memref)
else:
- break
- prev_op = operations[j]
-
- if op.is_guard_exception() and prev_op.can_raise():
- self._inhert_all_dependencies(operations, j, i)
- # respect an overflow guard after an ovf statement!
- if op.is_guard_overflow() and prev_op.is_ovf():
- self._inhert_all_dependencies(operations, j, i)
- if op.getopnum() == rop.GUARD_NOT_FORCED and prev_op.can_raise():
- self._inhert_all_dependencies(operations, j, i)
- if op.getopnum() == rop.GUARD_NOT_FORCED_2 and prev_op.can_raise():
- self._inhert_all_dependencies(operations, j, i)
-
- def _inhert_all_dependencies(self, operations, op_idx, from_idx):
- assert op_idx < from_idx
- for dep in self.instr_dependencies(from_idx):
- for dep in self.instr_dependencies(dep.idx_from):
- if dep.idx_to >= op_idx:
+ break # an operation that is not tractable
+ for dep in self.depends(curidx):
+ curop = self.operations[dep.idx_from]
+ if curop.result == memref.origin:
+ curidx = dep.idx_from
break
- self._put_edge(dep.idx_to, op_idx, None)
- if dep.idx_from < op_idx:
- self._put_edge(dep.idx_from, op_idx, None)
- self._put_edge(op_idx, from_idx, None)
+ else:
+ break # cannot go further, this might be the label, or a constant
def _put_edge(self, idx_from, idx_to, arg):
assert idx_from != idx_to
- if idx_from == 6 and idx_to == 9:
- assert False
- dep = self.instr_dependency(idx_from, idx_to)
- if dep is None:
+ dep = self.directly_depends(idx_from, idx_to)
+ if not dep:
dep = Dependency(idx_from, idx_to, arg)
self.adjacent_list[idx_from].append(dep)
self.adjacent_list[idx_to].append(dep)
@@ -347,6 +356,8 @@
if idx > dep.idx_from:
yield dep
+ def dependencies(self, idx):
+ return self.adjacent_list[idx]
def instr_dependencies(self, idx):
edges = self.adjacent_list[idx]
return edges
@@ -363,7 +374,7 @@
stmt_indices = [bi]
while len(stmt_indices) > 0:
idx = stmt_indices.pop()
- for dep in self.instr_dependencies(idx):
+ for dep in self.dependencies(idx):
if idx < dep.idx_to:
# this dependency points downwards (thus unrelevant)
continue
@@ -378,13 +389,17 @@
return True
def definition_dependencies(self, idx):
+ # XXX remove
deps = []
for dep in self.adjacent_list[idx]:
for dep_def in self.adjacent_list[dep.idx_from]:
deps.append(dep_def)
return deps
+ def directly_depends(self, from_idx, to_idx):
+ return self.instr_dependency(from_idx, to_idx)
def instr_dependency(self, from_instr_idx, to_instr_idx):
+ # XXX
""" Does there exist a dependency from the instruction to another?
Returns None if there is no dependency or the Dependency object in
any other case.
@@ -404,15 +419,13 @@
idx = follow_dep.idx_from
if idx == point_to_idx:
idx = follow_dep.idx_to
-
- preount = len(self.adjacent_list[idx])
+ #preount = len(self.adjacent_list[idx])
self.adjacent_list[idx] = [d for d in self.adjacent_list[idx] \
if d.idx_to != point_to_idx and d.idx_from != point_to_idx]
#print "reduced", idx, "from",preount,"to",len(self.adjacent_list[idx])
def __repr__(self):
graph = "graph([\n"
-
for i,l in enumerate(self.adjacent_list):
graph += " " + str(i) + ": "
for d in l:
@@ -421,25 +434,20 @@
else:
graph += str(d.idx_from) + ","
graph += "\n"
-
return graph + " ])"
def loads_from_complex_object(self, op):
- opnum = op.getopnum()
- return rop._ALWAYS_PURE_LAST <= opnum and opnum <= rop._MALLOC_FIRST
+ return rop._ALWAYS_PURE_LAST <= op.getopnum() <= rop._MALLOC_FIRST
def modifies_complex_object(self, op):
- opnum = op.getopnum()
- return rop.SETARRAYITEM_GC<= opnum and opnum <= rop.UNICODESETITEM
+ return rop.SETARRAYITEM_GC <= op.getopnum() <= rop.UNICODESETITEM
def as_dot(self, operations):
if not we_are_translated():
dot = "digraph dep_graph {\n"
-
for i in range(len(self.adjacent_list)):
op = operations[i]
dot += " n%d [label=\"[%d]: %s\"];\n" % (i,i,str(op))
-
dot += "\n"
for i,alist in enumerate(self.adjacent_list):
for dep in alist:
@@ -447,7 +455,6 @@
dot += " n%d -> n%d;\n" % (i,dep.idx_to)
dot += "\n}\n"
return dot
-
return ""
class Scheduler(object):
@@ -476,14 +483,16 @@
print "shifting", index, "(", node ,")","to", len(self.schedulable_nodes)-1, "sched", self.schedulable_nodes
def schedule_all(self, opindices):
- indices = []
while len(opindices) > 0:
opidx = opindices.pop()
for i,node in enumerate(self.schedulable_nodes):
if node == opidx:
- indices.append(i)
- for index in indices:
- self.schedule(index)
+ print "will sch[",i,"]",node
+ break
+ else:
+ i = -1
+ if i != -1:
+ self.schedule(i)
def schedule(self, index):
node = self.schedulable_nodes[index]
@@ -494,7 +503,7 @@
for dep in adj_list:
self.graph.remove_depencency(dep, node)
#
- for dep in self.graph.provideso(node):
+ for dep in self.graph.provides(node):
candidate = dep.idx_to
if self.is_schedulable(dep.idx_to):
self.schedulable_nodes.append(dep.idx_to)
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
@@ -65,6 +65,29 @@
assert sorted([l.idx_from for l in la]) == \
sorted([l.idx_from for l in lb])
+ def assert_dependencies(self, ops, memref=False, full_check=True):
+ graph = self.build_dependency(ops, memref)
+ import re
+ deps = {}
+ for i,line in enumerate(ops.splitlines()):
+ dep_pattern = re.compile("#\s*(\d+):")
+ dep_match = dep_pattern.search(line)
+ if dep_match:
+ label = int(dep_match.group(1))
+ deps_list = [int(d) for d in line[dep_match.end():].split(',') if len(d) > 0]
+ deps[label] = deps_list
+
+ if full_check:
+ edges = [ None ] * len(deps)
+ for k,l in deps.items():
+ edges[k] = l
+ for k,l in deps.items():
+ for rk in l:
+ if rk > k:
+ edges[rk].append(k)
+ self.assert_edges(graph, edges)
+ return graph
+
def assert_independent(self, a, b):
assert self.last_graph.independent(a,b), "{a} and {b} are dependent!".format(a=a,b=b)
@@ -82,208 +105,155 @@
class BaseTestDependencyGraph(DepTestHelper):
def test_dependency_empty(self):
ops = """
- []
- jump()
+ [] # 0: 1
+ jump() # 1:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph, [ [], [], ])
+ self.assert_dependencies(ops, full_check=True)
def test_dependency_of_constant_not_used(self):
ops = """
- []
- i1 = int_add(1,1)
- jump()
+ [] # 0: 2
+ i1 = int_add(1,1) # 1: 2
+ jump() # 2:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph, [ [], [], [] ])
+ self.assert_dependencies(ops, full_check=True)
def test_dependency_simple(self):
ops = """
- []
- i1 = int_add(1,1)
- i2 = int_add(i1,1)
- guard_value(i2,3) []
- jump()
+ [] # 0: 4
+ i1 = int_add(1,1) # 1: 2
+ i2 = int_add(i1,1) # 2: 3
+ guard_value(i2,3) [] # 3: 4
+ jump() # 4:
"""
- graph = self.build_dependency(ops)
- self.assert_edges(graph,
- [ [], [2], [1,3], [2], [], ])
- for i in range(0,5):
- self.assert_independent(0,i)
+ graph = self.assert_dependencies(ops, full_check=True)
+ self.assert_independent(0,1)
+ self.assert_independent(0,2)
+ self.assert_independent(0,3)
self.assert_dependent(1,2)
self.assert_dependent(2,3)
self.assert_dependent(1,3)
- self.assert_independent(2,4)
- self.assert_independent(3,4)
+ self.assert_dependent(2,4)
+ self.assert_dependent(3,4)
def test_def_use_jump_use_def(self):
ops = """
- [i3]
- i1 = int_add(i3,1)
- guard_value(i1,0) []
- jump(i1)
+ [i3] # 0: 1
+ i1 = int_add(i3,1) # 1: 2, 3
+ guard_value(i1,0) [] # 2: 3
+ jump(i1) # 3:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph,
- [ [1], [0,2,3], [1], [1] ])
+ self.assert_dependencies(ops, full_check=True)
def test_dependency_guard(self):
ops = """
- [i3]
- i1 = int_add(1,1)
- guard_value(i1,0) [i3]
- jump(i3)
+ [i3] # 0: 2,3
+ i1 = int_add(1,1) # 1: 2
+ guard_value(i1,0) [i3] # 2: 3
+ jump(i3) # 3:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph,
- [ [2,3], [2], [1,0], [0] ])
+ self.assert_dependencies(ops, full_check=True)
- #def test_dependency_guard_2(self):
- # ops = """
- # [i1]
- # i2 = int_le(i1, 10)
- # guard_true(i2) [i1]
- # i3 = int_add(i1,1)
- # jump(i3)
- # """
- # dep_graph = self.build_dependency(ops)
- # self.assert_edges(dep_graph,
- # [ [1], [0,2], [1], [2,4], [3] ])
+ def test_dependency_guard_2(self):
+ ops = """
+ [i1] # 0: 1,2,3
+ i2 = int_le(i1, 10) # 1: 2
+ guard_true(i2) [i1] # 2: 3
+ i3 = int_add(i1,1) # 3: 4
+ jump(i3) # 4:
+ """
+ self.assert_dependencies(ops, full_check=True)
def test_no_edge_duplication(self):
ops = """
- [i1]
- i2 = int_lt(i1,10)
- guard_false(i2) [i1]
- i3 = int_add(i1,i1)
- jump(i3)
+ [i1] # 0: 1,2,3
+ i2 = int_lt(i1,10) # 1: 2
+ guard_false(i2) [i1] # 2: 3
+ i3 = int_add(i1,i1) # 3: 4
+ jump(i3) # 4:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph,
- [ [1,2,3], [0,2], [1,0], [0,4], [3] ])
+ self.assert_dependencies(ops, full_check=True)
def test_no_edge_duplication_in_guard_failargs(self):
ops = """
- [i1]
- i2 = int_lt(i1,10)
- guard_false(i2) [i1,i1,i2,i1,i2,i1]
- jump(i1)
+ [i1] # 0: 1,2,3
+ i2 = int_lt(i1,10) # 1: 2
+ guard_false(i2) [i1,i1,i2,i1,i2,i1] # 2: 3
+ jump(i1) # 3:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph,
- [ [1,2,3], [0,2], [1,0], [0] ])
+ self.assert_dependencies(ops, full_check=True)
self.assert_dependent(0,1)
self.assert_dependent(0,2)
self.assert_dependent(0,3)
- def test_swap_dependencies(self):
- ops = """
- [i1,i4] # 0
- i2 = int_lt(i1,0) # 1
- i3 = int_lt(i4,0) # 2
- guard_value(i2,0) [] # 3
- jump(i1,i3) # 4
- """
- dep_graph = self.build_dependency(ops)
- dep_graph.swap_instructions(1,2)
- self.assert_edges(dep_graph,
- [ [1,2,4], [4,0], [3,0], [2], [0,1] ])
- dep_graph.swap_instructions(1,2)
- self.assert_graph_equal(dep_graph, self.build_dependency(ops))
-
- dep_graph.swap_instructions(2,3)
- ops2 = """
- [i1,i4] # 0
- i2 = int_lt(i1,0) # 1
- guard_value(i2,0) [] # 2
- i3 = int_lt(i4,0) # 3
- jump(i1,i3) # 4
- """
- dep_graph_final = self.build_dependency(ops2)
- self.assert_graph_equal(dep_graph, dep_graph_final)
-
def test_dependencies_1(self):
ops="""
- [i0, i1, i2] # 0
- i4 = int_gt(i1, 0) # 1
- guard_true(i4) [] # 2
- i6 = int_sub(i1, 1) # 3
- i8 = int_gt(i6, 0) # 4
- guard_false(i8) [] # 5
- i10 = int_add(i2, 1) # 6
- i12 = int_sub(i0, 1) # 7
- i14 = int_add(i10, 1) # 8
- i16 = int_gt(i12, 0) # 9
- guard_true(i16) [] # 10
- jump(i12, i1, i14) # 11
+ [i0, i1, i2] # 0: 1,3,6,7,11
+ i4 = int_gt(i1, 0) # 1: 2
+ guard_true(i4) [] # 2: 3, 11
+ i6 = int_sub(i1, 1) # 3: 4
+ i8 = int_gt(i6, 0) # 4: 5
+ guard_false(i8) [] # 5: 11
+ i10 = int_add(i2, 1) # 6: 8
+ i12 = int_sub(i0, 1) # 7: 9, 11
+ i14 = int_add(i10, 1) # 8: 11
+ i16 = int_gt(i12, 0) # 9: 10
+ guard_true(i16) [] # 10: 11
+ jump(i12, i1, i14) # 11:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph,
- [ [1,3,6,7,11], [0,2], [1], [0,4], [3,5], [4],
- # next entry is instr 6
- [0,8], [0,9,11], [6,11], [7,10], [9], [7,0,8] ])
+ self.assert_dependencies(ops, full_check=True)
self.assert_independent(6, 2)
self.assert_independent(6, 1)
self.assert_dependent(6, 0)
def test_prevent_double_arg(self):
ops="""
- [i0, i1, i2]
- i4 = int_gt(i1, i0)
- guard_true(i4) []
- jump(i0, i1, i2)
+ [i0, i1, i2] # 0: 1,3
+ i4 = int_gt(i1, i0) # 1: 2
+ guard_true(i4) [] # 2: 3
+ jump(i0, i1, i2) # 3:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph,
- [ [1,3], [0,2], [1], [0] ])
+ self.assert_dependencies(ops, full_check=True)
def test_ovf_dep(self):
ops="""
- [i0, i1, i2]
- i4 = int_sub_ovf(1, 0)
- guard_overflow() [i2]
- jump(i0, i1, i2)
+ [i0, i1, i2] # 0: 2,3
+ i4 = int_sub_ovf(1, 0) # 1: 2
+ guard_overflow() [i2] # 2: 3
+ jump(i0, i1, i2) # 3:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph,
- [ [1,2,3], [0,2], [0,1], [0] ])
+ self.assert_dependencies(ops, full_check=True)
def test_exception_dep(self):
ops="""
- [p0, i1, i2]
- i4 = call(p0, 1, descr=nonwritedescr)
- guard_no_exception() []
- jump(p0, i1, i2)
+ [p0, i1, i2] # 0: 1,3
+ i4 = call(p0, 1, descr=nonwritedescr) # 1: 2,3
+ guard_no_exception() [] # 2: 3
+ jump(p0, i1, i2) # 3:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph,
- [ [1,3], [0,2], [1], [0] ])
+ self.assert_dependencies(ops, full_check=True)
def test_call_dependency_on_ptr_but_not_index_value(self):
ops="""
- [p0, p1, i2]
- i3 = int_add(i2,1)
- i4 = call(p0, i3, descr=nonwritedescr)
- guard_no_exception() [i2]
- p2 = getarrayitem_gc(p1,i3)
- jump(p2, p1, i3)
+ [p0, p1, i2] # 0: 1,2,3,4,5
+ i3 = int_add(i2,1) # 1: 2
+ i4 = call(p0, i3, descr=nonwritedescr) # 2: 3,4,5
+ guard_no_exception() [i2] # 3: 4,5
+ p2 = getarrayitem_gc(p1,i3) # 4: 5
+ jump(p2, p1, i3) # 5:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph,
- [ [1,2,3,4,5], [0,2,4,5], [0,1,3], [0,2], [0,1,5], [4,0,1] ])
+ self.assert_dependencies(ops, full_check=True)
def test_call_dependency(self):
ops="""
- [p0, p1, i2, i5]
- i3 = int_add(i2,1)
- i4 = call(i5, i3, descr=nonwritedescr)
- guard_no_exception() [i2]
- p2 = getarrayitem_gc(p1,i3)
- jump(p2, p1, i3)
+ [p0, p1, i2, i5] # 0: 1,2,3,4,5
+ i3 = int_add(i2,1) # 1: 2
+ i4 = call(i5, i3, descr=nonwritedescr) # 2: 3,4,5
+ guard_no_exception() [i2] # 3: 4,5
+ p2 = getarrayitem_gc(p1,i3) # 4: 5
+ jump(p2, p1, i3) # 5:
"""
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph,
- [ [1,2,3,4,5], [0,2,4,5], [0,1,3], [0,2], [0,1,5], [4,0,1] ])
+ self.assert_dependencies(ops, full_check=True)
def test_setarrayitem_dependency(self):
ops="""
@@ -312,25 +282,29 @@
self.assert_dependent(1,2)
self.assert_dependent(0,3)
- def test_setarrayitem_same_modified_var_not_aliased(self):
- # #1 does NOT depend on #2, i1 and i2 are not aliased
+ def test_setarrayitem_depend_with_no_memref_info(self):
ops="""
- [p0, i1]
- setarrayitem_raw(p0, i1, 1, descr=floatarraydescr) #1
- i2 = int_add(i1,1)
- setarrayitem_raw(p0, i2, 2, descr=floatarraydescr) #2
- jump(p0, i1)
+ [p0, i1] # 0: 1,2,4
+ setarrayitem_raw(p0, i1, 1, descr=floatarraydescr) # 1: 3
+ i2 = int_add(i1,1) # 2: 3
+ setarrayitem_raw(p0, i2, 2, descr=floatarraydescr) # 3: 4
+ jump(p0, i1) # 4:
"""
- dep_graph = self.build_dependency(ops, True)
- self.assert_edges(dep_graph,
- [ [1,2,3,4], [0], [0,3], [0,2,4], [0,3] ])
- self.assert_independent(1,2)
- self.assert_independent(1,3)
- dep_graph = self.build_dependency(ops)
- self.assert_edges(dep_graph,
- [ [1,2,4], [0,3], [0,3], [1,2,4], [0,3] ])
+ self.assert_dependencies(ops, full_check=True)
self.assert_independent(1,2)
self.assert_dependent(1,3)
+ def test_setarrayitem_dont_depend_with_memref_info(self):
+ ops="""
+ [p0, i1] # 0: 1,2,3,4
+ setarrayitem_raw(p0, i1, 1, descr=floatarraydescr) # 1: 4
+ i2 = int_add(i1,1) # 2: 3
+ setarrayitem_raw(p0, i2, 2, descr=floatarraydescr) # 3: 4
+ jump(p0, i1) # 4:
+ """
+ self.assert_dependencies(ops, memref=True, full_check=True)
+ self.assert_independent(1,2)
+ self.assert_independent(1,3) # they modify 2 different cells
+
class TestLLtype(BaseTestDependencyGraph, LLtypeMixin):
pass
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
@@ -340,7 +340,7 @@
vopt = self.vec_optimizer_unrolled(self.parse_loop(ops),1)
vopt.build_dependency_graph()
self.assert_edges(vopt.dependency_graph,
- [ [1,2,3,5], [0], [0,3,4], [0,2], [2,5], [0,4] ])
+ [ [1,2,3,5], [0,5], [0,3,4], [0,2,5], [2,5], [0,4,1,3] ])
vopt.find_adjacent_memory_refs()
assert 1 in vopt.vec_info.memory_refs
@@ -498,9 +498,9 @@
vopt.build_dependency_graph()
self.assert_edges(vopt.dependency_graph,
[ [1,2,3,4,5,7,9],
- [0], [0,5,6], [0], [0,7,8],
- [0,2], [2,9], [0,4], [4,9],
- [0,6,8],
+ [0,9], [0,5,6], [0,9], [0,7,8],
+ [0,2,9], [2,9], [0,4,9], [4,9],
+ [0,6,8,1,3,5,7],
])
vopt.find_adjacent_memory_refs()
@@ -862,22 +862,24 @@
""".format(op=op)
vops = """
[p0,p1,p2,i0]
- i10 = int_le(i1, 128)
- guard_true(i10) []
+ i10 = int_le(i0, 128)
+ guard_true(i10) [p0,p1,p2,i0]
i1 = int_add(i0, 1)
- i12 = int_le(i11, 128)
- guard_true(i12) []
- i11 = int_add(i1, 1)
- i2 = vec_raw_load(p0, i0, 4, descr=floatarraydescr)
- i3 = vec_raw_load(p1, i0, 4, descr=floatarraydescr)
- i4 = {op}(i2,i3,4,descr=floatarraydescr)
- vec_raw_store(p2, i0, i4, 4, descr=floatarraydescr)
+ i11 = int_le(i1, 128)
+ guard_true(i11) [p0,p1,p2,i0]
+ i2 = vec_raw_load(p0, i0, 2, descr=floatarraydescr)
+ i3 = vec_raw_load(p1, i0, 2, descr=floatarraydescr)
+ i12 = int_add(i1, 1)
+ i4 = {op}(i2,i3,2)
+ vec_raw_store(p2, i0, i4, 2, descr=floatarraydescr)
jump(p0,p1,p2,i12)
""".format(op=vop)
loop = self.parse_loop(ops)
vopt = self.schedule(loop,1)
+ oo = self.vec_optimizer_unrolled(self.parse_loop(ops), 1)
+ self._write_dot_and_convert_to_svg(vopt.dependency_graph, oo.loop.operations, 'test_2')
self.debug_print_operations(vopt.loop)
- #self.assert_equal(loop, self.parse_loop(vops))
+ self.assert_equal(loop, self.parse_loop(vops))
class TestLLtype(BaseTestVectorize, 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
@@ -290,7 +290,6 @@
def schedule(self):
self.clear_newoperations()
scheduler = Scheduler(self.dependency_graph)
- i = 0
while scheduler.has_more_to_schedule():
candidate_index = scheduler.next_schedule_index()
candidate = self.loop.operations[candidate_index]
@@ -300,10 +299,6 @@
else:
self.emit_operation(candidate)
scheduler.schedule(0)
- i+=1
- if i > 20:
- print self.dependency_graph
- break
self.loop.operations = self._newoperations[:]
More information about the pypy-commit
mailing list