[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