1
from pypy.translator.backendopt.removenoops import remove_same_as, \
2
remove_unaryops, remove_duplicate_casts, remove_superfluous_keep_alive
3
from pypy.translator.backendopt.inline import simple_inline_function
4
from pypy.translator.translator import TranslationContext, graphof
5
from pypy.rpython.memory.gctransform.test.test_transform import getops
6
from pypy.translator.test.snippet import simple_method
7
from pypy.translator.backendopt.all import backend_optimizations
8
from pypy.translator.backendopt.all import INLINE_THRESHOLD_FOR_TEST
9
from pypy.objspace.flow.model import checkgraph, flatten, Block
10
from pypy.rpython.lltypesystem import lltype
11
from pypy.rpython.lltypesystem.lloperation import llop
12
from pypy.rpython.llinterp import LLInterpreter
13
from pypy import conftest
16
log = py.log.Producer('test_backendoptimization')
18
def get_graph(fn, signature, all_opts=True):
19
t = TranslationContext()
20
t.buildannotator().build_types(fn, signature)
21
t.buildrtyper().specialize()
23
backend_optimizations(t, inline_threshold=INLINE_THRESHOLD_FOR_TEST,
25
raisingop2direct_call=False)
26
graph = graphof(t, fn)
27
if conftest.option.view:
31
def check_graph(graph, args, expected_result, t):
32
interp = LLInterpreter(t.rtyper)
33
res = interp.eval_graph(graph, args)
34
assert res == expected_result
36
def check_get_graph(fn, signature, args, expected_result):
37
graph, t = get_graph(fn, signature)
38
check_graph(graph, args, expected_result, t)
42
def test_remove_same_as():
51
t = TranslationContext()
52
t.buildannotator().build_types(f, [])
53
t.buildrtyper().specialize()
54
# now we make the 'if True' appear
55
f_graph = graphof(t, f)
56
simple_inline_function(t, nothing, f_graph)
57
# here, the graph looks like v21=same_as(True); exitswitch: v21
58
remove_same_as(f_graph)
60
# only one path should be left
61
for block in f_graph.iterblocks():
62
assert len(block.exits) <= 1
64
interp = LLInterpreter(t.rtyper)
65
result = interp.eval_graph(f_graph, [])
68
def test_remove_unaryops():
69
# We really want to use remove_unaryops for things like ooupcast and
70
# oodowncast in dynamically typed languages, but it's easier to test
71
# it with operations on ints here.
73
i = llop.int_invert(lltype.Signed, x)
74
i = llop.int_add(lltype.Signed, x, 1)
75
return llop.int_neg(lltype.Signed, i)
76
t = TranslationContext()
77
t.buildannotator().build_types(f, [int])
78
t.buildrtyper().specialize()
79
f_graph = graphof(t, f)
80
remove_unaryops(f_graph, ["int_neg", "int_invert"])
83
interp = LLInterpreter(t.rtyper)
84
result = interp.eval_graph(f_graph, [-2])
87
def test_remove_keepalive():
88
S = lltype.GcStruct("s", ("f", lltype.Signed))
91
llop.keepalive(lltype.Void, s1)
93
llop.keepalive(lltype.Void, s1)
94
llop.keepalive(lltype.Void, s2)
95
return id(s1) + id(s2)
96
graph, t = get_graph(f, [])
97
remove_superfluous_keep_alive(graph)
99
assert len(ops['keepalive']) == 2
101
def test_remove_duplicate_casts():
103
def __init__(self, x, y):
107
return self.x + self.y
109
def __init__(self, x, y, z):
110
A.__init__(self, x, y)
113
return self.x + self.y + self.z
116
b = B(x, x + 1, x + 2)
120
c = B(x, x + 1, x + 2)
121
return a.x + a.y + b.x + b.y + b.z + c.getsum()
122
assert f(10, True) == 75
123
graph, t = get_graph(f, [int, bool], all_opts=False)
124
num_cast_pointer = len(getops(graph)['cast_pointer'])
125
changed = remove_duplicate_casts(graph, t)
128
assert len(ops['cast_pointer']) < num_cast_pointer
129
print len(ops['cast_pointer']), num_cast_pointer
130
graph_getsum = graphof(t, B.getsum.im_func)
131
num_cast_pointer = len(getops(graph_getsum)['cast_pointer'])
132
changed = remove_duplicate_casts(graph_getsum, t)
134
if conftest.option.view:
136
check_graph(graph, [10, True], 75, t)
137
ops = getops(graph_getsum)
138
assert len(ops['cast_pointer']) < num_cast_pointer
139
print len(ops['cast_pointer']), num_cast_pointer