1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
import py
from rpython.translator.translator import TranslationContext
from rpython.translator.backendopt import inline
from rpython.translator.backendopt.all import backend_optimizations
from rpython.translator.translator import TranslationContext, graphof
from rpython.rtyper.llinterp import LLInterpreter
from rpython.flowspace.model import checkgraph, Block
from rpython.conftest import option
import sys
from rpython.translator.backendopt.mallocprediction import *
def rtype(fn, signature):
t = TranslationContext()
t.buildannotator().build_types(fn, signature)
t.buildrtyper().specialize()
graph = graphof(t, fn)
if option.view:
t.view()
return t, graph
def check_inlining(t, graph, args, result):
callgraph, caller_candidates = find_malloc_removal_candidates(t, t.graphs)
nice_callgraph = {}
for caller, callee in callgraph:
nice_callgraph.setdefault(caller, {})[callee] = True
inline_and_remove(t, t.graphs)
if option.view:
t.view()
interp = LLInterpreter(t.rtyper)
res = interp.eval_graph(graph, args)
assert res == result
return nice_callgraph, caller_candidates
def test_fn():
class A:
pass
class B(A):
pass
def g(a, b, i):
a.b = b
b.i = i
return a.b.i
def h(x):
return x + 42
def fn(i):
a = A()
b = B()
x = h(i)
return g(a, b, x)
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)
assert callgraph == {graph: {ggraph: True}}
def test_multiple_calls():
class A:
pass
class B(A):
pass
def g2(b, i):
b.i = h(i)
def g1(a, b, i):
a.b = b
g2(b, h(i))
return a.b.i
def h(x):
return x + 42
def fn(i):
a = A()
b = B()
x = h(i)
return g1(a, b, x)
t, graph = rtype(fn, [int])
callgraph, caller_candidates = check_inlining(t, graph, [0], 3 * 42)
print callgraph
assert caller_candidates == {graph: True}
assert len(callgraph) == 1
g1graph = graphof(t, g1)
g2graph = graphof(t, g2)
assert callgraph == {graph: {g1graph: True}}
callgraph, caller_candidates = check_inlining(t, graph, [0], 3 * 42)
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):
pass
def f1(a, i):
return a.x
def f2(a, i):
return a.x + 1
def g1(a, i):
return a
def g2(a, i):
return None
def f(i):
a1 = A()
a2 = A()
a1.x = 1
a2.x = 2
if i:
f = f1
g = g1
else:
f = f2
g = g2
x = f(a1, 0)
a0 = g(a2, 1)
if a0 is not None:
return 43
else:
return 42
t, graph = rtype(f, [int])
callgraph, caller_candidate = check_inlining(t, graph, [0], 42)
assert caller_candidate == {}
def test_pystone():
from rpython.translator.goal.targetrpystonex import make_target_definition
entrypoint, _, _ = make_target_definition(10)
def heuristic(graph):
for block in graph.iterblocks():
for op in block.operations:
if op.opname in ('malloc',):
return inline.inlining_heuristic(graph)
return sys.maxint, False
# does not crash
t, graph = rtype(entrypoint, [int])
total0 = preparation(t, t.graphs, heuristic=heuristic)
total = clever_inlining_and_malloc_removal(t)
assert total in (6, 7) # XXX total0 appears to vary
# we get 6 before fbace1f687b0, but 7 afterwards on some
# platforms, probably because rtime.clock() now contains
# a fall-back path
def test_richards():
from rpython.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
|