[pypy-svn] r49888 - in pypy/dist/pypy/translator/backendopt: . test
arigo at codespeak.net
arigo at codespeak.net
Tue Dec 18 15:21:14 CET 2007
Author: arigo
Date: Tue Dec 18 15:21:14 2007
New Revision: 49888
Modified:
pypy/dist/pypy/translator/backendopt/constfold.py
pypy/dist/pypy/translator/backendopt/test/test_constfold.py
Log:
In constfold: For the case where link1.target contains only a switch,
rewire link1 to go directly to the correct exit based on a constant
switch value. This is a situation that occurs typically after inlining.
Modified: pypy/dist/pypy/translator/backendopt/constfold.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/constfold.py (original)
+++ pypy/dist/pypy/translator/backendopt/constfold.py Tue Dec 18 15:21:14 2007
@@ -130,8 +130,44 @@
else:
constants[v2] = v1
+def rewire_link_for_known_exitswitch(link1, llexitvalue):
+ # For the case where link1.target contains only a switch, rewire link1
+ # to go directly to the correct exit based on a constant switch value.
+ # This is a situation that occurs typically after inlining; see
+ # test_fold_exitswitch_along_one_path.
+ block = link1.target
+ if block.exits[-1].exitcase == "default":
+ defaultexit = block.exits[-1]
+ nondefaultexits = block.exits[:-1]
+ else:
+ defaultexit = None
+ nondefaultexits = block.exits
+ for nextlink in nondefaultexits:
+ if nextlink.llexitcase == llexitvalue:
+ break # found -- the result is in 'nextlink'
+ else:
+ if defaultexit is None:
+ return # exit case not found! just ignore the problem here
+ nextlink = defaultexit
+ blockmapping = dict(zip(block.inputargs, link1.args))
+ newargs = []
+ for v in nextlink.args:
+ if isinstance(v, Variable):
+ v = blockmapping[v]
+ newargs.append(v)
+ link1.target = nextlink.target
+ link1.args = newargs
+
def prepare_constant_fold_link(link, constants, splitblocks):
block = link.target
+ if not block.operations:
+ # when the target block has no operation, there is nothing we can do
+ # except trying to fold an exitswitch
+ if block.exitswitch is not None and block.exitswitch in constants:
+ llexitvalue = constants[block.exitswitch].value
+ rewire_link_for_known_exitswitch(link, llexitvalue)
+ return
+
folded_count = fold_op_list(block.operations, constants, exit_early=True)
n = len(block.operations)
Modified: pypy/dist/pypy/translator/backendopt/test/test_constfold.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_constfold.py (original)
+++ pypy/dist/pypy/translator/backendopt/test/test_constfold.py Tue Dec 18 15:21:14 2007
@@ -245,3 +245,31 @@
assert summary(graph) == {'debug_print': 1}
constant_fold_graph(graph)
assert summary(graph) == {'debug_print': 1}
+
+
+def test_fold_exitswitch_along_one_path():
+ def g(n):
+ if n == 42:
+ return 5
+ else:
+ return n+1
+ def fn(n):
+ if g(n) == 5:
+ return 100
+ else:
+ return 0
+
+ graph, t = get_graph(fn, [int])
+ from pypy.translator.backendopt import removenoops, inline
+ inline.auto_inline_graphs(t, [graph], threshold=999)
+ constant_fold_graph(graph)
+ removenoops.remove_same_as(graph)
+ if conftest.option.view:
+ t.view()
+ # check that the graph starts with a condition (which should be 'n==42')
+ # and that if this condition is true, it goes directly to 'return 100'.
+ assert len(graph.startblock.exits) == 2
+ assert graph.startblock.exits[1].exitcase == True
+ assert graph.startblock.exits[1].target is graph.returnblock
+ check_graph(graph, [10], 0, t)
+ check_graph(graph, [42], 100, t)
More information about the Pypy-commit
mailing list