PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/translator/backendopt/test/test_mallocprediction.py

https://bitbucket.org/pypy/pypy/
Python | 192 lines | 178 code | 13 blank | 1 comment | 12 complexity | da8fb0e57de60dbef851b996f735a0bb MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py
  2. from rpython.translator.translator import TranslationContext
  3. from rpython.translator.backendopt import inline
  4. from rpython.translator.backendopt.all import backend_optimizations
  5. from rpython.translator.translator import TranslationContext, graphof
  6. from rpython.rtyper.llinterp import LLInterpreter
  7. from rpython.flowspace.model import checkgraph, Block
  8. from rpython.conftest import option
  9. import sys
  10. from rpython.translator.backendopt.mallocprediction import *
  11. def rtype(fn, signature):
  12. t = TranslationContext()
  13. t.buildannotator().build_types(fn, signature)
  14. t.buildrtyper().specialize()
  15. graph = graphof(t, fn)
  16. if option.view:
  17. t.view()
  18. return t, graph
  19. def check_inlining(t, graph, args, result):
  20. callgraph, caller_candidates = find_malloc_removal_candidates(t, t.graphs)
  21. nice_callgraph = {}
  22. for caller, callee in callgraph:
  23. nice_callgraph.setdefault(caller, {})[callee] = True
  24. inline_and_remove(t, t.graphs)
  25. if option.view:
  26. t.view()
  27. interp = LLInterpreter(t.rtyper)
  28. res = interp.eval_graph(graph, args)
  29. assert res == result
  30. return nice_callgraph, caller_candidates
  31. def test_fn():
  32. class A:
  33. pass
  34. class B(A):
  35. pass
  36. def g(a, b, i):
  37. a.b = b
  38. b.i = i
  39. return a.b.i
  40. def h(x):
  41. return x + 42
  42. def fn(i):
  43. a = A()
  44. b = B()
  45. x = h(i)
  46. return g(a, b, x)
  47. t, graph = rtype(fn, [int])
  48. callgraph, caller_candidates = check_inlining(t, graph, [0], 42)
  49. assert caller_candidates == {graph: True}
  50. assert len(callgraph) == 1
  51. ggraph = graphof(t, g)
  52. assert callgraph == {graph: {ggraph: True}}
  53. def test_multiple_calls():
  54. class A:
  55. pass
  56. class B(A):
  57. pass
  58. def g2(b, i):
  59. b.i = h(i)
  60. def g1(a, b, i):
  61. a.b = b
  62. g2(b, h(i))
  63. return a.b.i
  64. def h(x):
  65. return x + 42
  66. def fn(i):
  67. a = A()
  68. b = B()
  69. x = h(i)
  70. return g1(a, b, x)
  71. t, graph = rtype(fn, [int])
  72. callgraph, caller_candidates = check_inlining(t, graph, [0], 3 * 42)
  73. print callgraph
  74. assert caller_candidates == {graph: True}
  75. assert len(callgraph) == 1
  76. g1graph = graphof(t, g1)
  77. g2graph = graphof(t, g2)
  78. assert callgraph == {graph: {g1graph: True}}
  79. callgraph, caller_candidates = check_inlining(t, graph, [0], 3 * 42)
  80. assert callgraph == {graph: {g2graph: True}}
  81. def test_malloc_returns():
  82. class A:
  83. pass
  84. def g(a):
  85. return a.x
  86. def h(x):
  87. return x + 42
  88. def make_a(x):
  89. a = A()
  90. a.x = x
  91. return a
  92. def fn(i):
  93. a = make_a(h(i))
  94. return g(a)
  95. t, graph = rtype(fn, [int])
  96. callgraph, caller_candidates = check_inlining(t, graph, [0], 42)
  97. assert caller_candidates == {graph: True}
  98. assert len(callgraph) == 1
  99. ggraph = graphof(t, g)
  100. makegraph = graphof(t, make_a)
  101. assert callgraph == {graph: {ggraph: True, makegraph: True}}
  102. def test_tuple():
  103. def f(x, y):
  104. return h(x + 1, x * y)
  105. def h(x, y):
  106. return x, y
  107. def g(x):
  108. a, b = f(x, x*5)
  109. return a + b
  110. t, graph = rtype(g, [int])
  111. callgraph, caller_candidates = check_inlining(t, graph, [2], 23)
  112. assert caller_candidates == {graph: True}
  113. assert len(callgraph) == 2
  114. fgraph = graphof(t, f)
  115. hgraph = graphof(t, h)
  116. assert callgraph == {graph: {fgraph: True}, fgraph: {hgraph: True}}
  117. def test_indirect_call():
  118. class A(object):
  119. pass
  120. def f1(a, i):
  121. return a.x
  122. def f2(a, i):
  123. return a.x + 1
  124. def g1(a, i):
  125. return a
  126. def g2(a, i):
  127. return None
  128. def f(i):
  129. a1 = A()
  130. a2 = A()
  131. a1.x = 1
  132. a2.x = 2
  133. if i:
  134. f = f1
  135. g = g1
  136. else:
  137. f = f2
  138. g = g2
  139. x = f(a1, 0)
  140. a0 = g(a2, 1)
  141. if a0 is not None:
  142. return 43
  143. else:
  144. return 42
  145. t, graph = rtype(f, [int])
  146. callgraph, caller_candidate = check_inlining(t, graph, [0], 42)
  147. assert caller_candidate == {}
  148. def test_pystone():
  149. from rpython.translator.goal.targetrpystonex import make_target_definition
  150. entrypoint, _, _ = make_target_definition(10)
  151. def heuristic(graph):
  152. for block in graph.iterblocks():
  153. for op in block.operations:
  154. if op.opname in ('malloc',):
  155. return inline.inlining_heuristic(graph)
  156. return sys.maxint, False
  157. # does not crash
  158. t, graph = rtype(entrypoint, [int])
  159. total0 = preparation(t, t.graphs, heuristic=heuristic)
  160. total = clever_inlining_and_malloc_removal(t)
  161. assert total == 6 # XXX total0 appears to vary
  162. def test_richards():
  163. from rpython.translator.goal.richards import entry_point
  164. t, graph = rtype(entry_point, [int])
  165. total0 = preparation(t, t.graphs)
  166. total = clever_inlining_and_malloc_removal(t)
  167. assert total0 + total == 10
  168. def test_loop():
  169. l = [10, 12, 15, 1]
  170. def f(x):
  171. res = 0
  172. for i in range(x):
  173. res += i
  174. for i in l:
  175. res += i
  176. return res
  177. t, graph = rtype(f, [int])
  178. total = clever_inlining_and_malloc_removal(t)
  179. assert total == 3 # range, two iterators