PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/pypy/pypy/
Python | 552 lines | 533 code | 18 blank | 1 comment | 18 complexity | 3a3c7ec885f0506beb18f747173d6695 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from __future__ import with_statement
  2. from rpython.jit.metainterp.optimizeopt.test.test_util import (
  3. LLtypeMixin, BaseTest, Storage,
  4. FakeMetaInterpStaticData)
  5. from rpython.jit.metainterp.history import TreeLoop, JitCellToken, TargetToken
  6. from rpython.jit.metainterp.resoperation import rop, opname, ResOperation
  7. from rpython.jit.metainterp.optimize import InvalidLoop
  8. from py.test import raises
  9. from rpython.jit.metainterp.optimizeopt.optimizer import Optimization
  10. from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
  11. from rpython.jit.metainterp.optimizeopt.heap import OptHeap
  12. from rpython.jit.metainterp.optimizeopt.rewrite import OptRewrite
  13. class BaseTestMultiLabel(BaseTest):
  14. enable_opts = "intbounds:rewrite:virtualize:string:earlyforce:pure:heap:unroll"
  15. def optimize_loop(self, ops, expected, expected_shorts=None):
  16. loop = self.parse(ops)
  17. if expected != "crash!":
  18. expected = self.parse(expected)
  19. part = TreeLoop('part')
  20. part.inputargs = loop.inputargs
  21. token = loop.original_jitcell_token
  22. optimized = TreeLoop('optimized')
  23. optimized.inputargs = loop.inputargs
  24. optimized.operations = []
  25. labels = [i for i, op in enumerate(loop.operations) \
  26. if op.getopnum()==rop.LABEL]
  27. prv = 0
  28. last_label = []
  29. state = None
  30. for nxt in labels + [len(loop.operations)]:
  31. assert prv != nxt
  32. operations = last_label + loop.operations[prv:nxt]
  33. if nxt < len(loop.operations):
  34. label = loop.operations[nxt]
  35. assert label.getopnum() == rop.LABEL
  36. if label.getdescr() is None:
  37. label.setdescr(token)
  38. operations.append(label)
  39. part.operations = operations
  40. self.add_guard_future_condition(part)
  41. state = self._do_optimize_loop(part, None, state,
  42. export_state=True)
  43. if part.operations[-1].getopnum() == rop.LABEL:
  44. last_label = [part.operations.pop()]
  45. else:
  46. last_label = []
  47. optimized.operations.extend(part.operations)
  48. prv = nxt + 1
  49. #
  50. print
  51. print "Optimized:"
  52. if optimized.operations:
  53. print '\n'.join([str(o) for o in optimized.operations])
  54. else:
  55. print 'Failed!'
  56. print
  57. shorts = [op.getdescr().short_preamble
  58. for op in optimized.operations
  59. if op.getopnum() == rop.LABEL]
  60. if expected_shorts:
  61. for short in shorts:
  62. print
  63. print "Short preamble:"
  64. print '\n'.join([str(o) for o in short])
  65. assert expected != "crash!", "should have raised an exception"
  66. self.assert_equal(optimized, expected)
  67. if expected_shorts:
  68. assert len(shorts) == len(expected_shorts)
  69. for short, expected_short in zip(shorts, expected_shorts):
  70. expected_short = self.parse(expected_short)
  71. short_preamble = TreeLoop('short preamble')
  72. assert short[0].getopnum() == rop.LABEL
  73. short_preamble.inputargs = short[0].getarglist()
  74. short_preamble.operations = short
  75. self.assert_equal(short_preamble, expected_short,
  76. text_right='expected short preamble')
  77. return optimized
  78. class OptimizeoptTestMultiLabel(BaseTestMultiLabel):
  79. def test_simple(self):
  80. ops = """
  81. [i1]
  82. i2 = int_add(i1, 1)
  83. escape(i2)
  84. label(i1)
  85. i3 = int_add(i1, 1)
  86. escape(i3)
  87. jump(i1)
  88. """
  89. expected = """
  90. [i1]
  91. i2 = int_add(i1, 1)
  92. escape(i2)
  93. label(i1, i2)
  94. escape(i2)
  95. jump(i1, i2)
  96. """
  97. self.optimize_loop(ops, expected)
  98. def test_forced_virtual(self):
  99. ops = """
  100. [p1]
  101. p3 = new_with_vtable(ConstClass(node_vtable))
  102. label(p3)
  103. escape(p3)
  104. jump(p3)
  105. """
  106. with raises(InvalidLoop):
  107. self.optimize_loop(ops, ops)
  108. def test_virtuals_with_nonmatching_fields(self):
  109. ops = """
  110. [p1]
  111. p3 = new_with_vtable(ConstClass(node_vtable))
  112. setfield_gc(p3, 1, descr=valuedescr)
  113. label(p3)
  114. p4 = new_with_vtable(ConstClass(node_vtable))
  115. setfield_gc(p4, 1, descr=nextdescr)
  116. jump(p4)
  117. """
  118. with raises(InvalidLoop):
  119. self.optimize_loop(ops, ops)
  120. def test_virtual_arrays_with_nonmatching_lens(self):
  121. ops = """
  122. [p1]
  123. p2 = new_array(3, descr=arraydescr)
  124. label(p2)
  125. p4 = new_array(2, descr=arraydescr)
  126. jump(p4)
  127. """
  128. with raises(InvalidLoop):
  129. self.optimize_loop(ops, ops)
  130. def test_nonmatching_arraystruct_1(self):
  131. ops = """
  132. [p1, f0]
  133. p2 = new_array_clear(3, descr=complexarraydescr)
  134. setinteriorfield_gc(p2, 2, f0, descr=complexrealdescr)
  135. label(p2, f0)
  136. p4 = new_array_clear(3, descr=complexarraydescr)
  137. setinteriorfield_gc(p4, 2, f0, descr=compleximagdescr)
  138. jump(p4, f0)
  139. """
  140. with raises(InvalidLoop):
  141. self.optimize_loop(ops, ops)
  142. def test_nonmatching_arraystruct_2(self):
  143. ops = """
  144. [p1, f0]
  145. p2 = new_array_clear(3, descr=complexarraydescr)
  146. setinteriorfield_gc(p2, 2, f0, descr=complexrealdescr)
  147. label(p2, f0)
  148. p4 = new_array_clear(2, descr=complexarraydescr)
  149. setinteriorfield_gc(p4, 0, f0, descr=complexrealdescr)
  150. jump(p4, f0)
  151. """
  152. with raises(InvalidLoop):
  153. self.optimize_loop(ops, ops)
  154. def test_not_virtual(self):
  155. ops = """
  156. [p1]
  157. p3 = new_with_vtable(ConstClass(node_vtable))
  158. label(p3)
  159. p4 = escape()
  160. jump(p4)
  161. """
  162. with raises(InvalidLoop):
  163. self.optimize_loop(ops, ops)
  164. def test_not_virtual_array(self):
  165. ops = """
  166. [p1]
  167. p3 = new_array(3, descr=arraydescr)
  168. label(p3)
  169. p4 = escape()
  170. jump(p4)
  171. """
  172. with raises(InvalidLoop):
  173. self.optimize_loop(ops, ops)
  174. def test_not_virtual_arraystruct(self):
  175. ops = """
  176. [p1]
  177. p3 = new_array_clear(3, descr=complexarraydescr)
  178. label(p3)
  179. p4 = escape()
  180. jump(p4)
  181. """
  182. with raises(InvalidLoop):
  183. self.optimize_loop(ops, ops)
  184. def test_virtual_turns_constant(self):
  185. ops = """
  186. [p1]
  187. p3 = new_with_vtable(ConstClass(node_vtable))
  188. label(p3)
  189. guard_value(p3, ConstPtr(myptr)) []
  190. jump(p3)
  191. """
  192. with raises(InvalidLoop):
  193. self.optimize_loop(ops, ops)
  194. def test_virtuals_turns_not_equal(self):
  195. ops = """
  196. [p1, p2]
  197. p3 = new_with_vtable(ConstClass(node_vtable))
  198. label(p3, p3)
  199. p4 = new_with_vtable(ConstClass(node_vtable))
  200. jump(p3, p4)
  201. """
  202. with raises(InvalidLoop):
  203. self.optimize_loop(ops, ops)
  204. def test_two_intermediate_labels_basic_1(self):
  205. ops = """
  206. [p1, i1]
  207. i2 = getfield_gc(p1, descr=valuedescr)
  208. label(p1, i1)
  209. i3 = getfield_gc(p1, descr=valuedescr)
  210. i4 = int_add(i1, i3)
  211. label(p1, i4)
  212. i5 = int_add(i4, 1)
  213. jump(p1, i5)
  214. """
  215. expected = """
  216. [p1, i1]
  217. i2 = getfield_gc(p1, descr=valuedescr)
  218. label(p1, i1, i2)
  219. i4 = int_add(i1, i2)
  220. label(p1, i4)
  221. i5 = int_add(i4, 1)
  222. jump(p1, i5)
  223. """
  224. short1 = """
  225. [p1, i1]
  226. label(p1, i1)
  227. i2 = getfield_gc(p1, descr=valuedescr)
  228. jump(p1, i1, i2)
  229. """
  230. short2 = """
  231. [p1, i1]
  232. label(p1, i1)
  233. jump(p1, i1)
  234. """
  235. self.optimize_loop(ops, expected, expected_shorts=[short1, short2])
  236. def test_two_intermediate_labels_basic_2(self):
  237. ops = """
  238. [p1, i1]
  239. i2 = int_add(i1, 1)
  240. label(p1, i1)
  241. i3 = getfield_gc(p1, descr=valuedescr)
  242. i4 = int_add(i1, i3)
  243. label(p1, i4)
  244. i5 = getfield_gc(p1, descr=valuedescr)
  245. i6 = int_add(i4, i5)
  246. jump(p1, i6)
  247. """
  248. expected = """
  249. [p1, i1]
  250. i2 = int_add(i1, 1)
  251. label(p1, i1)
  252. i3 = getfield_gc(p1, descr=valuedescr)
  253. i4 = int_add(i1, i3)
  254. label(p1, i4, i3)
  255. i6 = int_add(i4, i3)
  256. jump(p1, i6, i3)
  257. """
  258. short1 = """
  259. [p1, i1]
  260. label(p1, i1)
  261. jump(p1, i1)
  262. """
  263. short2 = """
  264. [p1, i1]
  265. label(p1, i1)
  266. i2 = getfield_gc(p1, descr=valuedescr)
  267. jump(p1, i1, i2)
  268. """
  269. self.optimize_loop(ops, expected, expected_shorts=[short1, short2])
  270. def test_two_intermediate_labels_both(self):
  271. ops = """
  272. [p1, i1]
  273. i2 = getfield_gc(p1, descr=valuedescr)
  274. label(p1, i1)
  275. i3 = getfield_gc(p1, descr=valuedescr)
  276. i4 = int_add(i1, i3)
  277. label(p1, i4)
  278. i5 = getfield_gc(p1, descr=valuedescr)
  279. i6 = int_mul(i4, i5)
  280. jump(p1, i6)
  281. """
  282. expected = """
  283. [p1, i1]
  284. i2 = getfield_gc(p1, descr=valuedescr)
  285. label(p1, i1, i2)
  286. i4 = int_add(i1, i2)
  287. label(p1, i4, i2)
  288. i6 = int_mul(i4, i2)
  289. jump(p1, i6, i2)
  290. """
  291. short = """
  292. [p1, i1]
  293. label(p1, i1)
  294. i2 = getfield_gc(p1, descr=valuedescr)
  295. jump(p1, i1, i2)
  296. """
  297. self.optimize_loop(ops, expected, expected_shorts=[short, short])
  298. def test_import_across_multiple_labels_basic(self):
  299. # Not supported, juts make sure we get a functional trace
  300. ops = """
  301. [p1, i1]
  302. i2 = getfield_gc(p1, descr=valuedescr)
  303. label(p1, i1)
  304. i3 = int_add(i1, 1)
  305. label(p1, i1)
  306. i4 = getfield_gc(p1, descr=valuedescr)
  307. i5 = int_add(i4, 1)
  308. jump(p1, i5)
  309. """
  310. self.optimize_loop(ops, ops)
  311. def test_import_across_multiple_labels_with_duplication(self):
  312. # Not supported, juts make sure we get a functional trace
  313. ops = """
  314. [p1, i1]
  315. i2 = getfield_gc(p1, descr=valuedescr)
  316. label(p1, i2)
  317. i3 = int_add(i2, 1)
  318. label(p1, i2)
  319. i4 = getfield_gc(p1, descr=valuedescr)
  320. i5 = int_add(i4, 1)
  321. jump(p1, i5)
  322. """
  323. exported = """
  324. [p1, i1]
  325. i2 = getfield_gc(p1, descr=valuedescr)
  326. i6 = same_as(i2)
  327. label(p1, i2)
  328. i3 = int_add(i2, 1)
  329. label(p1, i2)
  330. i4 = getfield_gc(p1, descr=valuedescr)
  331. i5 = int_add(i4, 1)
  332. jump(p1, i5)
  333. """
  334. self.optimize_loop(ops, exported)
  335. def test_import_virtual_across_multiple_labels(self):
  336. ops = """
  337. [p0, i1]
  338. i1a = int_add(i1, 1)
  339. pv = new_with_vtable(ConstClass(node_vtable))
  340. setfield_gc(pv, i1a, descr=valuedescr)
  341. label(pv, i1)
  342. i2 = int_mul(i1, 3)
  343. label(pv, i2)
  344. i3 = getfield_gc(pv, descr=valuedescr)
  345. i4 = int_add(i3, i2)
  346. jump(pv, i4)
  347. """
  348. expected = """
  349. [p0, i1]
  350. i1a = int_add(i1, 1)
  351. i5 = same_as(i1a)
  352. label(i1a, i1)
  353. i2 = int_mul(i1, 3)
  354. label(i1a, i2)
  355. i4 = int_add(i1a, i2)
  356. jump(i1a, i4)
  357. """
  358. self.optimize_loop(ops, expected)
  359. def test_virtual_as_field_of_forced_box(self):
  360. ops = """
  361. [p0]
  362. pv1 = new_with_vtable(ConstClass(node_vtable))
  363. label(pv1, p0)
  364. pv2 = new_with_vtable(ConstClass(node_vtable))
  365. setfield_gc(pv2, pv1, descr=valuedescr)
  366. jump(pv1, pv2)
  367. """
  368. with raises(InvalidLoop):
  369. self.optimize_loop(ops, ops)
  370. def test_issue1045(self):
  371. ops = """
  372. [i55]
  373. i73 = int_mod(i55, 2)
  374. i75 = int_rshift(i73, 63)
  375. i76 = int_and(2, i75)
  376. i77 = int_add(i73, i76)
  377. i81 = int_eq(i77, 1)
  378. i0 = int_ge(i55, 1)
  379. guard_true(i0) []
  380. label(i55)
  381. i3 = int_mod(i55, 2)
  382. i5 = int_rshift(i3, 63)
  383. i6 = int_and(2, i5)
  384. i7 = int_add(i3, i6)
  385. i8 = int_eq(i7, 1)
  386. escape(i8)
  387. jump(i55)
  388. """
  389. expected = """
  390. [i55]
  391. i73 = int_mod(i55, 2)
  392. i75 = int_rshift(i73, 63)
  393. i76 = int_and(2, i75)
  394. i77 = int_add(i73, i76)
  395. i81 = int_eq(i77, 1)
  396. i0 = int_ge(i55, 1)
  397. guard_true(i0) []
  398. label(i55, i81)
  399. escape(i81)
  400. jump(i55, i81)
  401. """
  402. self.optimize_loop(ops, expected)
  403. def test_boxed_opaque_unknown_class(self):
  404. ops = """
  405. [p1]
  406. p2 = getfield_gc(p1, descr=nextdescr)
  407. mark_opaque_ptr(p2)
  408. i3 = getfield_gc(p2, descr=otherdescr)
  409. label(p1)
  410. i4 = getfield_gc(p1, descr=otherdescr)
  411. label(p1)
  412. p5 = getfield_gc(p1, descr=nextdescr)
  413. mark_opaque_ptr(p5)
  414. i6 = getfield_gc(p5, descr=otherdescr)
  415. i7 = call(i6, descr=nonwritedescr)
  416. """
  417. expected = """
  418. [p1]
  419. p2 = getfield_gc(p1, descr=nextdescr)
  420. i3 = getfield_gc(p2, descr=otherdescr)
  421. label(p1)
  422. i4 = getfield_gc(p1, descr=otherdescr)
  423. label(p1)
  424. p5 = getfield_gc(p1, descr=nextdescr)
  425. i6 = getfield_gc(p5, descr=otherdescr)
  426. i7 = call(i6, descr=nonwritedescr)
  427. """
  428. self.optimize_loop(ops, expected)
  429. def test_opaque_pointer_fails_to_close_loop(self):
  430. ops = """
  431. [p1, p11]
  432. p2 = getfield_gc(p1, descr=nextdescr)
  433. guard_class(p2, ConstClass(node_vtable)) []
  434. mark_opaque_ptr(p2)
  435. i3 = getfield_gc(p2, descr=otherdescr)
  436. label(p1, p11)
  437. p12 = getfield_gc(p1, descr=nextdescr)
  438. i13 = getfield_gc(p2, descr=otherdescr)
  439. i14 = call(i13, descr=nonwritedescr)
  440. jump(p11, p1)
  441. """
  442. with raises(InvalidLoop):
  443. self.optimize_loop(ops, ops)
  444. class OptRenameStrlen(Optimization):
  445. def propagate_forward(self, op):
  446. dispatch_opt(self, op)
  447. def optimize_STRLEN(self, op):
  448. newop = op.clone()
  449. newop.result = op.result.clonebox()
  450. self.emit_operation(newop)
  451. self.make_equal_to(op.result, self.getvalue(newop.result))
  452. dispatch_opt = make_dispatcher_method(OptRenameStrlen, 'optimize_',
  453. default=OptRenameStrlen.emit_operation)
  454. class BaseTestOptimizerRenamingBoxes(BaseTestMultiLabel):
  455. def _do_optimize_loop(self, loop, call_pure_results, state,
  456. export_state=False):
  457. from rpython.jit.metainterp.optimizeopt.unroll import optimize_unroll
  458. from rpython.jit.metainterp.optimizeopt.util import args_dict
  459. from rpython.jit.metainterp.optimizeopt.pure import OptPure
  460. self.loop = loop
  461. loop.call_pure_results = args_dict()
  462. metainterp_sd = FakeMetaInterpStaticData(self.cpu)
  463. return optimize_unroll(metainterp_sd, loop, [OptRewrite(), OptRenameStrlen(), OptHeap(), OptPure()], True, state, export_state)
  464. def test_optimizer_renaming_boxes1(self):
  465. ops = """
  466. [p1]
  467. i1 = strlen(p1)
  468. label(p1)
  469. i2 = strlen(p1)
  470. i3 = int_add(i2, 7)
  471. jump(p1)
  472. """
  473. expected = """
  474. [p1]
  475. i1 = strlen(p1)
  476. label(p1, i1)
  477. i11 = same_as(i1)
  478. i2 = int_add(i11, 7)
  479. jump(p1, i11)
  480. """
  481. self.optimize_loop(ops, expected)
  482. def test_optimizer_renaming_boxes_not_imported(self):
  483. ops = """
  484. [p1]
  485. i1 = strlen(p1)
  486. label(p1)
  487. jump(p1)
  488. """
  489. expected = """
  490. [p1]
  491. i1 = strlen(p1)
  492. label(p1, i1)
  493. i11 = same_as(i1)
  494. jump(p1, i11)
  495. """
  496. self.optimize_loop(ops, expected)
  497. class XxxTestLLtype(OptimizeoptTestMultiLabel, LLtypeMixin):
  498. pass
  499. class XxxTestOptimizerRenamingBoxesLLtype(BaseTestOptimizerRenamingBoxes, LLtypeMixin):
  500. pass