PageRenderTime 40ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/kcr/pypy
Python | 5123 lines | 5095 code | 19 blank | 9 comment | 9 complexity | c906bec769f7eedc2479b4c3a8ca342c MD5 | raw file
Possible License(s): Apache-2.0
  1. import py
  2. from rpython.rlib.objectmodel import instantiate
  3. from rpython.jit.metainterp.optimizeopt.test.test_util import (
  4. LLtypeMixin, BaseTest, FakeMetaInterpStaticData, convert_old_style_to_targets)
  5. from rpython.jit.metainterp.history import TargetToken, JitCellToken
  6. from rpython.jit.metainterp.test.test_compile import FakeLogger
  7. import rpython.jit.metainterp.optimizeopt.optimizer as optimizeopt
  8. import rpython.jit.metainterp.optimizeopt.virtualize as virtualize
  9. from rpython.jit.metainterp.optimize import InvalidLoop
  10. from rpython.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt, get_const_ptr_for_string
  11. from rpython.jit.metainterp import executor, compile, resume, history
  12. from rpython.jit.metainterp.resoperation import rop, opname, ResOperation
  13. from rpython.rlib.rarithmetic import LONG_BIT
  14. def test_store_final_boxes_in_guard():
  15. from rpython.jit.metainterp.compile import ResumeGuardDescr
  16. from rpython.jit.metainterp.resume import tag, TAGBOX
  17. b0 = BoxInt()
  18. b1 = BoxInt()
  19. opt = optimizeopt.Optimizer(FakeMetaInterpStaticData(LLtypeMixin.cpu),
  20. None)
  21. fdescr = ResumeGuardDescr()
  22. op = ResOperation(rop.GUARD_TRUE, ['dummy'], None, descr=fdescr)
  23. # setup rd data
  24. fi0 = resume.FrameInfo(None, "code0", 11)
  25. fdescr.rd_frame_info_list = resume.FrameInfo(fi0, "code1", 33)
  26. snapshot0 = resume.Snapshot(None, [b0])
  27. fdescr.rd_snapshot = resume.Snapshot(snapshot0, [b1])
  28. #
  29. opt.store_final_boxes_in_guard(op)
  30. if op.getfailargs() == [b0, b1]:
  31. assert list(fdescr.rd_numb.nums) == [tag(1, TAGBOX)]
  32. assert list(fdescr.rd_numb.prev.nums) == [tag(0, TAGBOX)]
  33. else:
  34. assert op.getfailargs() == [b1, b0]
  35. assert list(fdescr.rd_numb.nums) == [tag(0, TAGBOX)]
  36. assert list(fdescr.rd_numb.prev.nums) == [tag(1, TAGBOX)]
  37. assert fdescr.rd_virtuals is None
  38. assert fdescr.rd_consts == []
  39. def test_sharing_field_lists_of_virtual():
  40. class FakeOptimizer(object):
  41. class optimizer(object):
  42. class cpu(object):
  43. pass
  44. opt = FakeOptimizer()
  45. virt1 = virtualize.AbstractVirtualStructValue(opt, None)
  46. lst1 = virt1._get_field_descr_list()
  47. assert lst1 == []
  48. lst2 = virt1._get_field_descr_list()
  49. assert lst1 is lst2
  50. virt1.setfield(LLtypeMixin.valuedescr, optimizeopt.OptValue(None))
  51. lst3 = virt1._get_field_descr_list()
  52. assert lst3 == [LLtypeMixin.valuedescr]
  53. lst4 = virt1._get_field_descr_list()
  54. assert lst3 is lst4
  55. virt2 = virtualize.AbstractVirtualStructValue(opt, None)
  56. lst5 = virt2._get_field_descr_list()
  57. assert lst5 is lst1
  58. virt2.setfield(LLtypeMixin.valuedescr, optimizeopt.OptValue(None))
  59. lst6 = virt1._get_field_descr_list()
  60. assert lst6 is lst3
  61. def test_reuse_vinfo():
  62. class FakeVInfo(object):
  63. def set_content(self, fieldnums):
  64. self.fieldnums = fieldnums
  65. def equals(self, fieldnums):
  66. return self.fieldnums == fieldnums
  67. class FakeVirtualValue(virtualize.AbstractVirtualValue):
  68. def _make_virtual(self, *args):
  69. return FakeVInfo()
  70. v1 = FakeVirtualValue(None, None)
  71. vinfo1 = v1.make_virtual_info(None, [1, 2, 4])
  72. vinfo2 = v1.make_virtual_info(None, [1, 2, 4])
  73. assert vinfo1 is vinfo2
  74. vinfo3 = v1.make_virtual_info(None, [1, 2, 6])
  75. assert vinfo3 is not vinfo2
  76. vinfo4 = v1.make_virtual_info(None, [1, 2, 6])
  77. assert vinfo3 is vinfo4
  78. def test_descrlist_dict():
  79. from rpython.jit.metainterp.optimizeopt import util as optimizeutil
  80. h1 = optimizeutil.descrlist_hash([])
  81. h2 = optimizeutil.descrlist_hash([LLtypeMixin.valuedescr])
  82. h3 = optimizeutil.descrlist_hash(
  83. [LLtypeMixin.valuedescr, LLtypeMixin.nextdescr])
  84. assert h1 != h2
  85. assert h2 != h3
  86. assert optimizeutil.descrlist_eq([], [])
  87. assert not optimizeutil.descrlist_eq([], [LLtypeMixin.valuedescr])
  88. assert optimizeutil.descrlist_eq([LLtypeMixin.valuedescr],
  89. [LLtypeMixin.valuedescr])
  90. assert not optimizeutil.descrlist_eq([LLtypeMixin.valuedescr],
  91. [LLtypeMixin.nextdescr])
  92. assert optimizeutil.descrlist_eq([LLtypeMixin.valuedescr, LLtypeMixin.nextdescr],
  93. [LLtypeMixin.valuedescr, LLtypeMixin.nextdescr])
  94. assert not optimizeutil.descrlist_eq([LLtypeMixin.nextdescr, LLtypeMixin.valuedescr],
  95. [LLtypeMixin.valuedescr, LLtypeMixin.nextdescr])
  96. # descrlist_eq should compare by identity of the descrs, not by the result
  97. # of sort_key
  98. class FakeDescr(object):
  99. def sort_key(self):
  100. return 1
  101. assert not optimizeutil.descrlist_eq([FakeDescr()], [FakeDescr()])
  102. # ____________________________________________________________
  103. class BaseTestBasic(BaseTest):
  104. enable_opts = "intbounds:rewrite:virtualize:string:earlyforce:pure:heap"
  105. def optimize_loop(self, ops, optops, call_pure_results=None):
  106. loop = self.parse(ops)
  107. token = JitCellToken()
  108. loop.operations = [ResOperation(rop.LABEL, loop.inputargs, None, descr=TargetToken(token))] + \
  109. loop.operations
  110. if loop.operations[-1].getopnum() == rop.JUMP:
  111. loop.operations[-1].setdescr(token)
  112. expected = convert_old_style_to_targets(self.parse(optops), jump=True)
  113. self._do_optimize_loop(loop, call_pure_results)
  114. print '\n'.join([str(o) for o in loop.operations])
  115. self.assert_equal(loop, expected)
  116. def setup_method(self, meth=None):
  117. class FailDescr(compile.ResumeGuardDescr):
  118. oparse = None
  119. def _oparser_uses_descr_of_guard(self, oparse, fail_args):
  120. # typically called 3 times: once when parsing 'ops',
  121. # once when parsing 'preamble', once when parsing 'expected'.
  122. self.oparse = oparse
  123. self.rd_frame_info_list, self.rd_snapshot = snapshot(fail_args)
  124. def _clone_if_mutable(self):
  125. assert self is fdescr
  126. return fdescr2
  127. def __repr__(self):
  128. if self is fdescr:
  129. return 'fdescr'
  130. if self is fdescr2:
  131. return 'fdescr2'
  132. return compile.ResumeGuardDescr.__repr__(self)
  133. #
  134. def snapshot(fail_args, got=[]):
  135. if not got: # only the first time, i.e. when parsing 'ops'
  136. rd_frame_info_list = resume.FrameInfo(None, "code", 11)
  137. rd_snapshot = resume.Snapshot(None, fail_args)
  138. got.append(rd_frame_info_list)
  139. got.append(rd_snapshot)
  140. return got
  141. #
  142. fdescr = instantiate(FailDescr)
  143. self.namespace['fdescr'] = fdescr
  144. fdescr2 = instantiate(FailDescr)
  145. self.namespace['fdescr2'] = fdescr2
  146. def teardown_method(self, meth):
  147. self.namespace.pop('fdescr', None)
  148. self.namespace.pop('fdescr2', None)
  149. class BaseTestOptimizeBasic(BaseTestBasic):
  150. def test_simple(self):
  151. ops = """
  152. [i]
  153. i0 = int_sub(i, 1)
  154. guard_value(i0, 0) [i0]
  155. jump(i)
  156. """
  157. expected = """
  158. [i]
  159. i0 = int_sub(i, 1)
  160. guard_value(i0, 0) [i0]
  161. jump(1)
  162. """
  163. self.optimize_loop(ops, expected)
  164. def test_constant_propagate(self):
  165. ops = """
  166. []
  167. i0 = int_add(2, 3)
  168. i1 = int_is_true(i0)
  169. guard_true(i1) []
  170. i2 = int_is_zero(i1)
  171. guard_false(i2) []
  172. guard_value(i0, 5) []
  173. jump()
  174. """
  175. expected = """
  176. []
  177. jump()
  178. """
  179. self.optimize_loop(ops, expected)
  180. def test_constant_propagate_ovf(self):
  181. ops = """
  182. []
  183. i0 = int_add_ovf(2, 3)
  184. guard_no_overflow() []
  185. i1 = int_is_true(i0)
  186. guard_true(i1) []
  187. i2 = int_is_zero(i1)
  188. guard_false(i2) []
  189. guard_value(i0, 5) []
  190. jump()
  191. """
  192. expected = """
  193. []
  194. jump()
  195. """
  196. self.optimize_loop(ops, expected)
  197. # ----------
  198. def test_remove_guard_class_1(self):
  199. ops = """
  200. [p0]
  201. guard_class(p0, ConstClass(node_vtable)) []
  202. guard_class(p0, ConstClass(node_vtable)) []
  203. jump(p0)
  204. """
  205. expected = """
  206. [p0]
  207. guard_class(p0, ConstClass(node_vtable)) []
  208. jump(p0)
  209. """
  210. self.optimize_loop(ops, expected)
  211. def test_remove_guard_class_2(self):
  212. ops = """
  213. [i0]
  214. p0 = new_with_vtable(ConstClass(node_vtable))
  215. escape(p0)
  216. guard_class(p0, ConstClass(node_vtable)) []
  217. jump(i0)
  218. """
  219. expected = """
  220. [i0]
  221. p0 = new_with_vtable(ConstClass(node_vtable))
  222. escape(p0)
  223. jump(i0)
  224. """
  225. self.optimize_loop(ops, expected)
  226. def test_remove_guard_class_constant(self):
  227. ops = """
  228. [i0]
  229. p0 = same_as(ConstPtr(myptr))
  230. guard_class(p0, ConstClass(node_vtable)) []
  231. jump(i0)
  232. """
  233. expected = """
  234. [i0]
  235. jump(i0)
  236. """
  237. self.optimize_loop(ops, expected)
  238. def test_constant_boolrewrite_lt(self):
  239. ops = """
  240. [i0]
  241. i1 = int_lt(i0, 0)
  242. guard_true(i1) []
  243. i2 = int_ge(i0, 0)
  244. guard_false(i2) []
  245. jump(i0)
  246. """
  247. expected = """
  248. [i0]
  249. i1 = int_lt(i0, 0)
  250. guard_true(i1) []
  251. jump(i0)
  252. """
  253. self.optimize_loop(ops, expected)
  254. def test_constant_boolrewrite_gt(self):
  255. ops = """
  256. [i0]
  257. i1 = int_gt(i0, 0)
  258. guard_true(i1) []
  259. i2 = int_le(i0, 0)
  260. guard_false(i2) []
  261. jump(i0)
  262. """
  263. expected = """
  264. [i0]
  265. i1 = int_gt(i0, 0)
  266. guard_true(i1) []
  267. jump(i0)
  268. """
  269. self.optimize_loop(ops, expected)
  270. def test_constant_boolrewrite_reflex(self):
  271. ops = """
  272. [i0]
  273. i1 = int_gt(i0, 0)
  274. guard_true(i1) []
  275. i2 = int_lt(0, i0)
  276. guard_true(i2) []
  277. jump(i0)
  278. """
  279. expected = """
  280. [i0]
  281. i1 = int_gt(i0, 0)
  282. guard_true(i1) []
  283. jump(i0)
  284. """
  285. self.optimize_loop(ops, expected)
  286. def test_constant_boolrewrite_reflex_invers(self):
  287. ops = """
  288. [i0]
  289. i1 = int_gt(i0, 0)
  290. guard_true(i1) []
  291. i2 = int_ge(0, i0)
  292. guard_false(i2) []
  293. jump(i0)
  294. """
  295. expected = """
  296. [i0]
  297. i1 = int_gt(i0, 0)
  298. guard_true(i1) []
  299. jump(i0)
  300. """
  301. self.optimize_loop(ops, expected)
  302. def test_remove_consecutive_guard_value_constfold(self):
  303. ops = """
  304. []
  305. i0 = escape()
  306. guard_value(i0, 0) []
  307. i1 = int_add(i0, 1)
  308. guard_value(i1, 1) []
  309. i2 = int_add(i1, 2)
  310. escape(i2)
  311. jump()
  312. """
  313. expected = """
  314. []
  315. i0 = escape()
  316. guard_value(i0, 0) []
  317. escape(3)
  318. jump()
  319. """
  320. self.optimize_loop(ops, expected)
  321. def test_remove_guard_value_if_constant(self):
  322. ops = """
  323. [p1]
  324. guard_value(p1, ConstPtr(myptr)) []
  325. jump(ConstPtr(myptr))
  326. """
  327. expected = """
  328. []
  329. jump()
  330. """
  331. py.test.skip("XXX")
  332. self.optimize_loop(ops, 'Constant(myptr)', expected)
  333. def test_ooisnull_oononnull_1(self):
  334. ops = """
  335. [p0]
  336. guard_class(p0, ConstClass(node_vtable)) []
  337. guard_nonnull(p0) []
  338. jump(p0)
  339. """
  340. expected = """
  341. [p0]
  342. guard_class(p0, ConstClass(node_vtable)) []
  343. jump(p0)
  344. """
  345. self.optimize_loop(ops, expected)
  346. def test_int_is_true_1(self):
  347. ops = """
  348. [i0]
  349. i1 = int_is_true(i0)
  350. guard_true(i1) []
  351. i2 = int_is_true(i0)
  352. guard_true(i2) []
  353. jump(i0)
  354. """
  355. expected = """
  356. [i0]
  357. i1 = int_is_true(i0)
  358. guard_true(i1) []
  359. jump(i0)
  360. """
  361. self.optimize_loop(ops, expected)
  362. def test_int_is_true_is_zero(self):
  363. py.test.skip("XXX implement me")
  364. ops = """
  365. [i0]
  366. i1 = int_is_true(i0)
  367. guard_true(i1) []
  368. i2 = int_is_zero(i0)
  369. guard_false(i2) []
  370. jump(i0)
  371. """
  372. expected = """
  373. [i0]
  374. i1 = int_is_true(i0)
  375. guard_true(i1) []
  376. jump(i0)
  377. """
  378. self.optimize_loop(ops, expected)
  379. def test_int_is_zero_int_is_true(self):
  380. ops = """
  381. [i0]
  382. i1 = int_is_zero(i0)
  383. guard_true(i1) []
  384. i2 = int_is_true(i0)
  385. guard_false(i2) []
  386. jump(i0)
  387. """
  388. expected = """
  389. [i0]
  390. i1 = int_is_zero(i0)
  391. guard_true(i1) []
  392. jump(0)
  393. """
  394. self.optimize_loop(ops, expected)
  395. def test_ooisnull_oononnull_2(self):
  396. ops = """
  397. [p0]
  398. guard_nonnull(p0) []
  399. guard_nonnull(p0) []
  400. jump(p0)
  401. """
  402. expected = """
  403. [p0]
  404. guard_nonnull(p0) []
  405. jump(p0)
  406. """
  407. self.optimize_loop(ops, expected)
  408. def test_ooisnull_on_null_ptr_1(self):
  409. ops = """
  410. []
  411. p0 = escape()
  412. guard_isnull(p0) []
  413. guard_isnull(p0) []
  414. jump()
  415. """
  416. expected = """
  417. []
  418. p0 = escape()
  419. guard_isnull(p0) []
  420. jump()
  421. """
  422. self.optimize_loop(ops, expected)
  423. def test_ooisnull_oononnull_via_virtual(self):
  424. ops = """
  425. [p0]
  426. pv = new_with_vtable(ConstClass(node_vtable))
  427. setfield_gc(pv, p0, descr=valuedescr)
  428. guard_nonnull(p0) []
  429. p1 = getfield_gc(pv, descr=valuedescr)
  430. guard_nonnull(p1) []
  431. jump(p0)
  432. """
  433. expected = """
  434. [p0]
  435. guard_nonnull(p0) []
  436. jump(p0)
  437. """
  438. self.optimize_loop(ops, expected)
  439. def test_oois_1(self):
  440. ops = """
  441. [p0]
  442. guard_class(p0, ConstClass(node_vtable)) []
  443. i0 = instance_ptr_ne(p0, NULL)
  444. guard_true(i0) []
  445. i1 = instance_ptr_eq(p0, NULL)
  446. guard_false(i1) []
  447. i2 = instance_ptr_ne(NULL, p0)
  448. guard_true(i0) []
  449. i3 = instance_ptr_eq(NULL, p0)
  450. guard_false(i1) []
  451. jump(p0)
  452. """
  453. expected = """
  454. [p0]
  455. guard_class(p0, ConstClass(node_vtable)) []
  456. jump(p0)
  457. """
  458. self.optimize_loop(ops, expected)
  459. def test_nonnull_1(self):
  460. ops = """
  461. [p0]
  462. setfield_gc(p0, 5, descr=valuedescr) # forces p0 != NULL
  463. i0 = ptr_ne(p0, NULL)
  464. guard_true(i0) []
  465. i1 = ptr_eq(p0, NULL)
  466. guard_false(i1) []
  467. i2 = ptr_ne(NULL, p0)
  468. guard_true(i0) []
  469. i3 = ptr_eq(NULL, p0)
  470. guard_false(i1) []
  471. guard_nonnull(p0) []
  472. jump(p0)
  473. """
  474. expected = """
  475. [p0]
  476. setfield_gc(p0, 5, descr=valuedescr)
  477. jump(p0)
  478. """
  479. self.optimize_loop(ops, expected)
  480. def test_const_guard_value(self):
  481. ops = """
  482. []
  483. i = int_add(5, 3)
  484. guard_value(i, 8) []
  485. jump()
  486. """
  487. expected = """
  488. []
  489. jump()
  490. """
  491. self.optimize_loop(ops, expected)
  492. def test_constptr_guard_value(self):
  493. ops = """
  494. []
  495. p1 = escape()
  496. guard_value(p1, ConstPtr(myptr)) []
  497. jump()
  498. """
  499. self.optimize_loop(ops, ops)
  500. def test_guard_value_to_guard_true(self):
  501. ops = """
  502. [i]
  503. i1 = int_lt(i, 3)
  504. guard_value(i1, 1) [i]
  505. jump(i)
  506. """
  507. expected = """
  508. [i]
  509. i1 = int_lt(i, 3)
  510. guard_true(i1) [i]
  511. jump(i)
  512. """
  513. self.optimize_loop(ops, expected)
  514. def test_guard_value_to_guard_false(self):
  515. ops = """
  516. [i]
  517. i1 = int_is_true(i)
  518. guard_value(i1, 0) [i]
  519. jump(i)
  520. """
  521. expected = """
  522. [i]
  523. i1 = int_is_true(i)
  524. guard_false(i1) [i]
  525. jump(i)
  526. """
  527. self.optimize_loop(ops, expected)
  528. def test_guard_value_on_nonbool(self):
  529. ops = """
  530. [i]
  531. i1 = int_add(i, 3)
  532. guard_value(i1, 0) [i]
  533. jump(i)
  534. """
  535. expected = """
  536. [i]
  537. i1 = int_add(i, 3)
  538. guard_value(i1, 0) [i]
  539. jump(-3)
  540. """
  541. self.optimize_loop(ops, expected)
  542. def test_int_is_true_of_bool(self):
  543. ops = """
  544. [i0, i1]
  545. i2 = int_gt(i0, i1)
  546. i3 = int_is_true(i2)
  547. i4 = int_is_true(i3)
  548. guard_value(i4, 0) [i0, i1]
  549. jump(i0, i1)
  550. """
  551. expected = """
  552. [i0, i1]
  553. i2 = int_gt(i0, i1)
  554. guard_false(i2) [i0, i1]
  555. jump(i0, i1)
  556. """
  557. self.optimize_loop(ops, expected)
  558. def test_p123_simple(self):
  559. ops = """
  560. [i1, p2, p3]
  561. i3 = getfield_gc(p3, descr=valuedescr)
  562. escape(i3)
  563. p1 = new_with_vtable(ConstClass(node_vtable))
  564. setfield_gc(p1, i1, descr=valuedescr)
  565. jump(i1, p1, p2)
  566. """
  567. # We cannot track virtuals that survive for more than two iterations.
  568. self.optimize_loop(ops, ops)
  569. def test_p123_nested(self):
  570. ops = """
  571. [i1, p2, p3]
  572. i3 = getfield_gc(p3, descr=valuedescr)
  573. escape(i3)
  574. p1 = new_with_vtable(ConstClass(node_vtable))
  575. p1sub = new_with_vtable(ConstClass(node_vtable2))
  576. setfield_gc(p1sub, i1, descr=valuedescr)
  577. setfield_gc(p1, i1, descr=valuedescr)
  578. setfield_gc(p1, p1sub, descr=nextdescr)
  579. jump(i1, p1, p2)
  580. """
  581. # The same as test_p123_simple, but with a virtual containing another
  582. # virtual.
  583. self.optimize_loop(ops, ops)
  584. def test_p123_anti_nested(self):
  585. ops = """
  586. [i1, p2, p3]
  587. p3sub = getfield_gc(p3, descr=nextdescr)
  588. i3 = getfield_gc(p3sub, descr=valuedescr)
  589. escape(i3)
  590. p1 = new_with_vtable(ConstClass(node_vtable))
  591. p2sub = new_with_vtable(ConstClass(node_vtable2))
  592. setfield_gc(p2sub, i1, descr=valuedescr)
  593. setfield_gc(p2, p2sub, descr=nextdescr)
  594. jump(i1, p1, p2)
  595. """
  596. # The same as test_p123_simple, but in the end the "old" p2 contains
  597. # a "young" virtual p2sub. Make sure it is all forced.
  598. self.optimize_loop(ops, ops)
  599. # ----------
  600. def test_keep_guard_no_exception(self):
  601. ops = """
  602. [i1]
  603. i2 = call(i1, descr=nonwritedescr)
  604. guard_no_exception() [i1, i2]
  605. jump(i2)
  606. """
  607. self.optimize_loop(ops, ops)
  608. def test_keep_guard_no_exception_with_call_pure_that_is_not_folded(self):
  609. ops = """
  610. [i1]
  611. i2 = call_pure(123456, i1, descr=nonwritedescr)
  612. guard_no_exception() [i1, i2]
  613. jump(i2)
  614. """
  615. expected = """
  616. [i1]
  617. i2 = call(123456, i1, descr=nonwritedescr)
  618. guard_no_exception() [i1, i2]
  619. jump(i2)
  620. """
  621. self.optimize_loop(ops, expected)
  622. def test_remove_guard_no_exception_with_call_pure_on_constant_args(self):
  623. arg_consts = [ConstInt(i) for i in (123456, 81)]
  624. call_pure_results = {tuple(arg_consts): ConstInt(5)}
  625. ops = """
  626. [i1]
  627. i3 = same_as(81)
  628. i2 = call_pure(123456, i3, descr=nonwritedescr)
  629. guard_no_exception() [i1, i2]
  630. jump(i2)
  631. """
  632. expected = """
  633. [i1]
  634. jump(5)
  635. """
  636. self.optimize_loop(ops, expected, call_pure_results)
  637. def test_remove_guard_no_exception_with_duplicated_call_pure(self):
  638. ops = """
  639. [i1]
  640. i2 = call_pure(123456, i1, descr=nonwritedescr)
  641. guard_no_exception() [i1, i2]
  642. i3 = call_pure(123456, i1, descr=nonwritedescr)
  643. guard_no_exception() [i1, i2, i3]
  644. jump(i3)
  645. """
  646. expected = """
  647. [i1]
  648. i2 = call(123456, i1, descr=nonwritedescr)
  649. guard_no_exception() [i1, i2]
  650. jump(i2)
  651. """
  652. self.optimize_loop(ops, expected)
  653. # ----------
  654. def test_call_loopinvariant(self):
  655. ops = """
  656. [i1]
  657. i2 = call_loopinvariant(1, i1, descr=nonwritedescr)
  658. guard_no_exception() []
  659. guard_value(i2, 1) []
  660. i3 = call_loopinvariant(1, i1, descr=nonwritedescr)
  661. guard_no_exception() []
  662. guard_value(i3, 1) []
  663. i4 = call_loopinvariant(1, i1, descr=nonwritedescr)
  664. guard_no_exception() []
  665. guard_value(i4, 1) []
  666. jump(i1)
  667. """
  668. expected = """
  669. [i1]
  670. i2 = call(1, i1, descr=nonwritedescr)
  671. guard_no_exception() []
  672. guard_value(i2, 1) []
  673. jump(i1)
  674. """
  675. self.optimize_loop(ops, expected)
  676. # ----------
  677. def test_virtual_1(self):
  678. ops = """
  679. [i, p0]
  680. i0 = getfield_gc(p0, descr=valuedescr)
  681. i1 = int_add(i0, i)
  682. setfield_gc(p0, i1, descr=valuedescr)
  683. jump(i, p0)
  684. """
  685. expected = """
  686. [i, i2]
  687. i1 = int_add(i2, i)
  688. jump(i, i1)
  689. """
  690. py.test.skip("XXX")
  691. self.optimize_loop(ops, 'Not, Virtual(node_vtable, valuedescr=Not)',
  692. expected)
  693. def test_virtual_float(self):
  694. ops = """
  695. [f, p0]
  696. f0 = getfield_gc(p0, descr=floatdescr)
  697. f1 = float_add(f0, f)
  698. setfield_gc(p0, f1, descr=floatdescr)
  699. jump(f, p0)
  700. """
  701. expected = """
  702. [f, f2]
  703. f1 = float_add(f2, f)
  704. jump(f, f1)
  705. """
  706. py.test.skip("XXX")
  707. self.optimize_loop(ops, 'Not, Virtual(node_vtable, floatdescr=Not)',
  708. expected)
  709. def test_virtual_2(self):
  710. ops = """
  711. [i, p0]
  712. i0 = getfield_gc(p0, descr=valuedescr)
  713. i1 = int_add(i0, i)
  714. p1 = new_with_vtable(ConstClass(node_vtable))
  715. setfield_gc(p1, i1, descr=valuedescr)
  716. jump(i, p1)
  717. """
  718. expected = """
  719. [i, i2]
  720. i1 = int_add(i2, i)
  721. jump(i, i1)
  722. """
  723. py.test.skip("XXX")
  724. self.optimize_loop(ops, 'Not, Virtual(node_vtable, valuedescr=Not)',
  725. expected)
  726. def test_virtual_oois(self):
  727. ops = """
  728. [p0, p1, p2]
  729. guard_nonnull(p0) []
  730. i3 = ptr_ne(p0, NULL)
  731. guard_true(i3) []
  732. i4 = ptr_eq(p0, NULL)
  733. guard_false(i4) []
  734. i5 = ptr_ne(NULL, p0)
  735. guard_true(i5) []
  736. i6 = ptr_eq(NULL, p0)
  737. guard_false(i6) []
  738. i7 = ptr_ne(p0, p1)
  739. guard_true(i7) []
  740. i8 = ptr_eq(p0, p1)
  741. guard_false(i8) []
  742. i9 = ptr_ne(p0, p2)
  743. guard_true(i9) []
  744. i10 = ptr_eq(p0, p2)
  745. guard_false(i10) []
  746. i11 = ptr_ne(p2, p1)
  747. guard_true(i11) []
  748. i12 = ptr_eq(p2, p1)
  749. guard_false(i12) []
  750. jump(p0, p1, p2)
  751. """
  752. expected = """
  753. [p2]
  754. # all constant-folded :-)
  755. jump(p2)
  756. """
  757. py.test.skip("XXX")
  758. self.optimize_loop(ops, '''Virtual(node_vtable),
  759. Virtual(node_vtable),
  760. Not''',
  761. expected)
  762. #
  763. # to be complete, we also check the no-opt case where most comparisons
  764. # are not removed. The exact set of comparisons removed depends on
  765. # the details of the algorithm...
  766. expected2 = """
  767. [p0, p1, p2]
  768. guard_nonnull(p0) []
  769. i7 = ptr_ne(p0, p1)
  770. guard_true(i7) []
  771. i9 = ptr_ne(p0, p2)
  772. guard_true(i9) []
  773. i11 = ptr_ne(p2, p1)
  774. guard_true(i11) []
  775. jump(p0, p1, p2)
  776. """
  777. self.optimize_loop(ops, expected2)
  778. def test_virtual_default_field(self):
  779. ops = """
  780. [p0]
  781. i0 = getfield_gc(p0, descr=valuedescr)
  782. guard_value(i0, 0) []
  783. p1 = new_with_vtable(ConstClass(node_vtable))
  784. # the field 'value' has its default value of 0
  785. jump(p1)
  786. """
  787. expected = """
  788. [i]
  789. guard_value(i, 0) []
  790. jump(0)
  791. """
  792. # the 'expected' is sub-optimal, but it should be done by another later
  793. # optimization step. See test_find_nodes_default_field() for why.
  794. py.test.skip("XXX")
  795. self.optimize_loop(ops, 'Virtual(node_vtable, valuedescr=Not)',
  796. expected)
  797. def test_virtual_3(self):
  798. ops = """
  799. [i]
  800. p1 = new_with_vtable(ConstClass(node_vtable))
  801. setfield_gc(p1, i, descr=valuedescr)
  802. i0 = getfield_gc(p1, descr=valuedescr)
  803. i1 = int_add(i0, 1)
  804. jump(i1)
  805. """
  806. expected = """
  807. [i]
  808. i1 = int_add(i, 1)
  809. jump(i1)
  810. """
  811. self.optimize_loop(ops, expected)
  812. def test_virtual_4(self):
  813. ops = """
  814. [i0, p0]
  815. guard_class(p0, ConstClass(node_vtable)) []
  816. i1 = getfield_gc(p0, descr=valuedescr)
  817. i2 = int_sub(i1, 1)
  818. i3 = int_add(i0, i1)
  819. p1 = new_with_vtable(ConstClass(node_vtable))
  820. setfield_gc(p1, i2, descr=valuedescr)
  821. jump(i3, p1)
  822. """
  823. expected = """
  824. [i0, i1]
  825. i2 = int_sub(i1, 1)
  826. i3 = int_add(i0, i1)
  827. jump(i3, i2)
  828. """
  829. py.test.skip("XXX")
  830. self.optimize_loop(ops, 'Not, Virtual(node_vtable, valuedescr=Not)',
  831. expected)
  832. def test_virtual_5(self):
  833. ops = """
  834. [i0, p0]
  835. guard_class(p0, ConstClass(node_vtable)) []
  836. i1 = getfield_gc(p0, descr=valuedescr)
  837. i2 = int_sub(i1, 1)
  838. i3 = int_add(i0, i1)
  839. p2 = new_with_vtable(ConstClass(node_vtable2))
  840. setfield_gc(p2, i1, descr=valuedescr)
  841. p1 = new_with_vtable(ConstClass(node_vtable))
  842. setfield_gc(p1, i2, descr=valuedescr)
  843. setfield_gc(p1, p2, descr=nextdescr)
  844. jump(i3, p1)
  845. """
  846. expected = """
  847. [i0, i1, i1bis]
  848. i2 = int_sub(i1, 1)
  849. i3 = int_add(i0, i1)
  850. jump(i3, i2, i1)
  851. """
  852. py.test.skip("XXX")
  853. self.optimize_loop(ops,
  854. '''Not, Virtual(node_vtable,
  855. valuedescr=Not,
  856. nextdescr=Virtual(node_vtable2,
  857. valuedescr=Not))''',
  858. expected)
  859. def test_virtual_constant_isnull(self):
  860. ops = """
  861. [i0]
  862. p0 = new_with_vtable(ConstClass(node_vtable))
  863. setfield_gc(p0, NULL, descr=nextdescr)
  864. p2 = getfield_gc(p0, descr=nextdescr)
  865. i1 = ptr_eq(p2, NULL)
  866. jump(i1)
  867. """
  868. expected = """
  869. [i0]
  870. jump(1)
  871. """
  872. self.optimize_loop(ops, expected)
  873. def test_virtual_constant_isnonnull(self):
  874. ops = """
  875. [i0]
  876. p0 = new_with_vtable(ConstClass(node_vtable))
  877. setfield_gc(p0, ConstPtr(myptr), descr=nextdescr)
  878. p2 = getfield_gc(p0, descr=nextdescr)
  879. i1 = ptr_eq(p2, NULL)
  880. jump(i1)
  881. """
  882. expected = """
  883. [i0]
  884. jump(0)
  885. """
  886. self.optimize_loop(ops, expected)
  887. def test_virtual_array_of_struct(self):
  888. ops = """
  889. [f0, f1, f2, f3]
  890. p0 = new_array(2, descr=complexarraydescr)
  891. setinteriorfield_gc(p0, 0, f1, descr=compleximagdescr)
  892. setinteriorfield_gc(p0, 0, f0, descr=complexrealdescr)
  893. setinteriorfield_gc(p0, 1, f3, descr=compleximagdescr)
  894. setinteriorfield_gc(p0, 1, f2, descr=complexrealdescr)
  895. f4 = getinteriorfield_gc(p0, 0, descr=complexrealdescr)
  896. f5 = getinteriorfield_gc(p0, 1, descr=complexrealdescr)
  897. f6 = float_mul(f4, f5)
  898. f7 = getinteriorfield_gc(p0, 0, descr=compleximagdescr)
  899. f8 = getinteriorfield_gc(p0, 1, descr=compleximagdescr)
  900. f9 = float_mul(f7, f8)
  901. f10 = float_add(f6, f9)
  902. finish(f10)
  903. """
  904. expected = """
  905. [f0, f1, f2, f3]
  906. f4 = float_mul(f0, f2)
  907. f5 = float_mul(f1, f3)
  908. f6 = float_add(f4, f5)
  909. finish(f6)
  910. """
  911. self.optimize_loop(ops, expected)
  912. def test_virtual_array_of_struct_forced(self):
  913. ops = """
  914. [f0, f1]
  915. p0 = new_array(1, descr=complexarraydescr)
  916. setinteriorfield_gc(p0, 0, f0, descr=complexrealdescr)
  917. setinteriorfield_gc(p0, 0, f1, descr=compleximagdescr)
  918. f2 = getinteriorfield_gc(p0, 0, descr=complexrealdescr)
  919. f3 = getinteriorfield_gc(p0, 0, descr=compleximagdescr)
  920. f4 = float_mul(f2, f3)
  921. i0 = escape(f4, p0)
  922. finish(i0)
  923. """
  924. expected = """
  925. [f0, f1]
  926. f2 = float_mul(f0, f1)
  927. p0 = new_array(1, descr=complexarraydescr)
  928. setinteriorfield_gc(p0, 0, f1, descr=compleximagdescr)
  929. setinteriorfield_gc(p0, 0, f0, descr=complexrealdescr)
  930. i0 = escape(f2, p0)
  931. finish(i0)
  932. """
  933. self.optimize_loop(ops, expected)
  934. def test_nonvirtual_1(self):
  935. ops = """
  936. [i]
  937. p1 = new_with_vtable(ConstClass(node_vtable))
  938. setfield_gc(p1, i, descr=valuedescr)
  939. i0 = getfield_gc(p1, descr=valuedescr)
  940. i1 = int_add(i0, 1)
  941. escape(p1)
  942. escape(p1)
  943. jump(i1)
  944. """
  945. expected = """
  946. [i]
  947. i1 = int_add(i, 1)
  948. p1 = new_with_vtable(ConstClass(node_vtable))
  949. setfield_gc(p1, i, descr=valuedescr)
  950. escape(p1)
  951. escape(p1)
  952. jump(i1)
  953. """
  954. self.optimize_loop(ops, expected)
  955. def test_nonvirtual_2(self):
  956. ops = """
  957. [i, p0]
  958. i0 = getfield_gc(p0, descr=valuedescr)
  959. escape(p0)
  960. i1 = int_add(i0, i)
  961. p1 = new_with_vtable(ConstClass(node_vtable))
  962. setfield_gc(p1, i1, descr=valuedescr)
  963. jump(i, p1)
  964. """
  965. expected = ops
  966. self.optimize_loop(ops, expected)
  967. def test_nonvirtual_later(self):
  968. ops = """
  969. [i]
  970. p1 = new_with_vtable(ConstClass(node_vtable))
  971. setfield_gc(p1, i, descr=valuedescr)
  972. i1 = getfield_gc(p1, descr=valuedescr)
  973. escape(p1)
  974. i2 = getfield_gc(p1, descr=valuedescr)
  975. i3 = int_add(i1, i2)
  976. jump(i3)
  977. """
  978. expected = """
  979. [i]
  980. p1 = new_with_vtable(ConstClass(node_vtable))
  981. setfield_gc(p1, i, descr=valuedescr)
  982. escape(p1)
  983. i2 = getfield_gc(p1, descr=valuedescr)
  984. i3 = int_add(i, i2)
  985. jump(i3)
  986. """
  987. self.optimize_loop(ops, expected)
  988. def test_nonvirtual_dont_write_null_fields_on_force(self):
  989. ops = """
  990. [i]
  991. p1 = new_with_vtable(ConstClass(node_vtable))
  992. setfield_gc(p1, i, descr=valuedescr)
  993. i1 = getfield_gc(p1, descr=valuedescr)
  994. setfield_gc(p1, 0, descr=valuedescr)
  995. escape(p1)
  996. i2 = getfield_gc(p1, descr=valuedescr)
  997. jump(i2)
  998. """
  999. expected = """
  1000. [i]
  1001. p1 = new_with_vtable(ConstClass(node_vtable))
  1002. escape(p1)
  1003. i2 = getfield_gc(p1, descr=valuedescr)
  1004. jump(i2)
  1005. """
  1006. self.optimize_loop(ops, expected)
  1007. def test_getfield_gc_pure_1(self):
  1008. ops = """
  1009. [i]
  1010. p1 = new_with_vtable(ConstClass(node_vtable))
  1011. setfield_gc(p1, i, descr=valuedescr)
  1012. i1 = getfield_gc_pure(p1, descr=valuedescr)
  1013. jump(i1)
  1014. """
  1015. expected = """
  1016. [i]
  1017. jump(i)
  1018. """
  1019. self.optimize_loop(ops, expected)
  1020. def test_getfield_gc_pure_2(self):
  1021. ops = """
  1022. [i]
  1023. i1 = getfield_gc_pure(ConstPtr(myptr), descr=valuedescr)
  1024. jump(i1)
  1025. """
  1026. expected = """
  1027. [i]
  1028. jump(5)
  1029. """
  1030. self.node.value = 5
  1031. self.optimize_loop(ops, expected)
  1032. def test_getfield_gc_nonpure_2(self):
  1033. ops = """
  1034. [i]
  1035. i1 = getfield_gc(ConstPtr(myptr), descr=valuedescr)
  1036. jump(i1)
  1037. """
  1038. expected = ops
  1039. self.optimize_loop(ops, expected)
  1040. def test_varray_1(self):
  1041. ops = """
  1042. [i1]
  1043. p1 = new_array(3, descr=arraydescr)
  1044. i3 = arraylen_gc(p1, descr=arraydescr)
  1045. guard_value(i3, 3) []
  1046. setarrayitem_gc(p1, 1, i1, descr=arraydescr)
  1047. setarrayitem_gc(p1, 0, 25, descr=arraydescr)
  1048. i2 = getarrayitem_gc(p1, 1, descr=arraydescr)
  1049. jump(i2)
  1050. """
  1051. expected = """
  1052. [i1]
  1053. jump(i1)
  1054. """
  1055. self.optimize_loop(ops, expected)
  1056. def test_varray_alloc_and_set(self):
  1057. ops = """
  1058. [i1]
  1059. p1 = new_array(2, descr=arraydescr)
  1060. setarrayitem_gc(p1, 0, 25, descr=arraydescr)
  1061. i2 = getarrayitem_gc(p1, 1, descr=arraydescr)
  1062. jump(i2)
  1063. """
  1064. expected = """
  1065. [i1]
  1066. jump(0)
  1067. """
  1068. self.optimize_loop(ops, expected)
  1069. def test_varray_float(self):
  1070. ops = """
  1071. [f1]
  1072. p1 = new_array(3, descr=floatarraydescr)
  1073. i3 = arraylen_gc(p1, descr=floatarraydescr)
  1074. guard_value(i3, 3) []
  1075. setarrayitem_gc(p1, 1, f1, descr=floatarraydescr)
  1076. setarrayitem_gc(p1, 0, 3.5, descr=floatarraydescr)
  1077. f2 = getarrayitem_gc(p1, 1, descr=floatarraydescr)
  1078. jump(f2)
  1079. """
  1080. expected = """
  1081. [f1]
  1082. jump(f1)
  1083. """
  1084. self.optimize_loop(ops, expected)
  1085. def test_array_non_optimized(self):
  1086. ops = """
  1087. [i1, p0]
  1088. setarrayitem_gc(p0, 0, i1, descr=arraydescr)
  1089. guard_nonnull(p0) []
  1090. p1 = new_array(i1, descr=arraydescr)
  1091. jump(i1, p1)
  1092. """
  1093. expected = """
  1094. [i1, p0]
  1095. p1 = new_array(i1, descr=arraydescr)
  1096. setarrayitem_gc(p0, 0, i1, descr=arraydescr)
  1097. jump(i1, p1)
  1098. """
  1099. self.optimize_loop(ops, expected)
  1100. def test_nonvirtual_array_dont_write_null_fields_on_force(self):
  1101. ops = """
  1102. [i1]
  1103. p1 = new_array(5, descr=arraydescr)
  1104. setarrayitem_gc(p1, 0, i1, descr=arraydescr)
  1105. setarrayitem_gc(p1, 1, 0, descr=arraydescr)
  1106. escape(p1)
  1107. jump(i1)
  1108. """
  1109. expected = """
  1110. [i1]
  1111. p1 = new_array(5, descr=arraydescr)
  1112. setarrayitem_gc(p1, 0, i1, descr=arraydescr)
  1113. escape(p1)
  1114. jump(i1)
  1115. """
  1116. self.optimize_loop(ops, expected)
  1117. def test_varray_2(self):
  1118. ops = """
  1119. [i0, p1]
  1120. i1 = getarrayitem_gc(p1, 0, descr=arraydescr)
  1121. i2 = getarrayitem_gc(p1, 1, descr=arraydescr)
  1122. i3 = int_sub(i1, i2)
  1123. guard_value(i3, 15) []
  1124. p2 = new_array(2, descr=arraydescr)
  1125. setarrayitem_gc(p2, 1, i0, descr=arraydescr)
  1126. setarrayitem_gc(p2, 0, 20, descr=arraydescr)
  1127. jump(i0, p2)
  1128. """
  1129. expected = """
  1130. [i0, i1, i2]
  1131. i3 = int_sub(i1, i2)
  1132. guard_value(i3, 15) []
  1133. jump(i0, 20, i0)
  1134. """
  1135. py.test.skip("XXX")
  1136. self.optimize_loop(ops, 'Not, VArray(arraydescr, Not, Not)', expected)
  1137. def test_p123_array(self):
  1138. ops = """
  1139. [i1, p2, p3]
  1140. i3 = getarrayitem_gc(p3, 0, descr=arraydescr)
  1141. escape(i3)
  1142. p1 = new_array(1, descr=arraydescr)
  1143. setarrayitem_gc(p1, 0, i1, descr=arraydescr)
  1144. jump(i1, p1, p2)
  1145. """
  1146. # We cannot track virtuals that survive for more than two iterations.
  1147. self.optimize_loop(ops, ops)
  1148. def test_varray_forced_1(self):
  1149. ops = """
  1150. []
  1151. p2 = new_with_vtable(ConstClass(node_vtable))
  1152. setfield_gc(p2, 3, descr=valuedescr)
  1153. i1 = getfield_gc(p2, descr=valuedescr) # i1 = const 3
  1154. p1 = new_array(i1, descr=arraydescr)
  1155. escape(p1)
  1156. i2 = arraylen_gc(p1)
  1157. escape(i2)
  1158. jump()
  1159. """
  1160. expected = """
  1161. []
  1162. p1 = new_array(3, descr=arraydescr)
  1163. escape(p1)
  1164. i2 = arraylen_gc(p1)
  1165. escape(i2)
  1166. jump()
  1167. """
  1168. self.optimize_loop(ops, expected)
  1169. def test_vstruct_1(self):
  1170. ops = """
  1171. [i1, p2]
  1172. i2 = getfield_gc(p2, descr=adescr)
  1173. escape(i2)
  1174. p3 = new(descr=ssize)
  1175. setfield_gc(p3, i1, descr=adescr)
  1176. jump(i1, p3)
  1177. """
  1178. expected = """
  1179. [i1, i2]
  1180. escape(i2)
  1181. jump(i1, i1)
  1182. """
  1183. py.test.skip("XXX")
  1184. self.optimize_loop(ops, 'Not, VStruct(ssize, adescr=Not)', expected)
  1185. def test_p123_vstruct(self):
  1186. ops = """
  1187. [i1, p2, p3]
  1188. i3 = getfield_gc(p3, descr=adescr)
  1189. escape(i3)
  1190. p1 = new(descr=ssize)
  1191. setfield_gc(p1, i1, descr=adescr)
  1192. jump(i1, p1, p2)
  1193. """
  1194. # We cannot track virtuals that survive for more than two iterations.
  1195. self.optimize_loop(ops, ops)
  1196. def test_duplicate_getfield_1(self):
  1197. ops = """
  1198. [p1, p2]
  1199. i1 = getfield_gc(p1, descr=valuedescr)
  1200. i2 = getfield_gc(p2, descr=valuedescr)
  1201. i3 = getfield_gc(p1, descr=valuedescr)
  1202. i4 = getfield_gc(p2, descr=valuedescr)
  1203. escape(i1)
  1204. escape(i2)
  1205. escape(i3)
  1206. escape(i4)
  1207. jump(p1, p2)
  1208. """
  1209. expected = """
  1210. [p1, p2]
  1211. i1 = getfield_gc(p1, descr=valuedescr)
  1212. i2 = getfield_gc(p2, descr=valuedescr)
  1213. escape(i1)
  1214. escape(i2)
  1215. escape(i1)
  1216. escape(i2)
  1217. jump(p1, p2)
  1218. """
  1219. self.optimize_loop(ops, expected)
  1220. def test_getfield_after_setfield(self):
  1221. ops = """
  1222. [p1, i1]
  1223. setfield_gc(p1, i1, descr=valuedescr)
  1224. i2 = getfield_gc(p1, descr=valuedescr)
  1225. escape(i2)
  1226. jump(p1, i1)
  1227. """
  1228. expected = """
  1229. [p1, i1]
  1230. setfield_gc(p1, i1, descr=valuedescr)
  1231. escape(i1)
  1232. jump(p1, i1)
  1233. """
  1234. self.optimize_loop(ops, expected)
  1235. def test_setfield_of_different_type_does_not_clear(self):
  1236. ops = """
  1237. [p1, p2, i1]
  1238. setfield_gc(p1, i1, descr=valuedescr)
  1239. setfield_gc(p2, p1, descr=nextdescr)
  1240. i2 = getfield_gc(p1, descr=valuedescr)
  1241. escape(i2)
  1242. jump(p1, p2, i1)
  1243. """
  1244. expected = """
  1245. [p1, p2, i1]
  1246. setfield_gc(p1, i1, descr=valuedescr)
  1247. setfield_gc(p2, p1, descr=nextdescr)
  1248. escape(i1)
  1249. jump(p1, p2, i1)
  1250. """
  1251. self.optimize_loop(ops, expected)
  1252. def test_setfield_of_same_type_clears(self):
  1253. ops = """
  1254. [p1, p2, i1, i2]
  1255. setfield_gc(p1, i1, descr=valuedescr)
  1256. setfield_gc(p2, i2, descr=valuedescr)
  1257. i3 = getfield_gc(p1, descr=valuedescr)
  1258. escape(i3)
  1259. jump(p1, p2, i1, i3)
  1260. """
  1261. self.optimize_loop(ops, ops)
  1262. def test_duplicate_getfield_mergepoint_has_no_side_effects(self):
  1263. ops = """
  1264. [p1]
  1265. i1 = getfield_gc(p1, descr=valuedescr)
  1266. debug_merge_point(15, 0)
  1267. i2 = getfield_gc(p1, descr=valuedescr)
  1268. escape(i1)
  1269. escape(i2)
  1270. jump(p1)
  1271. """
  1272. expected = """
  1273. [p1]
  1274. i1 = getfield_gc(p1, descr=valuedescr)
  1275. debug_merge_point(15, 0)
  1276. escape(i1)
  1277. escape(i1)
  1278. jump(p1)
  1279. """
  1280. self.optimize_loop(ops, expected)
  1281. def test_duplicate_getfield_ovf_op_does_not_clear(self):
  1282. ops = """
  1283. [p1]
  1284. i1 = getfield_gc(p1, descr=valuedescr)
  1285. i2 = int_add_ovf(i1, 14)
  1286. guard_no_overflow() []
  1287. i3 = getfield_gc(p1, descr=valuedescr)
  1288. escape(i2)
  1289. escape(i3)
  1290. jump(p1)
  1291. """
  1292. expected = """
  1293. [p1]
  1294. i1 = getfield_gc(p1, descr=valuedescr)
  1295. i2 = int_add_ovf(i1, 14)
  1296. guard_no_overflow() []
  1297. escape(i2)
  1298. escape(i1)
  1299. jump(p1)
  1300. """
  1301. self.optimize_loop(ops, expected)
  1302. def test_duplicate_getfield_setarrayitem_does_not_clear(self):
  1303. ops = """
  1304. [p1, p2]
  1305. i1 = getfield_gc(p1, descr=valuedescr)
  1306. setarrayitem_gc(p2, 0, p1, descr=arraydescr2)
  1307. i3 = getfield_gc(p1, descr=valuedescr)
  1308. escape(i1)
  1309. escape(i3)
  1310. jump(p1, p2)
  1311. """
  1312. expected = """
  1313. [p1, p2]
  1314. i1 = getfield_gc(p1, descr=valuedescr)
  1315. setarrayitem_gc(p2, 0, p1, descr=arraydescr2)
  1316. escape(i1)
  1317. escape(i1)
  1318. jump(p1, p2)
  1319. """
  1320. self.optimize_loop(ops, expected)
  1321. def test_duplicate_getfield_constant(self):
  1322. ops = """
  1323. []
  1324. i1 = getfield_gc(ConstPtr(myptr), descr=valuedescr)
  1325. i2 = getfield_gc(ConstPtr(myptr), descr=valuedescr)
  1326. escape(i1)
  1327. escape(i2)
  1328. jump()
  1329. """
  1330. expected = """
  1331. []
  1332. i1 = getfield_gc(ConstPtr(myptr), descr=valuedescr)
  1333. escape(i1)
  1334. escape(i1)
  1335. jump()
  1336. """
  1337. self.optimize_loop(ops, expected)
  1338. def test_duplicate_getfield_guard_value_const(self):
  1339. ops = """
  1340. [p1]
  1341. guard_value(p1, ConstPtr(myptr)) []
  1342. i1 = getfield_gc(p1, descr=valuedescr)
  1343. i2 = getfield_gc(ConstPtr(myptr), descr=valuedescr)
  1344. escape(i1)
  1345. escape(i2)
  1346. jump(p1)
  1347. """
  1348. expected = """
  1349. []
  1350. i1 = getfield_gc(ConstPtr(myptr), descr=valuedescr)
  1351. escape(i1)
  1352. escape(i1)
  1353. jump()
  1354. """
  1355. py.test.skip("XXX")
  1356. self.optimize_loop(ops, 'Constant(myptr)', expected)
  1357. def test_duplicate_getfield_sideeffects_1(self):
  1358. ops = """
  1359. [p1]
  1360. i1 = getfield_gc(p1, descr=valuedescr)
  1361. escape()
  1362. i2 = getfield_gc(p1, descr=valuedescr)
  1363. escape(i1)
  1364. escape(i2)
  1365. jump(p1)
  1366. """
  1367. self.optimize_loop(ops, ops)
  1368. def test_duplicate_getfield_sideeffects_2(self):
  1369. ops = """
  1370. [p1, i1]
  1371. setfield_gc(p1, i1, descr=valuedescr)
  1372. escape()
  1373. i2 = getfield_gc(p1, descr=valuedescr)
  1374. escape(i2)
  1375. jump(p1, i1)
  1376. """
  1377. self.optimize_loop(ops, ops)
  1378. def test_duplicate_setfield_1(self):
  1379. ops = """
  1380. [p1, i1, i2]
  1381. setfield_gc(p1, i1, descr=valuedescr)
  1382. setfield_gc(p1, i2, descr=valuedescr)
  1383. jump(p1, i1, i2)
  1384. """
  1385. expected = """
  1386. [p1, i1, i2]
  1387. setfield_gc(p1, i2, descr=valuedescr)
  1388. jump(p1, i1, i2)
  1389. """
  1390. self.optimize_loop(ops, expected)
  1391. def test_duplicate_setfield_2(self):
  1392. ops = """
  1393. [p1, i1, i3]
  1394. setfield_gc(p1, i1, descr=valuedescr)
  1395. i2 = getfield_gc(p1, descr=valuedescr)
  1396. setfield_gc(p1, i3, descr=valuedescr)
  1397. escape(i2)
  1398. jump(p1, i1, i3)
  1399. """
  1400. expected = """
  1401. [p1, i1, i3]
  1402. setfield_gc(p1, i3, descr=valuedescr)
  1403. escape(i1)
  1404. jump(p1, i1, i3)
  1405. """
  1406. self.optimize_loop(ops, expected)
  1407. def test_duplicate_setfield_3(self):
  1408. ops = """
  1409. [p1, p2, i1, i3]
  1410. setfield_gc(p1, i1, descr=valuedescr)
  1411. i2 = getfield_gc(p2, descr=valuedescr)
  1412. setfield_gc(p1, i3, descr=valuedescr)
  1413. escape(i2)
  1414. jump(p1, p2, i1, i3)
  1415. """
  1416. # potential aliasing of p1 and p2 means that we cannot kill the
  1417. # the setfield_gc
  1418. self.optimize_loop(ops, ops)
  1419. def test_duplicate_setfield_4(self):
  1420. ops = """
  1421. [p1, i1, i2, p3]
  1422. setfield_gc(p1, i1, descr=valuedescr)
  1423. #
  1424. # some operations on which the above setfield_gc cannot have effect
  1425. i3 = getarrayitem_gc_pure(p3, 1, descr=arraydescr)
  1426. i4 = getarrayitem_gc(p3, i3, descr=arraydescr)
  1427. i5 = int_add(i3, i4)
  1428. setarrayitem_gc(p3, 0, i5, descr=arraydescr)
  1429. setfield_gc(p1, i4, descr=nextdescr)
  1430. #
  1431. setfield_gc(p1, i2, descr=valuedescr)
  1432. jump(p1, i1, i2, p3)
  1433. """
  1434. expected = """
  1435. [p1, i1, i2, p3]
  1436. #
  1437. i3 = getarrayitem_gc_pure(p3, 1, descr=arraydescr)
  1438. i4 = getarrayitem_gc(p3, i3, descr=arraydescr)
  1439. i5 = int_add(i3, i4)
  1440. #
  1441. setfield_gc(p1, i2, descr=valuedescr)
  1442. setarrayitem_gc(p3, 0, i5, descr=arraydescr)
  1443. setfield_gc(p1, i4, descr=nextdescr)
  1444. jump(p1, i1, i2, p3)
  1445. """
  1446. self.optimize_loop(ops, expected)
  1447. def test_duplicate_setfield_5(self):
  1448. ops = """
  1449. [p0, i1]
  1450. p1 = new_with_vtable(ConstClass(node_vtable))
  1451. setfield_gc(p1, i1, descr=valuedescr)
  1452. setfield_gc(p0, p1, descr=nextdescr)
  1453. setfield_raw(i1, i1, descr=valuedescr) # random op with side-effects
  1454. p2 = getfield_gc(p0, descr=nextdescr)
  1455. i2 = getfield_gc(p2, descr=valuedescr)
  1456. setfield_gc(p0, NULL, descr=nextdescr)
  1457. escape(i2)
  1458. jump(p0, i1)
  1459. """
  1460. expected = """
  1461. [p0, i1]
  1462. setfield_raw(i1, i1, descr=valuedescr)
  1463. setfield_gc(p0, NULL, descr=nextdescr)
  1464. escape(i1)
  1465. jump(p0, i1)
  1466. """
  1467. self.optimize_loop(ops, expected)
  1468. def test_duplicate_setfield_sideeffects_1(self):
  1469. ops = """
  1470. [p1, i1, i2]
  1471. setfield_gc(p1, i1, descr=valuedescr)
  1472. escape()
  1473. setfield_gc(p1, i2, descr=valuedescr)
  1474. jump(p1, i1, i2)
  1475. """
  1476. self.optimize_loop(ops, ops)
  1477. def test_duplicate_setfield_residual_guard_1(self):
  1478. ops = """
  1479. [p1, i1, i2, i3]
  1480. setfield_gc(p1, i1, descr=valuedescr)
  1481. guard_true(i3) []
  1482. i4 = int_neg(i2)
  1483. setfield_gc(p1, i2, descr=valuedescr)
  1484. jump(p1, i1, i2, i4)
  1485. """
  1486. self.optimize_loop(ops, ops)
  1487. def test_duplicate_setfield_residual_guard_2(self):
  1488. # the difference with the previous test is that the field value is
  1489. # a virtual, which we try hard to keep virtual
  1490. ops = """
  1491. [p1, i2, i3]
  1492. p2 = new_with_vtable(ConstClass(node_vtable))
  1493. setfield_gc(p1, p2, descr=nextdescr)
  1494. guard_true(i3) []
  1495. i4 = int_neg(i2)
  1496. setfield_gc(p1, NULL, descr=nextdescr)
  1497. jump(p1, i2, i4)
  1498. """
  1499. expected = """
  1500. [p1, i2, i3]
  1501. guard_true(i3) [p1]
  1502. i4 = int_neg(i2)
  1503. setfield_gc(p1, NULL, descr=nextdescr)
  1504. jump(p1, i2, i4)
  1505. """
  1506. self.optimize_loop(ops, expected)
  1507. def test_duplicate_setfield_residual_guard_3(self):
  1508. ops = """
  1509. [p1, i2, i3]
  1510. p2 = new_with_vtable(ConstClass(node_vtable))
  1511. setfield_gc(p2, i2, descr=valuedescr)
  1512. setfield_gc(p1, p2, descr=nextdescr)
  1513. guard_true(i3) []
  1514. i4 = int_neg(i2)
  1515. setfield_gc(p1, NULL, descr=nextdescr)
  1516. jump(p1, i2, i4)
  1517. """
  1518. expected = """
  1519. [p1, i2, i3]
  1520. guard_true(i3) [i2, p1]
  1521. i4 = int_neg(i2)
  1522. setfield_gc(p1, NULL, descr=nextdescr)
  1523. jump(p1, i2, i4)
  1524. """
  1525. self.optimize_loop(ops, expected)
  1526. def test_duplicate_setfield_residual_guard_4(self):
  1527. # test that the setfield_gc does not end up between int_eq and
  1528. # the following guard_true
  1529. ops = """
  1530. [p1, i1, i2, i3]
  1531. setfield_gc(p1, i1, descr=valuedescr)
  1532. i5 = int_eq(i3, 5)
  1533. guard_true(i5) []
  1534. i4 = int_neg(i2)
  1535. setfield_gc(p1, i2, descr=valuedescr)
  1536. jump(p1, i1, i2, i4)
  1537. """
  1538. self.optimize_loop(ops, ops)
  1539. def test_duplicate_setfield_aliasing(self):
  1540. # a case where aliasing issues (and not enough cleverness) mean
  1541. # that we fail to remove any setfield_gc
  1542. ops = """
  1543. [p1, p2, i1, i2, i3]
  1544. setfield_gc(p1, i1, descr=valuedescr)
  1545. setfield_gc(p2, i2, descr=valuedescr)
  1546. setfield_gc(p1, i3, descr=valuedescr)
  1547. jump(p1, p2, i1, i2, i3)
  1548. """
  1549. self.optimize_loop(ops, ops)
  1550. def test_duplicate_setfield_guard_value_const(self):
  1551. ops = """
  1552. [p1, i1, i2]
  1553. guard_value(p1, ConstPtr(myptr)) []
  1554. setfield_gc(p1, i1, descr=valuedescr)
  1555. setfield_gc(ConstPtr(myptr), i2, descr=valuedescr)
  1556. jump(p1, i1, i2)
  1557. """
  1558. expected = """
  1559. [i1, i2]
  1560. setfield_gc(ConstPtr(myptr), i2, descr=valuedescr)
  1561. jump(i1, i2)
  1562. """
  1563. py.test.skip("XXX")
  1564. self.optimize_loop(ops, 'Constant(myptr), Not, Not', expected)
  1565. def test_duplicate_getarrayitem_1(self):
  1566. ops = """
  1567. [p1]
  1568. p2 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1569. p3 = getarrayitem_gc(p1, 1, descr=arraydescr2)
  1570. p4 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1571. p5 = getarrayitem_gc(p1, 1, descr=arraydescr2)
  1572. escape(p2)
  1573. escape(p3)
  1574. escape(p4)
  1575. escape(p5)
  1576. jump(p1)
  1577. """
  1578. expected = """
  1579. [p1]
  1580. p2 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1581. p3 = getarrayitem_gc(p1, 1, descr=arraydescr2)
  1582. escape(p2)
  1583. escape(p3)
  1584. escape(p2)
  1585. escape(p3)
  1586. jump(p1)
  1587. """
  1588. self.optimize_loop(ops, expected)
  1589. def test_duplicate_getarrayitem_after_setarrayitem_1(self):
  1590. ops = """
  1591. [p1, p2]
  1592. setarrayitem_gc(p1, 0, p2, descr=arraydescr2)
  1593. p3 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1594. escape(p3)
  1595. jump(p1, p3)
  1596. """
  1597. expected = """
  1598. [p1, p2]
  1599. setarrayitem_gc(p1, 0, p2, descr=arraydescr2)
  1600. escape(p2)
  1601. jump(p1, p2)
  1602. """
  1603. self.optimize_loop(ops, expected)
  1604. def test_duplicate_getarrayitem_after_setarrayitem_2(self):
  1605. py.test.skip("setarrayitem with variable index")
  1606. ops = """
  1607. [p1, p2, p3, i1]
  1608. setarrayitem_gc(p1, 0, p2, descr=arraydescr2)
  1609. setarrayitem_gc(p1, i1, p3, descr=arraydescr2)
  1610. p4 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1611. p5 = getarrayitem_gc(p1, i1, descr=arraydescr2)
  1612. escape(p4)
  1613. escape(p5)
  1614. jump(p1, p2, p3, i1)
  1615. """
  1616. expected = """
  1617. [p1, p2, p3, i1]
  1618. setarrayitem_gc(p1, 0, p2, descr=arraydescr2)
  1619. setarrayitem_gc(p1, i1, p3, descr=arraydescr2)
  1620. p4 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1621. escape(p4)
  1622. escape(p3)
  1623. jump(p1, p2, p3, i1)
  1624. """
  1625. self.optimize_loop(ops, expected)
  1626. def test_duplicate_getarrayitem_after_setarrayitem_3(self):
  1627. ops = """
  1628. [p1, p2, p3, p4, i1]
  1629. setarrayitem_gc(p1, i1, p2, descr=arraydescr2)
  1630. setarrayitem_gc(p1, 0, p3, descr=arraydescr2)
  1631. setarrayitem_gc(p1, 1, p4, descr=arraydescr2)
  1632. p5 = getarrayitem_gc(p1, i1, descr=arraydescr2)
  1633. p6 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1634. p7 = getarrayitem_gc(p1, 1, descr=arraydescr2)
  1635. escape(p5)
  1636. escape(p6)
  1637. escape(p7)
  1638. jump(p1, p2, p3, p4, i1)
  1639. """
  1640. expected = """
  1641. [p1, p2, p3, p4, i1]
  1642. setarrayitem_gc(p1, i1, p2, descr=arraydescr2)
  1643. setarrayitem_gc(p1, 0, p3, descr=arraydescr2)
  1644. setarrayitem_gc(p1, 1, p4, descr=arraydescr2)
  1645. p5 = getarrayitem_gc(p1, i1, descr=arraydescr2)
  1646. escape(p5)
  1647. escape(p3)
  1648. escape(p4)
  1649. jump(p1, p2, p3, p4, i1)
  1650. """
  1651. self.optimize_loop(ops, expected)
  1652. def test_getarrayitem_pure_does_not_invalidate(self):
  1653. ops = """
  1654. [p1, p2]
  1655. p3 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1656. i4 = getfield_gc_pure(ConstPtr(myptr), descr=valuedescr)
  1657. p5 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1658. escape(p3)
  1659. escape(i4)
  1660. escape(p5)
  1661. jump(p1, p2)
  1662. """
  1663. expected = """
  1664. [p1, p2]
  1665. p3 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1666. escape(p3)
  1667. escape(5)
  1668. escape(p3)
  1669. jump(p1, p2)
  1670. """
  1671. self.optimize_loop(ops, expected)
  1672. def test_duplicate_getarrayitem_after_setarrayitem_two_arrays(self):
  1673. ops = """
  1674. [p1, p2, p3, p4, i1]
  1675. setarrayitem_gc(p1, 0, p3, descr=arraydescr2)
  1676. setarrayitem_gc(p2, 1, p4, descr=arraydescr2)
  1677. p5 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1678. p6 = getarrayitem_gc(p2, 1, descr=arraydescr2)
  1679. escape(p5)
  1680. escape(p6)
  1681. jump(p1, p2, p3, p4, i1)
  1682. """
  1683. expected = """
  1684. [p1, p2, p3, p4, i1]
  1685. setarrayitem_gc(p1, 0, p3, descr=arraydescr2)
  1686. setarrayitem_gc(p2, 1, p4, descr=arraydescr2)
  1687. escape(p3)
  1688. escape(p4)
  1689. jump(p1, p2, p3, p4, i1)
  1690. """
  1691. self.optimize_loop(ops, expected)
  1692. def test_duplicate_getarrayitem_after_setarrayitem_bug(self):
  1693. ops = """
  1694. [p0, i0, i1]
  1695. setarrayitem_gc(p0, 0, i0, descr=arraydescr)
  1696. i6 = int_add(i0, 1)
  1697. setarrayitem_gc(p0, i1, i6, descr=arraydescr)
  1698. i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
  1699. i11 = int_add(i10, i0)
  1700. jump(p0, i11, i1)
  1701. """
  1702. expected = """
  1703. [p0, i0, i1]
  1704. i6 = int_add(i0, 1)
  1705. setarrayitem_gc(p0, 0, i0, descr=arraydescr)
  1706. setarrayitem_gc(p0, i1, i6, descr=arraydescr)
  1707. i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
  1708. i11 = int_add(i10, i0)
  1709. jump(p0, i11, i1)
  1710. """
  1711. self.optimize_loop(ops, expected)
  1712. def test_duplicate_getarrayitem_after_setarrayitem_bug2(self):
  1713. ops = """
  1714. [p0, i0, i1]
  1715. i2 = getarrayitem_gc(p0, 0, descr=arraydescr)
  1716. i6 = int_add(i0, 1)
  1717. setarrayitem_gc(p0, i1, i6, descr=arraydescr)
  1718. i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
  1719. i11 = int_add(i10, i2)
  1720. jump(p0, i11, i1)
  1721. """
  1722. expected = """
  1723. [p0, i0, i1]
  1724. i2 = getarrayitem_gc(p0, 0, descr=arraydescr)
  1725. i6 = int_add(i0, 1)
  1726. setarrayitem_gc(p0, i1, i6, descr=arraydescr)
  1727. i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
  1728. i11 = int_add(i10, i2)
  1729. jump(p0, i11, i1)
  1730. """
  1731. self.optimize_loop(ops, expected)
  1732. def test_bug_1(self):
  1733. ops = """
  1734. [i0, p1]
  1735. p4 = getfield_gc(p1, descr=nextdescr)
  1736. guard_nonnull(p4) []
  1737. escape(p4)
  1738. #
  1739. p2 = new_with_vtable(ConstClass(node_vtable))
  1740. p3 = escape()
  1741. setfield_gc(p2, p3, descr=nextdescr)
  1742. jump(i0, p2)
  1743. """
  1744. expected = """
  1745. [i0, p4]
  1746. guard_nonnull(p4) []
  1747. escape(p4)
  1748. #
  1749. p3 = escape()
  1750. jump(i0, p3)
  1751. """
  1752. py.test.skip("XXX")
  1753. self.optimize_loop(ops, 'Not, Virtual(node_vtable, nextdescr=Not)',
  1754. expected)
  1755. def test_bug_2(self):
  1756. ops = """
  1757. [i0, p1]
  1758. p4 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  1759. guard_nonnull(p4) []
  1760. escape(p4)
  1761. #
  1762. p2 = new_array(1, descr=arraydescr2)
  1763. p3 = escape()
  1764. setarrayitem_gc(p2, 0, p3, descr=arraydescr2)
  1765. jump(i0, p2)
  1766. """
  1767. expected = """
  1768. [i0, p4]
  1769. guard_nonnull(p4) []
  1770. escape(p4)
  1771. #
  1772. p3 = escape()
  1773. jump(i0, p3)
  1774. """
  1775. py.test.skip("XXX")
  1776. self.optimize_loop(ops, 'Not, VArray(arraydescr2, Not)',
  1777. expected)
  1778. def test_bug_3(self):
  1779. ops = """
  1780. [p1]
  1781. guard_nonnull(p1) []
  1782. guard_class(p1, ConstClass(node_vtable2)) []
  1783. p2 = getfield_gc(p1, descr=nextdescr)
  1784. guard_nonnull(12) []
  1785. guard_class(p2, ConstClass(node_vtable)) []
  1786. p3 = getfield_gc(p1, descr=otherdescr)
  1787. guard_nonnull(12) []
  1788. guard_class(p3, ConstClass(node_vtable)) []
  1789. setfield_gc(p3, p2, descr=otherdescr)
  1790. p1a = new_with_vtable(ConstClass(node_vtable2))
  1791. p2a = new_with_vtable(ConstClass(node_vtable))
  1792. p3a = new_with_vtable(ConstClass(node_vtable))
  1793. escape(p3a)
  1794. setfield_gc(p1a, p2a, descr=nextdescr)
  1795. setfield_gc(p1a, p3a, descr=otherdescr)
  1796. jump(p1a)
  1797. """
  1798. expected = """
  1799. [p2, p3]
  1800. guard_class(p2, ConstClass(node_vtable)) []
  1801. guard_class(p3, ConstClass(node_vtable)) []
  1802. setfield_gc(p3, p2, descr=otherdescr)
  1803. p3a = new_with_vtable(ConstClass(node_vtable))
  1804. escape(p3a)
  1805. p2a = new_with_vtable(ConstClass(node_vtable))
  1806. jump(p2a, p3a)
  1807. """
  1808. py.test.skip("XXX")
  1809. self.optimize_loop(ops, 'Virtual(node_vtable2, nextdescr=Not, otherdescr=Not)', expected)
  1810. def test_bug_3bis(self):
  1811. ops = """
  1812. [p1]
  1813. guard_nonnull(p1) []
  1814. guard_class(p1, ConstClass(node_vtable2)) []
  1815. p2 = getfield_gc(p1, descr=nextdescr)
  1816. guard_nonnull(12) []
  1817. guard_class(p2, ConstClass(node_vtable)) []
  1818. p3 = getfield_gc(p1, descr=otherdescr)
  1819. guard_nonnull(12) []
  1820. guard_class(p3, ConstClass(node_vtable)) []
  1821. p1a = new_with_vtable(ConstClass(node_vtable2))
  1822. p2a = new_with_vtable(ConstClass(node_vtable))
  1823. setfield_gc(p3, p2a, descr=otherdescr)
  1824. p3a = new_with_vtable(ConstClass(node_vtable))
  1825. escape(p3a)
  1826. setfield_gc(p1a, p2a, descr=nextdescr)
  1827. setfield_gc(p1a, p3a, descr=otherdescr)
  1828. jump(p1a)
  1829. """
  1830. expected = """
  1831. [p2, p3]
  1832. guard_class(p2, ConstClass(node_vtable)) []
  1833. guard_class(p3, ConstClass(node_vtable)) []
  1834. p2a = new_with_vtable(ConstClass(node_vtable))
  1835. setfield_gc(p3, p2a, descr=otherdescr)
  1836. p3a = new_with_vtable(ConstClass(node_vtable))
  1837. escape(p3a)
  1838. jump(p2a, p3a)
  1839. """
  1840. py.test.skip("XXX")
  1841. self.optimize_loop(ops, 'Virtual(node_vtable2, nextdescr=Not, otherdescr=Not)', expected)
  1842. def test_invalid_loop_1(self):
  1843. ops = """
  1844. [p1]
  1845. guard_isnull(p1) []
  1846. #
  1847. p2 = new_with_vtable(ConstClass(node_vtable))
  1848. jump(p2)
  1849. """
  1850. py.test.skip("XXX")
  1851. py.test.raises(InvalidLoop, self.optimize_loop,
  1852. ops, 'Virtual(node_vtable)', None)
  1853. def test_invalid_loop_2(self):
  1854. py.test.skip("this would fail if we had Fixed again in the specnodes")
  1855. ops = """
  1856. [p1]
  1857. guard_class(p1, ConstClass(node_vtable2)) []
  1858. #
  1859. p2 = new_with_vtable(ConstClass(node_vtable))
  1860. escape(p2) # prevent it from staying Virtual
  1861. jump(p2)
  1862. """
  1863. py.test.raises(InvalidLoop, self.optimize_loop,
  1864. ops, '...', None)
  1865. def test_invalid_loop_3(self):
  1866. ops = """
  1867. [p1]
  1868. p2 = getfield_gc(p1, descr=nextdescr)
  1869. guard_isnull(p2) []
  1870. #
  1871. p3 = new_with_vtable(ConstClass(node_vtable))
  1872. p4 = new_with_vtable(ConstClass(node_vtable))
  1873. setfield_gc(p3, p4, descr=nextdescr)
  1874. jump(p3)
  1875. """
  1876. py.test.skip("XXX")
  1877. py.test.raises(InvalidLoop, self.optimize_loop, ops,
  1878. 'Virtual(node_vtable, nextdescr=Virtual(node_vtable))',
  1879. None)
  1880. def test_merge_guard_class_guard_value(self):
  1881. ops = """
  1882. [p1, i0, i1, i2, p2]
  1883. guard_class(p1, ConstClass(node_vtable)) [i0]
  1884. i3 = int_add(i1, i2)
  1885. guard_value(p1, ConstPtr(myptr)) [i1]
  1886. jump(p2, i0, i1, i3, p2)
  1887. """
  1888. expected = """
  1889. [p1, i0, i1, i2, p2]
  1890. guard_value(p1, ConstPtr(myptr)) [i0]
  1891. i3 = int_add(i1, i2)
  1892. jump(p2, i0, i1, i3, p2)
  1893. """
  1894. self.optimize_loop(ops, expected)
  1895. def test_merge_guard_nonnull_guard_class(self):
  1896. ops = """
  1897. [p1, i0, i1, i2, p2]
  1898. guard_nonnull(p1, descr=fdescr) [i0]
  1899. i3 = int_add(i1, i2)
  1900. guard_class(p1, ConstClass(node_vtable)) [i1]
  1901. jump(p2, i0, i1, i3, p2)
  1902. """
  1903. expected = """
  1904. [p1, i0, i1, i2, p2]
  1905. guard_nonnull_class(p1, ConstClass(node_vtable), descr=fdescr) [i0]
  1906. i3 = int_add(i1, i2)
  1907. jump(p2, i0, i1, i3, p2)
  1908. """
  1909. self.optimize_loop(ops, expected)
  1910. self.check_expanded_fail_descr("i0", rop.GUARD_NONNULL_CLASS)
  1911. def test_merge_guard_nonnull_guard_value(self):
  1912. ops = """
  1913. [p1, i0, i1, i2, p2]
  1914. guard_nonnull(p1, descr=fdescr) [i0]
  1915. i3 = int_add(i1, i2)
  1916. guard_value(p1, ConstPtr(myptr)) [i1]
  1917. jump(p2, i0, i1, i3, p2)
  1918. """
  1919. expected = """
  1920. [p1, i0, i1, i2, p2]
  1921. guard_value(p1, ConstPtr(myptr), descr=fdescr) [i0]
  1922. i3 = int_add(i1, i2)
  1923. jump(p2, i0, i1, i3, p2)
  1924. """
  1925. self.optimize_loop(ops, expected)
  1926. self.check_expanded_fail_descr("i0", rop.GUARD_VALUE)
  1927. def test_merge_guard_nonnull_guard_class_guard_value(self):
  1928. ops = """
  1929. [p1, i0, i1, i2, p2]
  1930. guard_nonnull(p1, descr=fdescr) [i0]
  1931. i3 = int_add(i1, i2)
  1932. guard_class(p1, ConstClass(node_vtable)) [i2]
  1933. i4 = int_sub(i3, 1)
  1934. guard_value(p1, ConstPtr(myptr)) [i1]
  1935. jump(p2, i0, i1, i4, p2)
  1936. """
  1937. expected = """
  1938. [p1, i0, i1, i2, p2]
  1939. guard_value(p1, ConstPtr(myptr), descr=fdescr) [i0]
  1940. i3 = int_add(i1, i2)
  1941. i4 = int_sub(i3, 1)
  1942. jump(p2, i0, i1, i4, p2)
  1943. """
  1944. self.optimize_loop(ops, expected)
  1945. self.check_expanded_fail_descr("i0", rop.GUARD_VALUE)
  1946. def test_guard_class_oois(self):
  1947. ops = """
  1948. [p1]
  1949. guard_class(p1, ConstClass(node_vtable2)) []
  1950. i = instance_ptr_ne(ConstPtr(myptr), p1)
  1951. guard_true(i) []
  1952. jump(p1)
  1953. """
  1954. expected = """
  1955. [p1]
  1956. guard_class(p1, ConstClass(node_vtable2)) []
  1957. jump(p1)
  1958. """
  1959. self.optimize_loop(ops, expected)
  1960. def test_oois_of_itself(self):
  1961. ops = """
  1962. [p0]
  1963. p1 = getfield_gc(p0, descr=nextdescr)
  1964. p2 = getfield_gc(p0, descr=nextdescr)
  1965. i1 = ptr_eq(p1, p2)
  1966. guard_true(i1) []
  1967. i2 = ptr_ne(p1, p2)
  1968. guard_false(i2) []
  1969. jump(p0)
  1970. """
  1971. expected = """
  1972. [p0]
  1973. p1 = getfield_gc(p0, descr=nextdescr)
  1974. jump(p0)
  1975. """
  1976. self.optimize_loop(ops, expected)
  1977. def test_remove_duplicate_pure_op(self):
  1978. ops = """
  1979. [p1, p2]
  1980. i1 = ptr_eq(p1, p2)
  1981. i2 = ptr_eq(p1, p2)
  1982. i3 = int_add(i1, 1)
  1983. i3b = int_is_true(i3)
  1984. guard_true(i3b) []
  1985. i4 = int_add(i2, 1)
  1986. i4b = int_is_true(i4)
  1987. guard_true(i4b) []
  1988. escape(i3)
  1989. escape(i4)
  1990. guard_true(i1) []
  1991. guard_true(i2) []
  1992. jump(p1, p2)
  1993. """
  1994. expected = """
  1995. [p1, p2]
  1996. i1 = ptr_eq(p1, p2)
  1997. i3 = int_add(i1, 1)
  1998. i3b = int_is_true(i3)
  1999. guard_true(i3b) []
  2000. escape(i3)
  2001. escape(i3)
  2002. guard_true(i1) []
  2003. jump(p1, p2)
  2004. """
  2005. self.optimize_loop(ops, expected)
  2006. def test_remove_duplicate_pure_op_with_descr(self):
  2007. ops = """
  2008. [p1]
  2009. i0 = arraylen_gc(p1, descr=arraydescr)
  2010. i1 = int_gt(i0, 0)
  2011. guard_true(i1) []
  2012. i2 = arraylen_gc(p1, descr=arraydescr)
  2013. i3 = int_gt(i0, 0)
  2014. guard_true(i3) []
  2015. jump(p1)
  2016. """
  2017. expected = """
  2018. [p1]
  2019. i0 = arraylen_gc(p1, descr=arraydescr)
  2020. i1 = int_gt(i0, 0)
  2021. guard_true(i1) []
  2022. jump(p1)
  2023. """
  2024. self.optimize_loop(ops, expected)
  2025. def test_remove_duplicate_pure_op_ovf(self):
  2026. ops = """
  2027. [i1]
  2028. i3 = int_add_ovf(i1, 1)
  2029. guard_no_overflow() []
  2030. i3b = int_is_true(i3)
  2031. guard_true(i3b) []
  2032. i4 = int_add_ovf(i1, 1)
  2033. guard_no_overflow() []
  2034. i4b = int_is_true(i4)
  2035. guard_true(i4b) []
  2036. escape(i3)
  2037. escape(i4)
  2038. jump(i1)
  2039. """
  2040. expected = """
  2041. [i1]
  2042. i3 = int_add_ovf(i1, 1)
  2043. guard_no_overflow() []
  2044. i3b = int_is_true(i3)
  2045. guard_true(i3b) []
  2046. escape(i3)
  2047. escape(i3)
  2048. jump(i1)
  2049. """
  2050. self.optimize_loop(ops, expected)
  2051. def test_int_and_or_with_zero(self):
  2052. ops = """
  2053. [i0, i1]
  2054. i2 = int_and(i0, 0)
  2055. i3 = int_and(0, i2)
  2056. i4 = int_or(i2, i1)
  2057. i5 = int_or(i0, i3)
  2058. jump(i4, i5)
  2059. """
  2060. expected = """
  2061. [i0, i1]
  2062. jump(i1, i0)
  2063. """
  2064. self.optimize_loop(ops, expected)
  2065. def test_fold_partially_constant_ops(self):
  2066. ops = """
  2067. [i0]
  2068. i1 = int_sub(i0, 0)
  2069. jump(i1)
  2070. """
  2071. expected = """
  2072. [i0]
  2073. jump(i0)
  2074. """
  2075. self.optimize_loop(ops, expected)
  2076. ops = """
  2077. [i0]
  2078. i1 = int_add(i0, 0)
  2079. jump(i1)
  2080. """
  2081. expected = """
  2082. [i0]
  2083. jump(i0)
  2084. """
  2085. self.optimize_loop(ops, expected)
  2086. ops = """
  2087. [i0]
  2088. i1 = int_add(0, i0)
  2089. jump(i1)
  2090. """
  2091. expected = """
  2092. [i0]
  2093. jump(i0)
  2094. """
  2095. self.optimize_loop(ops, expected)
  2096. ops = """
  2097. [i0]
  2098. i1 = int_floordiv(0, i0)
  2099. jump(i1)
  2100. """
  2101. expected = """
  2102. [i0]
  2103. jump(0)
  2104. """
  2105. self.optimize_loop(ops, expected)
  2106. def test_fold_partially_constant_ops_ovf(self):
  2107. ops = """
  2108. [i0]
  2109. i1 = int_sub_ovf(i0, 0)
  2110. guard_no_overflow() []
  2111. jump(i1)
  2112. """
  2113. expected = """
  2114. [i0]
  2115. jump(i0)
  2116. """
  2117. self.optimize_loop(ops, expected)
  2118. ops = """
  2119. [i0]
  2120. i1 = int_add_ovf(i0, 0)
  2121. guard_no_overflow() []
  2122. jump(i1)
  2123. """
  2124. expected = """
  2125. [i0]
  2126. jump(i0)
  2127. """
  2128. self.optimize_loop(ops, expected)
  2129. ops = """
  2130. [i0]
  2131. i1 = int_add_ovf(0, i0)
  2132. guard_no_overflow() []
  2133. jump(i1)
  2134. """
  2135. expected = """
  2136. [i0]
  2137. jump(i0)
  2138. """
  2139. self.optimize_loop(ops, expected)
  2140. def test_fold_constant_partial_ops_float(self):
  2141. ops = """
  2142. [f0]
  2143. f1 = float_mul(f0, 1.0)
  2144. f2 = escape(f1)
  2145. jump(f2)
  2146. """
  2147. expected = """
  2148. [f0]
  2149. f2 = escape(f0)
  2150. jump(f2)
  2151. """
  2152. self.optimize_loop(ops, expected)
  2153. ops = """
  2154. [f0]
  2155. f1 = float_mul(1.0, f0)
  2156. f2 = escape(f1)
  2157. jump(f2)
  2158. """
  2159. expected = """
  2160. [f0]
  2161. f2 = escape(f0)
  2162. jump(f2)
  2163. """
  2164. self.optimize_loop(ops, expected)
  2165. ops = """
  2166. [f0]
  2167. f1 = float_mul(f0, -1.0)
  2168. f2 = escape(f1)
  2169. jump(f2)
  2170. """
  2171. expected = """
  2172. [f0]
  2173. f1 = float_neg(f0)
  2174. f2 = escape(f1)
  2175. jump(f2)
  2176. """
  2177. self.optimize_loop(ops, expected)
  2178. ops = """
  2179. [f0]
  2180. f1 = float_mul(-1.0, f0)
  2181. f2 = escape(f1)
  2182. jump(f2)
  2183. """
  2184. expected = """
  2185. [f0]
  2186. f1 = float_neg(f0)
  2187. f2 = escape(f1)
  2188. jump(f2)
  2189. """
  2190. self.optimize_loop(ops, expected)
  2191. def test_fold_repeated_float_neg(self):
  2192. ops = """
  2193. [f0]
  2194. f1 = float_neg(f0)
  2195. f2 = float_neg(f1)
  2196. f3 = float_neg(f2)
  2197. f4 = float_neg(f3)
  2198. escape(f4)
  2199. jump(f4)
  2200. """
  2201. expected = """
  2202. [f0]
  2203. # The backend removes this dead op.
  2204. f1 = float_neg(f0)
  2205. escape(f0)
  2206. jump(f0)
  2207. """
  2208. self.optimize_loop(ops, expected)
  2209. # ----------
  2210. def _verify_fail_args(self, boxes, oparse, text):
  2211. import re
  2212. r = re.compile(r"\bwhere\s+(\w+)\s+is a\s+(\w+)")
  2213. parts = list(r.finditer(text))
  2214. ends = [match.start() for match in parts] + [len(text)]
  2215. #
  2216. virtuals = {}
  2217. for match, end in zip(parts, ends[1:]):
  2218. pvar = match.group(1)
  2219. fieldstext = text[match.end():end]
  2220. if match.group(2) == 'varray':
  2221. arrayname, fieldstext = fieldstext.split(':', 1)
  2222. tag = ('varray', self.namespace[arrayname.strip()])
  2223. elif match.group(2) == 'vstruct':
  2224. if ',' in fieldstext:
  2225. structname, fieldstext = fieldstext.split(',', 1)
  2226. else:
  2227. structname, fieldstext = fieldstext, ''
  2228. tag = ('vstruct', self.namespace[structname.strip()])
  2229. else:
  2230. tag = ('virtual', self.namespace[match.group(2)])
  2231. virtuals[pvar] = (tag, None, fieldstext)
  2232. #
  2233. r2 = re.compile(r"([\w\d()]+)[.](\w+)\s*=\s*([\w\d()]+)")
  2234. pendingfields = []
  2235. for match in r2.finditer(text):
  2236. pvar = match.group(1)
  2237. pfieldname = match.group(2)
  2238. pfieldvar = match.group(3)
  2239. pendingfields.append((pvar, pfieldname, pfieldvar))
  2240. #
  2241. def _variables_equal(box, varname, strict):
  2242. if varname not in virtuals:
  2243. if strict:
  2244. assert box.same_box(oparse.getvar(varname))
  2245. else:
  2246. assert box.value == oparse.getvar(varname).value
  2247. else:
  2248. tag, resolved, fieldstext = virtuals[varname]
  2249. if tag[0] == 'virtual':
  2250. assert self.get_class_of_box(box) == tag[1]
  2251. elif tag[0] == 'varray':
  2252. pass # xxx check arraydescr
  2253. elif tag[0] == 'vstruct':
  2254. pass # xxx check typedescr
  2255. else:
  2256. assert 0
  2257. if resolved is not None:
  2258. assert resolved.value == box.value
  2259. else:
  2260. virtuals[varname] = tag, box, fieldstext
  2261. #
  2262. basetext = text.splitlines()[0]
  2263. varnames = [s.strip() for s in basetext.split(',')]
  2264. if varnames == ['']:
  2265. varnames = []
  2266. assert len(boxes) == len(varnames)
  2267. for box, varname in zip(boxes, varnames):
  2268. _variables_equal(box, varname, strict=True)
  2269. for pvar, pfieldname, pfieldvar in pendingfields:
  2270. box = oparse.getvar(pvar)
  2271. fielddescr = self.namespace[pfieldname.strip()]
  2272. fieldbox = executor.execute(self.cpu, None,
  2273. rop.GETFIELD_GC,
  2274. fielddescr,
  2275. box)
  2276. _variables_equal(fieldbox, pfieldvar, strict=True)
  2277. #
  2278. for match in parts:
  2279. pvar = match.group(1)
  2280. tag, resolved, fieldstext = virtuals[pvar]
  2281. assert resolved is not None
  2282. index = 0
  2283. for fieldtext in fieldstext.split(','):
  2284. fieldtext = fieldtext.strip()
  2285. if not fieldtext:
  2286. continue
  2287. if tag[0] in ('virtual', 'vstruct'):
  2288. fieldname, fieldvalue = fieldtext.split('=')
  2289. fielddescr = self.namespace[fieldname.strip()]
  2290. fieldbox = executor.execute(self.cpu, None,
  2291. rop.GETFIELD_GC,
  2292. fielddescr,
  2293. resolved)
  2294. elif tag[0] == 'varray':
  2295. fieldvalue = fieldtext
  2296. fieldbox = executor.execute(self.cpu, None,
  2297. rop.GETARRAYITEM_GC,
  2298. tag[1],
  2299. resolved, ConstInt(index))
  2300. else:
  2301. assert 0
  2302. _variables_equal(fieldbox, fieldvalue.strip(), strict=False)
  2303. index += 1
  2304. def check_expanded_fail_descr(self, expectedtext, guard_opnum):
  2305. from rpython.jit.metainterp.test.test_resume import ResumeDataFakeReader
  2306. from rpython.jit.metainterp.test.test_resume import MyMetaInterp
  2307. guard_op, = [op for op in self.loop.operations if op.is_guard()]
  2308. fail_args = guard_op.getfailargs()
  2309. fdescr = guard_op.getdescr()
  2310. assert fdescr.guard_opnum == guard_opnum
  2311. reader = ResumeDataFakeReader(fdescr, fail_args,
  2312. MyMetaInterp(self.cpu))
  2313. boxes = reader.consume_boxes()
  2314. self._verify_fail_args(boxes, fdescr.oparse, expectedtext)
  2315. def test_expand_fail_1(self):
  2316. ops = """
  2317. [i1, i3]
  2318. # first rename i3 into i4
  2319. p1 = new_with_vtable(ConstClass(node_vtable))
  2320. setfield_gc(p1, i3, descr=valuedescr)
  2321. i4 = getfield_gc(p1, descr=valuedescr)
  2322. #
  2323. i2 = int_add(10, 5)
  2324. guard_true(i1, descr=fdescr) [i2, i4]
  2325. jump(i1, i4)
  2326. """
  2327. expected = """
  2328. [i1, i3]
  2329. guard_true(i1, descr=fdescr) [i3]
  2330. jump(1, i3)
  2331. """
  2332. self.optimize_loop(ops, expected)
  2333. self.check_expanded_fail_descr('15, i3', rop.GUARD_TRUE)
  2334. def test_expand_fail_2(self):
  2335. ops = """
  2336. [i1, i2]
  2337. p1 = new_with_vtable(ConstClass(node_vtable))
  2338. setfield_gc(p1, i2, descr=valuedescr)
  2339. setfield_gc(p1, p1, descr=nextdescr)
  2340. guard_true(i1, descr=fdescr) [p1]
  2341. jump(i1, i2)
  2342. """
  2343. expected = """
  2344. [i1, i2]
  2345. guard_true(i1, descr=fdescr) [i2]
  2346. jump(1, i2)
  2347. """
  2348. self.optimize_loop(ops, expected)
  2349. self.check_expanded_fail_descr('''ptr
  2350. where ptr is a node_vtable, valuedescr=i2
  2351. ''', rop.GUARD_TRUE)
  2352. def test_expand_fail_3(self):
  2353. ops = """
  2354. [i1, i2, i3, p3]
  2355. p1 = new_with_vtable(ConstClass(node_vtable))
  2356. p2 = new_with_vtable(ConstClass(node_vtable))
  2357. setfield_gc(p1, 1, descr=valuedescr)
  2358. setfield_gc(p1, p2, descr=nextdescr)
  2359. setfield_gc(p2, i2, descr=valuedescr)
  2360. setfield_gc(p2, p3, descr=nextdescr)
  2361. guard_true(i1, descr=fdescr) [i3, p1]
  2362. jump(i2, i1, i3, p3)
  2363. """
  2364. expected = """
  2365. [i1, i2, i3, p3]
  2366. guard_true(i1, descr=fdescr) [i3, i2, p3]
  2367. jump(i2, 1, i3, p3)
  2368. """
  2369. self.optimize_loop(ops, expected)
  2370. self.check_expanded_fail_descr('''i3, p1
  2371. where p1 is a node_vtable, valuedescr=1, nextdescr=p2
  2372. where p2 is a node_vtable, valuedescr=i2, nextdescr=p3
  2373. ''', rop.GUARD_TRUE)
  2374. def test_expand_fail_4(self):
  2375. for arg in ['p1', 'i2,p1', 'p1,p2', 'p2,p1',
  2376. 'i2,p1,p2', 'i2,p2,p1']:
  2377. self.setup_method() # humpf
  2378. ops = """
  2379. [i1, i2, i3]
  2380. p1 = new_with_vtable(ConstClass(node_vtable))
  2381. setfield_gc(p1, i3, descr=valuedescr)
  2382. i4 = getfield_gc(p1, descr=valuedescr) # copy of i3
  2383. p2 = new_with_vtable(ConstClass(node_vtable))
  2384. setfield_gc(p1, i2, descr=valuedescr)
  2385. setfield_gc(p1, p2, descr=nextdescr)
  2386. setfield_gc(p2, i2, descr=valuedescr)
  2387. guard_true(i1, descr=fdescr) [i4, i3, %s]
  2388. jump(i1, i2, i3)
  2389. """
  2390. expected = """
  2391. [i1, i2, i3]
  2392. guard_true(i1, descr=fdescr) [i3, i2]
  2393. jump(1, i2, i3)
  2394. """
  2395. self.optimize_loop(ops % arg, expected)
  2396. self.check_expanded_fail_descr('''i3, i3, %s
  2397. where p1 is a node_vtable, valuedescr=i2, nextdescr=p2
  2398. where p2 is a node_vtable, valuedescr=i2''' % arg,
  2399. rop.GUARD_TRUE)
  2400. def test_expand_fail_5(self):
  2401. ops = """
  2402. [i1, i2, i3, i4]
  2403. p1 = new_with_vtable(ConstClass(node_vtable))
  2404. p2 = new_with_vtable(ConstClass(node_vtable))
  2405. setfield_gc(p1, i4, descr=valuedescr)
  2406. setfield_gc(p1, p2, descr=nextdescr)
  2407. setfield_gc(p2, i2, descr=valuedescr)
  2408. setfield_gc(p2, p1, descr=nextdescr) # a cycle
  2409. guard_true(i1, descr=fdescr) [i3, i4, p1, p2]
  2410. jump(i2, i1, i3, i4)
  2411. """
  2412. expected = """
  2413. [i1, i2, i3, i4]
  2414. guard_true(i1, descr=fdescr) [i3, i4, i2]
  2415. jump(i2, 1, i3, i4)
  2416. """
  2417. self.optimize_loop(ops, expected)
  2418. self.check_expanded_fail_descr('''i3, i4, p1, p2
  2419. where p1 is a node_vtable, valuedescr=i4, nextdescr=p2
  2420. where p2 is a node_vtable, valuedescr=i2, nextdescr=p1
  2421. ''', rop.GUARD_TRUE)
  2422. def test_expand_fail_6(self):
  2423. ops = """
  2424. [p0, i0, i1]
  2425. guard_true(i0, descr=fdescr) [p0]
  2426. p1 = new_with_vtable(ConstClass(node_vtable))
  2427. setfield_gc(p1, i1, descr=valuedescr)
  2428. jump(p1, i1, i1)
  2429. """
  2430. expected = """
  2431. [i1b, i0, i1]
  2432. guard_true(i0, descr=fdescr) [i1b]
  2433. jump(i1, i1, i1)
  2434. """
  2435. py.test.skip("XXX")
  2436. self.optimize_loop(ops, '''Virtual(node_vtable, valuedescr=Not),
  2437. Not, Not''', expected)
  2438. self.check_expanded_fail_descr('''p0
  2439. where p0 is a node_vtable, valuedescr=i1b
  2440. ''', rop.GUARD_TRUE)
  2441. def test_expand_fail_varray(self):
  2442. ops = """
  2443. [i1]
  2444. p1 = new_array(3, descr=arraydescr)
  2445. setarrayitem_gc(p1, 1, i1, descr=arraydescr)
  2446. setarrayitem_gc(p1, 0, 25, descr=arraydescr)
  2447. guard_true(i1, descr=fdescr) [p1]
  2448. i2 = getarrayitem_gc(p1, 1, descr=arraydescr)
  2449. jump(i2)
  2450. """
  2451. expected = """
  2452. [i1]
  2453. guard_true(i1, descr=fdescr) [i1]
  2454. jump(1)
  2455. """
  2456. self.optimize_loop(ops, expected)
  2457. self.check_expanded_fail_descr('''p1
  2458. where p1 is a varray arraydescr: 25, i1
  2459. ''', rop.GUARD_TRUE)
  2460. def test_expand_fail_vstruct(self):
  2461. ops = """
  2462. [i1, p1]
  2463. p2 = new(descr=ssize)
  2464. setfield_gc(p2, i1, descr=adescr)
  2465. setfield_gc(p2, p1, descr=bdescr)
  2466. guard_true(i1, descr=fdescr) [p2]
  2467. i3 = getfield_gc(p2, descr=adescr)
  2468. p3 = getfield_gc(p2, descr=bdescr)
  2469. jump(i3, p3)
  2470. """
  2471. expected = """
  2472. [i1, p1]
  2473. guard_true(i1, descr=fdescr) [i1, p1]
  2474. jump(1, p1)
  2475. """
  2476. self.optimize_loop(ops, expected)
  2477. self.check_expanded_fail_descr('''p2
  2478. where p2 is a vstruct ssize, adescr=i1, bdescr=p1
  2479. ''', rop.GUARD_TRUE)
  2480. def test_expand_fail_v_all_1(self):
  2481. ops = """
  2482. [i1, p1a, i2]
  2483. p6s = getarrayitem_gc(p1a, 0, descr=arraydescr2)
  2484. p7v = getfield_gc(p6s, descr=bdescr)
  2485. p5s = new(descr=ssize)
  2486. setfield_gc(p5s, i2, descr=adescr)
  2487. setfield_gc(p5s, p7v, descr=bdescr)
  2488. setarrayitem_gc(p1a, 1, p5s, descr=arraydescr2)
  2489. guard_true(i1, descr=fdescr) [p1a]
  2490. p2s = new(descr=ssize)
  2491. p3v = new_with_vtable(ConstClass(node_vtable))
  2492. p4a = new_array(2, descr=arraydescr2)
  2493. setfield_gc(p2s, i1, descr=adescr)
  2494. setfield_gc(p2s, p3v, descr=bdescr)
  2495. setfield_gc(p3v, i2, descr=valuedescr)
  2496. setarrayitem_gc(p4a, 0, p2s, descr=arraydescr2)
  2497. jump(i1, p4a, i2)
  2498. """
  2499. expected = """
  2500. [i1, ia, iv, pnull, i2]
  2501. guard_true(i1, descr=fdescr) [ia, iv, i2]
  2502. jump(1, 1, i2, NULL, i2)
  2503. """
  2504. py.test.skip("XXX")
  2505. self.optimize_loop(ops, '''
  2506. Not,
  2507. VArray(arraydescr2,
  2508. VStruct(ssize,
  2509. adescr=Not,
  2510. bdescr=Virtual(node_vtable,
  2511. valuedescr=Not)),
  2512. Not),
  2513. Not''', expected)
  2514. self.check_expanded_fail_descr('''p1a
  2515. where p1a is a varray arraydescr2: p6s, p5s
  2516. where p6s is a vstruct ssize, adescr=ia, bdescr=p7v
  2517. where p5s is a vstruct ssize, adescr=i2, bdescr=p7v
  2518. where p7v is a node_vtable, valuedescr=iv
  2519. ''', rop.GUARD_TRUE)
  2520. def test_expand_fail_lazy_setfield_1(self):
  2521. ops = """
  2522. [p1, i2, i3]
  2523. p2 = new_with_vtable(ConstClass(node_vtable))
  2524. setfield_gc(p2, i2, descr=valuedescr)
  2525. setfield_gc(p1, p2, descr=nextdescr)
  2526. guard_true(i3, descr=fdescr) []
  2527. i4 = int_neg(i2)
  2528. setfield_gc(p1, NULL, descr=nextdescr)
  2529. jump(p1, i2, i4)
  2530. """
  2531. expected = """
  2532. [p1, i2, i3]
  2533. guard_true(i3, descr=fdescr) [p1, i2]
  2534. i4 = int_neg(i2)
  2535. setfield_gc(p1, NULL, descr=nextdescr)
  2536. jump(p1, i2, i4)
  2537. """
  2538. self.optimize_loop(ops, expected)
  2539. self.loop.inputargs[0].value = self.nodebox.value
  2540. self.check_expanded_fail_descr('''
  2541. p1.nextdescr = p2
  2542. where p2 is a node_vtable, valuedescr=i2
  2543. ''', rop.GUARD_TRUE)
  2544. def test_expand_fail_lazy_setfield_2(self):
  2545. ops = """
  2546. [i2, i3]
  2547. p2 = new_with_vtable(ConstClass(node_vtable))
  2548. setfield_gc(p2, i2, descr=valuedescr)
  2549. setfield_gc(ConstPtr(myptr), p2, descr=nextdescr)
  2550. guard_true(i3, descr=fdescr) []
  2551. i4 = int_neg(i2)
  2552. setfield_gc(ConstPtr(myptr), NULL, descr=nextdescr)
  2553. jump(i2, i4)
  2554. """
  2555. expected = """
  2556. [i2, i3]
  2557. guard_true(i3, descr=fdescr) [i2]
  2558. i4 = int_neg(i2)
  2559. setfield_gc(ConstPtr(myptr), NULL, descr=nextdescr)
  2560. jump(i2, i4)
  2561. """
  2562. self.optimize_loop(ops, expected)
  2563. self.check_expanded_fail_descr('''
  2564. ConstPtr(myptr).nextdescr = p2
  2565. where p2 is a node_vtable, valuedescr=i2
  2566. ''', rop.GUARD_TRUE)
  2567. def test_residual_call_does_not_invalidate_caches(self):
  2568. ops = """
  2569. [p1, p2]
  2570. i1 = getfield_gc(p1, descr=valuedescr)
  2571. i2 = call(i1, descr=nonwritedescr)
  2572. i3 = getfield_gc(p1, descr=valuedescr)
  2573. escape(i1)
  2574. escape(i3)
  2575. jump(p1, p2)
  2576. """
  2577. expected = """
  2578. [p1, p2]
  2579. i1 = getfield_gc(p1, descr=valuedescr)
  2580. i2 = call(i1, descr=nonwritedescr)
  2581. escape(i1)
  2582. escape(i1)
  2583. jump(p1, p2)
  2584. """
  2585. self.optimize_loop(ops, expected)
  2586. def test_residual_call_invalidate_some_caches(self):
  2587. ops = """
  2588. [p1, p2]
  2589. i1 = getfield_gc(p1, descr=adescr)
  2590. i2 = getfield_gc(p1, descr=bdescr)
  2591. i3 = call(i1, descr=writeadescr)
  2592. i4 = getfield_gc(p1, descr=adescr)
  2593. i5 = getfield_gc(p1, descr=bdescr)
  2594. escape(i1)
  2595. escape(i2)
  2596. escape(i4)
  2597. escape(i5)
  2598. jump(p1, p2)
  2599. """
  2600. expected = """
  2601. [p1, p2]
  2602. i1 = getfield_gc(p1, descr=adescr)
  2603. i2 = getfield_gc(p1, descr=bdescr)
  2604. i3 = call(i1, descr=writeadescr)
  2605. i4 = getfield_gc(p1, descr=adescr)
  2606. escape(i1)
  2607. escape(i2)
  2608. escape(i4)
  2609. escape(i2)
  2610. jump(p1, p2)
  2611. """
  2612. self.optimize_loop(ops, expected)
  2613. def test_residual_call_invalidate_arrays(self):
  2614. ops = """
  2615. [p1, p2, i1]
  2616. p3 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  2617. p4 = getarrayitem_gc(p2, 1, descr=arraydescr2)
  2618. i3 = call(i1, descr=writeadescr)
  2619. p5 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  2620. p6 = getarrayitem_gc(p2, 1, descr=arraydescr2)
  2621. escape(p3)
  2622. escape(p4)
  2623. escape(p5)
  2624. escape(p6)
  2625. jump(p1, p2, i1)
  2626. """
  2627. expected = """
  2628. [p1, p2, i1]
  2629. p3 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  2630. p4 = getarrayitem_gc(p2, 1, descr=arraydescr2)
  2631. i3 = call(i1, descr=writeadescr)
  2632. escape(p3)
  2633. escape(p4)
  2634. escape(p3)
  2635. escape(p4)
  2636. jump(p1, p2, i1)
  2637. """
  2638. self.optimize_loop(ops, expected)
  2639. def test_residual_call_invalidate_some_arrays(self):
  2640. ops = """
  2641. [p1, p2, i1]
  2642. p3 = getarrayitem_gc(p2, 0, descr=arraydescr2)
  2643. p4 = getarrayitem_gc(p2, 1, descr=arraydescr2)
  2644. i2 = getarrayitem_gc(p1, 1, descr=arraydescr)
  2645. i3 = call(i1, descr=writearraydescr)
  2646. p5 = getarrayitem_gc(p2, 0, descr=arraydescr2)
  2647. p6 = getarrayitem_gc(p2, 1, descr=arraydescr2)
  2648. i4 = getarrayitem_gc(p1, 1, descr=arraydescr)
  2649. escape(p3)
  2650. escape(p4)
  2651. escape(p5)
  2652. escape(p6)
  2653. escape(i2)
  2654. escape(i4)
  2655. jump(p1, p2, i1)
  2656. """
  2657. expected = """
  2658. [p1, p2, i1]
  2659. p3 = getarrayitem_gc(p2, 0, descr=arraydescr2)
  2660. p4 = getarrayitem_gc(p2, 1, descr=arraydescr2)
  2661. i2 = getarrayitem_gc(p1, 1, descr=arraydescr)
  2662. i3 = call(i1, descr=writearraydescr)
  2663. i4 = getarrayitem_gc(p1, 1, descr=arraydescr)
  2664. escape(p3)
  2665. escape(p4)
  2666. escape(p3)
  2667. escape(p4)
  2668. escape(i2)
  2669. escape(i4)
  2670. jump(p1, p2, i1)
  2671. """
  2672. self.optimize_loop(ops, expected)
  2673. def test_residual_call_invalidates_some_read_caches_1(self):
  2674. ops = """
  2675. [p1, i1, p2, i2]
  2676. setfield_gc(p1, i1, descr=valuedescr)
  2677. setfield_gc(p2, i2, descr=adescr)
  2678. i3 = call(i1, descr=readadescr)
  2679. setfield_gc(p1, i3, descr=valuedescr)
  2680. setfield_gc(p2, i3, descr=adescr)
  2681. jump(p1, i1, p2, i2)
  2682. """
  2683. expected = """
  2684. [p1, i1, p2, i2]
  2685. setfield_gc(p2, i2, descr=adescr)
  2686. i3 = call(i1, descr=readadescr)
  2687. setfield_gc(p1, i3, descr=valuedescr)
  2688. setfield_gc(p2, i3, descr=adescr)
  2689. jump(p1, i1, p2, i2)
  2690. """
  2691. self.optimize_loop(ops, expected)
  2692. def test_residual_call_invalidates_some_read_caches_2(self):
  2693. ops = """
  2694. [p1, i1, p2, i2]
  2695. setfield_gc(p1, i1, descr=valuedescr)
  2696. setfield_gc(p2, i2, descr=adescr)
  2697. i3 = call(i1, descr=writeadescr)
  2698. setfield_gc(p1, i3, descr=valuedescr)
  2699. setfield_gc(p2, i3, descr=adescr)
  2700. jump(p1, i1, p2, i2)
  2701. """
  2702. expected = """
  2703. [p1, i1, p2, i2]
  2704. setfield_gc(p2, i2, descr=adescr)
  2705. i3 = call(i1, descr=writeadescr)
  2706. setfield_gc(p1, i3, descr=valuedescr)
  2707. setfield_gc(p2, i3, descr=adescr)
  2708. jump(p1, i1, p2, i2)
  2709. """
  2710. self.optimize_loop(ops, expected)
  2711. def test_residual_call_invalidates_some_read_caches_3(self):
  2712. ops = """
  2713. [p1, i1, p2, i2]
  2714. setfield_gc(p1, i1, descr=valuedescr)
  2715. setfield_gc(p2, i2, descr=adescr)
  2716. i3 = call(i1, descr=plaincalldescr)
  2717. setfield_gc(p1, i3, descr=valuedescr)
  2718. setfield_gc(p2, i3, descr=adescr)
  2719. jump(p1, i1, p2, i2)
  2720. """
  2721. self.optimize_loop(ops, ops)
  2722. def test_call_assembler_invalidates_caches(self):
  2723. ops = '''
  2724. [p1, i1]
  2725. setfield_gc(p1, i1, descr=valuedescr)
  2726. i3 = call_assembler(i1, descr=asmdescr)
  2727. setfield_gc(p1, i3, descr=valuedescr)
  2728. jump(p1, i3)
  2729. '''
  2730. self.optimize_loop(ops, ops)
  2731. def test_call_pure_invalidates_caches(self):
  2732. # CALL_PURE should still force the setfield_gc() to occur before it
  2733. ops = '''
  2734. [p1, i1]
  2735. setfield_gc(p1, i1, descr=valuedescr)
  2736. i3 = call_pure(p1, descr=plaincalldescr)
  2737. setfield_gc(p1, i3, descr=valuedescr)
  2738. jump(p1, i3)
  2739. '''
  2740. expected = '''
  2741. [p1, i1]
  2742. setfield_gc(p1, i1, descr=valuedescr)
  2743. i3 = call(p1, descr=plaincalldescr)
  2744. setfield_gc(p1, i3, descr=valuedescr)
  2745. jump(p1, i3)
  2746. '''
  2747. self.optimize_loop(ops, expected)
  2748. def test_call_pure_constant_folding(self):
  2749. # CALL_PURE is not marked as is_always_pure(), because it is wrong
  2750. # to call the function arbitrary many times at arbitrary points in
  2751. # time. Check that it is either constant-folded (and replaced by
  2752. # the result of the call, recorded as the first arg), or turned into
  2753. # a regular CALL.
  2754. arg_consts = [ConstInt(i) for i in (123456, 4, 5, 6)]
  2755. call_pure_results = {tuple(arg_consts): ConstInt(42)}
  2756. ops = '''
  2757. [i0, i1, i2]
  2758. escape(i1)
  2759. escape(i2)
  2760. i3 = call_pure(123456, 4, 5, 6, descr=plaincalldescr)
  2761. i4 = call_pure(123456, 4, i0, 6, descr=plaincalldescr)
  2762. jump(i0, i3, i4)
  2763. '''
  2764. expected = '''
  2765. [i0, i1, i2]
  2766. escape(i1)
  2767. escape(i2)
  2768. i4 = call(123456, 4, i0, 6, descr=plaincalldescr)
  2769. jump(i0, 42, i4)
  2770. '''
  2771. self.optimize_loop(ops, expected, call_pure_results)
  2772. def test_vref_nonvirtual_nonescape(self):
  2773. ops = """
  2774. [p1]
  2775. p2 = virtual_ref(p1, 5)
  2776. virtual_ref_finish(p2, p1)
  2777. jump(p1)
  2778. """
  2779. expected = """
  2780. [p1]
  2781. p0 = force_token()
  2782. jump(p1)
  2783. """
  2784. self.optimize_loop(ops, expected)
  2785. def test_vref_nonvirtual_escape(self):
  2786. ops = """
  2787. [p1]
  2788. p2 = virtual_ref(p1, 5)
  2789. escape(p2)
  2790. virtual_ref_finish(p2, p1)
  2791. jump(p1)
  2792. """
  2793. expected = """
  2794. [p1]
  2795. p0 = force_token()
  2796. p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
  2797. setfield_gc(p2, p0, descr=virtualtokendescr)
  2798. escape(p2)
  2799. setfield_gc(p2, p1, descr=virtualforceddescr)
  2800. setfield_gc(p2, NULL, descr=virtualtokendescr)
  2801. jump(p1)
  2802. """
  2803. # XXX we should optimize a bit more the case of a nonvirtual.
  2804. # in theory it is enough to just do 'p2 = p1'.
  2805. self.optimize_loop(ops, expected)
  2806. def test_vref_virtual_1(self):
  2807. ops = """
  2808. [p0, i1]
  2809. #
  2810. p1 = new_with_vtable(ConstClass(node_vtable))
  2811. p1b = new_with_vtable(ConstClass(node_vtable))
  2812. setfield_gc(p1b, 252, descr=valuedescr)
  2813. setfield_gc(p1, p1b, descr=nextdescr)
  2814. #
  2815. p2 = virtual_ref(p1, 3)
  2816. setfield_gc(p0, p2, descr=nextdescr)
  2817. call_may_force(i1, descr=mayforcevirtdescr)
  2818. guard_not_forced() [i1]
  2819. virtual_ref_finish(p2, p1)
  2820. setfield_gc(p0, NULL, descr=nextdescr)
  2821. jump(p0, i1)
  2822. """
  2823. expected = """
  2824. [p0, i1]
  2825. p3 = force_token()
  2826. #
  2827. p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
  2828. setfield_gc(p2, p3, descr=virtualtokendescr)
  2829. setfield_gc(p0, p2, descr=nextdescr)
  2830. #
  2831. call_may_force(i1, descr=mayforcevirtdescr)
  2832. guard_not_forced() [i1]
  2833. #
  2834. setfield_gc(p0, NULL, descr=nextdescr)
  2835. p1 = new_with_vtable(ConstClass(node_vtable))
  2836. p1b = new_with_vtable(ConstClass(node_vtable))
  2837. setfield_gc(p1b, 252, descr=valuedescr)
  2838. setfield_gc(p1, p1b, descr=nextdescr)
  2839. setfield_gc(p2, p1, descr=virtualforceddescr)
  2840. setfield_gc(p2, NULL, descr=virtualtokendescr)
  2841. jump(p0, i1)
  2842. """
  2843. self.optimize_loop(ops, expected)
  2844. def test_vref_virtual_2(self):
  2845. ops = """
  2846. [p0, i1]
  2847. #
  2848. p1 = new_with_vtable(ConstClass(node_vtable))
  2849. p1b = new_with_vtable(ConstClass(node_vtable))
  2850. setfield_gc(p1b, i1, descr=valuedescr)
  2851. setfield_gc(p1, p1b, descr=nextdescr)
  2852. #
  2853. p2 = virtual_ref(p1, 2)
  2854. setfield_gc(p0, p2, descr=nextdescr)
  2855. call_may_force(i1, descr=mayforcevirtdescr)
  2856. guard_not_forced(descr=fdescr) [p2, p1]
  2857. virtual_ref_finish(p2, p1)
  2858. setfield_gc(p0, NULL, descr=nextdescr)
  2859. jump(p0, i1)
  2860. """
  2861. expected = """
  2862. [p0, i1]
  2863. p3 = force_token()
  2864. #
  2865. p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
  2866. setfield_gc(p2, p3, descr=virtualtokendescr)
  2867. setfield_gc(p0, p2, descr=nextdescr)
  2868. #
  2869. call_may_force(i1, descr=mayforcevirtdescr)
  2870. guard_not_forced(descr=fdescr) [p2, i1]
  2871. #
  2872. setfield_gc(p0, NULL, descr=nextdescr)
  2873. p1 = new_with_vtable(ConstClass(node_vtable))
  2874. p1b = new_with_vtable(ConstClass(node_vtable))
  2875. setfield_gc(p1b, i1, descr=valuedescr)
  2876. setfield_gc(p1, p1b, descr=nextdescr)
  2877. setfield_gc(p2, p1, descr=virtualforceddescr)
  2878. setfield_gc(p2, NULL, descr=virtualtokendescr)
  2879. jump(p0, i1)
  2880. """
  2881. # the point of this test is that 'i1' should show up in the fail_args
  2882. # of 'guard_not_forced', because it was stored in the virtual 'p1b'.
  2883. self.optimize_loop(ops, expected)
  2884. self.check_expanded_fail_descr('''p2, p1
  2885. where p1 is a node_vtable, nextdescr=p1b
  2886. where p1b is a node_vtable, valuedescr=i1
  2887. ''', rop.GUARD_NOT_FORCED)
  2888. def test_vref_virtual_and_lazy_setfield(self):
  2889. ops = """
  2890. [p0, i1]
  2891. #
  2892. p1 = new_with_vtable(ConstClass(node_vtable))
  2893. p1b = new_with_vtable(ConstClass(node_vtable))
  2894. setfield_gc(p1b, i1, descr=valuedescr)
  2895. setfield_gc(p1, p1b, descr=nextdescr)
  2896. #
  2897. p2 = virtual_ref(p1, 2)
  2898. setfield_gc(p0, p2, descr=refdescr)
  2899. call(i1, descr=nonwritedescr)
  2900. guard_no_exception(descr=fdescr) [p2, p1]
  2901. virtual_ref_finish(p2, p1)
  2902. setfield_gc(p0, NULL, descr=refdescr)
  2903. jump(p0, i1)
  2904. """
  2905. expected = """
  2906. [p0, i1]
  2907. p3 = force_token()
  2908. call(i1, descr=nonwritedescr)
  2909. guard_no_exception(descr=fdescr) [p3, i1, p0]
  2910. setfield_gc(p0, NULL, descr=refdescr)
  2911. jump(p0, i1)
  2912. """
  2913. self.optimize_loop(ops, expected)
  2914. # the fail_args contain [p3, i1, p0]:
  2915. # - p3 is from the virtual expansion of p2
  2916. # - i1 is from the virtual expansion of p1
  2917. # - p0 is from the extra pendingfields
  2918. self.loop.inputargs[0].value = self.nodeobjvalue
  2919. self.check_expanded_fail_descr('''p2, p1
  2920. p0.refdescr = p2
  2921. where p2 is a jit_virtual_ref_vtable, virtualtokendescr=p3
  2922. where p1 is a node_vtable, nextdescr=p1b
  2923. where p1b is a node_vtable, valuedescr=i1
  2924. ''', rop.GUARD_NO_EXCEPTION)
  2925. def test_vref_virtual_after_finish(self):
  2926. ops = """
  2927. [i1]
  2928. p1 = new_with_vtable(ConstClass(node_vtable))
  2929. p2 = virtual_ref(p1, 7)
  2930. escape(p2)
  2931. virtual_ref_finish(p2, p1)
  2932. call_may_force(i1, descr=mayforcevirtdescr)
  2933. guard_not_forced() []
  2934. jump(i1)
  2935. """
  2936. expected = """
  2937. [i1]
  2938. p3 = force_token()
  2939. p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
  2940. setfield_gc(p2, p3, descr=virtualtokendescr)
  2941. escape(p2)
  2942. p1 = new_with_vtable(ConstClass(node_vtable))
  2943. setfield_gc(p2, p1, descr=virtualforceddescr)
  2944. setfield_gc(p2, NULL, descr=virtualtokendescr)
  2945. call_may_force(i1, descr=mayforcevirtdescr)
  2946. guard_not_forced() []
  2947. jump(i1)
  2948. """
  2949. self.optimize_loop(ops, expected)
  2950. def test_vref_nonvirtual_and_lazy_setfield(self):
  2951. ops = """
  2952. [i1, p1]
  2953. p2 = virtual_ref(p1, 23)
  2954. escape(p2)
  2955. virtual_ref_finish(p2, p1)
  2956. call_may_force(i1, descr=mayforcevirtdescr)
  2957. guard_not_forced() [i1]
  2958. jump(i1, p1)
  2959. """
  2960. expected = """
  2961. [i1, p1]
  2962. p3 = force_token()
  2963. p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
  2964. setfield_gc(p2, p3, descr=virtualtokendescr)
  2965. escape(p2)
  2966. setfield_gc(p2, p1, descr=virtualforceddescr)
  2967. setfield_gc(p2, NULL, descr=virtualtokendescr)
  2968. call_may_force(i1, descr=mayforcevirtdescr)
  2969. guard_not_forced() [i1]
  2970. jump(i1, p1)
  2971. """
  2972. self.optimize_loop(ops, expected)
  2973. def test_arraycopy_1(self):
  2974. ops = '''
  2975. [i0]
  2976. p1 = new_array(3, descr=arraydescr)
  2977. setarrayitem_gc(p1, 1, 1, descr=arraydescr)
  2978. p2 = new_array(3, descr=arraydescr)
  2979. setarrayitem_gc(p2, 1, 3, descr=arraydescr)
  2980. call(0, p1, p2, 1, 1, 2, descr=arraycopydescr)
  2981. i2 = getarrayitem_gc(p2, 1, descr=arraydescr)
  2982. jump(i2)
  2983. '''
  2984. expected = '''
  2985. [i0]
  2986. jump(1)
  2987. '''
  2988. self.optimize_loop(ops, expected)
  2989. def test_arraycopy_2(self):
  2990. ops = '''
  2991. [i0]
  2992. p1 = new_array(3, descr=arraydescr)
  2993. p2 = new_array(3, descr=arraydescr)
  2994. setarrayitem_gc(p1, 0, i0, descr=arraydescr)
  2995. setarrayitem_gc(p2, 0, 3, descr=arraydescr)
  2996. call(0, p1, p2, 1, 1, 2, descr=arraycopydescr)
  2997. i2 = getarrayitem_gc(p2, 0, descr=arraydescr)
  2998. jump(i2)
  2999. '''
  3000. expected = '''
  3001. [i0]
  3002. jump(3)
  3003. '''
  3004. self.optimize_loop(ops, expected)
  3005. def test_arraycopy_not_virtual(self):
  3006. ops = '''
  3007. [p0]
  3008. p1 = new_array(3, descr=arraydescr)
  3009. p2 = new_array(3, descr=arraydescr)
  3010. setarrayitem_gc(p1, 2, 10, descr=arraydescr)
  3011. setarrayitem_gc(p2, 2, 13, descr=arraydescr)
  3012. call(0, p1, p2, 0, 0, 3, descr=arraycopydescr)
  3013. jump(p2)
  3014. '''
  3015. expected = '''
  3016. [p0]
  3017. p2 = new_array(3, descr=arraydescr)
  3018. setarrayitem_gc(p2, 2, 10, descr=arraydescr)
  3019. jump(p2)
  3020. '''
  3021. self.optimize_loop(ops, expected)
  3022. def test_arraycopy_not_virtual_2(self):
  3023. ops = '''
  3024. [p0]
  3025. p1 = new_array(3, descr=arraydescr)
  3026. call(0, p0, p1, 0, 0, 3, descr=arraycopydescr)
  3027. i0 = getarrayitem_gc(p1, 0, descr=arraydescr)
  3028. jump(i0)
  3029. '''
  3030. expected = '''
  3031. [p0]
  3032. i0 = getarrayitem_gc(p0, 0, descr=arraydescr)
  3033. i1 = getarrayitem_gc(p0, 1, descr=arraydescr) # removed by the backend
  3034. i2 = getarrayitem_gc(p0, 2, descr=arraydescr) # removed by the backend
  3035. jump(i0)
  3036. '''
  3037. self.optimize_loop(ops, expected)
  3038. def test_arraycopy_not_virtual_3(self):
  3039. ops = '''
  3040. [p0, p1]
  3041. call(0, p0, p1, 0, 0, 3, descr=arraycopydescr)
  3042. i0 = getarrayitem_gc(p1, 0, descr=arraydescr)
  3043. jump(i0)
  3044. '''
  3045. expected = '''
  3046. [p0, p1]
  3047. i0 = getarrayitem_gc(p0, 0, descr=arraydescr)
  3048. i1 = getarrayitem_gc(p0, 1, descr=arraydescr)
  3049. i2 = getarrayitem_gc(p0, 2, descr=arraydescr)
  3050. setarrayitem_gc(p1, 0, i0, descr=arraydescr)
  3051. setarrayitem_gc(p1, 1, i1, descr=arraydescr)
  3052. setarrayitem_gc(p1, 2, i2, descr=arraydescr)
  3053. jump(i0)
  3054. '''
  3055. self.optimize_loop(ops, expected)
  3056. def test_arraycopy_no_elem(self):
  3057. """ this was actually observed in the wild
  3058. """
  3059. ops = '''
  3060. [p1]
  3061. p0 = new_array(0, descr=arraydescr)
  3062. call(0, p0, p1, 0, 0, 0, descr=arraycopydescr)
  3063. jump(p1)
  3064. '''
  3065. expected = '''
  3066. [p1]
  3067. jump(p1)
  3068. '''
  3069. self.optimize_loop(ops, expected)
  3070. def test_bound_lt(self):
  3071. ops = """
  3072. [i0]
  3073. i1 = int_lt(i0, 4)
  3074. guard_true(i1) []
  3075. i2 = int_lt(i0, 5)
  3076. guard_true(i2) []
  3077. jump(i0)
  3078. """
  3079. expected = """
  3080. [i0]
  3081. i1 = int_lt(i0, 4)
  3082. guard_true(i1) []
  3083. jump(i0)
  3084. """
  3085. self.optimize_loop(ops, expected)
  3086. def test_bound_lt_noguard(self):
  3087. ops = """
  3088. [i0]
  3089. i1 = int_lt(i0, 4)
  3090. i2 = int_lt(i0, 5)
  3091. jump(i2)
  3092. """
  3093. expected = """
  3094. [i0]
  3095. i1 = int_lt(i0, 4)
  3096. i2 = int_lt(i0, 5)
  3097. jump(i2)
  3098. """
  3099. self.optimize_loop(ops, expected)
  3100. def test_bound_lt_noopt(self):
  3101. ops = """
  3102. [i0]
  3103. i1 = int_lt(i0, 4)
  3104. guard_false(i1) []
  3105. i2 = int_lt(i0, 5)
  3106. guard_true(i2) []
  3107. jump(i0)
  3108. """
  3109. expected = """
  3110. [i0]
  3111. i1 = int_lt(i0, 4)
  3112. guard_false(i1) []
  3113. i2 = int_lt(i0, 5)
  3114. guard_true(i2) []
  3115. jump(4)
  3116. """
  3117. self.optimize_loop(ops, expected)
  3118. def test_bound_lt_rev(self):
  3119. ops = """
  3120. [i0]
  3121. i1 = int_lt(i0, 4)
  3122. guard_false(i1) []
  3123. i2 = int_gt(i0, 3)
  3124. guard_true(i2) []
  3125. jump(i0)
  3126. """
  3127. expected = """
  3128. [i0]
  3129. i1 = int_lt(i0, 4)
  3130. guard_false(i1) []
  3131. jump(i0)
  3132. """
  3133. self.optimize_loop(ops, expected)
  3134. def test_bound_lt_tripple(self):
  3135. ops = """
  3136. [i0]
  3137. i1 = int_lt(i0, 0)
  3138. guard_true(i1) []
  3139. i2 = int_lt(i0, 7)
  3140. guard_true(i2) []
  3141. i3 = int_lt(i0, 5)
  3142. guard_true(i3) []
  3143. jump(i0)
  3144. """
  3145. expected = """
  3146. [i0]
  3147. i1 = int_lt(i0, 0)
  3148. guard_true(i1) []
  3149. jump(i0)
  3150. """
  3151. self.optimize_loop(ops, expected)
  3152. def test_bound_lt_add(self):
  3153. ops = """
  3154. [i0]
  3155. i1 = int_lt(i0, 4)
  3156. guard_true(i1) []
  3157. i2 = int_add(i0, 10)
  3158. i3 = int_lt(i2, 15)
  3159. guard_true(i3) []
  3160. jump(i0)
  3161. """
  3162. expected = """
  3163. [i0]
  3164. i1 = int_lt(i0, 4)
  3165. guard_true(i1) []
  3166. i2 = int_add(i0, 10)
  3167. jump(i0)
  3168. """
  3169. self.optimize_loop(ops, expected)
  3170. def test_bound_lt_add_before(self):
  3171. ops = """
  3172. [i0]
  3173. i2 = int_add(i0, 10)
  3174. i3 = int_lt(i2, 15)
  3175. guard_true(i3) []
  3176. i1 = int_lt(i0, 6)
  3177. guard_true(i1) []
  3178. jump(i0)
  3179. """
  3180. expected = """
  3181. [i0]
  3182. i2 = int_add(i0, 10)
  3183. i3 = int_lt(i2, 15)
  3184. guard_true(i3) []
  3185. jump(i0)
  3186. """
  3187. self.optimize_loop(ops, expected)
  3188. def test_bound_lt_add_ovf(self):
  3189. ops = """
  3190. [i0]
  3191. i1 = int_lt(i0, 4)
  3192. guard_true(i1) []
  3193. i2 = int_add_ovf(i0, 10)
  3194. guard_no_overflow() []
  3195. i3 = int_lt(i2, 15)
  3196. guard_true(i3) []
  3197. jump(i0)
  3198. """
  3199. expected = """
  3200. [i0]
  3201. i1 = int_lt(i0, 4)
  3202. guard_true(i1) []
  3203. i2 = int_add(i0, 10)
  3204. jump(i0)
  3205. """
  3206. self.optimize_loop(ops, expected)
  3207. def test_bound_lt_add_ovf_before(self):
  3208. ops = """
  3209. [i0]
  3210. i2 = int_add_ovf(i0, 10)
  3211. guard_no_overflow() []
  3212. i3 = int_lt(i2, 15)
  3213. guard_true(i3) []
  3214. i1 = int_lt(i0, 6)
  3215. guard_true(i1) []
  3216. jump(i0)
  3217. """
  3218. expected = """
  3219. [i0]
  3220. i2 = int_add_ovf(i0, 10)
  3221. guard_no_overflow() []
  3222. i3 = int_lt(i2, 15)
  3223. guard_true(i3) []
  3224. jump(i0)
  3225. """
  3226. self.optimize_loop(ops, expected)
  3227. def test_bound_lt_sub(self):
  3228. ops = """
  3229. [i0]
  3230. i1 = int_lt(i0, 4)
  3231. guard_true(i1) []
  3232. i1p = int_gt(i0, -4)
  3233. guard_true(i1p) []
  3234. i2 = int_sub(i0, 10)
  3235. i3 = int_lt(i2, -5)
  3236. guard_true(i3) []
  3237. jump(i0)
  3238. """
  3239. expected = """
  3240. [i0]
  3241. i1 = int_lt(i0, 4)
  3242. guard_true(i1) []
  3243. i1p = int_gt(i0, -4)
  3244. guard_true(i1p) []
  3245. i2 = int_sub(i0, 10)
  3246. jump(i0)
  3247. """
  3248. self.optimize_loop(ops, expected)
  3249. def test_bound_lt_sub_before(self):
  3250. ops = """
  3251. [i0]
  3252. i2 = int_sub(i0, 10)
  3253. i3 = int_lt(i2, -5)
  3254. guard_true(i3) []
  3255. i1 = int_lt(i0, 5)
  3256. guard_true(i1) []
  3257. jump(i0)
  3258. """
  3259. expected = """
  3260. [i0]
  3261. i2 = int_sub(i0, 10)
  3262. i3 = int_lt(i2, -5)
  3263. guard_true(i3) []
  3264. jump(i0)
  3265. """
  3266. self.optimize_loop(ops, expected)
  3267. def test_bound_ltle(self):
  3268. ops = """
  3269. [i0]
  3270. i1 = int_lt(i0, 4)
  3271. guard_true(i1) []
  3272. i2 = int_le(i0, 3)
  3273. guard_true(i2) []
  3274. jump(i0)
  3275. """
  3276. expected = """
  3277. [i0]
  3278. i1 = int_lt(i0, 4)
  3279. guard_true(i1) []
  3280. jump(i0)
  3281. """
  3282. self.optimize_loop(ops, expected)
  3283. def test_bound_lelt(self):
  3284. ops = """
  3285. [i0]
  3286. i1 = int_le(i0, 4)
  3287. guard_true(i1) []
  3288. i2 = int_lt(i0, 5)
  3289. guard_true(i2) []
  3290. jump(i0)
  3291. """
  3292. expected = """
  3293. [i0]
  3294. i1 = int_le(i0, 4)
  3295. guard_true(i1) []
  3296. jump(i0)
  3297. """
  3298. self.optimize_loop(ops, expected)
  3299. def test_bound_gt(self):
  3300. ops = """
  3301. [i0]
  3302. i1 = int_gt(i0, 5)
  3303. guard_true(i1) []
  3304. i2 = int_gt(i0, 4)
  3305. guard_true(i2) []
  3306. jump(i0)
  3307. """
  3308. expected = """
  3309. [i0]
  3310. i1 = int_gt(i0, 5)
  3311. guard_true(i1) []
  3312. jump(i0)
  3313. """
  3314. self.optimize_loop(ops, expected)
  3315. def test_bound_gtge(self):
  3316. ops = """
  3317. [i0]
  3318. i1 = int_gt(i0, 5)
  3319. guard_true(i1) []
  3320. i2 = int_ge(i0, 6)
  3321. guard_true(i2) []
  3322. jump(i0)
  3323. """
  3324. expected = """
  3325. [i0]
  3326. i1 = int_gt(i0, 5)
  3327. guard_true(i1) []
  3328. jump(i0)
  3329. """
  3330. self.optimize_loop(ops, expected)
  3331. def test_bound_gegt(self):
  3332. ops = """
  3333. [i0]
  3334. i1 = int_ge(i0, 5)
  3335. guard_true(i1) []
  3336. i2 = int_gt(i0, 4)
  3337. guard_true(i2) []
  3338. jump(i0)
  3339. """
  3340. expected = """
  3341. [i0]
  3342. i1 = int_ge(i0, 5)
  3343. guard_true(i1) []
  3344. jump(i0)
  3345. """
  3346. self.optimize_loop(ops, expected)
  3347. def test_bound_ovf(self):
  3348. ops = """
  3349. [i0]
  3350. i1 = int_ge(i0, 0)
  3351. guard_true(i1) []
  3352. i2 = int_lt(i0, 10)
  3353. guard_true(i2) []
  3354. i3 = int_add_ovf(i0, 1)
  3355. guard_no_overflow() []
  3356. jump(i3)
  3357. """
  3358. expected = """
  3359. [i0]
  3360. i1 = int_ge(i0, 0)
  3361. guard_true(i1) []
  3362. i2 = int_lt(i0, 10)
  3363. guard_true(i2) []
  3364. i3 = int_add(i0, 1)
  3365. jump(i3)
  3366. """
  3367. self.optimize_loop(ops, expected)
  3368. def test_bound_arraylen(self):
  3369. ops = """
  3370. [i0, p0]
  3371. p1 = new_array(i0, descr=arraydescr)
  3372. i1 = arraylen_gc(p1)
  3373. i2 = int_gt(i1, -1)
  3374. guard_true(i2) []
  3375. setarrayitem_gc(p0, 0, p1)
  3376. jump(i0, p0)
  3377. """
  3378. # The dead arraylen_gc will be eliminated by the backend.
  3379. expected = """
  3380. [i0, p0]
  3381. p1 = new_array(i0, descr=arraydescr)
  3382. i1 = arraylen_gc(p1)
  3383. setarrayitem_gc(p0, 0, p1)
  3384. jump(i0, p0)
  3385. """
  3386. self.optimize_loop(ops, expected)
  3387. def test_bound_strlen(self):
  3388. ops = """
  3389. [p0]
  3390. i0 = strlen(p0)
  3391. i1 = int_ge(i0, 0)
  3392. guard_true(i1) []
  3393. jump(p0)
  3394. """
  3395. # The dead strlen will be eliminated be the backend.
  3396. expected = """
  3397. [p0]
  3398. i0 = strlen(p0)
  3399. jump(p0)
  3400. """
  3401. self.optimize_strunicode_loop(ops, expected)
  3402. def test_addsub_const(self):
  3403. ops = """
  3404. [i0]
  3405. i1 = int_add(i0, 1)
  3406. i2 = int_sub(i1, 1)
  3407. i3 = int_add(i2, 1)
  3408. i4 = int_mul(i2, i3)
  3409. jump(i4)
  3410. """
  3411. expected = """
  3412. [i0]
  3413. i1 = int_add(i0, 1)
  3414. i4 = int_mul(i0, i1)
  3415. jump(i4)
  3416. """
  3417. self.optimize_loop(ops, expected)
  3418. def test_addsub_int(self):
  3419. ops = """
  3420. [i0, i10]
  3421. i1 = int_add(i0, i10)
  3422. i2 = int_sub(i1, i10)
  3423. i3 = int_add(i2, i10)
  3424. i4 = int_add(i2, i3)
  3425. jump(i4, i10)
  3426. """
  3427. expected = """
  3428. [i0, i10]
  3429. i1 = int_add(i0, i10)
  3430. i4 = int_add(i0, i1)
  3431. jump(i4, i10)
  3432. """
  3433. self.optimize_loop(ops, expected)
  3434. def test_addsub_int2(self):
  3435. ops = """
  3436. [i0, i10]
  3437. i1 = int_add(i10, i0)
  3438. i2 = int_sub(i1, i10)
  3439. i3 = int_add(i10, i2)
  3440. i4 = int_add(i2, i3)
  3441. jump(i4, i10)
  3442. """
  3443. expected = """
  3444. [i0, i10]
  3445. i1 = int_add(i10, i0)
  3446. i4 = int_add(i0, i1)
  3447. jump(i4, i10)
  3448. """
  3449. self.optimize_loop(ops, expected)
  3450. def test_framestackdepth_overhead(self):
  3451. ops = """
  3452. [p0, i22]
  3453. i1 = getfield_gc(p0, descr=valuedescr)
  3454. i2 = int_gt(i1, i22)
  3455. guard_false(i2) []
  3456. i3 = int_add(i1, 1)
  3457. setfield_gc(p0, i3, descr=valuedescr)
  3458. i4 = int_sub(i3, 1)
  3459. setfield_gc(p0, i4, descr=valuedescr)
  3460. i5 = int_gt(i4, i22)
  3461. guard_false(i5) []
  3462. i6 = int_add(i4, 1)
  3463. p331 = force_token()
  3464. i7 = int_sub(i6, 1)
  3465. setfield_gc(p0, i7, descr=valuedescr)
  3466. jump(p0, i22)
  3467. """
  3468. expected = """
  3469. [p0, i22]
  3470. i1 = getfield_gc(p0, descr=valuedescr)
  3471. i2 = int_gt(i1, i22)
  3472. guard_false(i2) []
  3473. i3 = int_add(i1, 1)
  3474. p331 = force_token()
  3475. jump(p0, i22)
  3476. """
  3477. self.optimize_loop(ops, expected)
  3478. def test_addsub_ovf(self):
  3479. ops = """
  3480. [i0]
  3481. i1 = int_add_ovf(i0, 10)
  3482. guard_no_overflow() []
  3483. i2 = int_sub_ovf(i1, 5)
  3484. guard_no_overflow() []
  3485. jump(i2)
  3486. """
  3487. expected = """
  3488. [i0]
  3489. i1 = int_add_ovf(i0, 10)
  3490. guard_no_overflow() []
  3491. i2 = int_sub(i1, 5)
  3492. jump(i2)
  3493. """
  3494. self.optimize_loop(ops, expected)
  3495. def test_subadd_ovf(self):
  3496. ops = """
  3497. [i0]
  3498. i1 = int_sub_ovf(i0, 10)
  3499. guard_no_overflow() []
  3500. i2 = int_add_ovf(i1, 5)
  3501. guard_no_overflow() []
  3502. jump(i2)
  3503. """
  3504. expected = """
  3505. [i0]
  3506. i1 = int_sub_ovf(i0, 10)
  3507. guard_no_overflow() []
  3508. i2 = int_add(i1, 5)
  3509. jump(i2)
  3510. """
  3511. self.optimize_loop(ops, expected)
  3512. def test_bound_and(self):
  3513. ops = """
  3514. [i0]
  3515. i1 = int_and(i0, 255)
  3516. i2 = int_lt(i1, 500)
  3517. guard_true(i2) []
  3518. i3 = int_le(i1, 255)
  3519. guard_true(i3) []
  3520. i4 = int_gt(i1, -1)
  3521. guard_true(i4) []
  3522. i5 = int_ge(i1, 0)
  3523. guard_true(i5) []
  3524. i6 = int_lt(i1, 0)
  3525. guard_false(i6) []
  3526. i7 = int_le(i1, -1)
  3527. guard_false(i7) []
  3528. i8 = int_gt(i1, 255)
  3529. guard_false(i8) []
  3530. i9 = int_ge(i1, 500)
  3531. guard_false(i9) []
  3532. i12 = int_lt(i1, 100)
  3533. guard_true(i12) []
  3534. i13 = int_le(i1, 90)
  3535. guard_true(i13) []
  3536. i14 = int_gt(i1, 10)
  3537. guard_true(i14) []
  3538. i15 = int_ge(i1, 20)
  3539. guard_true(i15) []
  3540. jump(i1)
  3541. """
  3542. expected = """
  3543. [i0]
  3544. i1 = int_and(i0, 255)
  3545. i12 = int_lt(i1, 100)
  3546. guard_true(i12) []
  3547. i13 = int_le(i1, 90)
  3548. guard_true(i13) []
  3549. i14 = int_gt(i1, 10)
  3550. guard_true(i14) []
  3551. i15 = int_ge(i1, 20)
  3552. guard_true(i15) []
  3553. jump(i1)
  3554. """
  3555. self.optimize_loop(ops, expected)
  3556. def test_subsub_ovf(self):
  3557. ops = """
  3558. [i0]
  3559. i1 = int_sub_ovf(1, i0)
  3560. guard_no_overflow() []
  3561. i2 = int_gt(i1, 1)
  3562. guard_true(i2) []
  3563. i3 = int_sub_ovf(1, i0)
  3564. guard_no_overflow() []
  3565. i4 = int_gt(i3, 1)
  3566. guard_true(i4) []
  3567. jump(i0)
  3568. """
  3569. expected = """
  3570. [i0]
  3571. i1 = int_sub_ovf(1, i0)
  3572. guard_no_overflow() []
  3573. i2 = int_gt(i1, 1)
  3574. guard_true(i2) []
  3575. jump(i0)
  3576. """
  3577. self.optimize_loop(ops, expected)
  3578. def test_bound_eq(self):
  3579. ops = """
  3580. [i0, i1]
  3581. i2 = int_le(i0, 4)
  3582. guard_true(i2) []
  3583. i3 = int_eq(i0, i1)
  3584. guard_true(i3) []
  3585. i4 = int_lt(i1, 5)
  3586. guard_true(i4) []
  3587. jump(i0, i1)
  3588. """
  3589. expected = """
  3590. [i0, i1]
  3591. i2 = int_le(i0, 4)
  3592. guard_true(i2) []
  3593. i3 = int_eq(i0, i1)
  3594. guard_true(i3) []
  3595. jump(i0, i1)
  3596. """
  3597. self.optimize_loop(ops, expected)
  3598. def test_bound_eq_const(self):
  3599. ops = """
  3600. [i0]
  3601. i1 = int_eq(i0, 7)
  3602. guard_true(i1) []
  3603. i2 = int_add(i0, 3)
  3604. jump(i2)
  3605. """
  3606. expected = """
  3607. [i0]
  3608. i1 = int_eq(i0, 7)
  3609. guard_true(i1) []
  3610. jump(10)
  3611. """
  3612. self.optimize_loop(ops, expected)
  3613. def test_bound_eq_const_not(self):
  3614. ops = """
  3615. [i0]
  3616. i1 = int_eq(i0, 7)
  3617. guard_false(i1) []
  3618. i2 = int_add(i0, 3)
  3619. jump(i2)
  3620. """
  3621. expected = """
  3622. [i0]
  3623. i1 = int_eq(i0, 7)
  3624. guard_false(i1) []
  3625. i2 = int_add(i0, 3)
  3626. jump(i2)
  3627. """
  3628. self.optimize_loop(ops, expected)
  3629. def test_bound_ne_const(self):
  3630. ops = """
  3631. [i0]
  3632. i1 = int_ne(i0, 7)
  3633. guard_false(i1) []
  3634. i2 = int_add(i0, 3)
  3635. jump(i2)
  3636. """
  3637. expected = """
  3638. [i0]
  3639. i1 = int_ne(i0, 7)
  3640. guard_false(i1) []
  3641. jump(10)
  3642. """
  3643. self.optimize_loop(ops, expected)
  3644. def test_bound_ne_const_not(self):
  3645. ops = """
  3646. [i0]
  3647. i1 = int_ne(i0, 7)
  3648. guard_true(i1) []
  3649. i2 = int_add(i0, 3)
  3650. jump(i2)
  3651. """
  3652. expected = """
  3653. [i0]
  3654. i1 = int_ne(i0, 7)
  3655. guard_true(i1) []
  3656. i2 = int_add(i0, 3)
  3657. jump(i2)
  3658. """
  3659. self.optimize_loop(ops, expected)
  3660. def test_bound_ltne(self):
  3661. ops = """
  3662. [i0, i1]
  3663. i2 = int_lt(i0, 7)
  3664. guard_true(i2) []
  3665. i3 = int_ne(i0, 10)
  3666. guard_true(i2) []
  3667. jump(i0, i1)
  3668. """
  3669. expected = """
  3670. [i0, i1]
  3671. i2 = int_lt(i0, 7)
  3672. guard_true(i2) []
  3673. jump(i0, i1)
  3674. """
  3675. self.optimize_loop(ops, expected)
  3676. def test_bound_lege_const(self):
  3677. ops = """
  3678. [i0]
  3679. i1 = int_ge(i0, 7)
  3680. guard_true(i1) []
  3681. i2 = int_le(i0, 7)
  3682. guard_true(i2) []
  3683. i3 = int_add(i0, 3)
  3684. jump(i3)
  3685. """
  3686. expected = """
  3687. [i0]
  3688. i1 = int_ge(i0, 7)
  3689. guard_true(i1) []
  3690. i2 = int_le(i0, 7)
  3691. guard_true(i2) []
  3692. jump(10)
  3693. """
  3694. self.optimize_loop(ops, expected)
  3695. def test_mul_ovf(self):
  3696. ops = """
  3697. [i0, i1]
  3698. i2 = int_and(i0, 255)
  3699. i3 = int_lt(i1, 5)
  3700. guard_true(i3) []
  3701. i4 = int_gt(i1, -10)
  3702. guard_true(i4) []
  3703. i5 = int_mul_ovf(i2, i1)
  3704. guard_no_overflow() []
  3705. i6 = int_lt(i5, -2550)
  3706. guard_false(i6) []
  3707. i7 = int_ge(i5, 1276)
  3708. guard_false(i7) []
  3709. i8 = int_gt(i5, 126)
  3710. guard_true(i8) []
  3711. jump(i0, i1)
  3712. """
  3713. expected = """
  3714. [i0, i1]
  3715. i2 = int_and(i0, 255)
  3716. i3 = int_lt(i1, 5)
  3717. guard_true(i3) []
  3718. i4 = int_gt(i1, -10)
  3719. guard_true(i4) []
  3720. i5 = int_mul(i2, i1)
  3721. i8 = int_gt(i5, 126)
  3722. guard_true(i8) []
  3723. jump(i0, i1)
  3724. """
  3725. self.optimize_loop(ops, expected)
  3726. def test_mul_ovf_before(self):
  3727. ops = """
  3728. [i0, i1]
  3729. i2 = int_and(i0, 255)
  3730. i22 = int_add(i2, 1)
  3731. i3 = int_mul_ovf(i22, i1)
  3732. guard_no_overflow() []
  3733. i4 = int_lt(i3, 10)
  3734. guard_true(i4) []
  3735. i5 = int_gt(i3, 2)
  3736. guard_true(i5) []
  3737. i6 = int_lt(i1, 0)
  3738. guard_false(i6) []
  3739. jump(i0, i1)
  3740. """
  3741. expected = """
  3742. [i0, i1]
  3743. i2 = int_and(i0, 255)
  3744. i22 = int_add(i2, 1)
  3745. i3 = int_mul_ovf(i22, i1)
  3746. guard_no_overflow() []
  3747. i4 = int_lt(i3, 10)
  3748. guard_true(i4) []
  3749. i5 = int_gt(i3, 2)
  3750. guard_true(i5) []
  3751. jump(i0, i1)
  3752. """
  3753. self.optimize_loop(ops, expected)
  3754. def test_sub_ovf_before(self):
  3755. ops = """
  3756. [i0, i1]
  3757. i2 = int_and(i0, 255)
  3758. i3 = int_sub_ovf(i2, i1)
  3759. guard_no_overflow() []
  3760. i4 = int_le(i3, 10)
  3761. guard_true(i4) []
  3762. i5 = int_ge(i3, 2)
  3763. guard_true(i5) []
  3764. i6 = int_lt(i1, -10)
  3765. guard_false(i6) []
  3766. i7 = int_gt(i1, 253)
  3767. guard_false(i7) []
  3768. jump(i0, i1)
  3769. """
  3770. expected = """
  3771. [i0, i1]
  3772. i2 = int_and(i0, 255)
  3773. i3 = int_sub_ovf(i2, i1)
  3774. guard_no_overflow() []
  3775. i4 = int_le(i3, 10)
  3776. guard_true(i4) []
  3777. i5 = int_ge(i3, 2)
  3778. guard_true(i5) []
  3779. jump(i0, i1)
  3780. """
  3781. self.optimize_loop(ops, expected)
  3782. # ----------
  3783. def optimize_strunicode_loop(self, ops, optops):
  3784. # check with the arguments passed in
  3785. self.optimize_loop(ops, optops)
  3786. # check with replacing 'str' with 'unicode' everywhere
  3787. self.optimize_loop(ops.replace('str','unicode').replace('s"', 'u"'),
  3788. optops.replace('str','unicode').replace('s"', 'u"'))
  3789. def test_newstr_1(self):
  3790. ops = """
  3791. [i0]
  3792. p1 = newstr(1)
  3793. strsetitem(p1, 0, i0)
  3794. i1 = strgetitem(p1, 0)
  3795. jump(i1)
  3796. """
  3797. expected = """
  3798. [i0]
  3799. jump(i0)
  3800. """
  3801. self.optimize_strunicode_loop(ops, expected)
  3802. def test_newstr_2(self):
  3803. ops = """
  3804. [i0, i1]
  3805. p1 = newstr(2)
  3806. strsetitem(p1, 0, i0)
  3807. strsetitem(p1, 1, i1)
  3808. i2 = strgetitem(p1, 1)
  3809. i3 = strgetitem(p1, 0)
  3810. jump(i2, i3)
  3811. """
  3812. expected = """
  3813. [i0, i1]
  3814. jump(i1, i0)
  3815. """
  3816. self.optimize_strunicode_loop(ops, expected)
  3817. def test_str_concat_1(self):
  3818. ops = """
  3819. [p1, p2]
  3820. p3 = call(0, p1, p2, descr=strconcatdescr)
  3821. jump(p2, p3)
  3822. """
  3823. expected = """
  3824. [p1, p2]
  3825. i1 = strlen(p1)
  3826. i2 = strlen(p2)
  3827. i3 = int_add(i1, i2)
  3828. p3 = newstr(i3)
  3829. copystrcontent(p1, p3, 0, 0, i1)
  3830. copystrcontent(p2, p3, 0, i1, i2)
  3831. jump(p2, p3)
  3832. """
  3833. self.optimize_strunicode_loop(ops, expected)
  3834. def test_str_concat_vstr2_str(self):
  3835. ops = """
  3836. [i0, i1, p2]
  3837. p1 = newstr(2)
  3838. strsetitem(p1, 0, i0)
  3839. strsetitem(p1, 1, i1)
  3840. p3 = call(0, p1, p2, descr=strconcatdescr)
  3841. jump(i1, i0, p3)
  3842. """
  3843. expected = """
  3844. [i0, i1, p2]
  3845. i2 = strlen(p2)
  3846. i3 = int_add(2, i2)
  3847. p3 = newstr(i3)
  3848. strsetitem(p3, 0, i0)
  3849. strsetitem(p3, 1, i1)
  3850. copystrcontent(p2, p3, 0, 2, i2)
  3851. jump(i1, i0, p3)
  3852. """
  3853. self.optimize_strunicode_loop(ops, expected)
  3854. def test_str_concat_str_vstr2(self):
  3855. ops = """
  3856. [i0, i1, p2]
  3857. p1 = newstr(2)
  3858. strsetitem(p1, 0, i0)
  3859. strsetitem(p1, 1, i1)
  3860. p3 = call(0, p2, p1, descr=strconcatdescr)
  3861. jump(i1, i0, p3)
  3862. """
  3863. expected = """
  3864. [i0, i1, p2]
  3865. i2 = strlen(p2)
  3866. i3 = int_add(i2, 2)
  3867. p3 = newstr(i3)
  3868. copystrcontent(p2, p3, 0, 0, i2)
  3869. strsetitem(p3, i2, i0)
  3870. i5 = int_add(i2, 1)
  3871. strsetitem(p3, i5, i1)
  3872. i6 = int_add(i5, 1) # will be killed by the backend
  3873. jump(i1, i0, p3)
  3874. """
  3875. self.optimize_strunicode_loop(ops, expected)
  3876. def test_str_concat_str_str_str(self):
  3877. ops = """
  3878. [p1, p2, p3]
  3879. p4 = call(0, p1, p2, descr=strconcatdescr)
  3880. p5 = call(0, p4, p3, descr=strconcatdescr)
  3881. jump(p2, p3, p5)
  3882. """
  3883. expected = """
  3884. [p1, p2, p3]
  3885. i1 = strlen(p1)
  3886. i2 = strlen(p2)
  3887. i12 = int_add(i1, i2)
  3888. i3 = strlen(p3)
  3889. i123 = int_add(i12, i3)
  3890. p5 = newstr(i123)
  3891. copystrcontent(p1, p5, 0, 0, i1)
  3892. copystrcontent(p2, p5, 0, i1, i2)
  3893. copystrcontent(p3, p5, 0, i12, i3)
  3894. jump(p2, p3, p5)
  3895. """
  3896. self.optimize_strunicode_loop(ops, expected)
  3897. def test_str_concat_str_cstr1(self):
  3898. ops = """
  3899. [p2]
  3900. p3 = call(0, p2, s"x", descr=strconcatdescr)
  3901. jump(p3)
  3902. """
  3903. expected = """
  3904. [p2]
  3905. i2 = strlen(p2)
  3906. i3 = int_add(i2, 1)
  3907. p3 = newstr(i3)
  3908. copystrcontent(p2, p3, 0, 0, i2)
  3909. strsetitem(p3, i2, 120) # == ord('x')
  3910. jump(p3)
  3911. """
  3912. self.optimize_strunicode_loop(ops, expected)
  3913. def test_str_concat_consts(self):
  3914. ops = """
  3915. []
  3916. p1 = same_as(s"ab")
  3917. p2 = same_as(s"cde")
  3918. p3 = call(0, p1, p2, descr=strconcatdescr)
  3919. escape(p3)
  3920. jump()
  3921. """
  3922. expected = """
  3923. []
  3924. escape(s"abcde")
  3925. jump()
  3926. """
  3927. self.optimize_strunicode_loop(ops, expected)
  3928. def test_str_concat_constant_lengths(self):
  3929. ops = """
  3930. [i0]
  3931. p0 = newstr(1)
  3932. strsetitem(p0, 0, i0)
  3933. p1 = newstr(0)
  3934. p2 = call(0, p0, p1, descr=strconcatdescr)
  3935. i1 = call(0, p2, p0, descr=strequaldescr)
  3936. finish(i1)
  3937. """
  3938. expected = """
  3939. [i0]
  3940. finish(1)
  3941. """
  3942. self.optimize_strunicode_loop(ops, expected)
  3943. def test_str_concat_constant_lengths_2(self):
  3944. ops = """
  3945. [i0]
  3946. p0 = newstr(0)
  3947. p1 = newstr(1)
  3948. strsetitem(p1, 0, i0)
  3949. p2 = call(0, p0, p1, descr=strconcatdescr)
  3950. i1 = call(0, p2, p1, descr=strequaldescr)
  3951. finish(i1)
  3952. """
  3953. expected = """
  3954. [i0]
  3955. finish(1)
  3956. """
  3957. self.optimize_strunicode_loop(ops, expected)
  3958. def test_str_slice_1(self):
  3959. ops = """
  3960. [p1, i1, i2]
  3961. p2 = call(0, p1, i1, i2, descr=strslicedescr)
  3962. jump(p2, i1, i2)
  3963. """
  3964. expected = """
  3965. [p1, i1, i2]
  3966. i3 = int_sub(i2, i1)
  3967. p2 = newstr(i3)
  3968. copystrcontent(p1, p2, i1, 0, i3)
  3969. jump(p2, i1, i2)
  3970. """
  3971. self.optimize_strunicode_loop(ops, expected)
  3972. def test_str_slice_2(self):
  3973. ops = """
  3974. [p1, i2]
  3975. p2 = call(0, p1, 0, i2, descr=strslicedescr)
  3976. jump(p2, i2)
  3977. """
  3978. expected = """
  3979. [p1, i2]
  3980. p2 = newstr(i2)
  3981. copystrcontent(p1, p2, 0, 0, i2)
  3982. jump(p2, i2)
  3983. """
  3984. self.optimize_strunicode_loop(ops, expected)
  3985. def test_str_slice_3(self):
  3986. ops = """
  3987. [p1, i1, i2, i3, i4]
  3988. p2 = call(0, p1, i1, i2, descr=strslicedescr)
  3989. p3 = call(0, p2, i3, i4, descr=strslicedescr)
  3990. jump(p3, i1, i2, i3, i4)
  3991. """
  3992. expected = """
  3993. [p1, i1, i2, i3, i4]
  3994. i0 = int_sub(i2, i1) # killed by the backend
  3995. i5 = int_sub(i4, i3)
  3996. i6 = int_add(i1, i3)
  3997. p3 = newstr(i5)
  3998. copystrcontent(p1, p3, i6, 0, i5)
  3999. jump(p3, i1, i2, i3, i4)
  4000. """
  4001. self.optimize_strunicode_loop(ops, expected)
  4002. def test_str_slice_getitem1(self):
  4003. ops = """
  4004. [p1, i1, i2, i3]
  4005. p2 = call(0, p1, i1, i2, descr=strslicedescr)
  4006. i4 = strgetitem(p2, i3)
  4007. escape(i4)
  4008. jump(p1, i1, i2, i3)
  4009. """
  4010. expected = """
  4011. [p1, i1, i2, i3]
  4012. i6 = int_sub(i2, i1) # killed by the backend
  4013. i5 = int_add(i1, i3)
  4014. i4 = strgetitem(p1, i5)
  4015. escape(i4)
  4016. jump(p1, i1, i2, i3)
  4017. """
  4018. self.optimize_strunicode_loop(ops, expected)
  4019. def test_str_slice_plain(self):
  4020. ops = """
  4021. [i3, i4]
  4022. p1 = newstr(2)
  4023. strsetitem(p1, 0, i3)
  4024. strsetitem(p1, 1, i4)
  4025. p2 = call(0, p1, 1, 2, descr=strslicedescr)
  4026. i5 = strgetitem(p2, 0)
  4027. escape(i5)
  4028. jump(i3, i4)
  4029. """
  4030. expected = """
  4031. [i3, i4]
  4032. escape(i4)
  4033. jump(i3, i4)
  4034. """
  4035. self.optimize_strunicode_loop(ops, expected)
  4036. def test_str_slice_concat(self):
  4037. ops = """
  4038. [p1, i1, i2, p2]
  4039. p3 = call(0, p1, i1, i2, descr=strslicedescr)
  4040. p4 = call(0, p3, p2, descr=strconcatdescr)
  4041. jump(p4, i1, i2, p2)
  4042. """
  4043. expected = """
  4044. [p1, i1, i2, p2]
  4045. i3 = int_sub(i2, i1) # length of p3
  4046. i4 = strlen(p2)
  4047. i5 = int_add(i3, i4)
  4048. p4 = newstr(i5)
  4049. copystrcontent(p1, p4, i1, 0, i3)
  4050. copystrcontent(p2, p4, 0, i3, i4)
  4051. jump(p4, i1, i2, p2)
  4052. """
  4053. self.optimize_strunicode_loop(ops, expected)
  4054. def test_str_slice_plain_virtual(self):
  4055. ops = """
  4056. []
  4057. p0 = newstr(11)
  4058. copystrcontent(s"hello world", p0, 0, 0, 11)
  4059. p1 = call(0, p0, 0, 5, descr=strslicedescr)
  4060. finish(p1)
  4061. """
  4062. expected = """
  4063. []
  4064. finish(s"hello")
  4065. """
  4066. self.optimize_strunicode_loop(ops, expected)
  4067. # ----------
  4068. def optimize_strunicode_loop_extradescrs(self, ops, optops):
  4069. class FakeCallInfoCollection:
  4070. def callinfo_for_oopspec(self, oopspecindex):
  4071. calldescrtype = type(LLtypeMixin.strequaldescr)
  4072. effectinfotype = type(LLtypeMixin.strequaldescr.get_extra_info())
  4073. for value in LLtypeMixin.__dict__.values():
  4074. if isinstance(value, calldescrtype):
  4075. extra = value.get_extra_info()
  4076. if (extra and isinstance(extra, effectinfotype) and
  4077. extra.oopspecindex == oopspecindex):
  4078. # returns 0 for 'func' in this test
  4079. return value, 0
  4080. raise AssertionError("not found: oopspecindex=%d" %
  4081. oopspecindex)
  4082. #
  4083. self.callinfocollection = FakeCallInfoCollection()
  4084. self.optimize_strunicode_loop(ops, optops)
  4085. def test_str_equal_noop1(self):
  4086. ops = """
  4087. [p1, p2]
  4088. i0 = call(0, p1, p2, descr=strequaldescr)
  4089. escape(i0)
  4090. jump(p1, p2)
  4091. """
  4092. self.optimize_strunicode_loop_extradescrs(ops, ops)
  4093. def test_str_equal_noop2(self):
  4094. ops = """
  4095. [p1, p2, p3]
  4096. p4 = call(0, p1, p2, descr=strconcatdescr)
  4097. i0 = call(0, p3, p4, descr=strequaldescr)
  4098. escape(i0)
  4099. jump(p1, p2, p3)
  4100. """
  4101. expected = """
  4102. [p1, p2, p3]
  4103. i1 = strlen(p1)
  4104. i2 = strlen(p2)
  4105. i3 = int_add(i1, i2)
  4106. p4 = newstr(i3)
  4107. copystrcontent(p1, p4, 0, 0, i1)
  4108. copystrcontent(p2, p4, 0, i1, i2)
  4109. i0 = call(0, p3, p4, descr=strequaldescr)
  4110. escape(i0)
  4111. jump(p1, p2, p3)
  4112. """
  4113. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4114. def test_str_equal_slice1(self):
  4115. ops = """
  4116. [p1, i1, i2, p3]
  4117. p4 = call(0, p1, i1, i2, descr=strslicedescr)
  4118. i0 = call(0, p4, p3, descr=strequaldescr)
  4119. escape(i0)
  4120. jump(p1, i1, i2, p3)
  4121. """
  4122. expected = """
  4123. [p1, i1, i2, p3]
  4124. i3 = int_sub(i2, i1)
  4125. i0 = call(0, p1, i1, i3, p3, descr=streq_slice_checknull_descr)
  4126. escape(i0)
  4127. jump(p1, i1, i2, p3)
  4128. """
  4129. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4130. def test_str_equal_slice2(self):
  4131. ops = """
  4132. [p1, i1, i2, p3]
  4133. p4 = call(0, p1, i1, i2, descr=strslicedescr)
  4134. i0 = call(0, p3, p4, descr=strequaldescr)
  4135. escape(i0)
  4136. jump(p1, i1, i2, p3)
  4137. """
  4138. expected = """
  4139. [p1, i1, i2, p3]
  4140. i4 = int_sub(i2, i1)
  4141. i0 = call(0, p1, i1, i4, p3, descr=streq_slice_checknull_descr)
  4142. escape(i0)
  4143. jump(p1, i1, i2, p3)
  4144. """
  4145. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4146. def test_str_equal_slice3(self):
  4147. ops = """
  4148. [p1, i1, i2, p3]
  4149. guard_nonnull(p3) []
  4150. p4 = call(0, p1, i1, i2, descr=strslicedescr)
  4151. i0 = call(0, p3, p4, descr=strequaldescr)
  4152. escape(i0)
  4153. jump(p1, i1, i2, p3)
  4154. """
  4155. expected = """
  4156. [p1, i1, i2, p3]
  4157. guard_nonnull(p3) []
  4158. i4 = int_sub(i2, i1)
  4159. i0 = call(0, p1, i1, i4, p3, descr=streq_slice_nonnull_descr)
  4160. escape(i0)
  4161. jump(p1, i1, i2, p3)
  4162. """
  4163. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4164. def test_str_equal_slice4(self):
  4165. ops = """
  4166. [p1, i1, i2]
  4167. p3 = call(0, p1, i1, i2, descr=strslicedescr)
  4168. i0 = call(0, p3, s"x", descr=strequaldescr)
  4169. escape(i0)
  4170. jump(p1, i1, i2)
  4171. """
  4172. expected = """
  4173. [p1, i1, i2]
  4174. i3 = int_sub(i2, i1)
  4175. i0 = call(0, p1, i1, i3, 120, descr=streq_slice_char_descr)
  4176. escape(i0)
  4177. jump(p1, i1, i2)
  4178. """
  4179. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4180. def test_str_equal_slice5(self):
  4181. ops = """
  4182. [p1, i1, i2, i3]
  4183. p4 = call(0, p1, i1, i2, descr=strslicedescr)
  4184. p5 = newstr(1)
  4185. strsetitem(p5, 0, i3)
  4186. i0 = call(0, p5, p4, descr=strequaldescr)
  4187. escape(i0)
  4188. jump(p1, i1, i2, i3)
  4189. """
  4190. expected = """
  4191. [p1, i1, i2, i3]
  4192. i4 = int_sub(i2, i1)
  4193. i0 = call(0, p1, i1, i4, i3, descr=streq_slice_char_descr)
  4194. escape(i0)
  4195. jump(p1, i1, i2, i3)
  4196. """
  4197. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4198. def test_str_equal_none1(self):
  4199. ops = """
  4200. [p1]
  4201. i0 = call(0, p1, NULL, descr=strequaldescr)
  4202. escape(i0)
  4203. jump(p1)
  4204. """
  4205. expected = """
  4206. [p1]
  4207. i0 = ptr_eq(p1, NULL)
  4208. escape(i0)
  4209. jump(p1)
  4210. """
  4211. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4212. def test_str_equal_none2(self):
  4213. ops = """
  4214. [p1]
  4215. i0 = call(0, NULL, p1, descr=strequaldescr)
  4216. escape(i0)
  4217. jump(p1)
  4218. """
  4219. expected = """
  4220. [p1]
  4221. i0 = ptr_eq(p1, NULL)
  4222. escape(i0)
  4223. jump(p1)
  4224. """
  4225. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4226. def test_str_equal_nonnull1(self):
  4227. ops = """
  4228. [p1]
  4229. guard_nonnull(p1) []
  4230. i0 = call(0, p1, s"hello world", descr=strequaldescr)
  4231. escape(i0)
  4232. jump(p1)
  4233. """
  4234. expected = """
  4235. [p1]
  4236. guard_nonnull(p1) []
  4237. i0 = call(0, p1, s"hello world", descr=streq_nonnull_descr)
  4238. escape(i0)
  4239. jump(p1)
  4240. """
  4241. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4242. def test_str_equal_nonnull2(self):
  4243. ops = """
  4244. [p1]
  4245. guard_nonnull(p1) []
  4246. i0 = call(0, p1, s"", descr=strequaldescr)
  4247. escape(i0)
  4248. jump(p1)
  4249. """
  4250. expected = """
  4251. [p1]
  4252. guard_nonnull(p1) []
  4253. i1 = strlen(p1)
  4254. i0 = int_eq(i1, 0)
  4255. escape(i0)
  4256. jump(p1)
  4257. """
  4258. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4259. def test_str_equal_nonnull3(self):
  4260. ops = """
  4261. [p1]
  4262. guard_nonnull(p1) []
  4263. i0 = call(0, p1, s"x", descr=strequaldescr)
  4264. escape(i0)
  4265. jump(p1)
  4266. """
  4267. expected = """
  4268. [p1]
  4269. guard_nonnull(p1) []
  4270. i0 = call(0, p1, 120, descr=streq_nonnull_char_descr)
  4271. escape(i0)
  4272. jump(p1)
  4273. """
  4274. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4275. def test_str_equal_nonnull4(self):
  4276. ops = """
  4277. [p1, p2]
  4278. p4 = call(0, p1, p2, descr=strconcatdescr)
  4279. i0 = call(0, s"hello world", p4, descr=strequaldescr)
  4280. escape(i0)
  4281. jump(p1, p2)
  4282. """
  4283. expected = """
  4284. [p1, p2]
  4285. i1 = strlen(p1)
  4286. i2 = strlen(p2)
  4287. i3 = int_add(i1, i2)
  4288. p4 = newstr(i3)
  4289. copystrcontent(p1, p4, 0, 0, i1)
  4290. copystrcontent(p2, p4, 0, i1, i2)
  4291. i0 = call(0, s"hello world", p4, descr=streq_nonnull_descr)
  4292. escape(i0)
  4293. jump(p1, p2)
  4294. """
  4295. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4296. def test_str_equal_chars0(self):
  4297. ops = """
  4298. [i1]
  4299. p1 = newstr(0)
  4300. i0 = call(0, p1, s"", descr=strequaldescr)
  4301. escape(i0)
  4302. jump(i1)
  4303. """
  4304. expected = """
  4305. [i1]
  4306. escape(1)
  4307. jump(i1)
  4308. """
  4309. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4310. def test_str_equal_chars1(self):
  4311. ops = """
  4312. [i1]
  4313. p1 = newstr(1)
  4314. strsetitem(p1, 0, i1)
  4315. i0 = call(0, p1, s"x", descr=strequaldescr)
  4316. escape(i0)
  4317. jump(i1)
  4318. """
  4319. expected = """
  4320. [i1]
  4321. i0 = int_eq(i1, 120) # ord('x')
  4322. escape(i0)
  4323. jump(i1)
  4324. """
  4325. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4326. def test_str_equal_chars2(self):
  4327. ops = """
  4328. [i1, i2]
  4329. p1 = newstr(2)
  4330. strsetitem(p1, 0, i1)
  4331. strsetitem(p1, 1, i2)
  4332. i0 = call(0, p1, s"xy", descr=strequaldescr)
  4333. escape(i0)
  4334. jump(i1, i2)
  4335. """
  4336. expected = """
  4337. [i1, i2]
  4338. p1 = newstr(2)
  4339. strsetitem(p1, 0, i1)
  4340. strsetitem(p1, 1, i2)
  4341. i0 = call(0, p1, s"xy", descr=streq_lengthok_descr)
  4342. escape(i0)
  4343. jump(i1, i2)
  4344. """
  4345. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4346. def test_str_equal_chars3(self):
  4347. ops = """
  4348. [p1]
  4349. i0 = call(0, s"x", p1, descr=strequaldescr)
  4350. escape(i0)
  4351. jump(p1)
  4352. """
  4353. expected = """
  4354. [p1]
  4355. i0 = call(0, p1, 120, descr=streq_checknull_char_descr)
  4356. escape(i0)
  4357. jump(p1)
  4358. """
  4359. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4360. def test_str_equal_lengthmismatch1(self):
  4361. ops = """
  4362. [i1]
  4363. p1 = newstr(1)
  4364. strsetitem(p1, 0, i1)
  4365. i0 = call(0, s"xy", p1, descr=strequaldescr)
  4366. escape(i0)
  4367. jump(i1)
  4368. """
  4369. expected = """
  4370. [i1]
  4371. escape(0)
  4372. jump(i1)
  4373. """
  4374. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4375. def test_str2unicode_constant(self):
  4376. ops = """
  4377. []
  4378. p0 = call(0, "xy", descr=s2u_descr) # string -> unicode
  4379. escape(p0)
  4380. jump()
  4381. """
  4382. expected = """
  4383. []
  4384. escape(u"xy")
  4385. jump()
  4386. """
  4387. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4388. def test_str2unicode_nonconstant(self):
  4389. ops = """
  4390. [p0]
  4391. p1 = call(0, p0, descr=s2u_descr) # string -> unicode
  4392. escape(p1)
  4393. jump(p1)
  4394. """
  4395. self.optimize_strunicode_loop_extradescrs(ops, ops)
  4396. # more generally, supporting non-constant but virtual cases is
  4397. # not obvious, because of the exception UnicodeDecodeError that
  4398. # can be raised by ll_str2unicode()
  4399. def test_strgetitem_repeated(self):
  4400. ops = """
  4401. [p0, i0]
  4402. i1 = strgetitem(p0, i0)
  4403. i2 = strgetitem(p0, i0)
  4404. i3 = int_eq(i1, i2)
  4405. guard_true(i3) []
  4406. escape(i2)
  4407. jump(p0, i0)
  4408. """
  4409. expected = """
  4410. [p0, i0]
  4411. i1 = strgetitem(p0, i0)
  4412. escape(i1)
  4413. jump(p0, i0)
  4414. """
  4415. self.optimize_strunicode_loop(ops, expected)
  4416. def test_int_is_true_bounds(self):
  4417. ops = """
  4418. [p0]
  4419. i0 = strlen(p0)
  4420. i1 = int_is_true(i0)
  4421. guard_true(i1) []
  4422. i2 = int_ge(0, i0)
  4423. guard_false(i2) []
  4424. jump(p0)
  4425. """
  4426. expected = """
  4427. [p0]
  4428. i0 = strlen(p0)
  4429. i1 = int_is_true(i0)
  4430. guard_true(i1) []
  4431. jump(p0)
  4432. """
  4433. self.optimize_strunicode_loop(ops, expected)
  4434. def test_strslice_subtraction_folds(self):
  4435. ops = """
  4436. [p0, i0]
  4437. i1 = int_add(i0, 1)
  4438. p1 = call(0, p0, i0, i1, descr=strslicedescr)
  4439. escape(p1)
  4440. jump(p0, i1)
  4441. """
  4442. expected = """
  4443. [p0, i0]
  4444. i1 = int_add(i0, 1)
  4445. p1 = newstr(1)
  4446. i2 = strgetitem(p0, i0)
  4447. strsetitem(p1, 0, i2)
  4448. escape(p1)
  4449. jump(p0, i1)
  4450. """
  4451. self.optimize_strunicode_loop(ops, expected)
  4452. def test_float_mul_reversed(self):
  4453. ops = """
  4454. [f0, f1]
  4455. f2 = float_mul(f0, f1)
  4456. f3 = float_mul(f1, f0)
  4457. jump(f2, f3)
  4458. """
  4459. expected = """
  4460. [f0, f1]
  4461. f2 = float_mul(f0, f1)
  4462. jump(f2, f2)
  4463. """
  4464. self.optimize_loop(ops, expected)
  4465. def test_null_char_str(self):
  4466. ops = """
  4467. [p0]
  4468. p1 = newstr(4)
  4469. setfield_gc(p0, p1, descr=valuedescr)
  4470. jump(p0)
  4471. """
  4472. # It used to be the case that this would have a series of
  4473. # strsetitem(p1, idx, 0), which was silly because memory is 0 filled
  4474. # when allocated.
  4475. expected = """
  4476. [p0]
  4477. p1 = newstr(4)
  4478. setfield_gc(p0, p1, descr=valuedescr)
  4479. jump(p0)
  4480. """
  4481. self.optimize_strunicode_loop(ops, expected)
  4482. def test_newstr_strlen(self):
  4483. ops = """
  4484. [i0]
  4485. p0 = newstr(i0)
  4486. escape(p0)
  4487. i1 = strlen(p0)
  4488. i2 = int_add(i1, 1)
  4489. jump(i2)
  4490. """
  4491. expected = """
  4492. [i0]
  4493. p0 = newstr(i0)
  4494. escape(p0)
  4495. i1 = int_add(i0, 1)
  4496. jump(i1)
  4497. """
  4498. self.optimize_strunicode_loop(ops, expected)
  4499. def test_intmod_bounds(self):
  4500. ops = """
  4501. [i0, i1]
  4502. i2 = int_mod(i0, 12)
  4503. i3 = int_gt(i2, 12)
  4504. guard_false(i3) []
  4505. i4 = int_lt(i2, -12)
  4506. guard_false(i4) []
  4507. i5 = int_mod(i1, -12)
  4508. i6 = int_lt(i5, -12)
  4509. guard_false(i6) []
  4510. i7 = int_gt(i5, 12)
  4511. guard_false(i7) []
  4512. jump(i2, i5)
  4513. """
  4514. expected = """
  4515. [i0, i1]
  4516. i2 = int_mod(i0, 12)
  4517. i5 = int_mod(i1, -12)
  4518. jump(i2, i5)
  4519. """
  4520. self.optimize_loop(ops, expected)
  4521. # This the sequence of resoperations that is generated for a Python
  4522. # app-level int % int. When the modulus is constant and when i0
  4523. # is known non-negative it should be optimized to a single int_mod.
  4524. ops = """
  4525. [i0]
  4526. i5 = int_ge(i0, 0)
  4527. guard_true(i5) []
  4528. i1 = int_mod(i0, 42)
  4529. i2 = int_rshift(i1, %d)
  4530. i3 = int_and(42, i2)
  4531. i4 = int_add(i1, i3)
  4532. finish(i4)
  4533. """ % (LONG_BIT-1)
  4534. expected = """
  4535. [i0]
  4536. i5 = int_ge(i0, 0)
  4537. guard_true(i5) []
  4538. i1 = int_mod(i0, 42)
  4539. finish(i1)
  4540. """
  4541. self.optimize_loop(ops, expected)
  4542. # 'n % power-of-two' can be turned into int_and(); at least that's
  4543. # easy to do now if n is known to be non-negative.
  4544. ops = """
  4545. [i0]
  4546. i5 = int_ge(i0, 0)
  4547. guard_true(i5) []
  4548. i1 = int_mod(i0, 8)
  4549. i2 = int_rshift(i1, %d)
  4550. i3 = int_and(42, i2)
  4551. i4 = int_add(i1, i3)
  4552. finish(i4)
  4553. """ % (LONG_BIT-1)
  4554. expected = """
  4555. [i0]
  4556. i5 = int_ge(i0, 0)
  4557. guard_true(i5) []
  4558. i1 = int_and(i0, 7)
  4559. finish(i1)
  4560. """
  4561. self.optimize_loop(ops, expected)
  4562. # Of course any 'maybe-negative % power-of-two' can be turned into
  4563. # int_and(), but that's a bit harder to detect here because it turns
  4564. # into several operations, and of course it is wrong to just turn
  4565. # int_mod(i0, 16) into int_and(i0, 15).
  4566. ops = """
  4567. [i0]
  4568. i1 = int_mod(i0, 16)
  4569. i2 = int_rshift(i1, %d)
  4570. i3 = int_and(16, i2)
  4571. i4 = int_add(i1, i3)
  4572. finish(i4)
  4573. """ % (LONG_BIT-1)
  4574. expected = """
  4575. [i0]
  4576. i4 = int_and(i0, 15)
  4577. finish(i4)
  4578. """
  4579. py.test.skip("harder")
  4580. self.optimize_loop(ops, expected)
  4581. def test_intmod_bounds_bug1(self):
  4582. ops = """
  4583. [i0]
  4584. i1 = int_mod(i0, %d)
  4585. i2 = int_eq(i1, 0)
  4586. guard_false(i2) []
  4587. finish()
  4588. """ % (-(1<<(LONG_BIT-1)),)
  4589. self.optimize_loop(ops, ops)
  4590. def test_bounded_lazy_setfield(self):
  4591. ops = """
  4592. [p0, i0]
  4593. i1 = int_gt(i0, 2)
  4594. guard_true(i1) []
  4595. setarrayitem_gc(p0, 0, 3)
  4596. setarrayitem_gc(p0, 2, 4)
  4597. setarrayitem_gc(p0, i0, 15)
  4598. i2 = getarrayitem_gc(p0, 2)
  4599. jump(p0, i2)
  4600. """
  4601. # Remove the getarrayitem_gc, because we know that p[i0] does not alias
  4602. # p0[2]
  4603. expected = """
  4604. [p0, i0]
  4605. i1 = int_gt(i0, 2)
  4606. guard_true(i1) []
  4607. setarrayitem_gc(p0, i0, 15)
  4608. setarrayitem_gc(p0, 0, 3)
  4609. setarrayitem_gc(p0, 2, 4)
  4610. jump(p0, 4)
  4611. """
  4612. self.optimize_loop(ops, expected)
  4613. def test_empty_copystrunicontent(self):
  4614. ops = """
  4615. [p0, p1, i0, i2, i3]
  4616. i4 = int_eq(i3, 0)
  4617. guard_true(i4) []
  4618. copystrcontent(p0, p1, i0, i2, i3)
  4619. jump(p0, p1, i0, i2, i3)
  4620. """
  4621. expected = """
  4622. [p0, p1, i0, i2, i3]
  4623. i4 = int_eq(i3, 0)
  4624. guard_true(i4) []
  4625. jump(p0, p1, i0, i2, 0)
  4626. """
  4627. self.optimize_strunicode_loop(ops, expected)
  4628. def test_empty_copystrunicontent_virtual(self):
  4629. ops = """
  4630. [p0]
  4631. p1 = newstr(23)
  4632. copystrcontent(p0, p1, 0, 0, 0)
  4633. jump(p0)
  4634. """
  4635. expected = """
  4636. [p0]
  4637. jump(p0)
  4638. """
  4639. self.optimize_strunicode_loop(ops, expected)
  4640. def test_forced_virtuals_aliasing(self):
  4641. ops = """
  4642. [i0, i1]
  4643. p0 = new(descr=ssize)
  4644. p1 = new(descr=ssize)
  4645. escape(p0)
  4646. escape(p1)
  4647. setfield_gc(p0, i0, descr=adescr)
  4648. setfield_gc(p1, i1, descr=adescr)
  4649. i2 = getfield_gc(p0, descr=adescr)
  4650. jump(i2, i2)
  4651. """
  4652. expected = """
  4653. [i0, i1]
  4654. p0 = new(descr=ssize)
  4655. escape(p0)
  4656. p1 = new(descr=ssize)
  4657. escape(p1)
  4658. setfield_gc(p0, i0, descr=adescr)
  4659. setfield_gc(p1, i1, descr=adescr)
  4660. jump(i0, i0)
  4661. """
  4662. py.test.skip("not implemented")
  4663. # setfields on things that used to be virtual still can't alias each
  4664. # other
  4665. self.optimize_loop(ops, expected)
  4666. def test_plain_virtual_string_copy_content(self):
  4667. ops = """
  4668. [i1]
  4669. p0 = newstr(6)
  4670. copystrcontent(s"hello!", p0, 0, 0, 6)
  4671. p1 = call(0, p0, s"abc123", descr=strconcatdescr)
  4672. i0 = strgetitem(p1, i1)
  4673. finish(i0)
  4674. """
  4675. expected = """
  4676. [i1]
  4677. i0 = strgetitem(s"hello!abc123", i1)
  4678. finish(i0)
  4679. """
  4680. self.optimize_strunicode_loop(ops, expected)
  4681. def test_plain_virtual_string_copy_content_2(self):
  4682. ops = """
  4683. []
  4684. p0 = newstr(6)
  4685. copystrcontent(s"hello!", p0, 0, 0, 6)
  4686. p1 = call(0, p0, s"abc123", descr=strconcatdescr)
  4687. i0 = strgetitem(p1, 0)
  4688. finish(i0)
  4689. """
  4690. expected = """
  4691. []
  4692. finish(104)
  4693. """
  4694. self.optimize_strunicode_loop(ops, expected)
  4695. def test_ptr_eq_str_constant(self):
  4696. ops = """
  4697. []
  4698. i0 = ptr_eq(s"abc", s"\x00")
  4699. finish(i0)
  4700. """
  4701. expected = """
  4702. []
  4703. finish(0)
  4704. """
  4705. self.optimize_loop(ops, expected)
  4706. def test_known_equal_ints(self):
  4707. py.test.skip("in-progress")
  4708. ops = """
  4709. [i0, i1, i2, p0]
  4710. i3 = int_eq(i0, i1)
  4711. guard_true(i3) []
  4712. i4 = int_lt(i2, i0)
  4713. guard_true(i4) []
  4714. i5 = int_lt(i2, i1)
  4715. guard_true(i5) []
  4716. i6 = getarrayitem_gc(p0, i2)
  4717. finish(i6)
  4718. """
  4719. expected = """
  4720. [i0, i1, i2, p0]
  4721. i3 = int_eq(i0, i1)
  4722. guard_true(i3) []
  4723. i4 = int_lt(i2, i0)
  4724. guard_true(i4) []
  4725. i6 = getarrayitem_gc(p0, i3)
  4726. finish(i6)
  4727. """
  4728. self.optimize_loop(ops, expected)
  4729. def test_str_copy_virtual(self):
  4730. ops = """
  4731. [i0]
  4732. p0 = newstr(8)
  4733. strsetitem(p0, 0, i0)
  4734. strsetitem(p0, 1, i0)
  4735. strsetitem(p0, 2, i0)
  4736. strsetitem(p0, 3, i0)
  4737. strsetitem(p0, 4, i0)
  4738. strsetitem(p0, 5, i0)
  4739. strsetitem(p0, 6, i0)
  4740. strsetitem(p0, 7, i0)
  4741. p1 = newstr(12)
  4742. copystrcontent(p0, p1, 0, 0, 8)
  4743. strsetitem(p1, 8, 3)
  4744. strsetitem(p1, 9, 0)
  4745. strsetitem(p1, 10, 0)
  4746. strsetitem(p1, 11, 0)
  4747. finish(p1)
  4748. """
  4749. expected = """
  4750. [i0]
  4751. p1 = newstr(12)
  4752. strsetitem(p1, 0, i0)
  4753. strsetitem(p1, 1, i0)
  4754. strsetitem(p1, 2, i0)
  4755. strsetitem(p1, 3, i0)
  4756. strsetitem(p1, 4, i0)
  4757. strsetitem(p1, 5, i0)
  4758. strsetitem(p1, 6, i0)
  4759. strsetitem(p1, 7, i0)
  4760. strsetitem(p1, 8, 3)
  4761. finish(p1)
  4762. """
  4763. self.optimize_strunicode_loop(ops, expected)
  4764. def test_str_copy_constant_virtual(self):
  4765. ops = """
  4766. []
  4767. p0 = newstr(10)
  4768. copystrcontent(s"abcd", p0, 0, 0, 4)
  4769. strsetitem(p0, 4, 101)
  4770. copystrcontent(s"fghij", p0, 0, 5, 5)
  4771. finish(p0)
  4772. """
  4773. expected = """
  4774. []
  4775. finish(s"abcdefghij")
  4776. """
  4777. self.optimize_strunicode_loop(ops, expected)
  4778. def test_call_pure_vstring_const(self):
  4779. py.test.skip("implement me")
  4780. ops = """
  4781. []
  4782. p0 = newstr(3)
  4783. strsetitem(p0, 0, 97)
  4784. strsetitem(p0, 1, 98)
  4785. strsetitem(p0, 2, 99)
  4786. i0 = call_pure(123, p0, descr=nonwritedescr)
  4787. finish(i0)
  4788. """
  4789. expected = """
  4790. []
  4791. finish(5)
  4792. """
  4793. call_pure_results = {
  4794. (ConstInt(123), get_const_ptr_for_string("abc"),): ConstInt(5),
  4795. }
  4796. self.optimize_loop(ops, expected, call_pure_results)
  4797. class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
  4798. pass
  4799. ##class TestOOtype(BaseTestOptimizeBasic, OOtypeMixin):
  4800. ## def test_instanceof(self):
  4801. ## ops = """
  4802. ## [i0]
  4803. ## p0 = new_with_vtable(ConstClass(node_vtable))
  4804. ## i1 = instanceof(p0, descr=nodesize)
  4805. ## jump(i1)
  4806. ## """
  4807. ## expected = """
  4808. ## [i0]
  4809. ## jump(1)
  4810. ## """
  4811. ## self.optimize_loop(ops, expected)
  4812. ## def test_instanceof_guard_class(self):
  4813. ## ops = """
  4814. ## [i0, p0]
  4815. ## guard_class(p0, ConstClass(node_vtable)) []
  4816. ## i1 = instanceof(p0, descr=nodesize)
  4817. ## jump(i1, p0)
  4818. ## """
  4819. ## expected = """
  4820. ## [i0, p0]
  4821. ## guard_class(p0, ConstClass(node_vtable)) []
  4822. ## jump(1, p0)
  4823. ## """
  4824. ## self.optimize_loop(ops, expected)