PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/jit/metainterp/optimizeopt/test/test_unroll.py

https://bitbucket.org/pypy/pypy/
Python | 300 lines | 282 code | 16 blank | 2 comment | 3 complexity | f31277ef49abec15d294e34f79406d17 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """ More direct tests for unrolling
  2. """
  3. import py
  4. from rpython.jit.metainterp.optimizeopt.test.test_util import BaseTest,\
  5. LLtypeMixin, FakeMetaInterpStaticData
  6. from rpython.jit.metainterp.optimizeopt.util import equaloplists
  7. from rpython.jit.metainterp.history import (TreeLoop, ConstInt,
  8. JitCellToken, TargetToken)
  9. from rpython.jit.metainterp.resoperation import rop, ResOperation,\
  10. InputArgRef, InputArgInt
  11. from rpython.jit.metainterp.optimizeopt.shortpreamble import \
  12. ShortPreambleBuilder, PreambleOp, ShortInputArg
  13. from rpython.jit.metainterp.compile import LoopCompileData
  14. from rpython.jit.metainterp.optimizeopt.virtualstate import \
  15. NotVirtualStateInfo, LEVEL_CONSTANT, LEVEL_UNKNOWN, LEVEL_KNOWNCLASS,\
  16. VirtualStateInfo
  17. from rpython.jit.metainterp.optimizeopt import info
  18. from rpython.jit.codewriter import heaptracker
  19. from rpython.jit.tool import oparser
  20. class FakeOptimizer(object):
  21. optearlyforce = None
  22. class cpu:
  23. remove_gctypeptr = True
  24. def getptrinfo(self, box):
  25. return box.get_forwarded()
  26. def setinfo_from_preamble(self, *args):
  27. pass
  28. def get_box_replacement(self, box):
  29. return box
  30. class BaseTestUnroll(BaseTest, LLtypeMixin):
  31. enable_opts = "intbounds:rewrite:virtualize:string:earlyforce:pure:heap:unroll"
  32. def optimize(self, ops):
  33. loop = self.parse(ops)
  34. self.add_guard_future_condition(loop)
  35. operations = loop.operations
  36. jumpop = operations[-1]
  37. assert jumpop.getopnum() == rop.JUMP
  38. inputargs = loop.inputargs
  39. jump_args = jumpop.getarglist()[:]
  40. operations = operations[:-1]
  41. preamble = TreeLoop('preamble')
  42. token = JitCellToken()
  43. trace = oparser.convert_loop_to_trace(loop, FakeMetaInterpStaticData(self.cpu))
  44. compile_data = LoopCompileData(trace, inputargs)
  45. start_state, newops = self._do_optimize_loop(compile_data)
  46. preamble.operations = newops
  47. preamble.inputargs = start_state.renamed_inputargs
  48. return start_state, loop, preamble
  49. def compare_short(self, short, expected_short):
  50. expected_short = self.parse(expected_short)
  51. remap = {}
  52. exp = ([ResOperation(rop.LABEL, expected_short.inputargs)] +
  53. expected_short.operations)
  54. for k, v in zip(short[0].getarglist(), expected_short.inputargs):
  55. remap[v] = k
  56. equaloplists(short, exp, remap=remap)
  57. def producable_short_boxes(l):
  58. return [x for x in l if not isinstance(x.short_op, ShortInputArg)]
  59. class TestUnroll(BaseTestUnroll):
  60. def test_simple(self):
  61. loop = """
  62. [i0]
  63. i1 = int_add(i0, 1)
  64. guard_value(i1, 1) []
  65. jump(i1)
  66. """
  67. es, loop, preamble = self.optimize(loop)
  68. vs = es.virtual_state
  69. assert isinstance(vs.state[0], NotVirtualStateInfo)
  70. # the virtual state is constant, so we don't need to have it in
  71. # inputargs
  72. assert vs.make_inputargs([1], FakeOptimizer()) == []
  73. assert vs.state[0].level == LEVEL_CONSTANT
  74. # we have exported values for i1, which happens to be an inputarg
  75. sb = ShortPreambleBuilder([], es.short_boxes, es.short_inputargs,
  76. es.exported_infos)
  77. sp = sb.build_short_preamble()
  78. exp = """
  79. []
  80. jump()
  81. """
  82. self.compare_short(sp, exp)
  83. # sb = ShortPreambleBuilder(es.short_boxes, es.short_inputargs,
  84. # es.exported_infos)
  85. # sb.use_box(es.short_boxes[0].short_op.res)
  86. # assert len(es.short_boxes) == 1
  87. # exp = """
  88. # [i0]
  89. # i1 = int_add(i0, 1)
  90. # guard_value(i1, 1) []
  91. # jump()
  92. # """
  93. # self.compare_short(sb.build_short_preamble(), exp)
  94. def test_not_constant(self):
  95. loop = """
  96. [i0]
  97. i1 = int_add(i0, 1)
  98. jump(i0)
  99. """
  100. es, loop, preamble = self.optimize(loop)
  101. vs = es.virtual_state
  102. assert isinstance(vs.state[0], NotVirtualStateInfo)
  103. assert vs.state[0].level == LEVEL_UNKNOWN
  104. op = preamble.operations[0]
  105. short_boxes = [box for box in es.short_boxes
  106. if not isinstance(box.short_op, ShortInputArg)]
  107. assert len(short_boxes) == 1
  108. assert short_boxes[0].short_op.res is op
  109. def test_guard_class(self):
  110. loop = """
  111. [p0]
  112. guard_class(p0, ConstClass(node_vtable)) []
  113. jump(p0)
  114. """
  115. es, loop, preamble = self.optimize(loop)
  116. p0 = preamble.inputargs[0]
  117. expected_class = heaptracker.adr2int(self.node_vtable_adr)
  118. assert expected_class == es.exported_infos[p0]._known_class.getint()
  119. vs = es.virtual_state
  120. assert vs.state[0].level == LEVEL_KNOWNCLASS
  121. assert vs.state[0].known_class.getint() == expected_class
  122. def test_virtual(self):
  123. loop = """
  124. [p1, p2, i3]
  125. p0 = new_with_vtable(descr=simpledescr)
  126. setfield_gc(p0, i3, descr=simplevalue)
  127. jump(p0, p0, i3)
  128. """
  129. es, loop, preamble = self.optimize(loop)
  130. vs = es.virtual_state
  131. assert vs.state[0] is vs.state[1]
  132. assert isinstance(vs.state[0], VirtualStateInfo)
  133. assert isinstance(vs.state[0].fieldstate[0], NotVirtualStateInfo)
  134. assert vs.state[0].fieldstate[0].level == LEVEL_UNKNOWN
  135. assert vs.numnotvirtuals == 1
  136. p = InputArgRef()
  137. i = InputArgInt()
  138. ptrinfo = info.StructPtrInfo(self.nodesize, is_virtual=True)
  139. ptrinfo._fields = [i]
  140. p.set_forwarded(ptrinfo)
  141. vs.make_inputargs([p, p, i], FakeOptimizer())
  142. def test_short_boxes_heapcache(self):
  143. loop = """
  144. [p0, i1]
  145. i0 = getfield_gc_i(p0, descr=valuedescr)
  146. jump(p0, i1)
  147. """
  148. es, loop, preamble = self.optimize(loop)
  149. op = preamble.operations[0]
  150. short_boxes = [box for box in es.short_boxes
  151. if not isinstance(box.short_op, ShortInputArg)]
  152. assert len(short_boxes) == 1
  153. assert short_boxes[0].short_op.res is op
  154. sb = ShortPreambleBuilder(loop.inputargs,
  155. es.short_boxes, es.short_inputargs,
  156. es.exported_infos, FakeOptimizer())
  157. op = preamble.operations[0]
  158. short_op = sb.use_box(op, short_boxes[0].preamble_op, FakeOptimizer())
  159. sb.add_preamble_op(PreambleOp(op, short_op, False))
  160. exp_short = """
  161. [p0, i1]
  162. guard_nonnull(p0) []
  163. guard_subclass(p0, ConstClass(node_vtable)) []
  164. i0 = getfield_gc_i(p0, descr=valuedescr)
  165. jump(i0)
  166. """
  167. self.compare_short(sb.build_short_preamble(), exp_short)
  168. def test_int_is_true(self):
  169. loop = """
  170. [i0]
  171. i1 = int_is_true(i0)
  172. guard_true(i1) []
  173. jump(i0)
  174. """
  175. es, loop, preamble = self.optimize(loop)
  176. op = preamble.operations[0]
  177. short_boxes = [box for box in es.short_boxes
  178. if not isinstance(box.short_op, ShortInputArg)]
  179. assert short_boxes[0].short_op.res is op
  180. assert es.exported_infos[op].is_constant()
  181. def test_only_setfield(self):
  182. loop = """
  183. [p0, p1]
  184. setfield_gc(p0, 5, descr=valuedescr)
  185. setfield_gc(p1, 5, descr=nextdescr)
  186. jump(p0, p1)
  187. """
  188. es, loop, preamble = self.optimize(loop)
  189. p0, p1 = es.short_inputargs
  190. short_boxes = [box for box in es.short_boxes
  191. if not isinstance(box.short_op, ShortInputArg)]
  192. assert short_boxes[0].short_op.res.getint() == 5
  193. assert short_boxes[1].short_op.res.getint() == 5
  194. assert short_boxes[0].preamble_op.getarg(0) is p0
  195. assert short_boxes[1].preamble_op.getarg(0) is p1
  196. def test_double_getfield_plus_pure(self):
  197. loop = """
  198. [p0]
  199. pc = getfield_gc_r(p0, descr=nextdescr3)
  200. escape_n(p0) # that should flush the caches
  201. p1 = getfield_gc_r(pc, descr=nextdescr3)
  202. i0 = getfield_gc_i(p1, descr=valuedescr3)
  203. jump(p0)
  204. """
  205. es, loop, preamble = self.optimize(loop)
  206. assert len(es.short_boxes) == 4
  207. # both getfields are available as
  208. # well as getfield_gc
  209. def test_p123_anti_nested(self):
  210. loop = """
  211. [i1, p2, p3]
  212. p3sub = getfield_gc_r(p3, descr=nextdescr)
  213. i3 = getfield_gc_i(p3sub, descr=valuedescr)
  214. escape_n(i3)
  215. p1 = new_with_vtable(descr=nodesize)
  216. p2sub = new_with_vtable(descr=nodesize2)
  217. setfield_gc(p2sub, i1, descr=valuedescr)
  218. setfield_gc(p2, p2sub, descr=nextdescr)
  219. jump(i1, p1, p2)
  220. """
  221. es, loop, preamble = self.optimize(loop)
  222. assert len(producable_short_boxes(es.short_boxes)) == 1
  223. def test_setfield_forced_virtual(self):
  224. loop = """
  225. [p1, p2]
  226. i1 = getfield_gc_i(p1, descr=valuedescr)
  227. setfield_gc(p2, i1, descr=valuedescr)
  228. p3 = new_with_vtable(descr=nodesize)
  229. jump(p2, p3)
  230. """
  231. es, loop, preamble = self.optimize(loop)
  232. sb = ShortPreambleBuilder(loop.inputargs, es.short_boxes,
  233. es.short_inputargs,
  234. es.exported_infos)
  235. short_boxes = [box for box in es.short_boxes
  236. if not isinstance(box.short_op, ShortInputArg)]
  237. op = short_boxes[0].short_op.res
  238. pop = sb.use_box(op, short_boxes[0].preamble_op, FakeOptimizer())
  239. sb.add_preamble_op(PreambleOp(op, pop, False))
  240. exp_short = """
  241. [p0, p1]
  242. guard_nonnull(p0) []
  243. guard_subclass(p0, ConstClass(node_vtable)) []
  244. i1 = getfield_gc_i(p0, descr=valuedescr)
  245. jump(i1)
  246. """
  247. self.compare_short(sb.build_short_preamble(), exp_short)
  248. def test_loopinvariant(self):
  249. loop = """
  250. [i1]
  251. i2 = call_loopinvariant_i(1, i1, descr=nonwritedescr)
  252. guard_no_exception() []
  253. guard_value(i2, 1) []
  254. jump(i1)
  255. """
  256. es, loop, preamble = self.optimize(loop)
  257. assert len(es.short_boxes) == 2
  258. def test_circular_force(self):
  259. ops = """
  260. [p0]
  261. p41 = getfield_gc_r(p0, descr=nextdescr)
  262. i0 = getfield_gc_i(p41, descr=valuedescr)
  263. p1 = new_with_vtable(descr=nodesize2)
  264. p2 = new_with_vtable(descr=nodesize2)
  265. setfield_gc(p2, p1, descr=nextdescr)
  266. setfield_gc(p1, p2, descr=nextdescr)
  267. i1 = int_add(i0, 1)
  268. setfield_gc(p2, i1, descr=valuedescr)
  269. setfield_gc(p0, p1, descr=nextdescr)
  270. jump(p1)
  271. """
  272. es, loop, preamble = self.optimize(ops)
  273. # assert did not crash