[pypy-svn] r68748 - in pypy/trunk/pypy/translator/backendopt: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Mon Oct 26 11:55:12 CET 2009


Author: cfbolz
Date: Mon Oct 26 11:55:12 2009
New Revision: 68748

Modified:
   pypy/trunk/pypy/translator/backendopt/mallocprediction.py
   pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py
Log:
Improve malloc prediction to also consider malloc-like calls to be mallocs,
works rather well, but not quite well enough.
 - 


Modified: pypy/trunk/pypy/translator/backendopt/mallocprediction.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/mallocprediction.py	(original)
+++ pypy/trunk/pypy/translator/backendopt/mallocprediction.py	Mon Oct 26 11:55:12 2009
@@ -1,15 +1,16 @@
 from pypy.translator.backendopt.escape import AbstractDataFlowInterpreter
+from pypy.translator.backendopt.escape import malloc_like_graphs
 from pypy.translator.backendopt.all import remove_mallocs
 from pypy.translator.backendopt import inline
 from pypy.rpython.lltypesystem import lltype
-from pypy.translator import simplify
+from pypy.translator.simplify import get_graph
 from pypy.translator.backendopt import removenoops
 from pypy.translator.backendopt.support import log
 
 SMALL_THRESHOLD = 15
 BIG_THRESHOLD = 50
 
-def find_malloc_creps(graph, adi, translator):
+def find_malloc_creps(graph, adi, translator, malloc_graphs):
     # mapping from malloc creation point to graphs that it flows into
     malloc_creps = {}
     # find all mallocs that don't escape
@@ -29,8 +30,17 @@
                 pass
             varstate = adi.getstate(op.result)
             assert len(varstate.creation_points) == 1
-            crep = varstate.creation_points.keys()[0]
-            if not crep.escapes:
+            crep, = varstate.creation_points
+            if not crep.escapes and not crep.returns:
+                malloc_creps[crep] = {}
+        if op.opname == 'direct_call':
+            called_graph = get_graph(op.args[0], translator)
+            if called_graph not in malloc_graphs:
+                continue
+            varstate = adi.getstate(op.result)
+            assert len(varstate.creation_points) == 1
+            crep, = varstate.creation_points
+            if not crep.escapes and not crep.returns:
                 malloc_creps[crep] = {}
     return malloc_creps
 
@@ -64,16 +74,19 @@
                         del interesting_creps[crep]
         elif op.opname == "direct_call":
             #print op, interesting_creps
-            called_graph = simplify.get_graph(op.args[0], translator)
+            called_graph = get_graph(op.args[0], translator)
             interesting = {}
-            for i, var in enumerate(op.args[1:]):
-                #print i, var,
+            if called_graph is None:
+                graphvars = [None] * len(op.args)
+            else:
+                graphvars = called_graph.getargs() + [called_graph.getreturnvar()]
+            for var, graphvar in zip(op.args[1:] + [op.result], graphvars):
                 varstate = adi.getstate(var)
                 if varstate is None:
                     #print "no varstate"
                     continue
                 if len(varstate.creation_points) == 1:
-                    crep = varstate.creation_points.keys()[0]
+                    crep, = varstate.creation_points
                     if crep not in interesting_creps:
                         #print "not interesting"
                         continue
@@ -81,16 +94,14 @@
                         del interesting_creps[crep]
                         #print "graph not found"
                         continue
-                    if (called_graph, i) in seen:
-                        seen[(called_graph, i)][graph] = True
+                    if called_graph in seen:
+                        seen[called_graph][graph] = True
                         #print "seen already"
                     else:
                         #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]
+                        seen[called_graph] = {graph: True}
+                        argstate = adi.getstate(graphvar)
+                        argcrep, = argstate.creation_points
                         interesting[argcrep] = True
             #print interesting
             if interesting:
@@ -104,21 +115,21 @@
         if graph.startblock not in adi.flown_blocks:
             adi.schedule_function(graph)
             adi.complete()
