[pypy-svn] r25676 - in pypy/dist/pypy/translator: . backendopt backendopt/test

cfbolz at codespeak.net cfbolz at codespeak.net
Mon Apr 10 20:46:57 CEST 2006


Author: cfbolz
Date: Mon Apr 10 20:46:55 2006
New Revision: 25676

Modified:
   pypy/dist/pypy/translator/backendopt/propagate.py
   pypy/dist/pypy/translator/backendopt/test/test_propagate.py
   pypy/dist/pypy/translator/simplify.py
Log:
fix constant folding of calls


Modified: pypy/dist/pypy/translator/backendopt/propagate.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/propagate.py	(original)
+++ pypy/dist/pypy/translator/backendopt/propagate.py	Mon Apr 10 20:46:55 2006
@@ -133,6 +133,9 @@
             raise TooManyOperations
         return super(CountingLLFrame, self).eval_operation(operation)
 
+def op_can_be_folded(op):
+    return not lloperation.LL_OPERATIONS[op.opname].canfold
+
 def constant_folding(graph, translator):
     """do constant folding if the arguments of an operations are constants"""
     lli = LLInterpreter(translator.rtyper)
@@ -158,23 +161,24 @@
                     block.operations[i].opname = "same_as"
                     block.operations[i].args = [res]
                     changed = True
-            # disabling the code for now, since it is not correct
-            elif 0: #op.opname == "direct_call":
+            elif op.opname == "direct_call":
                 called_graph = get_graph(op.args[0], translator)
                 if (called_graph is not None and
-                    simplify.has_no_side_effects(translator, called_graph) and
+                    simplify.has_no_side_effects(
+                        translator, called_graph,
+                        is_operation_false=op_can_be_folded) and
                     (block.exitswitch != c_last_exception or 
                      i != len(block.operations) - 1)):
                     args = [arg.value for arg in op.args[1:]]
                     countingframe = CountingLLFrame(called_graph, args, lli)
-                    print "folding call", op, "in graph", graph.name
+                    #print "folding call", op, "in graph", graph.name
                     try:
                         res = countingframe.eval()
                     except:
-                        print "did not work"
+                        #print "did not work"
                         pass
                     else:
-                        print "result", res
+                        #print "result", res
                         res = Constant(res)
                         res.concretetype = op.result.concretetype
                         block.operations[i].opname = "same_as"
@@ -341,16 +345,19 @@
         log.removegetfield("removed %s getfields in %s" % (count, graph.name))
     return count
 
+def propagate_all_per_graph(graph, translator):
+    def prop():
+        changed = False
+        changed = rewire_links(graph) or changed
+        changed = propagate_consts(graph) or changed
+        changed = coalesce_links(graph) or changed
+        changed = do_atmost(100, constant_folding, graph,
+                                       translator) or changed
+        changed = partial_folding(graph, translator) or changed
+        changed = remove_all_getfields(graph, translator) or changed
+        return changed
+    do_atmost(10, prop)    
+
 def propagate_all(translator):
     for graph in translator.graphs:
-        def prop():
-            changed = False
-            changed = rewire_links(graph) or changed
-            changed = propagate_consts(graph) or changed
-            changed = coalesce_links(graph) or changed
-            changed = do_atmost(100, constant_folding, graph,
-                                           translator) or changed
-            changed = partial_folding(graph, translator) or changed
-            changed = remove_all_getfields(graph, translator) or changed
-            return changed
-        do_atmost(10, prop)
+        propagate_all_per_graph(graph, translator)

Modified: pypy/dist/pypy/translator/backendopt/test/test_propagate.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_propagate.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_propagate.py	Mon Apr 10 20:46:55 2006
@@ -82,22 +82,33 @@
     check_graph(graph, [1], None, t)
 
 def test_propagate_despite_vars():
-    py.test.skip("immediate test")
     patterns = [1, 1, 2, 3, 5, 7, 12]
     class A(object): pass
-    a = A()
-    a.x = 10
-    a.y = 20
-    def f(x):
+    global_a = A()
+    global_a.x = 10
+    global_a.y = 20
+    def f(x):
+        a = A()
+        a.x = 10
+        a.y = 20
         result = 0
+        i = 0
         for i in range(a.x):
-            for j in range(a.y):
+            j = 0
+            for i in range(global_a.y):
                 result += i * j
+                j += 1
         return result
     graph, t = get_graph(f, [int])
-    propagate_consts(graph)
     if conftest.option.view:
         t.view()
+    while propagate_consts(graph):
+        pass
+    assert len(graph.startblock.exits[0].args) == 2
+    innerloopblock = graph.startblock.exits[0].target.exits[0].target.exits[0].target
+    assert len(innerloopblock.inputargs) == 4
+    assert len(innerloopblock.exits[0].args) == 4
+    check_graph(graph, [0], f(0), t)
 
 def test_constant_fold():
     def f(x):
@@ -112,8 +123,6 @@
     check_graph(graph, [1], g(1), t)
 
 def test_constant_fold_call():
-    # fix the logic and try again :-)
-    py.test.skip("constant folding calls is disabled, for sanity reasons")
     def s(x):
         res = 0
         i = 1
@@ -131,6 +140,21 @@
     assert len(graph.startblock.operations) == 1
     check_graph(graph, [10], g(10), t)
 
+def test_dont_constant_fold_call():
+    class A(object):
+        pass
+    global_a = A()
+    global_a.x = 1
+    def g():
+        return global_a.x
+    def f(x):
+        global_a.x = x
+        return g()
+    graph, t = get_graph(f, [int], inline_threshold=0)
+    while constant_folding(graph, t):
+        pass
+    check_graph(graph, [10], 10, t)
+
 def test_dont_fold_getfield():
     # must not constant fold this, because the container might be collected
     string = "blablabla"

Modified: pypy/dist/pypy/translator/simplify.py
==============================================================================
--- pypy/dist/pypy/translator/simplify.py	(original)
+++ pypy/dist/pypy/translator/simplify.py	Mon Apr 10 20:46:55 2006
@@ -9,6 +9,7 @@
 from pypy.objspace.flow.model import Variable, Constant, Block, Link
 from pypy.objspace.flow.model import c_last_exception
 from pypy.objspace.flow.model import checkgraph, traverse, mkentrymap
+from pypy.rpython.lltypesystem import lloperation
 
 def get_graph(arg, translator):
     from pypy.translator.translator import graphof
@@ -373,8 +374,11 @@
 class HasSideEffects(Exception):
     pass
 
-def has_no_side_effects(translator, graph, seen=None):
-    from pypy.rpython.lltypesystem import lloperation
+def op_has_side_effects(op):
+    return lloperation.LL_OPERATIONS[op.opname].sideeffects
+
+def has_no_side_effects(translator, graph, seen=None,
+                        is_operation_false=op_has_side_effects):
     #is the graph specialized? if no we can't say anything
     #don't cache the result though
     if translator.rtyper is None:
@@ -406,7 +410,7 @@
                     for g in graphs:
                         if not has_no_side_effects(translator, g, newseen):
                             raise HasSideEffects
-                elif lloperation.LL_OPERATIONS[op.opname].sideeffects:
+                elif is_operation_false(op):
                     raise HasSideEffects
         traverse(visit, graph)
     except HasSideEffects:



More information about the Pypy-commit mailing list