[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