+    malloc_graphs = malloc_like_graphs(adi)
     targetset = dict.fromkeys(graphs)
     caller_candidates = {}
     seen = {}
     for graph in adi.seen_graphs():
-        creps = find_malloc_creps(graph, adi, t)
-        #print "malloc creps", creps
+        creps = find_malloc_creps(graph, adi, t, malloc_graphs)
         if creps:
             find_calls_where_creps_go(creps, graph, adi, t, seen)
             if creps:
                 if graph in targetset:
                     caller_candidates[graph] = True
     callgraph = []
-    for (called_graph, i), callers in seen.iteritems():
+    for called_graph, callers in seen.iteritems():
         for caller in callers:
-            if caller in targetset:
+            if caller in targetset and called_graph in targetset:
                 callgraph.append((caller, called_graph))
             else:
                 log.inlineandremove.WARNING("would like to inline into"

Modified: pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py	(original)
+++ pypy/trunk/pypy/translator/backendopt/test/test_mallocprediction.py	Mon Oct 26 11:55:12 2009
@@ -54,7 +54,7 @@
     assert caller_candidates == {graph: True}
     assert len(callgraph) == 1
     ggraph = graphof(t, g)
-    assert callgraph[graph] == {ggraph: True}
+    assert callgraph == {graph: {ggraph: True}}
 
 def test_multiple_calls():
     class A:
@@ -81,9 +81,48 @@
     assert len(callgraph) == 1
     g1graph = graphof(t, g1)
     g2graph = graphof(t, g2)
-    assert callgraph[graph] == {g1graph: True}
+    assert callgraph == {graph: {g1graph: True}}
     callgraph, caller_candidates = check_inlining(t, graph, [0], 3 * 42)
-    assert callgraph[graph] == {g2graph: True}
+    assert callgraph == {graph: {g2graph: True}}
+
+def test_malloc_returns():
+    class A:
+        pass
+    def g(a):
+        return a.x
+    def h(x):
+        return x + 42
+    def make_a(x):
+        a = A()
+        a.x = x
+        return a
+    def fn(i):
+        a = make_a(h(i))
+        return g(a)
+    t, graph = rtype(fn, [int])
+    callgraph, caller_candidates = check_inlining(t, graph, [0], 42)
+    assert caller_candidates == {graph: True}
+    assert len(callgraph) == 1
+    ggraph = graphof(t, g)
+    makegraph = graphof(t, make_a)
+    assert callgraph == {graph: {ggraph: True, makegraph: True}}
+
+def test_tuple():
+    def f(x, y):
+        return h(x + 1, x * y)
+    def h(x, y):
+        return x, y
+
+    def g(x):
+        a, b = f(x, x*5)
+        return a + b
+    t, graph = rtype(g, [int])
+    callgraph, caller_candidates = check_inlining(t, graph, [2], 23)
+    assert caller_candidates == {graph: True}
+    assert len(callgraph) == 2
+    fgraph = graphof(t, f)
+    hgraph = graphof(t, h)
+    assert callgraph == {graph: {fgraph: True}, fgraph: {hgraph:  True}}
     
 def test_indirect_call():
     class A(object):
@@ -133,9 +172,21 @@
     assert total0 + total == 10
 
 def test_richards():
-    py.test.skip("Unsure if this makes any sense any more")
     from pypy.translator.goal.richards import entry_point
     t, graph = rtype(entry_point, [int])
     total0 = preparation(t, t.graphs)
     total = clever_inlining_and_malloc_removal(t)
     assert total0 + total == 9
+
+def test_loop():
+    l = [10, 12, 15, 1]
+    def f(x):
+        res = 0
+        for i in range(x):
+            res += i
+        for i in l:
+            res += i
+        return res
+    t, graph = rtype(f, [int])
+    total = clever_inlining_and_malloc_removal(t)
+    assert total == 3 # range, two iterators



More information about the Pypy-commit mailing list