[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