[pypy-svn] r26907 - pypy/dist/pypy/translator/backendopt

cfbolz at codespeak.net cfbolz at codespeak.net
Sat May 6 23:18:49 CEST 2006


Author: cfbolz
Date: Sat May  6 23:18:48 2006
New Revision: 26907

Modified:
   pypy/dist/pypy/translator/backendopt/propagate.py
Log:
remove the terrible abuse of has_no_side_effects


Modified: pypy/dist/pypy/translator/backendopt/propagate.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/propagate.py	(original)
+++ pypy/dist/pypy/translator/backendopt/propagate.py	Sat May  6 23:18:48 2006
@@ -9,6 +9,7 @@
 from pypy.translator.backendopt.inline import OP_WEIGHTS
 from pypy.translator.backendopt.ssa import DataFlowFamilyBuilder
 from pypy.translator.backendopt.support import log, var_needsgc
+from pypy.translator.backendopt.graphanalyze import GraphAnalyzer
 
 def do_atmost(n, f, *args):
     i = 0
@@ -133,24 +134,29 @@
             raise TooManyOperations
         return super(CountingLLFrame, self).eval_operation(operation)
 
-def op_dont_fold(op):
-    if op.opname in ('getfield', 'getarrayitem'):
-        CONTAINER = op.args[0].concretetype.TO
-        if CONTAINER._hints.get('immutable'):
-            return False
-    if op.opname in ("getsubstruct", "getarraysubstruct"):
-        # this is needed so that the parent of the result (op.args[0])
-        # does not go away after the op is folded. see test_dont_fold_getsubstruct
-        if not var_needsgc(op.result):
+class CanfoldAnalyzer(GraphAnalyzer):
+    def operation_is_true(self, op):
+        if op.opname in ('getfield', 'getarrayitem'):
+            CONTAINER = op.args[0].concretetype.TO
+            if CONTAINER._hints.get('immutable'):
+                return False
+        if op.opname in ("getsubstruct", "getarraysubstruct"):
+            # this is needed so that the parent of the result (op.args[0])
+            # does not go away after the op is folded. see test_dont_fold_getsubstruct
+            if not var_needsgc(op.result):
+                # if the containing object is immortal, one can still fold:
+                if isinstance(op.args[0], Constant) and op.args[0].value._solid:
+                    return False
+                return True
+        try:
+            return not lloperation.LL_OPERATIONS[op.opname].canfold
+        except KeyError:
             return True
-        # XXX if the result is immortal, one could still fold...
-    try:
-        return not lloperation.LL_OPERATIONS[op.opname].canfold
-    except KeyError:
-        return True
 
-def constant_folding(graph, translator):
+def constant_folding(graph, translator, analyzer=None):
     """do constant folding if the arguments of an operations are constants"""
+    if analyzer is None:
+        analyzer = CanfoldAnalyzer(translator)
     lli = LLInterpreter(translator.rtyper)
     llframe = LLFrame(graph, None, lli)
     changed = False
@@ -158,42 +164,31 @@
         for i, op in enumerate(block.operations):
             if sum([isinstance(arg, Variable) for arg in op.args]):
                 continue
-            if not op_dont_fold(op):
-                try:
-                    llframe.eval_operation(op)
-                except:
-                    pass
-                else:
-                    res = Constant(llframe.getval(op.result))
-                    log.constantfolding("in graph %s, %s = %s" %
-                                        (graph.name, op, res))
-                    res.concretetype = op.result.concretetype
-                    block.operations[i].opname = "same_as"
-                    block.operations[i].args = [res]
-                    changed = True
-            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,
-                        is_operation_false=op_dont_fold) and
-                    (block.exitswitch != c_last_exception or 
-                     i != len(block.operations) - 1)):
+            # don't fold stuff with exception handling
+            if (block.exitswitch == c_last_exception and
+                i == len(block.operation) - 1):
+                continue
+            if analyzer.analyze(op):
+                continue
+            try:
+                if op.opname == "direct_call":
+                    called_graph = get_graph(op.args[0], translator)
                     args = [arg.value for arg in op.args[1:]]
                     countingframe = CountingLLFrame(called_graph, args, lli)
-                    #print "folding call", op, "in graph", graph.name
-                    try:
-                        res = countingframe.eval()
-                    except:
-                        #print "did not work"
-                        pass
-                    else:
-                        #print "result", res
-                        res = Constant(res)
-                        res.concretetype = op.result.concretetype
-                        block.operations[i].opname = "same_as"
-                        block.operations[i].args = [res]
-                        changed = True
+                    res = Constant(countingframe.eval())
+                else:
+                    llframe.eval_operation(op)
+                    res = Constant(llframe.getval(op.result))
+            except (SystemExit, KeyboardInterrupt):
+                raise
+            except:
+                continue
+            log.constantfolding("in graph %s, %s = %s" %
+                                (graph.name, op, res))
+            res.concretetype = op.result.concretetype
+            block.operations[i].opname = "same_as"
+            block.operations[i].args = [res]
+            changed = True
         block.operations = [op for op in block.operations if op is not None]
     if changed:
         remove_same_as(graph)
@@ -202,7 +197,9 @@
         return True
     return False
 
-def partial_folding_once(graph, translator):
+def partial_folding_once(graph, translator, analyzer=None):
+    if analyzer is None:
+        analyzer = CanfoldAnalyzer(translator)
     lli = LLInterpreter(translator.rtyper)
     entrymap = mkentrymap(graph)
     def visit(block):
@@ -211,7 +208,7 @@
             return
         usedvars = {}
         for op in block.operations:
-            if op_dont_fold(op):
+            if analyzer.analyze(op):
                 return
             for arg in op.args:
                 if (isinstance(arg, Variable) and arg in block.inputargs):
@@ -249,8 +246,6 @@
             else:
                 assert 0, "this should not occur"
             unchanged = link.target == nextblock and link.args == newargs
-#            if not unchanged:
-#                print "doing partial folding in graph", graph.name
             link.target = nextblock
             link.args = newargs
             checkgraph(graph)
@@ -365,13 +360,14 @@
 
 def propagate_all_per_graph(graph, translator):
     def prop():
+        analyzer = CanfoldAnalyzer(translator)
         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
+#                                       translator, analyzer) or changed
+#        changed = partial_folding(graph, translator, analyzer) or changed
         changed = remove_all_getfields(graph, translator) or changed
         checkgraph(graph)
         return changed



More information about the Pypy-commit mailing list