File: test_removenoops.py

package info (click to toggle)
pypy 7.0.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 107,216 kB
  • sloc: python: 1,201,787; ansic: 62,419; asm: 5,169; cpp: 3,017; sh: 2,534; makefile: 545; xml: 243; lisp: 45; awk: 4
file content (153 lines) | stat: -rw-r--r-- 5,134 bytes parent folder | download | duplicates (8)
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
from rpython.translator.backendopt.removenoops import remove_same_as, \
        remove_unaryops, remove_duplicate_casts
from rpython.translator.backendopt.inline import simple_inline_function
from rpython.translator.translator import TranslationContext, graphof
from rpython.memory.gctransform.test.test_transform import getops
from rpython.translator.test.snippet import simple_method
from rpython.translator.backendopt.all import backend_optimizations
from rpython.translator.backendopt.all import INLINE_THRESHOLD_FOR_TEST
from rpython.flowspace.model import checkgraph, Block
from rpython.rtyper.lltypesystem import lltype
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rtyper.llinterp import LLInterpreter
from rpython.conftest import option


def get_graph(fn, signature, all_opts=True):
    t = TranslationContext()
    t.buildannotator().build_types(fn, signature)
    t.buildrtyper().specialize()
    if all_opts:
        backend_optimizations(t, inline_threshold=INLINE_THRESHOLD_FOR_TEST,
                              constfold=False)
    graph = graphof(t, fn)
    if option.view:
        t.view()
    return graph, t

def check_graph(graph, args, expected_result, t):
    interp = LLInterpreter(t.rtyper)
    res = interp.eval_graph(graph, args)
    assert res == expected_result

def check_get_graph(fn, signature, args, expected_result):
    graph, t = get_graph(fn, signature)
    check_graph(graph, args, expected_result, t)
    return graph


def test_remove_same_as():
    def nothing(x):
        return x
    def f():
        nothing(False)
        if nothing(True):
            return 42
        else:
            return 666
    t = TranslationContext()
    t.buildannotator().build_types(f, [])
    t.buildrtyper().specialize()
    # now we make the 'if True' appear
    f_graph = graphof(t, f)
    simple_inline_function(t, nothing, f_graph)
    # here, the graph looks like  v21=same_as(True);  exitswitch: v21
    remove_same_as(f_graph)
    t.checkgraphs()
    # only one path should be left
    for block in f_graph.iterblocks():
        assert len(block.exits) <= 1

    interp = LLInterpreter(t.rtyper)
    result = interp.eval_graph(f_graph, [])
    assert result == 42


def test_remove_same_as_nonconst():
    from rpython.rlib.nonconst import NonConstant
    from rpython.rtyper.lltypesystem.lloperation import llop
    from rpython.rtyper.lltypesystem import lltype

    def f():
        if NonConstant(False):
            x = llop.same_as(lltype.Signed, 666)
        return 42

    t = TranslationContext()
    t.buildannotator().build_types(f, [])
    t.buildrtyper().specialize()
    f_graph = graphof(t, f)
    #simple_inline_function(t, nothing, f_graph)
    # here, the graph looks like  v21=same_as(True);  exitswitch: v21
    remove_same_as(f_graph)
    t.checkgraphs()
    # only one path should be left
    for block in f_graph.iterblocks():
        assert len(block.exits) <= 1

    for block in t.annotator.annotated:
        assert None not in block.operations

    interp = LLInterpreter(t.rtyper)
    result = interp.eval_graph(f_graph, [])
    assert result == 42


def test_remove_unaryops():
    # We really want to use remove_unaryops for more complex operations, but
    # it's easier to test it with operations on ints here.
    def f(x):
        i = llop.int_invert(lltype.Signed, x)
        i = llop.int_add(lltype.Signed, x, 1)
        return llop.int_neg(lltype.Signed, i)
    t = TranslationContext()
    t.buildannotator().build_types(f, [int])
    t.buildrtyper().specialize()
    f_graph = graphof(t, f)
    remove_unaryops(f_graph, ["int_neg", "int_invert"])
    t.checkgraphs()

    interp = LLInterpreter(t.rtyper)
    result = interp.eval_graph(f_graph, [-2])
    assert result == -1

def test_remove_duplicate_casts():
    class A(object):
        def __init__(self, x, y):
            self.x = x
            self.y = y
        def getsum(self):
            return self.x + self.y
    class B(A):
        def __init__(self, x, y, z):
            A.__init__(self, x, y)
            self.z = z
        def getsum(self):
            return self.x + self.y + self.z
    def f(x, switch):
        a = A(x, x + 1)
        b = B(x, x + 1, x + 2)
        if switch:
            c = A(x, x + 1)
        else:
            c = B(x, x + 1, x + 2)
        return a.x + a.y + b.x + b.y + b.z + c.getsum()
    assert f(10, True) == 75
    graph, t = get_graph(f, [int, bool], all_opts=False)
    num_cast_pointer = len(getops(graph)['cast_pointer'])
    changed = remove_duplicate_casts(graph, t)
    assert changed
    ops = getops(graph)
    assert len(ops['cast_pointer']) < num_cast_pointer
    print len(ops['cast_pointer']), num_cast_pointer
    graph_getsum = graphof(t, B.getsum.im_func)
    num_cast_pointer = len(getops(graph_getsum)['cast_pointer'])
    changed = remove_duplicate_casts(graph_getsum, t)
    assert changed
    if option.view:
        t.view()
    check_graph(graph, [10, True], 75, t)
    ops = getops(graph_getsum)
    assert len(ops['cast_pointer']) < num_cast_pointer
    print len(ops['cast_pointer']), num_cast_pointer