[pypy-svn] r25786 - in pypy/dist/pypy/translator: . backendopt test
cfbolz at codespeak.net
cfbolz at codespeak.net
Thu Apr 13 14:53:25 CEST 2006
Author: cfbolz
Date: Thu Apr 13 14:53:24 2006
New Revision: 25786
Modified:
pypy/dist/pypy/translator/backendopt/removenoops.py
pypy/dist/pypy/translator/simplify.py
pypy/dist/pypy/translator/test/test_simplify.py
Log:
fix a rarely occuring bug in join_blocks: if the exitswitch of the second block
was a constant in eh link coming from the first block, the exits of the second
block would not be properly pruned. Also remove some op.cleanup leftovers as
well as some visit usages in removenoops.
Modified: pypy/dist/pypy/translator/backendopt/removenoops.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/removenoops.py (original)
+++ pypy/dist/pypy/translator/backendopt/removenoops.py Thu Apr 13 14:53:24 2006
@@ -9,12 +9,10 @@
"""Removes unary low-level ops with a name appearing in the opnames list.
"""
positions = []
- def visit(node):
- if isinstance(node, Block):
- for i, op in enumerate(node.operations):
- if op.opname in opnames:
- positions.append((node, i))
- traverse(visit, graph)
+ for block in graph.iterblocks():
+ for i, op in enumerate(block.operations):
+ if op.opname in opnames:
+ positions.append((block, i))
while positions:
block, index = positions.pop()
op_result = block.operations[index].result
@@ -34,22 +32,13 @@
if isinstance(op_arg, Variable):
block.exitswitch = op_arg
else:
- assert isinstance(op_arg, Constant)
- newexits = [link for link in block.exits
- if link.exitcase == op_arg.value]
- assert len(newexits) == 1
- newexits[0].exitcase = None
- if hasattr(newexits[0], 'llexitcase'):
- newexits[0].llexitcase = None
- block.exitswitch = None
- block.recloseblock(*newexits)
+ simplify.replace_exitswitch_by_constant(block, op_arg)
block.operations[index] = None
# remove all operations
- def visit(node):
- if isinstance(node, Block) and node.operations:
- node.operations[:] = filter(None, node.operations)
- traverse(visit, graph)
+ for block in graph.iterblocks():
+ if block.operations:
+ block.operations[:] = filter(None, block.operations)
def remove_same_as(graph):
remove_unaryops(graph, ["same_as"])
Modified: pypy/dist/pypy/translator/simplify.py
==============================================================================
--- pypy/dist/pypy/translator/simplify.py (original)
+++ pypy/dist/pypy/translator/simplify.py Thu Apr 13 14:53:24 2006
@@ -37,6 +37,18 @@
return None
+def replace_exitswitch_by_constant(block, const):
+ assert isinstance(const, Constant)
+ assert const != c_last_exception
+ newexits = [link for link in block.exits
+ if link.exitcase == const.value]
+ assert len(newexits) == 1
+ newexits[0].exitcase = None
+ if hasattr(newexits[0], 'llexitcase'):
+ newexits[0].llexitcase = None
+ block.exitswitch = None
+ block.recloseblock(*newexits)
+
# ____________________________________________________________
def eliminate_empty_blocks(graph):
@@ -303,26 +315,13 @@
len(entrymap[link.target]) == 1 and
link.target.exits): # stop at the returnblock
renaming = {}
- cache_cleanups = {}
for vprev, vtarg in zip(link.args, link.target.inputargs):
renaming[vtarg] = vprev
def rename(v):
return renaming.get(v, v)
def rename_op(op):
args = [rename(a) for a in op.args]
- if hasattr(op, "cleanup"):
- if op.cleanup is None:
- cleanup = None
- elif op.cleanup not in cache_cleanups:
- finallyops, exceptops = op.cleanup
- cleanup = (tuple([rename_op(fo) for fo in finallyops]),
- tuple([rename_op(eo) for eo in exceptops]))
- cache_cleanups[op.cleanup] = cleanup
- else:
- cleanup = cache_cleanups[op.cleanup]
- op = SpaceOperation(op.opname, args, rename(op.result), cleanup=cleanup)
- else:
- op = SpaceOperation(op.opname, args, rename(op.result))
+ op = SpaceOperation(op.opname, args, rename(op.result))
return op
for op in link.target.operations:
link.prevblock.operations.append(rename_op(op))
@@ -330,8 +329,11 @@
for exit in link.target.exits:
newexit = exit.copy(rename)
exits.append(newexit)
- link.prevblock.exitswitch = rename(link.target.exitswitch)
+ newexitswitch = rename(link.target.exitswitch)
+ link.prevblock.exitswitch = newexitswitch
link.prevblock.recloseblock(*exits)
+ if isinstance(newexitswitch, Constant) and newexitswitch != c_last_exception:
+ replace_exitswitch_by_constant(link.prevblock, newexitswitch)
stack.extend(exits)
else:
if link.target not in seen:
Modified: pypy/dist/pypy/translator/test/test_simplify.py
==============================================================================
--- pypy/dist/pypy/translator/test/test_simplify.py (original)
+++ pypy/dist/pypy/translator/test/test_simplify.py Thu Apr 13 14:53:24 2006
@@ -154,3 +154,21 @@
assert g(1) == 1001
# does not crash: previously join_blocks would barf on this
graph, t = translate(g, [int])
+
+def test_join_blocks_cleans_links():
+ from pypy.rpython.lltypesystem import lltype
+ from pypy.objspace.flow.model import Constant
+ from pypy.translator.backendopt.removenoops import remove_same_as
+ def f(x):
+ return bool(x + 2)
+ def g(x):
+ if f(x):
+ return 1
+ else:
+ return 2
+ graph, t = translate(g, [int], backend_optimize=False)
+ fgraph = graphof(t, f)
+ fgraph.startblock.exits[0].args = [Constant(True, lltype.Bool)]
+ # does not crash: previously join_blocks would barf on this
+ remove_same_as(graph)
+ backend_optimizations(t)
More information about the Pypy-commit
mailing list