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

cfbolz at codespeak.net cfbolz at codespeak.net
Sun Apr 9 13:03:10 CEST 2006


Author: cfbolz
Date: Sun Apr  9 13:03:08 2006
New Revision: 25614

Modified:
   pypy/dist/pypy/translator/backendopt/all.py
   pypy/dist/pypy/translator/backendopt/escape.py
   pypy/dist/pypy/translator/backendopt/inline.py
   pypy/dist/pypy/translator/backendopt/mallocprediction.py
   pypy/dist/pypy/translator/backendopt/test/test_inline.py
   pypy/dist/pypy/translator/backendopt/test/test_mallocprediction.py
Log:
(pedronis, cfbolz):

a clever inliner that tries to inline stuff more if it might lead to the
removal of mallocs


Modified: pypy/dist/pypy/translator/backendopt/all.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/all.py	(original)
+++ pypy/dist/pypy/translator/backendopt/all.py	Sun Apr  9 13:03:08 2006
@@ -8,6 +8,7 @@
 from pypy.translator.backendopt.merge_if_blocks import merge_if_blocks
 from pypy.translator import simplify
 from pypy.translator.backendopt.escape import malloc_to_stack
+from pypy.translator.backendopt.mallocprediction import clever_inlining_and_malloc_removal
 from pypy.translator.backendopt.support import log
 
 PRINT_STATISTICS = False
@@ -18,7 +19,8 @@
                                       ssa_form=True,
                                       merge_if_blocks_to_switch=True,
                                       propagate=False,
-                                      heap2stack=False):
+                                      heap2stack=False,
+                                      clever_malloc_removal=False):
 
     if PRINT_STATISTICS:
         print "before optimizations:"
@@ -42,33 +44,40 @@
     if propagate:
         propagate_all(translator)
 
-    # inline functions in each other
-    if inline_threshold:
-        auto_inlining(translator, inline_threshold)
-        for graph in translator.graphs:
-            removenoops.remove_superfluous_keep_alive(graph)
-            removenoops.remove_duplicate_casts(graph, translator)
-
-    if PRINT_STATISTICS:
-        print "after inlining:"
-        print_statistics(translator.graphs[0], translator)
-
-    # vaporize mallocs
-    if mallocs:
-        tot = 0
-        for graph in translator.graphs:
-            count = remove_simple_mallocs(graph)
-            if count:
-                # remove typical leftovers from malloc removal
-                removenoops.remove_same_as(graph)
-                simplify.eliminate_empty_blocks(graph)
-                simplify.transform_dead_op_vars(graph, translator)
-                tot += count
-        log.malloc("removed %d simple mallocs in total" % tot)
-
-    if PRINT_STATISTICS:
-        print "after malloc removal:"
-        print_statistics(translator.graphs[0], translator)
+    if not clever_malloc_removal:
+        # inline functions in each other
+        if inline_threshold:
+            auto_inlining(translator, inline_threshold)
+            for graph in translator.graphs:
+                removenoops.remove_superfluous_keep_alive(graph)
+                removenoops.remove_duplicate_casts(graph, translator)
+
+        if PRINT_STATISTICS:
+            print "after inlining:"
+            print_statistics(translator.graphs[0], translator)
+
+        # vaporize mallocs
+        if mallocs:
+            tot = 0
+            for graph in translator.graphs:
+                count = remove_simple_mallocs(graph)
+                if count:
+                    # remove typical leftovers from malloc removal
+                    removenoops.remove_same_as(graph)
+                    simplify.eliminate_empty_blocks(graph)
+                    simplify.transform_dead_op_vars(graph, translator)
+                    tot += count
+            log.malloc("removed %d simple mallocs in total" % tot)
+
+        if PRINT_STATISTICS:
+            print "after malloc removal:"
+            print_statistics(translator.graphs[0], translator)
+    else:
+        clever_inlining_and_malloc_removal(translator)
+
+        if PRINT_STATISTICS:
+            print "after clever inlining and malloc removal"
+            print_statistics(translator.graphs[0], translator)
 
     if propagate:
         propagate_all(translator)

Modified: pypy/dist/pypy/translator/backendopt/escape.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/escape.py	(original)
+++ pypy/dist/pypy/translator/backendopt/escape.py	Sun Apr  9 13:03:08 2006
@@ -131,7 +131,7 @@
         return resultstate, args
 
     def flow_block(self, block, graph):
-        print "flowing in block %s of function %s" % (block, graph.name)
+        #print "flowing in block %s of function %s" % (block, graph.name)
         self.flown_blocks[block] = True
         if block is graph.returnblock:
             if isonheap(block.inputargs[0]):

Modified: pypy/dist/pypy/translator/backendopt/inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/inline.py	(original)
+++ pypy/dist/pypy/translator/backendopt/inline.py	Sun Apr  9 13:03:08 2006
@@ -494,7 +494,7 @@
 def inlining_heuristic(graph):
     # XXX ponderation factors?
     return (0.9999 * measure_median_execution_cost(graph) +
-            static_instruction_count(graph)) * factor
+            static_instruction_count(graph))
 
 
 def static_callers(translator, ignore_primitives=False):
@@ -516,9 +516,10 @@
     return result
 
 
-def auto_inlining(translator, threshold=1, callgraph=None):
+def auto_inlining(translator, multiplier=1, callgraph=None,
+                  threshold=BASE_INLINE_THRESHOLD):
     from heapq import heappush, heappop, heapreplace
-    threshold *= BASE_INLINE_THRESHOLD
+    threshold = threshold * multiplier
     callers = {}     # {graph: {graphs-that-call-it}}
     callees = {}     # {graph: {graphs-that-it-calls}}
     if callgraph is None:
@@ -530,6 +531,7 @@
     valid_weight = {}
     couldnt_inline = {}
     lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping()
+    count = 0
 
     while heap:
         weight, _, graph = heap[0]
@@ -557,6 +559,7 @@
                 couldnt_inline[graph] = True
                 res = CannotInline
             if res is True:
+                count += 1
                 # the parentgraph should now contain all calls that were
                 # done by 'graph'
                 for graph2 in callees.get(graph, {}):
@@ -569,3 +572,4 @@
                     del couldnt_inline[parentgraph]
                     heappush(heap, (0.0, -len(callers[parentgraph]), parentgraph))
                 valid_weight[parentgraph] = False
+    return count

Modified: pypy/dist/pypy/translator/backendopt/mallocprediction.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/mallocprediction.py	(original)
+++ pypy/dist/pypy/translator/backendopt/mallocprediction.py	Sun Apr  9 13:03:08 2006
@@ -1,8 +1,13 @@
 from pypy.translator.backendopt.escape import AbstractDataFlowInterpreter
 from pypy.translator.backendopt.malloc import remove_simple_mallocs
 from pypy.translator.backendopt.inline import auto_inlining
+from pypy.translator.backendopt import removenoops
 from pypy.rpython.lltypesystem import lltype
-from pypy.translator.simplify import get_graph
+from pypy.translator import simplify
+from pypy.translator.backendopt.support import log
+
+SMALL_THRESHOLD = 15
+BIG_THRESHOLD = 50
 
 def find_malloc_creps(graph, adi, translator):
     # mapping from malloc creation point to graphs that it flows into
@@ -28,8 +33,8 @@
 
 def find_calls_where_creps_go(interesting_creps, graph, adi,
                               translator, seen):
-    print "find_calls_where_creps_go", interesting_creps, graph.name
-    print seen
+    #print "find_calls_where_creps_go", interesting_creps, graph.name
+    #print seen
     # drop creps that are merged with another creation point
     for block in graph.iterblocks():
         for var in block.getvariables():
@@ -53,36 +58,36 @@
                     if crep in interesting_creps:
                         del interesting_creps[crep]
         elif op.opname == "direct_call":
-            print op, interesting_creps
-            called_graph = get_graph(op.args[0], translator)
-            if called_graph is None:
-                del interesting_creps[crep]
-                print "graph not found"
-                continue
+            #print op, interesting_creps
+            called_graph = simplify.get_graph(op.args[0], translator)
             interesting = {}
             for i, var in enumerate(op.args[1:]):
-                print i, var,
+                #print i, var,
                 varstate = adi.getstate(var)
                 if varstate is None:
-                    print "no varstate"
+                    #print "no varstate"
                     continue
                 if len(varstate.creation_points) == 1:
                     crep = varstate.creation_points.keys()[0]
                     if crep not in interesting_creps:
-                        print "not interesting"
+                        #print "not interesting"
+                        continue
+                    if called_graph is None:
+                        del interesting_creps[crep]
+                        #print "graph not found"
                         continue
                     if (called_graph, i) in seen:
                         seen[(called_graph, i)][graph] = True
-                        print "seen already"
+                        #print "seen already"
                     else:
-                        print "taking", crep
+                        #print "taking", crep
                         seen[(called_graph, i)] = {graph: True}
                         arg = called_graph.startblock.inputargs[i]
                         argstate = adi.getstate(arg)
                         argcrep = [c for c in argstate.creation_points
                                     if c.creation_method == "arg"][0]
                         interesting[argcrep] = True
-            print interesting
+            #print interesting
             if interesting:
                 find_calls_where_creps_go(interesting, called_graph,
                                           adi, translator, seen)
@@ -98,7 +103,7 @@
     seen = {}
     for graph in t.graphs:
         creps = find_malloc_creps(graph, adi, t)
-        print "malloc creps", creps
+        #print "malloc creps", creps
         if creps:
             find_calls_where_creps_go(creps, graph, adi, t, seen)
             if creps:
@@ -109,8 +114,46 @@
             callgraph.append((caller, called_graph))
     return callgraph, caller_candidates
 
-def inline_and_remove(t, threshold=1):
+def inline_and_remove(t, threshold=BIG_THRESHOLD):
     callgraph, caller_candidates = find_malloc_removal_candidates(t)
-    auto_inlining(t, threshold, callgraph)
-    for graph in caller_candidates:
-        remove_simple_mallocs(graph)
+    log.inlineandremove("found %s malloc removal candidates" %
+                        len(caller_candidates))
+    if callgraph:
+        count = auto_inlining(t, callgraph=callgraph, threshold=threshold)
+        if not count:
+            return False
+        count = remove_mallocs(t, caller_candidates.keys())
+        return count
+    else:
+        return False
+
+def remove_mallocs(translator, graphs=None):
+    tot = 0
+    if graphs is None:
+        graphs = translator.graphs
+    for graph in translator.graphs:
+        count = remove_simple_mallocs(graph)
+        if count:
+            # remove typical leftovers from malloc removal
+            removenoops.remove_same_as(graph)
+            simplify.eliminate_empty_blocks(graph)
+            simplify.transform_dead_op_vars(graph, translator)
+            tot += count
+    log.malloc("removed %d simple mallocs in total" % tot)
+    return tot
+
+def clever_inlining_and_malloc_removal(translator):
+    count = remove_mallocs(translator)
+    auto_inlining(translator, threshold=SMALL_THRESHOLD)
+    count += remove_mallocs(translator)
+    while 1:
+        newcount = inline_and_remove(translator)
+        if not newcount:
+            break
+        count += newcount
+    log.inlineandremove("removed %s mallocs in total" % count)
+    for graph in translator.graphs:
+        removenoops.remove_superfluous_keep_alive(graph)
+        removenoops.remove_duplicate_casts(graph, translator)
+    return count
+

Modified: pypy/dist/pypy/translator/backendopt/test/test_inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_inline.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_inline.py	Sun Apr  9 13:03:08 2006
@@ -69,16 +69,16 @@
         return interp.eval_graph(graphof(t, entry), args)
     return eval_func
 
-def check_auto_inlining(func, sig, threshold=None):
+def check_auto_inlining(func, sig, multiplier=None):
     t = translate(func, sig)
     if option.view:
         t.view()
     # inline!
     sanity_check(t)    # also check before inlining (so we don't blame it)
-    if threshold is None:
+    if multiplier is None:
         auto_inlining(t)
     else:
-        auto_inlining(t, threshold=threshold)
+        auto_inlining(t, multiplier=multiplier)
     sanity_check(t)
     if option.view:
         t.view()
@@ -229,7 +229,7 @@
             return 3
         return 1
 
-    eval_func, _ = check_auto_inlining(g, [int], threshold=10)
+    eval_func, _ = check_auto_inlining(g, [int], multiplier=10)
     result = eval_func([0])
     assert result == 2
     result = eval_func([1])
@@ -329,7 +329,7 @@
             return g(n)
         except OverflowError:
             return -1
-    eval_func, t = check_auto_inlining(f, [int], threshold=10)
+    eval_func, t = check_auto_inlining(f, [int], multiplier=10)
     f_graph = graphof(t, f)
     assert len(collect_called_graphs(f_graph, t)) == 0
 

Modified: pypy/dist/pypy/translator/backendopt/test/test_mallocprediction.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_mallocprediction.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_mallocprediction.py	Sun Apr  9 13:03:08 2006
@@ -9,7 +9,7 @@
 
 from pypy.translator.backendopt.mallocprediction import *
 
-def compile(fn, signature):
+def rtype(fn, signature):
     t = TranslationContext()
     t.buildannotator().build_types(fn, signature)
     t.buildrtyper().specialize()
@@ -48,7 +48,7 @@
         b = B()
         x = h(i)
         return g(a, b, x)
-    t, graph = compile(fn, [int])
+    t, graph = rtype(fn, [int])
     callgraph, caller_candidates = check_inlining(t, graph, [0], 42)
     assert caller_candidates == {graph: True}
     assert len(callgraph) == 1
@@ -73,7 +73,7 @@
         b = B()
         x = h(i)
         return g1(a, b, x)
-    t, graph = compile(fn, [int])
+    t, graph = rtype(fn, [int])
     callgraph, caller_candidates = check_inlining(t, graph, [0], 3 * 42)
     print callgraph
     assert caller_candidates == {graph: True}
@@ -83,4 +83,17 @@
     assert callgraph[graph] == {g1graph: True}
     callgraph, caller_candidates = check_inlining(t, graph, [0], 3 * 42)
     assert callgraph[graph] == {g2graph: True}
-
+    
+def test_pystone():
+    from pypy.translator.goal.targetrpystonex import make_target_definition
+    entrypoint, _, _ = make_target_definition(10)
+    # does not crash
+    t, graph = rtype(entrypoint, [int])
+    total = clever_inlining_and_malloc_removal(t)
+    assert total == 12
+
+def test_richards():
+    from pypy.translator.goal.richards import entry_point
+    t, graph = rtype(entry_point, [int])
+    total = clever_inlining_and_malloc_removal(t)
+    assert total == 11



More information about the Pypy-commit mailing list