PageRenderTime 54ms CodeModel.GetById 21ms RepoModel.GetById 4ms app.codeStats 1ms

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

https://bitbucket.org/pypy/pypy/
Python | 9385 lines | 9382 code | 2 blank | 1 comment | 6 complexity | b4c3685e7aa08298a029ba818824dc06 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py, sys
  2. from rpython.rlib.objectmodel import instantiate
  3. from rpython.rlib.rarithmetic import intmask
  4. from rpython.rtyper.lltypesystem import lltype
  5. from rpython.jit.metainterp import compile, resume
  6. from rpython.jit.metainterp.history import AbstractDescr, ConstInt, TreeLoop
  7. from rpython.jit.metainterp.optimize import InvalidLoop
  8. from rpython.jit.metainterp.optimizeopt import build_opt_chain
  9. from rpython.jit.metainterp.optimizeopt.test.test_util import (
  10. LLtypeMixin, BaseTest, convert_old_style_to_targets)
  11. from rpython.jit.metainterp.optimizeopt.test.test_optimizebasic import \
  12. FakeMetaInterpStaticData
  13. from rpython.jit.metainterp.resoperation import rop, opname, oparity,\
  14. InputArgInt
  15. def test_build_opt_chain():
  16. def check(chain, expected_names):
  17. names = [opt.__class__.__name__ for opt in chain]
  18. assert names == expected_names
  19. #
  20. metainterp_sd = FakeMetaInterpStaticData(None)
  21. chain, _ = build_opt_chain(metainterp_sd, "")
  22. check(chain, ["OptSimplify"])
  23. #
  24. chain, _ = build_opt_chain(metainterp_sd, "")
  25. check(chain, ["OptSimplify"])
  26. #
  27. chain, _ = build_opt_chain(metainterp_sd, "")
  28. check(chain, ["OptSimplify"])
  29. #
  30. chain, _ = build_opt_chain(metainterp_sd, "heap:intbounds")
  31. check(chain, ["OptIntBounds", "OptHeap", "OptSimplify"])
  32. #
  33. chain, unroll = build_opt_chain(metainterp_sd, "unroll")
  34. check(chain, ["OptSimplify"])
  35. assert unroll
  36. #
  37. chain, _ = build_opt_chain(metainterp_sd, "aaa:bbb")
  38. check(chain, ["OptSimplify"])
  39. # ____________________________________________________________
  40. class BaseTestWithUnroll(BaseTest):
  41. enable_opts = "intbounds:rewrite:virtualize:string:earlyforce:pure:heap:unroll"
  42. def optimize_loop(self, ops, expected, expected_preamble=None,
  43. call_pure_results=None, expected_short=None,
  44. jump_values=None):
  45. loop = self.parse(ops)
  46. if expected != "crash!":
  47. expected = self.parse(expected)
  48. if expected_preamble:
  49. expected_preamble = self.parse(expected_preamble)
  50. if expected_short:
  51. # the short preamble doesn't have fail descrs, they are patched in when it is used
  52. expected_short = self.parse(expected_short, want_fail_descr=False)
  53. info = self.unroll_and_optimize(loop, call_pure_results, jump_values)
  54. preamble = info.preamble
  55. preamble.check_consistency(check_descr=False)
  56. #
  57. print
  58. print "Preamble:"
  59. if preamble.operations:
  60. print '\n'.join([str(o) for o in preamble.operations])
  61. else:
  62. print 'Failed!'
  63. print
  64. print "Loop:"
  65. print '\n'.join([str(o) for o in loop.operations])
  66. print
  67. if expected_short:
  68. print "Short Preamble:"
  69. short = info.short_preamble
  70. print '\n'.join([str(o) for o in short])
  71. print
  72. assert expected != "crash!", "should have raised an exception"
  73. loop.check_consistency(check_descr=False)
  74. self.assert_equal(loop, convert_old_style_to_targets(expected, jump=True))
  75. assert loop.operations[0].getdescr() == loop.operations[-1].getdescr()
  76. if expected_preamble:
  77. self.assert_equal(preamble, convert_old_style_to_targets(expected_preamble, jump=False),
  78. text_right='expected preamble')
  79. if expected_short:
  80. short_preamble = TreeLoop('short preamble')
  81. assert short[0].getopnum() == rop.LABEL
  82. short_preamble.inputargs = short[0].getarglist()
  83. short_preamble.operations = short
  84. self.assert_equal(short_preamble, convert_old_style_to_targets(expected_short, jump=True),
  85. text_right='expected short preamble')
  86. #assert short[-1].getdescr() == loop.operations[0].getdescr()
  87. # XXX not sure what to do about that one
  88. return loop
  89. def raises(self, e, fn, *args):
  90. return py.test.raises(e, fn, *args).value
  91. class OptimizeOptTest(BaseTestWithUnroll):
  92. def test_simple(self):
  93. ops = """
  94. []
  95. f = escape_f()
  96. f0 = float_sub(f, 1.0)
  97. guard_value(f0, 0.0) [f0]
  98. escape_n(f)
  99. jump()
  100. """
  101. self.optimize_loop(ops, ops)
  102. def test_constant_propagate(self):
  103. ops = """
  104. []
  105. i0 = int_add(2, 3)
  106. i1 = int_is_true(i0)
  107. guard_true(i1) []
  108. i2 = int_is_zero(i1)
  109. guard_false(i2) []
  110. guard_value(i0, 5) []
  111. jump()
  112. """
  113. expected = """
  114. []
  115. jump()
  116. """
  117. self.optimize_loop(ops, expected)
  118. def test_constant_propagate_ovf(self):
  119. ops = """
  120. []
  121. i0 = int_add_ovf(2, 3)
  122. guard_no_overflow() []
  123. i1 = int_is_true(i0)
  124. guard_true(i1) []
  125. i2 = int_is_zero(i1)
  126. guard_false(i2) []
  127. guard_value(i0, 5) []
  128. jump()
  129. """
  130. expected = """
  131. []
  132. jump()
  133. """
  134. self.optimize_loop(ops, expected)
  135. def test_constfold_all(self):
  136. from rpython.jit.metainterp.executor import _execute_arglist
  137. import random
  138. for opnum in range(rop.INT_ADD, rop.SAME_AS_I+1):
  139. try:
  140. op = opname[opnum]
  141. except KeyError:
  142. continue
  143. if 'FLOAT' in op:
  144. continue
  145. if 'VEC' in op:
  146. continue
  147. args = []
  148. for _ in range(oparity[opnum]):
  149. args.append(random.randrange(1, 20))
  150. if opnum == rop.INT_SIGNEXT:
  151. # 2nd arg is number of bytes to extend from ---
  152. # must not be too random
  153. args[-1] = random.choice([1, 2] if sys.maxint < 2**32 else
  154. [1, 2, 4])
  155. ops = """
  156. []
  157. i1 = %s(%s)
  158. escape_n(i1)
  159. jump()
  160. """ % (op.lower(), ', '.join(map(str, args)))
  161. argboxes = [InputArgInt(a) for a in args]
  162. expected_value = _execute_arglist(self.cpu, None, opnum, argboxes)
  163. expected = """
  164. []
  165. escape_n(%d)
  166. jump()
  167. """ % expected_value
  168. self.optimize_loop(ops, expected)
  169. def test_reverse_of_cast_1(self):
  170. ops = """
  171. [i0]
  172. p0 = cast_int_to_ptr(i0)
  173. i1 = cast_ptr_to_int(p0)
  174. jump(i1)
  175. """
  176. expected = """
  177. [i0]
  178. jump(i0)
  179. """
  180. short = """
  181. [i2]
  182. p3 = cast_int_to_ptr(i2)
  183. jump()
  184. """
  185. self.optimize_loop(ops, expected, expected_short=short)
  186. def test_reverse_of_cast_2(self):
  187. ops = """
  188. [p0]
  189. i1 = cast_ptr_to_int(p0)
  190. p1 = cast_int_to_ptr(i1)
  191. jump(p1)
  192. """
  193. expected = """
  194. [p0]
  195. jump(p0)
  196. """
  197. self.optimize_loop(ops, expected)
  198. # ----------
  199. def test_remove_guard_class_1(self):
  200. ops = """
  201. [p0]
  202. guard_class(p0, ConstClass(node_vtable)) []
  203. guard_class(p0, ConstClass(node_vtable)) []
  204. jump(p0)
  205. """
  206. preamble = """
  207. [p0]
  208. guard_class(p0, ConstClass(node_vtable)) []
  209. jump(p0)
  210. """
  211. expected = """
  212. [p0]
  213. jump(p0)
  214. """
  215. self.optimize_loop(ops, expected, expected_preamble=preamble)
  216. def test_remove_guard_class_2(self):
  217. ops = """
  218. [i0]
  219. p0 = new_with_vtable(descr=nodesize)
  220. escape_n(p0)
  221. guard_class(p0, ConstClass(node_vtable)) []
  222. jump(i0)
  223. """
  224. expected = """
  225. [i0]
  226. p0 = new_with_vtable(descr=nodesize)
  227. escape_n(p0)
  228. jump(i0)
  229. """
  230. self.optimize_loop(ops, expected)
  231. def test_remove_guard_class_constant(self):
  232. ops = """
  233. [i0]
  234. p0 = same_as_r(ConstPtr(myptr))
  235. guard_class(p0, ConstClass(node_vtable)) []
  236. jump(i0)
  237. """
  238. expected = """
  239. [i0]
  240. jump(i0)
  241. """
  242. self.optimize_loop(ops, expected)
  243. def test_constant_boolrewrite_lt(self):
  244. ops = """
  245. [i0]
  246. i1 = int_lt(i0, 0)
  247. guard_true(i1) []
  248. i2 = int_ge(i0, 0)
  249. guard_false(i2) []
  250. jump(i0)
  251. """
  252. preamble = """
  253. [i0]
  254. i1 = int_lt(i0, 0)
  255. guard_true(i1) []
  256. jump(i0)
  257. """
  258. expected = """
  259. [i0]
  260. jump(i0)
  261. """
  262. self.optimize_loop(ops, expected, expected_preamble=preamble)
  263. def test_constant_boolrewrite_gt(self):
  264. ops = """
  265. [i0]
  266. i1 = int_gt(i0, 0)
  267. guard_true(i1) []
  268. i2 = int_le(i0, 0)
  269. guard_false(i2) []
  270. jump(i0)
  271. """
  272. preamble = """
  273. [i0]
  274. i1 = int_gt(i0, 0)
  275. guard_true(i1) []
  276. jump(i0)
  277. """
  278. expected = """
  279. [i0]
  280. jump(i0)
  281. """
  282. self.optimize_loop(ops, expected, expected_preamble=preamble)
  283. def test_constant_boolrewrite_reflex(self):
  284. ops = """
  285. [i0]
  286. i1 = int_gt(i0, 0)
  287. guard_true(i1) []
  288. i2 = int_lt(0, i0)
  289. guard_true(i2) []
  290. jump(i0)
  291. """
  292. preamble = """
  293. [i0]
  294. i1 = int_gt(i0, 0)
  295. guard_true(i1) []
  296. jump(i0)
  297. """
  298. expected = """
  299. [i0]
  300. jump(i0)
  301. """
  302. self.optimize_loop(ops, expected, expected_preamble=preamble)
  303. def test_constant_boolrewrite_reflex_invers(self):
  304. ops = """
  305. [i0]
  306. i1 = int_gt(i0, 0)
  307. guard_true(i1) []
  308. i2 = int_ge(0, i0)
  309. guard_false(i2) []
  310. jump(i0)
  311. """
  312. preamble = """
  313. [i0]
  314. i1 = int_gt(i0, 0)
  315. guard_true(i1) []
  316. jump(i0)
  317. """
  318. expected = """
  319. [i0]
  320. jump(i0)
  321. """
  322. self.optimize_loop(ops, expected, expected_preamble=preamble)
  323. def test_remove_consecutive_guard_value_constfold(self):
  324. ops = """
  325. []
  326. i0 = escape_i()
  327. guard_value(i0, 0) []
  328. i1 = int_add(i0, 1)
  329. guard_value(i1, 1) []
  330. i2 = int_add(i1, 2)
  331. escape_n(i2)
  332. jump()
  333. """
  334. expected = """
  335. []
  336. i0 = escape_i()
  337. guard_value(i0, 0) []
  338. escape_n(3)
  339. jump()
  340. """
  341. self.optimize_loop(ops, expected)
  342. def test_remove_guard_value_if_constant(self):
  343. ops = """
  344. [p1]
  345. guard_value(p1, ConstPtr(myptr)) []
  346. jump(p1)
  347. """
  348. expected = """
  349. []
  350. jump()
  351. """
  352. self.optimize_loop(ops, expected)
  353. def test_ooisnull_oononnull_1(self):
  354. ops = """
  355. [p0]
  356. guard_class(p0, ConstClass(node_vtable)) []
  357. guard_nonnull(p0) []
  358. jump(p0)
  359. """
  360. preamble = """
  361. [p0]
  362. guard_class(p0, ConstClass(node_vtable)) []
  363. jump(p0)
  364. """
  365. expected = """
  366. [p0]
  367. jump(p0)
  368. """
  369. self.optimize_loop(ops, expected, preamble)
  370. def test_guard_nonnull_class_1(self):
  371. ops = """
  372. [p0]
  373. guard_class(p0, ConstClass(node_vtable)) []
  374. guard_nonnull(p0) []
  375. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  376. jump(p0)
  377. """
  378. preamble = """
  379. [p0]
  380. guard_class(p0, ConstClass(node_vtable)) []
  381. jump(p0)
  382. """
  383. expected = """
  384. [p0]
  385. jump(p0)
  386. """
  387. self.optimize_loop(ops, expected, preamble)
  388. def test_guard_nonnull_class_2(self):
  389. ops = """
  390. [p0]
  391. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  392. jump(p0)
  393. """
  394. preamble = """
  395. [p0]
  396. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  397. jump(p0)
  398. """
  399. expected = """
  400. [p0]
  401. jump(p0)
  402. """
  403. self.optimize_loop(ops, expected, preamble)
  404. def test_int_is_true_1(self):
  405. ops = """
  406. [i0]
  407. i1 = int_is_true(i0)
  408. guard_true(i1) []
  409. i2 = int_is_true(i0)
  410. guard_true(i2) []
  411. jump(i0)
  412. """
  413. preamble = """
  414. [i0]
  415. i1 = int_is_true(i0)
  416. guard_true(i1) []
  417. jump(i0)
  418. """
  419. expected = """
  420. [i0]
  421. jump(i0)
  422. """
  423. short = """
  424. [i0]
  425. i1 = int_is_true(i0)
  426. guard_value(i1, 1) []
  427. jump()
  428. """
  429. self.optimize_loop(ops, expected, preamble, expected_short=short)
  430. def test_bound_int_is_true(self):
  431. ops = """
  432. [i0]
  433. i1 = int_add(i0, 1)
  434. i2 = int_gt(i1, 0)
  435. guard_true(i2) []
  436. i3 = int_is_true(i1)
  437. guard_true(i3) []
  438. jump(i1)
  439. """
  440. expected = """
  441. [i0]
  442. i1 = int_add(i0, 1)
  443. i2 = int_gt(i1, 0)
  444. guard_true(i2) []
  445. jump(i1)
  446. """
  447. self.optimize_loop(ops, expected, expected)
  448. def test_int_is_true_is_zero(self):
  449. py.test.skip("in-progress")
  450. ops = """
  451. [i0]
  452. i1 = int_add(i0, 1)
  453. i2 = int_is_true(i1)
  454. guard_true(i2) []
  455. i3 = int_is_zero(i1)
  456. guard_false(i3) []
  457. jump(i1)
  458. """
  459. expected = """
  460. [i0]
  461. i1 = int_add(i0, 1)
  462. i2 = int_is_true(i1)
  463. guard_true(i2) []
  464. jump(i1)
  465. """
  466. self.optimize_loop(ops, expected)
  467. def test_ooisnull_oononnull_2(self):
  468. ops = """
  469. [p0]
  470. guard_nonnull(p0) []
  471. guard_nonnull(p0) []
  472. jump(p0)
  473. """
  474. preamble = """
  475. [p0]
  476. guard_nonnull(p0) []
  477. jump(p0)
  478. """
  479. expected = """
  480. [p0]
  481. jump(p0)
  482. """
  483. self.optimize_loop(ops, expected, preamble)
  484. def test_ooisnull_on_null_ptr_1(self):
  485. ops = """
  486. []
  487. p0 = escape_r()
  488. guard_isnull(p0) []
  489. guard_isnull(p0) []
  490. jump()
  491. """
  492. expected = """
  493. []
  494. p0 = escape_r()
  495. guard_isnull(p0) []
  496. jump()
  497. """
  498. self.optimize_loop(ops, expected)
  499. def test_ooisnull_oononnull_via_virtual(self):
  500. ops = """
  501. [p0]
  502. pv = new_with_vtable(descr=nodesize)
  503. setfield_gc(pv, p0, descr=valuedescr)
  504. guard_nonnull(p0) []
  505. p1 = getfield_gc_r(pv, descr=valuedescr)
  506. guard_nonnull(p1) []
  507. jump(p0)
  508. """
  509. preamble = """
  510. [p0]
  511. guard_nonnull(p0) []
  512. jump(p0)
  513. """
  514. expected = """
  515. [p0]
  516. jump(p0)
  517. """
  518. self.optimize_loop(ops, expected, preamble)
  519. def test_oois_1(self):
  520. ops = """
  521. [p0]
  522. guard_class(p0, ConstClass(node_vtable)) []
  523. i0 = ptr_ne(p0, NULL)
  524. guard_true(i0) []
  525. i1 = ptr_eq(p0, NULL)
  526. guard_false(i1) []
  527. i2 = ptr_ne(NULL, p0)
  528. guard_true(i0) []
  529. i3 = ptr_eq(NULL, p0)
  530. guard_false(i1) []
  531. jump(p0)
  532. """
  533. preamble = """
  534. [p0]
  535. guard_class(p0, ConstClass(node_vtable)) []
  536. jump(p0)
  537. """
  538. expected = """
  539. [p0]
  540. jump(p0)
  541. """
  542. self.optimize_loop(ops, expected, preamble)
  543. def test_nonnull_1(self):
  544. ops = """
  545. [p0]
  546. setfield_gc(p0, 5, descr=valuedescr) # forces p0 != NULL
  547. i0 = ptr_ne(p0, NULL)
  548. guard_true(i0) []
  549. i1 = ptr_eq(p0, NULL)
  550. guard_false(i1) []
  551. i2 = ptr_ne(NULL, p0)
  552. guard_true(i2) []
  553. i3 = ptr_eq(NULL, p0)
  554. guard_false(i3) []
  555. guard_nonnull(p0) []
  556. jump(p0)
  557. """
  558. preamble = """
  559. [p0]
  560. setfield_gc(p0, 5, descr=valuedescr)
  561. jump(p0)
  562. """
  563. expected = """
  564. [p0]
  565. jump(p0)
  566. """
  567. self.optimize_loop(ops, expected, preamble)
  568. def test_nonnull_2(self):
  569. ops = """
  570. []
  571. p0 = new_array(5, descr=arraydescr) # forces p0 != NULL
  572. i0 = ptr_ne(p0, NULL)
  573. guard_true(i0) []
  574. i1 = ptr_eq(p0, NULL)
  575. guard_false(i1) []
  576. i2 = ptr_ne(NULL, p0)
  577. guard_true(i2) []
  578. i3 = ptr_eq(NULL, p0)
  579. guard_false(i3) []
  580. guard_nonnull(p0) []
  581. escape_r(p0)
  582. jump()
  583. """
  584. expected = """
  585. []
  586. p0 = new_array(5, descr=arraydescr)
  587. escape_r(p0)
  588. jump()
  589. """
  590. self.optimize_loop(ops, expected)
  591. def test_const_guard_value(self):
  592. ops = """
  593. []
  594. i = int_add(5, 3)
  595. guard_value(i, 8) []
  596. jump()
  597. """
  598. expected = """
  599. []
  600. jump()
  601. """
  602. self.optimize_loop(ops, expected)
  603. def test_constptr_guard_value(self):
  604. ops = """
  605. []
  606. p1 = escape_r()
  607. guard_value(p1, ConstPtr(myptr)) []
  608. jump()
  609. """
  610. self.optimize_loop(ops, ops)
  611. def test_guard_value_to_guard_true(self):
  612. ops = """
  613. [i]
  614. i1 = int_lt(i, 3)
  615. guard_value(i1, 1) [i]
  616. jump(i)
  617. """
  618. preamble = """
  619. [i]
  620. i1 = int_lt(i, 3)
  621. guard_true(i1) [i]
  622. jump(i)
  623. """
  624. expected = """
  625. [i]
  626. jump(i)
  627. """
  628. self.optimize_loop(ops, expected, preamble)
  629. def test_guard_value_to_guard_false(self):
  630. ops = """
  631. [i]
  632. i1 = int_is_true(i)
  633. guard_value(i1, 0) [i]
  634. jump(i)
  635. """
  636. preamble = """
  637. [i]
  638. i1 = int_is_true(i)
  639. guard_false(i1) [i]
  640. jump()
  641. """
  642. expected = """
  643. []
  644. jump()
  645. """
  646. self.optimize_loop(ops, expected, preamble)
  647. def test_guard_value_on_nonbool(self):
  648. ops = """
  649. [i]
  650. i1 = int_add(i, 3)
  651. guard_value(i1, 0) [i]
  652. jump(i)
  653. """
  654. preamble = """
  655. [i]
  656. i1 = int_add(i, 3)
  657. guard_value(i1, 0) [i]
  658. jump()
  659. """
  660. expected = """
  661. []
  662. jump()
  663. """
  664. self.optimize_loop(ops, expected, preamble)
  665. def test_int_is_true_of_bool(self):
  666. ops = """
  667. [i0, i1]
  668. i2 = int_gt(i0, i1)
  669. i3 = int_is_true(i2)
  670. i4 = int_is_true(i3)
  671. guard_value(i4, 0) [i0, i1]
  672. jump(i0, i1)
  673. """
  674. preamble = """
  675. [i0, i1]
  676. i2 = int_gt(i0, i1)
  677. guard_false(i2) [i0, i1]
  678. jump(i0, i1)
  679. """
  680. expected = """
  681. [i0, i1]
  682. jump(i0, i1)
  683. """
  684. self.optimize_loop(ops, expected, preamble)
  685. def test_compare_with_itself(self):
  686. ops = """
  687. []
  688. i0 = escape_i()
  689. i1 = int_lt(i0, i0)
  690. guard_false(i1) []
  691. i2 = int_le(i0, i0)
  692. guard_true(i2) []
  693. i3 = int_eq(i0, i0)
  694. guard_true(i3) []
  695. i4 = int_ne(i0, i0)
  696. guard_false(i4) []
  697. i5 = int_gt(i0, i0)
  698. guard_false(i5) []
  699. i6 = int_ge(i0, i0)
  700. guard_true(i6) []
  701. jump()
  702. """
  703. expected = """
  704. []
  705. i0 = escape_i()
  706. jump()
  707. """
  708. self.optimize_loop(ops, expected)
  709. def test_compare_with_itself_uint(self):
  710. py.test.skip("implement me")
  711. ops = """
  712. []
  713. i0 = escape_i()
  714. i7 = uint_lt(i0, i0)
  715. guard_false(i7) []
  716. i8 = uint_le(i0, i0)
  717. guard_true(i8) []
  718. i9 = uint_gt(i0, i0)
  719. guard_false(i9) []
  720. i10 = uint_ge(i0, i0)
  721. guard_true(i10) []
  722. jump()
  723. """
  724. expected = """
  725. []
  726. i0 = escape_i()
  727. jump()
  728. """
  729. self.optimize_loop(ops, expected)
  730. def test_p123_simple(self):
  731. ops = """
  732. [i1, p2, p3]
  733. i3 = getfield_gc_i(p3, descr=valuedescr)
  734. escape_n(i3)
  735. p1 = new_with_vtable(descr=nodesize)
  736. setfield_gc(p1, i1, descr=valuedescr)
  737. jump(i1, p1, p2)
  738. """
  739. preamble = """
  740. [i1, p2, p3]
  741. i3 = getfield_gc_i(p3, descr=valuedescr)
  742. escape_n(i3)
  743. jump(i1, p2)
  744. """
  745. expected = """
  746. [i1, p2]
  747. i3 = getfield_gc_i(p2, descr=valuedescr)
  748. escape_n(i3)
  749. p3 = new_with_vtable(descr=nodesize)
  750. setfield_gc(p3, i1, descr=valuedescr)
  751. jump(i1, p3)
  752. """
  753. # We cannot track virtuals that survive for more than two iterations.
  754. self.optimize_loop(ops, expected, preamble,
  755. jump_values=[None, self.nodefulladdr, None])
  756. def test_p123_nested(self):
  757. ops = """
  758. [i1, p2, p3]
  759. i3 = getfield_gc_i(p3, descr=valuedescr)
  760. escape_n(i3)
  761. p1 = new_with_vtable(descr=nodesize)
  762. setfield_gc(p1, i1, descr=valuedescr)
  763. p1sub = new_with_vtable(descr=nodesize2)
  764. setfield_gc(p1sub, i1, descr=valuedescr)
  765. setfield_gc(p1, p1sub, descr=nextdescr)
  766. jump(i1, p1, p2)
  767. """
  768. # The same as test_p123_simple, but with a virtual containing another
  769. # virtual.
  770. preamble = """
  771. [i1, p2, p3]
  772. i3 = getfield_gc_i(p3, descr=valuedescr)
  773. escape_n(i3)
  774. jump(i1, p2)
  775. """
  776. expected = """
  777. [i1, p2]
  778. i3 = getfield_gc_i(p2, descr=valuedescr)
  779. escape_n(i3)
  780. p4 = new_with_vtable(descr=nodesize)
  781. p1sub = new_with_vtable(descr=nodesize2)
  782. setfield_gc(p1sub, i1, descr=valuedescr)
  783. setfield_gc(p4, i1, descr=valuedescr)
  784. setfield_gc(p4, p1sub, descr=nextdescr)
  785. jump(i1, p4)
  786. """
  787. self.optimize_loop(ops, expected, preamble,
  788. jump_values=[None, self.nodefulladdr, self.nodefulladdr])
  789. def test_p123_anti_nested(self):
  790. ops = """
  791. [i1, p2, p3]
  792. p3sub = getfield_gc_r(p3, descr=nextdescr)
  793. i3 = getfield_gc_i(p3sub, descr=valuedescr)
  794. escape_n(i3)
  795. p1 = new_with_vtable(descr=nodesize)
  796. p2sub = new_with_vtable(descr=nodesize2)
  797. setfield_gc(p2sub, i1, descr=valuedescr)
  798. setfield_gc(p2, p2sub, descr=nextdescr)
  799. jump(i1, p1, p2)
  800. """
  801. # The same as test_p123_simple, but in the end the "old" p2 contains
  802. # a "young" virtual p2sub. Make sure it is all forced.
  803. preamble = """
  804. [i1, p2, p3]
  805. p3sub = getfield_gc_r(p3, descr=nextdescr)
  806. i3 = getfield_gc_i(p3sub, descr=valuedescr)
  807. escape_n(i3)
  808. p2sub = new_with_vtable(descr=nodesize2)
  809. setfield_gc(p2sub, i1, descr=valuedescr)
  810. setfield_gc(p2, p2sub, descr=nextdescr)
  811. jump(i1, p2, p2sub)
  812. """
  813. expected = """
  814. [i1, p2, p10]
  815. i3 = getfield_gc_i(p10, descr=valuedescr)
  816. escape_n(i3)
  817. p1 = new_with_vtable(descr=nodesize)
  818. p3sub = new_with_vtable(descr=nodesize2)
  819. setfield_gc(p3sub, i1, descr=valuedescr)
  820. setfield_gc(p1, p3sub, descr=nextdescr)
  821. jump(i1, p1, p3sub)
  822. """
  823. self.optimize_loop(ops, expected, preamble,
  824. jump_values=[None, self.nodefulladdr, self.nodefulladdr])
  825. def test_dont_delay_setfields(self):
  826. ops = """
  827. [p1, p2]
  828. i1 = getfield_gc_i(p1, descr=valuedescr)
  829. i2 = int_sub(i1, 1)
  830. i2b = int_is_true(i2)
  831. guard_true(i2b) []
  832. setfield_gc(p2, i2, descr=valuedescr)
  833. p3 = new_with_vtable(descr=nodesize)
  834. jump(p2, p3)
  835. """
  836. short = """
  837. [p1, p2]
  838. guard_nonnull(p1) []
  839. guard_is_object(p1) []
  840. guard_subclass(p1, ConstClass(node_vtable)) []
  841. i1 = getfield_gc_i(p1, descr=valuedescr)
  842. jump(i1)
  843. """
  844. preamble = """
  845. [p1, p2]
  846. i1 = getfield_gc_i(p1, descr=valuedescr)
  847. i2 = int_sub(i1, 1)
  848. i2b = int_is_true(i2)
  849. guard_true(i2b) []
  850. setfield_gc(p2, i2, descr=valuedescr)
  851. jump(p2, i2)
  852. """
  853. expected = """
  854. [p2, i1]
  855. i2 = int_sub(i1, 1)
  856. i2b = int_is_true(i2)
  857. guard_true(i2b) []
  858. p3 = new_with_vtable(descr=nodesize)
  859. setfield_gc(p3, i2, descr=valuedescr)
  860. jump(p3, i2)
  861. """
  862. self.optimize_loop(ops, expected, preamble, expected_short=short,
  863. jump_values=[None, self.nodefulladdr])
  864. # ----------
  865. def test_fold_guard_no_exception(self):
  866. ops = """
  867. [i]
  868. guard_no_exception() []
  869. i1 = int_add(i, 3)
  870. i2 = call_i(i1, descr=nonwritedescr)
  871. guard_no_exception() [i1, i2]
  872. i3 = call_i(i2, descr=nonwritedescr)
  873. jump(i1) # the exception is considered lost when we loop back
  874. """
  875. preamble = """
  876. [i]
  877. guard_no_exception() [] # occurs at the start of bridges, so keep it
  878. i1 = int_add(i, 3)
  879. i2 = call_i(i1, descr=nonwritedescr)
  880. guard_no_exception() [i1, i2]
  881. i3 = call_i(i2, descr=nonwritedescr)
  882. jump(i1)
  883. """
  884. expected = """
  885. [i]
  886. guard_no_exception() [] # occurs at the start of bridges, so keep it
  887. i1 = int_add(i, 3)
  888. i2 = call_i(i1, descr=nonwritedescr)
  889. guard_no_exception() [i1, i2]
  890. i3 = call_i(i2, descr=nonwritedescr)
  891. jump(i1)
  892. """
  893. self.optimize_loop(ops, expected, preamble)
  894. def test_bug_guard_no_exception(self):
  895. ops = """
  896. []
  897. i0 = call_i(123, descr=nonwritedescr)
  898. p0 = call_r(0, "xy", descr=s2u_descr) # string -> unicode
  899. guard_no_exception() []
  900. escape_n(p0)
  901. jump()
  902. """
  903. expected = """
  904. []
  905. i0 = call_i(123, descr=nonwritedescr)
  906. escape_n(u"xy")
  907. jump()
  908. """
  909. self.optimize_loop(ops, expected)
  910. # ----------
  911. def test_call_loopinvariant(self):
  912. ops = """
  913. [i1]
  914. i2 = call_loopinvariant_i(1, i1, descr=nonwritedescr)
  915. guard_no_exception() []
  916. guard_value(i2, 1) []
  917. i3 = call_loopinvariant_i(1, i1, descr=nonwritedescr)
  918. guard_no_exception() []
  919. guard_value(i3, 1) []
  920. i4 = call_loopinvariant_i(1, i1, descr=nonwritedescr)
  921. guard_no_exception() []
  922. guard_value(i4, 1) []
  923. jump(i1)
  924. """
  925. preamble = """
  926. [i1]
  927. i2 = call_i(1, i1, descr=nonwritedescr)
  928. guard_no_exception() []
  929. guard_value(i2, 1) []
  930. jump(i1)
  931. """
  932. expected = """
  933. [i1]
  934. jump(i1)
  935. """
  936. self.optimize_loop(ops, expected, preamble)
  937. # ----------
  938. def test_virtual_1(self):
  939. ops = """
  940. [i, p0]
  941. i0 = getfield_gc_i(p0, descr=valuedescr)
  942. i1 = int_add(i0, i)
  943. p1 = new_with_vtable(descr=nodesize)
  944. setfield_gc(p1, i1, descr=valuedescr)
  945. jump(i, p1)
  946. """
  947. preamble = """
  948. [i, p0]
  949. i0 = getfield_gc_i(p0, descr=valuedescr)
  950. i1 = int_add(i0, i)
  951. jump(i, i1)
  952. """
  953. expected = """
  954. [i, i2]
  955. i1 = int_add(i2, i)
  956. jump(i, i1)
  957. """
  958. self.optimize_loop(ops, expected, preamble,
  959. jump_values=[None, self.nodefulladdr])
  960. def test_virtual_float(self):
  961. ops = """
  962. [f, p0]
  963. f0 = getfield_gc_f(p0, descr=floatdescr)
  964. f1 = float_add(f0, f)
  965. p1 = new_with_vtable(descr=nodesize)
  966. setfield_gc(p1, f1, descr=floatdescr)
  967. jump(f, p1)
  968. """
  969. preamble = """
  970. [f, p0]
  971. f2 = getfield_gc_f(p0, descr=floatdescr)
  972. f1 = float_add(f2, f)
  973. jump(f, f1)
  974. """
  975. expected = """
  976. [f, f2]
  977. f1 = float_add(f2, f)
  978. jump(f, f1)
  979. """
  980. self.optimize_loop(ops, expected, preamble)
  981. def test_virtual_oois(self):
  982. ops = """
  983. [p0, p1, p2]
  984. guard_nonnull(p0) []
  985. i3 = ptr_ne(p0, NULL)
  986. guard_true(i3) []
  987. i4 = ptr_eq(p0, NULL)
  988. guard_false(i4) []
  989. i5 = ptr_ne(NULL, p0)
  990. guard_true(i5) []
  991. i6 = ptr_eq(NULL, p0)
  992. guard_false(i6) []
  993. i7 = ptr_ne(p0, p1)
  994. guard_true(i7) []
  995. i8 = ptr_eq(p0, p1)
  996. guard_false(i8) []
  997. i9 = ptr_ne(p0, p2)
  998. guard_true(i9) []
  999. i10 = ptr_eq(p0, p2)
  1000. guard_false(i10) []
  1001. i11 = ptr_ne(p2, p1)
  1002. guard_true(i11) []
  1003. i12 = ptr_eq(p2, p1)
  1004. guard_false(i12) []
  1005. jump(p0, p1, p2)
  1006. """
  1007. expected = """
  1008. [p0, p1, p2]
  1009. # all constant-folded :-)
  1010. jump(p0, p1, p2)
  1011. """
  1012. #
  1013. # to be complete, we also check the no-opt case where most comparisons
  1014. # are not removed. The exact set of comparisons removed depends on
  1015. # the details of the algorithm...
  1016. expected2 = """
  1017. [p0, p1, p2]
  1018. guard_nonnull(p0) []
  1019. i7 = ptr_ne(p0, p1)
  1020. guard_true(i7) []
  1021. i9 = ptr_ne(p0, p2)
  1022. guard_true(i9) []
  1023. i11 = ptr_ne(p2, p1)
  1024. guard_true(i11) []
  1025. jump(p0, p1, p2)
  1026. """
  1027. self.optimize_loop(ops, expected, expected2)
  1028. def test_virtual_default_field(self):
  1029. ops = """
  1030. [p0]
  1031. i0 = getfield_gc_i(p0, descr=valuedescr)
  1032. guard_value(i0, 0) []
  1033. p1 = new_with_vtable(descr=nodesize)
  1034. # the field 'value' has its default value of 0
  1035. jump(p1)
  1036. """
  1037. preamble = """
  1038. [p0]
  1039. i0 = getfield_gc_i(p0, descr=valuedescr)
  1040. guard_value(i0, 0) []
  1041. jump()
  1042. """
  1043. expected = """
  1044. []
  1045. jump()
  1046. """
  1047. self.optimize_loop(ops, expected, preamble)
  1048. def test_virtual_3(self):
  1049. ops = """
  1050. [i]
  1051. p1 = new_with_vtable(descr=nodesize)
  1052. setfield_gc(p1, i, descr=valuedescr)
  1053. i0 = getfield_gc_i(p1, descr=valuedescr)
  1054. i1 = int_add(i0, 1)
  1055. jump(i1)
  1056. """
  1057. expected = """
  1058. [i]
  1059. i1 = int_add(i, 1)
  1060. jump(i1)
  1061. """
  1062. self.optimize_loop(ops, expected)
  1063. def test_virtual_4(self):
  1064. ops = """
  1065. [i0, p0]
  1066. guard_class(p0, ConstClass(node_vtable)) []
  1067. i1 = getfield_gc_i(p0, descr=valuedescr)
  1068. i2 = int_sub(i1, 1)
  1069. i3 = int_add(i0, i1)
  1070. p1 = new_with_vtable(descr=nodesize)
  1071. setfield_gc(p1, i2, descr=valuedescr)
  1072. jump(i3, p1)
  1073. """
  1074. preamble = """
  1075. [i0, p0]
  1076. guard_class(p0, ConstClass(node_vtable)) []
  1077. i1 = getfield_gc_i(p0, descr=valuedescr)
  1078. i2 = int_sub(i1, 1)
  1079. i3 = int_add(i0, i1)
  1080. jump(i3, i2)
  1081. """
  1082. expected = """
  1083. [i0, i1]
  1084. i2 = int_sub(i1, 1)
  1085. i3 = int_add(i0, i1)
  1086. jump(i3, i2)
  1087. """
  1088. self.optimize_loop(ops, expected, preamble)
  1089. def test_virtual_5(self):
  1090. ops = """
  1091. [i0, p0]
  1092. guard_class(p0, ConstClass(node_vtable)) []
  1093. i1 = getfield_gc_i(p0, descr=valuedescr)
  1094. i2 = int_sub(i1, 1)
  1095. i3 = int_add(i0, i1)
  1096. p2 = new_with_vtable(descr=nodesize2)
  1097. setfield_gc(p2, i1, descr=valuedescr)
  1098. p1 = new_with_vtable(descr=nodesize)
  1099. setfield_gc(p1, i2, descr=valuedescr)
  1100. setfield_gc(p1, p2, descr=nextdescr)
  1101. jump(i3, p1)
  1102. """
  1103. preamble = """
  1104. [i0, p0]
  1105. guard_class(p0, ConstClass(node_vtable)) []
  1106. i1 = getfield_gc_i(p0, descr=valuedescr)
  1107. i2 = int_sub(i1, 1)
  1108. i3 = int_add(i0, i1)
  1109. jump(i3, i2, i1)
  1110. """
  1111. expected = """
  1112. [i0, i1bis, i1]
  1113. i2 = int_sub(i1bis, 1)
  1114. i3 = int_add(i0, i1bis)
  1115. jump(i3, i2, i1bis)
  1116. """
  1117. self.optimize_loop(ops, expected, preamble)
  1118. def test_virtual_recursive(self):
  1119. ops = """
  1120. [p0]
  1121. p41 = getfield_gc_r(p0, descr=nextdescr)
  1122. i0 = getfield_gc_i(p41, descr=valuedescr)
  1123. p1 = new_with_vtable(descr=nodesize2)
  1124. p2 = new_with_vtable(descr=nodesize2)
  1125. setfield_gc(p2, p1, descr=nextdescr)
  1126. setfield_gc(p1, p2, descr=nextdescr)
  1127. i1 = int_add(i0, 1)
  1128. setfield_gc(p2, i1, descr=valuedescr)
  1129. jump(p1)
  1130. """
  1131. preamble = """
  1132. [p0]
  1133. p41 = getfield_gc_r(p0, descr=nextdescr)
  1134. i0 = getfield_gc_i(p41, descr=valuedescr)
  1135. i3 = int_add(i0, 1)
  1136. jump(i3)
  1137. """
  1138. expected = """
  1139. [i0]
  1140. i1 = int_add(i0, 1)
  1141. jump(i1)
  1142. """
  1143. self.optimize_loop(ops, expected, preamble)
  1144. def test_virtual_recursive_forced(self):
  1145. ops = """
  1146. [p0]
  1147. p41 = getfield_gc_r(p0, descr=nextdescr)
  1148. i0 = getfield_gc_i(p41, descr=valuedescr)
  1149. p1 = new_with_vtable(descr=nodesize2)
  1150. p2 = new_with_vtable(descr=nodesize2)
  1151. setfield_gc(p2, p1, descr=nextdescr)
  1152. setfield_gc(p1, p2, descr=nextdescr)
  1153. i1 = int_add(i0, 1)
  1154. setfield_gc(p2, i1, descr=valuedescr)
  1155. setfield_gc(p0, p1, descr=nextdescr)
  1156. jump(p1)
  1157. """
  1158. preamble = """
  1159. [p0]
  1160. p41 = getfield_gc_r(p0, descr=nextdescr)
  1161. i0 = getfield_gc_i(p41, descr=valuedescr)
  1162. i1 = int_add(i0, 1)
  1163. p1 = new_with_vtable(descr=nodesize2)
  1164. p2 = new_with_vtable(descr=nodesize2)
  1165. setfield_gc(p2, i1, descr=valuedescr)
  1166. setfield_gc(p2, p1, descr=nextdescr)
  1167. setfield_gc(p1, p2, descr=nextdescr)
  1168. setfield_gc(p0, p1, descr=nextdescr)
  1169. jump(p1)
  1170. """
  1171. loop = """
  1172. [p0]
  1173. p41 = getfield_gc_r(p0, descr=nextdescr)
  1174. i0 = getfield_gc_i(p41, descr=valuedescr)
  1175. i1 = int_add(i0, 1)
  1176. p1 = new_with_vtable(descr=nodesize2)
  1177. p2 = new_with_vtable(descr=nodesize2)
  1178. setfield_gc(p2, i1, descr=valuedescr)
  1179. setfield_gc(p2, p1, descr=nextdescr)
  1180. setfield_gc(p0, p1, descr=nextdescr)
  1181. setfield_gc(p1, p2, descr=nextdescr)
  1182. jump(p1)
  1183. """
  1184. self.optimize_loop(ops, loop, preamble)
  1185. def test_virtual_constant_isnull(self):
  1186. ops = """
  1187. [i0]
  1188. p0 = new_with_vtable(descr=nodesize)
  1189. setfield_gc(p0, NULL, descr=nextdescr)
  1190. p2 = getfield_gc_r(p0, descr=nextdescr)
  1191. i1 = ptr_eq(p2, NULL)
  1192. jump(i1)
  1193. """
  1194. preamble = """
  1195. [i0]
  1196. jump()
  1197. """
  1198. expected = """
  1199. []
  1200. jump()
  1201. """
  1202. self.optimize_loop(ops, expected, preamble)
  1203. def test_virtual_constant_isnonnull(self):
  1204. ops = """
  1205. [i0]
  1206. p0 = new_with_vtable(descr=nodesize)
  1207. setfield_gc(p0, ConstPtr(myptr), descr=nextdescr)
  1208. p2 = getfield_gc_r(p0, descr=nextdescr)
  1209. i1 = ptr_eq(p2, NULL)
  1210. jump(i1)
  1211. """
  1212. expected = """
  1213. []
  1214. jump()
  1215. """
  1216. self.optimize_loop(ops, expected)
  1217. def test_virtual_field_forced_by_lazy_setfield(self):
  1218. ops = """
  1219. [i0, p1, p3]
  1220. i28 = int_add(i0, 1)
  1221. p30 = new_with_vtable(descr=nodesize)
  1222. setfield_gc(p30, i28, descr=valuedescr)
  1223. setfield_gc(p3, p30, descr=nextdescr)
  1224. p45 = getfield_gc_r(p3, descr=nextdescr)
  1225. i29 = int_add(i28, 1)
  1226. jump(i29, p45, p3)
  1227. """
  1228. preamble = """
  1229. [i0, p1, p3]
  1230. i28 = int_add(i0, 1)
  1231. i29 = int_add(i28, 1)
  1232. p30 = new_with_vtable(descr=nodesize)
  1233. setfield_gc(p30, i28, descr=valuedescr)
  1234. setfield_gc(p3, p30, descr=nextdescr)
  1235. #p46 = same_as(p30) # This same_as should be killed by backend
  1236. jump(i29, p30, p3)
  1237. """
  1238. expected = """
  1239. [i0, p1, p3]
  1240. i28 = int_add(i0, 1)
  1241. i29 = int_add(i28, 1)
  1242. p30 = new_with_vtable(descr=nodesize)
  1243. setfield_gc(p30, i28, descr=valuedescr)
  1244. setfield_gc(p3, p30, descr=nextdescr)
  1245. jump(i29, p30, p3)
  1246. """
  1247. self.optimize_loop(ops, expected, preamble)
  1248. def test_nonvirtual_1(self):
  1249. ops = """
  1250. [i]
  1251. p1 = new_with_vtable(descr=nodesize)
  1252. setfield_gc(p1, i, descr=valuedescr)
  1253. i0 = getfield_gc_i(p1, descr=valuedescr)
  1254. i1 = int_add(i0, 1)
  1255. escape_n(p1)
  1256. escape_n(p1)
  1257. jump(i1)
  1258. """
  1259. expected = """
  1260. [i]
  1261. i1 = int_add(i, 1)
  1262. p1 = new_with_vtable(descr=nodesize)
  1263. setfield_gc(p1, i, descr=valuedescr)
  1264. escape_n(p1)
  1265. escape_n(p1)
  1266. jump(i1)
  1267. """
  1268. self.optimize_loop(ops, expected)
  1269. def test_nonvirtual_2(self):
  1270. ops = """
  1271. [i, p0]
  1272. i0 = getfield_gc_i(p0, descr=valuedescr)
  1273. escape_n(p0)
  1274. i1 = int_add(i0, i)
  1275. p1 = new_with_vtable(descr=nodesize)
  1276. setfield_gc(p1, i1, descr=valuedescr)
  1277. jump(i, p1)
  1278. """
  1279. preamble = """
  1280. [i, p0]
  1281. i0 = getfield_gc_i(p0, descr=valuedescr)
  1282. escape_n(p0)
  1283. i1 = int_add(i0, i)
  1284. jump(i, i1)
  1285. """
  1286. expected = """
  1287. [i, i1]
  1288. p1 = new_with_vtable(descr=nodesize)
  1289. setfield_gc(p1, i1, descr=valuedescr)
  1290. escape_n(p1)
  1291. i2 = int_add(i1, i)
  1292. jump(i, i2)
  1293. """
  1294. self.optimize_loop(ops, expected, preamble)
  1295. def test_nonvirtual_later(self):
  1296. ops = """
  1297. [i]
  1298. p1 = new_with_vtable(descr=nodesize)
  1299. setfield_gc(p1, i, descr=valuedescr)
  1300. i1 = getfield_gc_i(p1, descr=valuedescr)
  1301. escape_n(p1)
  1302. i2 = getfield_gc_i(p1, descr=valuedescr)
  1303. i3 = int_add(i1, i2)
  1304. jump(i3)
  1305. """
  1306. expected = """
  1307. [i]
  1308. p1 = new_with_vtable(descr=nodesize)
  1309. setfield_gc(p1, i, descr=valuedescr)
  1310. escape_n(p1)
  1311. i2 = getfield_gc_i(p1, descr=valuedescr)
  1312. i3 = int_add(i, i2)
  1313. jump(i3)
  1314. """
  1315. self.optimize_loop(ops, expected)
  1316. def test_nonvirtual_write_null_fields_on_force(self):
  1317. ops = """
  1318. [i]
  1319. p1 = new_with_vtable(descr=nodesize)
  1320. setfield_gc(p1, i, descr=valuedescr)
  1321. i1 = getfield_gc_i(p1, descr=valuedescr)
  1322. setfield_gc(p1, 0, descr=valuedescr)
  1323. escape_n(p1)
  1324. i2 = getfield_gc_i(p1, descr=valuedescr)
  1325. jump(i2)
  1326. """
  1327. expected = """
  1328. [i]
  1329. p1 = new_with_vtable(descr=nodesize)
  1330. setfield_gc(p1, 0, descr=valuedescr)
  1331. escape_n(p1)
  1332. i2 = getfield_gc_i(p1, descr=valuedescr)
  1333. jump(i2)
  1334. """
  1335. self.optimize_loop(ops, expected)
  1336. def test_pure_getfield_gc_1(self):
  1337. ops = """
  1338. [i]
  1339. p1 = new_with_vtable(descr=nodesize)
  1340. setfield_gc(p1, i, descr=valuedescr)
  1341. i1 = getfield_gc_i(p1, descr=valuedescr)
  1342. jump(i1)
  1343. """
  1344. expected = """
  1345. [i]
  1346. jump(i)
  1347. """
  1348. self.optimize_loop(ops, expected)
  1349. def test_pure_getfield_gc_2(self):
  1350. ops = """
  1351. [i]
  1352. i1 = getfield_gc_i(ConstPtr(myptr3), descr=valuedescr3)
  1353. jump(i1)
  1354. """
  1355. expected = """
  1356. []
  1357. jump()
  1358. """
  1359. self.node.value = 5
  1360. self.optimize_loop(ops, expected)
  1361. def test_pure_getfield_gc_3(self):
  1362. ops = """
  1363. []
  1364. p1 = escape_r()
  1365. p2 = getfield_gc_r(p1, descr=nextdescr3)
  1366. escape_n(p2)
  1367. p3 = getfield_gc_r(p1, descr=nextdescr3)
  1368. escape_n(p3)
  1369. jump()
  1370. """
  1371. expected = """
  1372. []
  1373. p1 = escape_r()
  1374. p2 = getfield_gc_r(p1, descr=nextdescr3)
  1375. escape_n(p2)
  1376. escape_n(p2)
  1377. jump()
  1378. """
  1379. self.optimize_loop(ops, expected)
  1380. def test_getfield_gc_nonpure_2(self):
  1381. ops = """
  1382. [i]
  1383. i1 = getfield_gc_i(ConstPtr(myptr), descr=valuedescr)
  1384. call_n(i1, descr=nonwritedescr)
  1385. jump(i)
  1386. """
  1387. preamble = """
  1388. [i]
  1389. i1 = getfield_gc_i(ConstPtr(myptr), descr=valuedescr)
  1390. call_n(i1, descr=nonwritedescr)
  1391. jump(i, i1)
  1392. """
  1393. expected = """
  1394. [i, i1]
  1395. call_n(i1, descr=nonwritedescr)
  1396. jump(i, i1)
  1397. """
  1398. self.optimize_loop(ops, expected, preamble)
  1399. def test_varray_boxed1(self):
  1400. ops = """
  1401. [p0, p8]
  1402. p11 = getfield_gc_r(p0, descr=otherdescr)
  1403. guard_nonnull(p11) [p0, p8]
  1404. guard_class(p11, ConstClass(node_vtable2)) [p0, p8]
  1405. p14 = getfield_gc_r(p11, descr=otherdescr)
  1406. guard_isnull(p14) [p0, p8]
  1407. p18 = getfield_gc_r(ConstPtr(myptr), descr=otherdescr)
  1408. guard_isnull(p18) [p0, p8]
  1409. p31 = new(descr=ssize)
  1410. setfield_gc(p31, 0, descr=adescr)
  1411. p33 = new_array(0, descr=arraydescr)
  1412. setfield_gc(p31, p33, descr=bdescr)
  1413. p35 = new_with_vtable(descr=nodesize)
  1414. setfield_gc(p35, p31, descr=nexttupledescr)
  1415. jump(p0, p35)
  1416. """
  1417. expected = """
  1418. [p0, p1]
  1419. jump(p0, p1)
  1420. """
  1421. self.optimize_loop(ops, expected)
  1422. def test_varray_boxed_simplified(self):
  1423. ops = """
  1424. [p0, p8]
  1425. p18 = getfield_gc_r(ConstPtr(myptr), descr=otherdescr)
  1426. guard_isnull(p18) [p0, p8]
  1427. p31 = new(descr=ssize)
  1428. p35 = new_with_vtable(descr=nodesize)
  1429. setfield_gc(p35, p31, descr=nexttupledescr)
  1430. jump(p0, p35)
  1431. """
  1432. expected = """
  1433. [p0]
  1434. jump(p0)
  1435. """
  1436. self.optimize_loop(ops, expected)
  1437. def test_varray_boxed_noconst(self):
  1438. ops = """
  1439. [p0, p8, p18, p19]
  1440. guard_isnull(p18) [p0, p8]
  1441. p31 = new(descr=ssize)
  1442. p35 = new_with_vtable(descr=nodesize)
  1443. setfield_gc(p35, p31, descr=nexttupledescr)
  1444. jump(p0, p35, p19, p18)
  1445. """
  1446. expected = """
  1447. [p0, p19]
  1448. guard_isnull(p19) [p0]
  1449. jump(p0, NULL)
  1450. """
  1451. self.optimize_loop(ops, expected)
  1452. def test_varray_1(self):
  1453. ops = """
  1454. [i1]
  1455. p1 = new_array(3, descr=arraydescr)
  1456. i3 = arraylen_gc(p1, descr=arraydescr)
  1457. guard_value(i3, 3) []
  1458. setarrayitem_gc(p1, 1, i1, descr=arraydescr)
  1459. setarrayitem_gc(p1, 0, 25, descr=arraydescr)
  1460. i2 = getarrayitem_gc_i(p1, 1, descr=arraydescr)
  1461. jump(i2)
  1462. """
  1463. expected = """
  1464. [i1]
  1465. jump(i1)
  1466. """
  1467. self.optimize_loop(ops, expected)
  1468. def test_varray_clear_unroll_bug(self):
  1469. ops = """
  1470. [p0]
  1471. i0 = getarrayitem_gc_i(p0, 0, descr=arraydescr)
  1472. i1 = getarrayitem_gc_i(p0, 1, descr=arraydescr)
  1473. i2 = getarrayitem_gc_i(p0, 2, descr=arraydescr)
  1474. i3 = int_add(i0, i1)
  1475. i4 = int_add(i3, i2)
  1476. p1 = new_array_clear(3, descr=arraydescr)
  1477. setarrayitem_gc(p1, 1, i4, descr=arraydescr)
  1478. setarrayitem_gc(p1, 0, 25, descr=arraydescr)
  1479. jump(p1)
  1480. """
  1481. expected = """
  1482. [i1]
  1483. i2 = int_add(25, i1)
  1484. jump(i2)
  1485. """
  1486. jump_values = [self.arrayref]
  1487. self.optimize_loop(ops, expected, jump_values=jump_values)
  1488. def test_varray_alloc_and_set(self):
  1489. ops = """
  1490. [i1]
  1491. p1 = new_array(2, descr=arraydescr)
  1492. setarrayitem_gc(p1, 0, 25, descr=arraydescr)
  1493. i2 = getarrayitem_gc_i(p1, 0, descr=arraydescr)
  1494. jump(i2)
  1495. """
  1496. preamble = """
  1497. [i1]
  1498. jump()
  1499. """
  1500. expected = """
  1501. []
  1502. jump()
  1503. """
  1504. self.optimize_loop(ops, expected, preamble)
  1505. def test_varray_float(self):
  1506. ops = """
  1507. [f1]
  1508. p1 = new_array(3, descr=floatarraydescr)
  1509. i3 = arraylen_gc(p1, descr=floatarraydescr)
  1510. guard_value(i3, 3) []
  1511. setarrayitem_gc(p1, 1, f1, descr=floatarraydescr)
  1512. setarrayitem_gc(p1, 0, 3.5, descr=floatarraydescr)
  1513. f2 = getarrayitem_gc_f(p1, 1, descr=floatarraydescr)
  1514. jump(f2)
  1515. """
  1516. expected = """
  1517. [f1]
  1518. jump(f1)
  1519. """
  1520. self.optimize_loop(ops, expected)
  1521. def test_array_non_optimized(self):
  1522. ops = """
  1523. [i1, p0]
  1524. setarrayitem_gc(p0, 0, i1, descr=arraydescr)
  1525. guard_nonnull(p0) []
  1526. p1 = new_array(i1, descr=arraydescr)
  1527. jump(i1, p1)
  1528. """
  1529. expected = """
  1530. [i1, p0]
  1531. p1 = new_array(i1, descr=arraydescr)
  1532. setarrayitem_gc(p0, 0, i1, descr=arraydescr)
  1533. jump(i1, p1)
  1534. """
  1535. self.optimize_loop(ops, expected)
  1536. def test_nonvirtual_array_write_null_fields_on_force(self):
  1537. ops = """
  1538. [i1]
  1539. p1 = new_array(5, descr=arraydescr)
  1540. setarrayitem_gc(p1, 0, i1, descr=arraydescr)
  1541. setarrayitem_gc(p1, 1, 0, descr=arraydescr)
  1542. escape_n(p1)
  1543. jump(i1)
  1544. """
  1545. expected = """
  1546. [i1]
  1547. p1 = new_array(5, descr=arraydescr)
  1548. setarrayitem_gc(p1, 0, i1, descr=arraydescr)
  1549. setarrayitem_gc(p1, 1, 0, descr=arraydescr)
  1550. escape_n(p1)
  1551. jump(i1)
  1552. """
  1553. self.optimize_loop(ops, expected)
  1554. def test_varray_2(self):
  1555. ops = """
  1556. [i0, p1]
  1557. i1 = getarrayitem_gc_i(p1, 0, descr=arraydescr)
  1558. i2 = getarrayitem_gc_i(p1, 1, descr=arraydescr)
  1559. i3 = int_sub(i1, i2)
  1560. guard_value(i3, 15) []
  1561. p2 = new_array(2, descr=arraydescr)
  1562. setarrayitem_gc(p2, 1, i0, descr=arraydescr)
  1563. setarrayitem_gc(p2, 0, 20, descr=arraydescr)
  1564. jump(i0, p2)
  1565. """
  1566. preamble = """
  1567. [i0, p1]
  1568. i1 = getarrayitem_gc_i(p1, 0, descr=arraydescr)
  1569. i2 = getarrayitem_gc_i(p1, 1, descr=arraydescr)
  1570. i3 = int_sub(i1, i2)
  1571. guard_value(i3, 15) []
  1572. jump(i0)
  1573. """
  1574. expected = """
  1575. [i0]
  1576. i3 = int_sub(20, i0)
  1577. guard_value(i3, 15) []
  1578. jump(5)
  1579. """
  1580. self.optimize_loop(ops, expected, preamble,
  1581. jump_values=[None, self.arrayref])
  1582. def test_p123_array(self):
  1583. ops = """
  1584. [i1, p2, p3]
  1585. i3 = getarrayitem_gc_i(p3, 0, descr=arraydescr)
  1586. escape_n(i3)
  1587. p1 = new_array(1, descr=arraydescr)
  1588. setarrayitem_gc(p1, 0, i1, descr=arraydescr)
  1589. jump(i1, p1, p2)
  1590. """
  1591. preamble = """
  1592. [i1, p2, p3]
  1593. i3 = getarrayitem_gc_i(p3, 0, descr=arraydescr)
  1594. escape_n(i3)
  1595. jump(i1, p2)
  1596. """
  1597. expected = """
  1598. [i1, p2]
  1599. i3 = getarrayitem_gc_i(p2, 0, descr=arraydescr)
  1600. escape_n(i3)
  1601. p1 = new_array(1, descr=arraydescr)
  1602. setarrayitem_gc(p1, 0, i1, descr=arraydescr)
  1603. jump(i1, p1)
  1604. """
  1605. # We cannot track virtuals that survive for more than two iterations.
  1606. self.optimize_loop(ops, expected, preamble,
  1607. jump_values=[None, self.arrayref, None])
  1608. def test_varray_forced_1(self):
  1609. ops = """
  1610. []
  1611. p2 = new_with_vtable(descr=nodesize)
  1612. setfield_gc(p2, 3, descr=valuedescr)
  1613. i1 = getfield_gc_i(p2, descr=valuedescr) # i1 = const 3
  1614. p1 = new_array(i1, descr=arraydescr)
  1615. escape_n(p1)
  1616. i2 = arraylen_gc(p1)
  1617. escape_n(i2)
  1618. jump()
  1619. """
  1620. expected = """
  1621. []
  1622. p1 = new_array(3, descr=arraydescr)
  1623. escape_n(p1)
  1624. escape_n(3)
  1625. jump()
  1626. """
  1627. self.optimize_loop(ops, expected)
  1628. def test_vstruct_1(self):
  1629. ops = """
  1630. [i1, p2]
  1631. i2 = getfield_gc_i(p2, descr=adescr)
  1632. escape_n(i2)
  1633. p3 = new(descr=ssize)
  1634. setfield_gc(p3, i1, descr=adescr)
  1635. jump(i1, p3)
  1636. """
  1637. preamble = """
  1638. [i1, p2]
  1639. i2 = getfield_gc_i(p2, descr=adescr)
  1640. escape_n(i2)
  1641. jump(i1)
  1642. """
  1643. expected = """
  1644. [i1]
  1645. escape_n(i1)
  1646. jump(i1)
  1647. """
  1648. self.optimize_loop(ops, expected, preamble,
  1649. jump_values=[None, self.tupleaddr])
  1650. def test_p123_vstruct(self):
  1651. ops = """
  1652. [i1, p2, p3]
  1653. i3 = getfield_gc_i(p3, descr=adescr)
  1654. escape_n(i3)
  1655. p1 = new(descr=ssize)
  1656. setfield_gc(p1, i1, descr=adescr)
  1657. jump(i1, p1, p2)
  1658. """
  1659. preamble = """
  1660. [i1, p2, p3]
  1661. i3 = getfield_gc_i(p3, descr=adescr)
  1662. escape_n(i3)
  1663. jump(i1, p2)
  1664. """
  1665. expected = """
  1666. [i1, p2]
  1667. i3 = getfield_gc_i(p2, descr=adescr)
  1668. escape_n(i3)
  1669. p1 = new(descr=ssize)
  1670. setfield_gc(p1, i1, descr=adescr)
  1671. jump(i1, p1)
  1672. """
  1673. # We cannot track virtuals that survive for more than two iterations.
  1674. self.optimize_loop(ops, expected, preamble,
  1675. jump_values=[None, self.tupleaddr, None])
  1676. def test_virtual_raw_malloc_basic(self):
  1677. ops = """
  1678. [i1]
  1679. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  1680. guard_no_exception() []
  1681. setarrayitem_raw(i2, 0, i1, descr=rawarraydescr)
  1682. i3 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr)
  1683. call_n('free', i2, descr=raw_free_descr)
  1684. jump(i3)
  1685. """
  1686. expected = """
  1687. [i1]
  1688. jump(i1)
  1689. """
  1690. self.optimize_loop(ops, expected)
  1691. def test_virtual_raw_malloc_const(self):
  1692. ops = """
  1693. [i1]
  1694. i5 = int_mul(10, 1)
  1695. i2 = call_i('malloc', i5, descr=raw_malloc_descr)
  1696. guard_no_exception() []
  1697. setarrayitem_raw(i2, 0, i1, descr=rawarraydescr)
  1698. i3 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr)
  1699. call_n('free', i2, descr=raw_free_descr)
  1700. jump(i3)
  1701. """
  1702. expected = """
  1703. [i1]
  1704. jump(i1)
  1705. """
  1706. self.optimize_loop(ops, expected)
  1707. def test_virtual_raw_malloc_force(self):
  1708. ops = """
  1709. [i1]
  1710. i2 = call_i('malloc', 20, descr=raw_malloc_descr)
  1711. guard_no_exception() []
  1712. setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char)
  1713. setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char)
  1714. setarrayitem_raw(i2, 1, 123, descr=rawarraydescr_char)
  1715. setarrayitem_raw(i2, 1, 789, descr=rawarraydescr_float)
  1716. label(i1, descr=123) # we expect the buffer to be forced *after* the label
  1717. escape_n(i2)
  1718. call_n('free', i2, descr=raw_free_descr)
  1719. jump(i1)
  1720. """
  1721. expected = """
  1722. [i1]
  1723. label(i1)
  1724. i2 = call_i('malloc', 20, descr=raw_malloc_descr)
  1725. check_memory_error(i2)
  1726. raw_store(i2, 0, i1, descr=rawarraydescr_char)
  1727. raw_store(i2, 1, 123, descr=rawarraydescr_char)
  1728. raw_store(i2, 2, 456, descr=rawarraydescr_char)
  1729. raw_store(i2, 8, 789, descr=rawarraydescr_float)
  1730. escape_n(i2)
  1731. call_n('free', i2, descr=raw_free_descr)
  1732. jump(i1)
  1733. """
  1734. self.optimize_loop(ops, expected)
  1735. def test_virtual_raw_malloc_invalid_write_force(self):
  1736. ops = """
  1737. [i1]
  1738. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  1739. guard_no_exception() []
  1740. setarrayitem_raw(i2, 0, i1, descr=rawarraydescr)
  1741. label(i1) # we expect the buffer to be forced *after* the label
  1742. setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) # overlap!
  1743. call_n('free', i2, descr=raw_free_descr)
  1744. jump(i1)
  1745. """
  1746. expected = """
  1747. [i1]
  1748. label(i1)
  1749. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  1750. check_memory_error(i2)
  1751. raw_store(i2, 0, i1, descr=rawarraydescr)
  1752. setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char)
  1753. call_n('free', i2, descr=raw_free_descr)
  1754. jump(i1)
  1755. """
  1756. self.optimize_loop(ops, expected)
  1757. def test_virtual_raw_malloc_invalid_read_force(self):
  1758. ops = """
  1759. [i1]
  1760. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  1761. guard_no_exception() []
  1762. setarrayitem_raw(i2, 0, i1, descr=rawarraydescr)
  1763. label(i1) # we expect the buffer to be forced *after* the label
  1764. i3 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr_char)
  1765. call_n('free', i2, descr=raw_free_descr)
  1766. jump(i1)
  1767. """
  1768. expected = """
  1769. [i1]
  1770. label(i1)
  1771. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  1772. check_memory_error(i2)
  1773. raw_store(i2, 0, i1, descr=rawarraydescr)
  1774. i3 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr_char)
  1775. call_n('free', i2, descr=raw_free_descr)
  1776. jump(i1)
  1777. """
  1778. self.optimize_loop(ops, expected)
  1779. def test_virtual_raw_slice(self):
  1780. ops = """
  1781. [i0, i1]
  1782. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  1783. guard_no_exception() []
  1784. setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char)
  1785. i3 = int_add(i2, 1) # get a slice of the original buffer
  1786. setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr) # write to the slice
  1787. i4 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr_char)
  1788. i5 = int_add(i2, 1)
  1789. i6 = getarrayitem_raw_i(i5, 0, descr=rawarraydescr)
  1790. call_n('free', i2, descr=raw_free_descr)
  1791. jump(i0, i1)
  1792. """
  1793. expected = """
  1794. [i0, i1]
  1795. jump(i0, i1)
  1796. """
  1797. self.optimize_loop(ops, expected)
  1798. def test_virtual_raw_slice_of_a_raw_slice(self):
  1799. ops = """
  1800. [i0, i1]
  1801. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  1802. guard_no_exception() []
  1803. i3 = int_add(i2, 1) # get a slice of the original buffer
  1804. i4 = int_add(i3, 1) # get a slice of a slice
  1805. setarrayitem_raw(i4, 0, i1, descr=rawarraydescr_char) # write to the slice
  1806. i5 = getarrayitem_raw_i(i2, 2, descr=rawarraydescr_char)
  1807. call_n('free', i2, descr=raw_free_descr)
  1808. jump(i0, i5)
  1809. """
  1810. expected = """
  1811. [i0, i1]
  1812. jump(i0, i1)
  1813. """
  1814. self.optimize_loop(ops, expected)
  1815. def test_virtual_raw_slice_force(self):
  1816. ops = """
  1817. [i0, i1]
  1818. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  1819. guard_no_exception() []
  1820. setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char)
  1821. i3 = int_add(i2, 1) # get a slice of the original buffer
  1822. setarrayitem_raw(i3, 4, 4242, descr=rawarraydescr_char) # write to the slice
  1823. label(i0, i1)
  1824. escape_n(i3)
  1825. jump(i0, i1)
  1826. """
  1827. expected = """
  1828. [i0, i1]
  1829. label(i0, i1)
  1830. # these ops are generated by VirtualRawBufferValue._really_force
  1831. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  1832. check_memory_error(i2)
  1833. raw_store(i2, 0, 42, descr=rawarraydescr_char)
  1834. raw_store(i2, 5, 4242, descr=rawarraydescr_char)
  1835. # this is generated by VirtualRawSliceValue._really_force
  1836. i4 = int_add(i2, 1)
  1837. escape_n(i4)
  1838. jump(i0, i1)
  1839. """
  1840. self.optimize_loop(ops, expected)
  1841. def test_virtual_raw_malloc_virtualstate(self):
  1842. ops = """
  1843. [i0]
  1844. i1 = getarrayitem_raw_i(i0, 0, descr=rawarraydescr)
  1845. i2 = int_add(i1, 1)
  1846. call_n('free', i0, descr=raw_free_descr)
  1847. i3 = call_i('malloc', 10, descr=raw_malloc_descr)
  1848. guard_no_exception() []
  1849. setarrayitem_raw(i3, 0, i2, descr=rawarraydescr)
  1850. label(i2)
  1851. jump(i3)
  1852. """
  1853. expected = """
  1854. [i0]
  1855. i1 = getarrayitem_raw_i(i0, 0, descr=rawarraydescr)
  1856. i2 = int_add(i1, 1)
  1857. call_n('free', i0, descr=raw_free_descr)
  1858. label(i2)
  1859. i3 = call_i('malloc', 10, descr=raw_malloc_descr)
  1860. check_memory_error(i3)
  1861. raw_store(i3, 0, i2, descr=rawarraydescr)
  1862. jump(i3)
  1863. """
  1864. self.optimize_loop(ops, expected)
  1865. def test_virtual_raw_store_raw_load(self):
  1866. ops = """
  1867. [i1]
  1868. i0 = call_i('malloc', 10, descr=raw_malloc_descr)
  1869. guard_no_exception() []
  1870. raw_store(i0, 0, i1, descr=rawarraydescr)
  1871. i2 = raw_load_i(i0, 0, descr=rawarraydescr)
  1872. i3 = int_add(i1, i2)
  1873. call_n('free', i0, descr=raw_free_descr)
  1874. jump(i3)
  1875. """
  1876. expected = """
  1877. [i1]
  1878. i2 = int_add(i1, i1)
  1879. jump(i2)
  1880. """
  1881. self.optimize_loop(ops, expected)
  1882. def test_virtual_raw_store_getarrayitem_raw(self):
  1883. ops = """
  1884. [f1]
  1885. i0 = call_i('malloc', 16, descr=raw_malloc_descr)
  1886. guard_no_exception() []
  1887. raw_store(i0, 8, f1, descr=rawarraydescr_float)
  1888. f2 = getarrayitem_raw_f(i0, 1, descr=rawarraydescr_float)
  1889. f3 = float_add(f1, f2)
  1890. call_n('free', i0, descr=raw_free_descr)
  1891. jump(f3)
  1892. """
  1893. expected = """
  1894. [f1]
  1895. f2 = float_add(f1, f1)
  1896. jump(f2)
  1897. """
  1898. self.optimize_loop(ops, expected)
  1899. def test_virtual_setarrayitem_raw_raw_load(self):
  1900. ops = """
  1901. [f1]
  1902. i0 = call_i('malloc', 16, descr=raw_malloc_descr)
  1903. guard_no_exception() []
  1904. setarrayitem_raw(i0, 1, f1, descr=rawarraydescr_float)
  1905. f2 = raw_load_f(i0, 8, descr=rawarraydescr_float)
  1906. f3 = float_add(f1, f2)
  1907. call_n('free', i0, descr=raw_free_descr)
  1908. jump(f3)
  1909. """
  1910. expected = """
  1911. [f1]
  1912. f2 = float_add(f1, f1)
  1913. jump(f2)
  1914. """
  1915. self.optimize_loop(ops, expected)
  1916. def test_virtual_raw_buffer_forced_but_slice_not_forced(self):
  1917. ops = """
  1918. [f1]
  1919. i0 = call_i('malloc', 16, descr=raw_malloc_descr)
  1920. guard_no_exception() []
  1921. i1 = int_add(i0, 8)
  1922. escape_n(i0)
  1923. setarrayitem_raw(i1, 0, f1, descr=rawarraydescr_float)
  1924. jump(f1)
  1925. """
  1926. expected = """
  1927. [f1]
  1928. i0 = call_i('malloc', 16, descr=raw_malloc_descr)
  1929. check_memory_error(i0)
  1930. escape_n(i0)
  1931. i1 = int_add(i0, 8)
  1932. setarrayitem_raw(i1, 0, f1, descr=rawarraydescr_float)
  1933. jump(f1)
  1934. """
  1935. self.optimize_loop(ops, expected)
  1936. def test_duplicate_getfield_1(self):
  1937. ops = """
  1938. [p1, p2]
  1939. i1 = getfield_gc_i(p1, descr=valuedescr)
  1940. i2 = getfield_gc_i(p2, descr=valuedescr)
  1941. i3 = getfield_gc_i(p1, descr=valuedescr)
  1942. i4 = getfield_gc_i(p2, descr=valuedescr)
  1943. escape_n(i1)
  1944. escape_n(i2)
  1945. escape_n(i3)
  1946. escape_n(i4)
  1947. jump(p1, p2)
  1948. """
  1949. expected = """
  1950. [p1, p2]
  1951. i1 = getfield_gc_i(p1, descr=valuedescr)
  1952. i2 = getfield_gc_i(p2, descr=valuedescr)
  1953. escape_n(i1)
  1954. escape_n(i2)
  1955. escape_n(i1)
  1956. escape_n(i2)
  1957. jump(p1, p2)
  1958. """
  1959. self.optimize_loop(ops, expected)
  1960. def test_duplicate_getfield_2(self):
  1961. ops = """
  1962. [p1, p2, i0]
  1963. i1 = getfield_gc_i(p1, descr=valuedescr)
  1964. i2 = getfield_gc_i(p2, descr=valuedescr)
  1965. i3 = getfield_gc_i(p1, descr=valuedescr)
  1966. i4 = getfield_gc_i(p2, descr=valuedescr)
  1967. i5 = int_add(i3, i4)
  1968. i6 = int_add(i0, i5)
  1969. jump(p1, p2, i6)
  1970. """
  1971. expected = """
  1972. [p1, p2, i0, i5]
  1973. i6 = int_add(i0, i5)
  1974. jump(p1, p2, i6, i5)
  1975. """
  1976. self.optimize_loop(ops, expected)
  1977. def test_getfield_after_setfield(self):
  1978. ops = """
  1979. [p1, i1]
  1980. setfield_gc(p1, i1, descr=valuedescr)
  1981. i2 = getfield_gc_i(p1, descr=valuedescr)
  1982. escape_n(i2)
  1983. jump(p1, i1)
  1984. """
  1985. expected = """
  1986. [p1, i1]
  1987. setfield_gc(p1, i1, descr=valuedescr)
  1988. escape_n(i1)
  1989. jump(p1, i1)
  1990. """
  1991. self.optimize_loop(ops, expected)
  1992. def test_setfield_of_different_type_does_not_clear(self):
  1993. ops = """
  1994. [p1, p2, i1]
  1995. setfield_gc(p1, i1, descr=valuedescr)
  1996. setfield_gc(p2, p1, descr=nextdescr)
  1997. i2 = getfield_gc_i(p1, descr=valuedescr)
  1998. escape_n(i2)
  1999. jump(p1, p2, i1)
  2000. """
  2001. expected = """
  2002. [p1, p2, i1]
  2003. setfield_gc(p1, i1, descr=valuedescr)
  2004. setfield_gc(p2, p1, descr=nextdescr)
  2005. escape_n(i1)
  2006. jump(p1, p2, i1)
  2007. """
  2008. self.optimize_loop(ops, expected)
  2009. def test_setfield_of_same_type_clears(self):
  2010. ops = """
  2011. [p1, p2, i1, i2]
  2012. setfield_gc(p1, i1, descr=valuedescr)
  2013. setfield_gc(p2, i2, descr=valuedescr)
  2014. i3 = getfield_gc_i(p1, descr=valuedescr)
  2015. escape_n(i3)
  2016. jump(p1, p2, i1, i3)
  2017. """
  2018. self.optimize_loop(ops, ops)
  2019. def test_duplicate_getfield_mergepoint_has_no_side_effects(self):
  2020. ops = """
  2021. [p1]
  2022. i1 = getfield_gc_i(p1, descr=valuedescr)
  2023. debug_merge_point(15, 0)
  2024. i2 = getfield_gc_i(p1, descr=valuedescr)
  2025. escape_n(i1)
  2026. escape_n(i2)
  2027. jump(p1)
  2028. """
  2029. expected = """
  2030. [p1]
  2031. i1 = getfield_gc_i(p1, descr=valuedescr)
  2032. debug_merge_point(15, 0)
  2033. escape_n(i1)
  2034. escape_n(i1)
  2035. jump(p1)
  2036. """
  2037. self.optimize_loop(ops, expected)
  2038. def test_duplicate_getfield_ovf_op_does_not_clear(self):
  2039. ops = """
  2040. [p1]
  2041. i1 = getfield_gc_i(p1, descr=valuedescr)
  2042. i2 = int_add_ovf(i1, 14)
  2043. guard_no_overflow() []
  2044. i3 = getfield_gc_i(p1, descr=valuedescr)
  2045. escape_n(i2)
  2046. escape_n(i3)
  2047. jump(p1)
  2048. """
  2049. expected = """
  2050. [p1]
  2051. i1 = getfield_gc_i(p1, descr=valuedescr)
  2052. i2 = int_add_ovf(i1, 14)
  2053. guard_no_overflow() []
  2054. escape_n(i2)
  2055. escape_n(i1)
  2056. jump(p1)
  2057. """
  2058. self.optimize_loop(ops, expected)
  2059. def test_duplicate_getfield_setarrayitem_does_not_clear(self):
  2060. ops = """
  2061. [p1, p2]
  2062. i1 = getfield_gc_i(p1, descr=valuedescr)
  2063. setarrayitem_gc(p2, 0, p1, descr=arraydescr2)
  2064. i3 = getfield_gc_i(p1, descr=valuedescr)
  2065. escape_n(i1)
  2066. escape_n(i3)
  2067. jump(p1, p2)
  2068. """
  2069. expected = """
  2070. [p1, p2]
  2071. i1 = getfield_gc_i(p1, descr=valuedescr)
  2072. setarrayitem_gc(p2, 0, p1, descr=arraydescr2)
  2073. escape_n(i1)
  2074. escape_n(i1)
  2075. jump(p1, p2)
  2076. """
  2077. self.optimize_loop(ops, expected)
  2078. def test_duplicate_getfield_constant(self):
  2079. ops = """
  2080. []
  2081. i1 = getfield_gc_i(ConstPtr(myptr), descr=valuedescr)
  2082. i2 = getfield_gc_i(ConstPtr(myptr), descr=valuedescr)
  2083. escape_n(i1)
  2084. escape_n(i2)
  2085. jump()
  2086. """
  2087. expected = """
  2088. []
  2089. i1 = getfield_gc_i(ConstPtr(myptr), descr=valuedescr)
  2090. escape_n(i1)
  2091. escape_n(i1)
  2092. jump()
  2093. """
  2094. self.optimize_loop(ops, expected)
  2095. def test_duplicate_getfield_guard_value_const(self):
  2096. ops = """
  2097. [p1]
  2098. guard_value(p1, ConstPtr(myptr)) []
  2099. i1 = getfield_gc_i(p1, descr=valuedescr)
  2100. i2 = getfield_gc_i(ConstPtr(myptr), descr=valuedescr)
  2101. escape_n(i1)
  2102. escape_n(i2)
  2103. jump(p1)
  2104. """
  2105. expected = """
  2106. []
  2107. i1 = getfield_gc_i(ConstPtr(myptr), descr=valuedescr)
  2108. escape_n(i1)
  2109. escape_n(i1)
  2110. jump()
  2111. """
  2112. self.optimize_loop(ops, expected)
  2113. def test_duplicate_getfield_sideeffects_1(self):
  2114. ops = """
  2115. [p1]
  2116. i1 = getfield_gc_i(p1, descr=valuedescr)
  2117. escape_n()
  2118. i2 = getfield_gc_i(p1, descr=valuedescr)
  2119. escape_n(i1)
  2120. escape_n(i2)
  2121. jump(p1)
  2122. """
  2123. self.optimize_loop(ops, ops)
  2124. def test_duplicate_getfield_sideeffects_2(self):
  2125. ops = """
  2126. [p1, i1]
  2127. setfield_gc(p1, i1, descr=valuedescr)
  2128. escape_n()
  2129. i2 = getfield_gc_i(p1, descr=valuedescr)
  2130. escape_n(i2)
  2131. jump(p1, i1)
  2132. """
  2133. self.optimize_loop(ops, ops)
  2134. def test_duplicate_setfield_0(self):
  2135. ops = """
  2136. [p1, i1, i2]
  2137. setfield_gc(p1, i1, descr=valuedescr)
  2138. setfield_gc(p1, i2, descr=valuedescr)
  2139. jump(p1, i1, i2)
  2140. """
  2141. expected = """
  2142. [p1, i1, i2]
  2143. setfield_gc(p1, i2, descr=valuedescr)
  2144. jump(p1, i1, i2)
  2145. """
  2146. # in this case, all setfields are removed, because we can prove
  2147. # that in the loop it will always have the same value
  2148. self.optimize_loop(ops, expected)
  2149. def test_duplicate_setfield_1(self):
  2150. ops = """
  2151. [p1]
  2152. i1 = escape_i()
  2153. i2 = escape_i()
  2154. setfield_gc(p1, i1, descr=valuedescr)
  2155. setfield_gc(p1, i2, descr=valuedescr)
  2156. jump(p1)
  2157. """
  2158. expected = """
  2159. [p1]
  2160. i1 = escape_i()
  2161. i2 = escape_i()
  2162. setfield_gc(p1, i2, descr=valuedescr)
  2163. jump(p1)
  2164. """
  2165. self.optimize_loop(ops, expected)
  2166. def test_duplicate_setfield_2(self):
  2167. ops = """
  2168. [p1, i1, i3]
  2169. setfield_gc(p1, i1, descr=valuedescr)
  2170. i2 = getfield_gc_i(p1, descr=valuedescr)
  2171. setfield_gc(p1, i3, descr=valuedescr)
  2172. escape_n(i2)
  2173. jump(p1, i1, i3)
  2174. """
  2175. expected = """
  2176. [p1, i1, i3]
  2177. setfield_gc(p1, i3, descr=valuedescr)
  2178. escape_n(i1)
  2179. jump(p1, i1, i3)
  2180. """
  2181. self.optimize_loop(ops, expected)
  2182. def test_duplicate_setfield_3(self):
  2183. ops = """
  2184. [p1, p2, i1, i3]
  2185. setfield_gc(p1, i1, descr=valuedescr)
  2186. i2 = getfield_gc_i(p2, descr=valuedescr)
  2187. setfield_gc(p1, i3, descr=valuedescr)
  2188. escape_n(i2)
  2189. jump(p1, p2, i1, i3)
  2190. """
  2191. # potential aliasing of p1 and p2 means that we cannot kill the
  2192. # the setfield_gc
  2193. self.optimize_loop(ops, ops)
  2194. def test_duplicate_setfield_4(self):
  2195. ops = """
  2196. [p1, i1, i2, p3]
  2197. setfield_gc(p1, i1, descr=valuedescr)
  2198. #
  2199. # some operations on which the above setfield_gc cannot have effect
  2200. i3 = getarrayitem_gc_i(p3, 1, descr=arraydescr)
  2201. i4 = getarrayitem_gc_i(p3, i3, descr=arraydescr)
  2202. i5 = int_add(i3, i4)
  2203. setarrayitem_gc(p3, 0, i5, descr=arraydescr)
  2204. setfield_gc(p1, i4, descr=nextdescr)
  2205. #
  2206. setfield_gc(p1, i2, descr=valuedescr)
  2207. escape_n()
  2208. jump(p1, i1, i2, p3)
  2209. """
  2210. preamble = """
  2211. [p1, i1, i2, p3]
  2212. #
  2213. i3 = getarrayitem_gc_i(p3, 1, descr=arraydescr)
  2214. i4 = getarrayitem_gc_i(p3, i3, descr=arraydescr)
  2215. i5 = int_add(i3, i4)
  2216. #
  2217. setfield_gc(p1, i2, descr=valuedescr)
  2218. setfield_gc(p1, i4, descr=nextdescr)
  2219. setarrayitem_gc(p3, 0, i5, descr=arraydescr)
  2220. escape_n()
  2221. jump(p1, i1, i2, p3)
  2222. """
  2223. expected = """
  2224. [p1, i1, i2, p3]
  2225. #
  2226. i3 = getarrayitem_gc_i(p3, 1, descr=arraydescr)
  2227. i4 = getarrayitem_gc_i(p3, i3, descr=arraydescr)
  2228. i5 = int_add(i3, i4)
  2229. #
  2230. setfield_gc(p1, i2, descr=valuedescr)
  2231. setfield_gc(p1, i4, descr=nextdescr)
  2232. setarrayitem_gc(p3, 0, i5, descr=arraydescr)
  2233. escape_n()
  2234. jump(p1, i1, i2, p3)
  2235. """
  2236. self.optimize_loop(ops, expected, preamble)
  2237. def test_duplicate_setfield_5(self):
  2238. ops = """
  2239. [p0, i1]
  2240. p1 = new_with_vtable(descr=nodesize)
  2241. setfield_gc(p1, i1, descr=valuedescr)
  2242. setfield_gc(p0, p1, descr=nextdescr)
  2243. setfield_raw(i1, i1, descr=valuedescr) # random op with side-effects
  2244. p2 = getfield_gc_r(p0, descr=nextdescr)
  2245. i2 = getfield_gc_i(p2, descr=valuedescr)
  2246. setfield_gc(p0, NULL, descr=nextdescr)
  2247. escape_n(i2)
  2248. jump(p0, i1)
  2249. """
  2250. expected = """
  2251. [p0, i1]
  2252. setfield_raw(i1, i1, descr=valuedescr)
  2253. setfield_gc(p0, NULL, descr=nextdescr)
  2254. escape_n(i1)
  2255. jump(p0, i1)
  2256. """
  2257. self.optimize_loop(ops, expected)
  2258. def test_duplicate_setfield_sideeffects_1(self):
  2259. ops = """
  2260. [p1, i1, i2]
  2261. setfield_gc(p1, i1, descr=valuedescr)
  2262. escape_n()
  2263. setfield_gc(p1, i2, descr=valuedescr)
  2264. jump(p1, i1, i2)
  2265. """
  2266. self.optimize_loop(ops, ops)
  2267. def test_duplicate_setfield_residual_guard_1(self):
  2268. ops = """
  2269. [p1, i1, i2, i3]
  2270. setfield_gc(p1, i1, descr=valuedescr)
  2271. guard_true(i3) []
  2272. i4 = int_neg(i2)
  2273. setfield_gc(p1, i2, descr=valuedescr)
  2274. jump(p1, i1, i2, i4)
  2275. """
  2276. preamble = """
  2277. [p1, i1, i2, i3]
  2278. setfield_gc(p1, i1, descr=valuedescr)
  2279. guard_true(i3) []
  2280. i4 = int_neg(i2)
  2281. setfield_gc(p1, i2, descr=valuedescr)
  2282. i6 = same_as_i(i4)
  2283. jump(p1, i1, i2, i4, i6)
  2284. """
  2285. expected = """
  2286. [p1, i1, i2, i4, i5]
  2287. setfield_gc(p1, i1, descr=valuedescr)
  2288. guard_true(i4) []
  2289. setfield_gc(p1, i2, descr=valuedescr)
  2290. jump(p1, i1, i2, i5, i5)
  2291. """
  2292. self.optimize_loop(ops, expected, preamble)
  2293. def test_duplicate_setfield_residual_guard_2(self):
  2294. # the difference with the previous test is that the field value is
  2295. # a virtual, which we try hard to keep virtual
  2296. ops = """
  2297. [p1, i2, i3]
  2298. p2 = new_with_vtable(descr=nodesize)
  2299. setfield_gc(p1, p2, descr=nextdescr)
  2300. guard_true(i3) []
  2301. i4 = int_neg(i2)
  2302. setfield_gc(p1, NULL, descr=nextdescr)
  2303. escape_n()
  2304. jump(p1, i2, i4)
  2305. """
  2306. preamble = """
  2307. [p1, i2, i3]
  2308. guard_true(i3) [p1]
  2309. i4 = int_neg(i2)
  2310. setfield_gc(p1, NULL, descr=nextdescr)
  2311. escape_n()
  2312. i5 = same_as_i(i4)
  2313. jump(p1, i2, i4, i5)
  2314. """
  2315. expected = """
  2316. [p1, i2, i4, i5]
  2317. guard_true(i4) [p1]
  2318. setfield_gc(p1, NULL, descr=nextdescr)
  2319. escape_n()
  2320. jump(p1, i2, i5, i5)
  2321. """
  2322. self.optimize_loop(ops, expected, preamble)
  2323. def test_duplicate_setfield_residual_guard_3(self):
  2324. ops = """
  2325. [p1, i2, i3]
  2326. p2 = new_with_vtable(descr=nodesize)
  2327. setfield_gc(p2, i2, descr=valuedescr)
  2328. setfield_gc(p1, p2, descr=nextdescr)
  2329. guard_true(i3) []
  2330. i4 = int_neg(i2)
  2331. setfield_gc(p1, NULL, descr=nextdescr)
  2332. escape_n()
  2333. jump(p1, i2, i4)
  2334. """
  2335. preamble = """
  2336. [p1, i2, i3]
  2337. guard_true(i3) [i2, p1]
  2338. i4 = int_neg(i2)
  2339. setfield_gc(p1, NULL, descr=nextdescr)
  2340. escape_n()
  2341. #i5 = same_as_i(i4)
  2342. jump(p1, i2, i4) #, i5)
  2343. """
  2344. expected = """
  2345. [p1, i2, i4, i5]
  2346. guard_true(i4) [i2, p1]
  2347. setfield_gc(p1, NULL, descr=nextdescr)
  2348. escape_n()
  2349. jump(p1, i2, i5, i5)
  2350. """
  2351. self.optimize_loop(ops, expected)
  2352. def test_duplicate_setfield_residual_guard_4(self):
  2353. # test that the setfield_gc does not end up between int_eq and
  2354. # the following guard_true
  2355. ops = """
  2356. [p1, i1, i2, i3]
  2357. setfield_gc(p1, i1, descr=valuedescr)
  2358. i5 = int_eq(i3, 5)
  2359. guard_true(i5) []
  2360. i4 = int_neg(i2)
  2361. setfield_gc(p1, i2, descr=valuedescr)
  2362. jump(p1, i1, i2, i4)
  2363. """
  2364. preamble = """
  2365. [p1, i1, i2, i3]
  2366. setfield_gc(p1, i1, descr=valuedescr)
  2367. i5 = int_eq(i3, 5)
  2368. guard_true(i5) []
  2369. i4 = int_neg(i2)
  2370. setfield_gc(p1, i2, descr=valuedescr)
  2371. i7 = same_as_i(i4)
  2372. jump(p1, i1, i2, i4, i7)
  2373. """
  2374. expected = """
  2375. [p1, i1, i2, i4, i7]
  2376. setfield_gc(p1, i1, descr=valuedescr)
  2377. i5 = int_eq(i4, 5)
  2378. guard_true(i5) []
  2379. setfield_gc(p1, i2, descr=valuedescr)
  2380. jump(p1, i1, i2, i7, i7)
  2381. """
  2382. self.optimize_loop(ops, expected, preamble)
  2383. def test_duplicate_setfield_aliasing(self):
  2384. # a case where aliasing issues (and not enough cleverness) mean
  2385. # that we fail to remove any setfield_gc
  2386. ops = """
  2387. [p1, p2, i1, i2, i3]
  2388. setfield_gc(p1, i1, descr=valuedescr)
  2389. setfield_gc(p2, i2, descr=valuedescr)
  2390. setfield_gc(p1, i3, descr=valuedescr)
  2391. jump(p1, p2, i1, i2, i3)
  2392. """
  2393. self.optimize_loop(ops, ops)
  2394. def test_duplicate_setfield_guard_value_const(self):
  2395. ops = """
  2396. [p1, i1, i2]
  2397. guard_value(p1, ConstPtr(myptr)) []
  2398. setfield_gc(p1, i1, descr=valuedescr)
  2399. setfield_gc(ConstPtr(myptr), i2, descr=valuedescr)
  2400. escape_n()
  2401. jump(p1, i1, i2)
  2402. """
  2403. expected = """
  2404. [i1, i2]
  2405. setfield_gc(ConstPtr(myptr), i2, descr=valuedescr)
  2406. escape_n()
  2407. jump(i1, i2)
  2408. """
  2409. self.optimize_loop(ops, expected)
  2410. def test_dont_force_setfield_around_copystrcontent(self):
  2411. ops = """
  2412. [p0, i0, p1, i1, i2]
  2413. setfield_gc(p0, i1, descr=valuedescr)
  2414. copystrcontent(p0, p1, i0, i1, i2)
  2415. escape_n()
  2416. jump(p0, i0, p1, i1, i2)
  2417. """
  2418. expected = """
  2419. [p0, i0, p1, i1, i2]
  2420. copystrcontent(p0, p1, i0, i1, i2)
  2421. setfield_gc(p0, i1, descr=valuedescr)
  2422. escape_n()
  2423. jump(p0, i0, p1, i1, i2)
  2424. """
  2425. self.optimize_loop(ops, expected)
  2426. def test_duplicate_getarrayitem_1(self):
  2427. ops = """
  2428. [p1]
  2429. p2 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  2430. p3 = getarrayitem_gc_r(p1, 1, descr=arraydescr2)
  2431. p4 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  2432. p5 = getarrayitem_gc_r(p1, 1, descr=arraydescr2)
  2433. escape_n(p2)
  2434. escape_n(p3)
  2435. escape_n(p4)
  2436. escape_n(p5)
  2437. jump(p1)
  2438. """
  2439. expected = """
  2440. [p1]
  2441. p2 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  2442. p3 = getarrayitem_gc_r(p1, 1, descr=arraydescr2)
  2443. escape_n(p2)
  2444. escape_n(p3)
  2445. escape_n(p2)
  2446. escape_n(p3)
  2447. jump(p1)
  2448. """
  2449. self.optimize_loop(ops, expected)
  2450. def test_duplicate_getarrayitem_2(self):
  2451. ops = """
  2452. [p1, i0]
  2453. i2 = getarrayitem_gc_i(p1, 0, descr=arraydescr)
  2454. i3 = getarrayitem_gc_i(p1, 1, descr=arraydescr)
  2455. i4 = getarrayitem_gc_i(p1, 0, descr=arraydescr)
  2456. i5 = getarrayitem_gc_i(p1, 1, descr=arraydescr)
  2457. i6 = int_add(i3, i4)
  2458. i7 = int_add(i0, i6)
  2459. jump(p1, i7)
  2460. """
  2461. expected = """
  2462. [p1, i0, i6]
  2463. i7 = int_add(i0, i6)
  2464. ifoo = arraylen_gc(p1, descr=arraydescr) # killed by the backend
  2465. jump(p1, i7, i6)
  2466. """
  2467. self.optimize_loop(ops, expected)
  2468. def test_duplicate_getarrayitem_after_setarrayitem_1(self):
  2469. ops = """
  2470. [p1, p2]
  2471. setarrayitem_gc(p1, 0, p2, descr=arraydescr2)
  2472. p3 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  2473. escape_n(p3)
  2474. jump(p1, p3)
  2475. """
  2476. expected = """
  2477. [p1, p2]
  2478. setarrayitem_gc(p1, 0, p2, descr=arraydescr2)
  2479. escape_n(p2)
  2480. jump(p1, p2)
  2481. """
  2482. self.optimize_loop(ops, expected)
  2483. def test_duplicate_getarrayitem_after_setarrayitem_2(self):
  2484. py.test.skip("setarrayitem with variable index")
  2485. ops = """
  2486. [p1, p2, p3, i1]
  2487. setarrayitem_gc(p1, 0, p2, descr=arraydescr2)
  2488. setarrayitem_gc(p1, i1, p3, descr=arraydescr2)
  2489. p4 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  2490. p5 = getarrayitem_gc(p1, i1, descr=arraydescr2)
  2491. escape_n(p4)
  2492. escape_n(p5)
  2493. jump(p1, p2, p3, i1)
  2494. """
  2495. expected = """
  2496. [p1, p2, p3, i1]
  2497. setarrayitem_gc(p1, 0, p2, descr=arraydescr2)
  2498. setarrayitem_gc(p1, i1, p3, descr=arraydescr2)
  2499. p4 = getarrayitem_gc(p1, 0, descr=arraydescr2)
  2500. escape_n(p4)
  2501. escape_n(p3)
  2502. jump(p1, p2, p3, i1)
  2503. """
  2504. self.optimize_loop(ops, expected)
  2505. def test_duplicate_getarrayitem_after_setarrayitem_3(self):
  2506. ops = """
  2507. [p1, p2, p3, p4, i1]
  2508. setarrayitem_gc(p1, i1, p2, descr=arraydescr2)
  2509. setarrayitem_gc(p1, 0, p3, descr=arraydescr2)
  2510. setarrayitem_gc(p1, 1, p4, descr=arraydescr2)
  2511. p5 = getarrayitem_gc_r(p1, i1, descr=arraydescr2)
  2512. p6 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  2513. p7 = getarrayitem_gc_r(p1, 1, descr=arraydescr2)
  2514. escape_n(p5)
  2515. escape_n(p6)
  2516. escape_n(p7)
  2517. jump(p1, p2, p3, p4, i1)
  2518. """
  2519. expected = """
  2520. [p1, p2, p3, p4, i1]
  2521. setarrayitem_gc(p1, i1, p2, descr=arraydescr2)
  2522. setarrayitem_gc(p1, 0, p3, descr=arraydescr2)
  2523. setarrayitem_gc(p1, 1, p4, descr=arraydescr2)
  2524. p5 = getarrayitem_gc_r(p1, i1, descr=arraydescr2)
  2525. escape_n(p5)
  2526. escape_n(p3)
  2527. escape_n(p4)
  2528. jump(p1, p2, p3, p4, i1)
  2529. """
  2530. self.optimize_loop(ops, expected)
  2531. def test_getarrayitem_pure_does_not_invalidate(self):
  2532. ops = """
  2533. [p1, p2]
  2534. p3 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  2535. i4 = getfield_gc_i(ConstPtr(myptr3), descr=valuedescr3)
  2536. p5 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  2537. escape_n(p3)
  2538. escape_n(i4)
  2539. escape_n(p5)
  2540. jump(p1, p2)
  2541. """
  2542. expected = """
  2543. [p1, p2]
  2544. p3 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  2545. escape_n(p3)
  2546. escape_n(7)
  2547. escape_n(p3)
  2548. jump(p1, p2)
  2549. """
  2550. self.optimize_loop(ops, expected)
  2551. def test_duplicate_getarrayitem_after_setarrayitem_two_arrays(self):
  2552. ops = """
  2553. [p1, p2, p3, p4, i1]
  2554. setarrayitem_gc(p1, 0, p3, descr=arraydescr2)
  2555. setarrayitem_gc(p2, 1, p4, descr=arraydescr2)
  2556. p5 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  2557. p6 = getarrayitem_gc_r(p2, 1, descr=arraydescr2)
  2558. escape_n(p5)
  2559. escape_n(p6)
  2560. jump(p1, p2, p3, p4, i1)
  2561. """
  2562. expected = """
  2563. [p1, p2, p3, p4, i1]
  2564. setarrayitem_gc(p1, 0, p3, descr=arraydescr2)
  2565. setarrayitem_gc(p2, 1, p4, descr=arraydescr2)
  2566. escape_n(p3)
  2567. escape_n(p4)
  2568. jump(p1, p2, p3, p4, i1)
  2569. """
  2570. self.optimize_loop(ops, expected)
  2571. def test_duplicate_setfield_virtual(self):
  2572. ops = """
  2573. [p1, i2, i3, p4]
  2574. p2 = new_with_vtable(descr=nodesize)
  2575. setfield_gc(p2, p4, descr=nextdescr)
  2576. setfield_gc(p1, p2, descr=nextdescr)
  2577. guard_true(i3) []
  2578. i4 = int_neg(i2)
  2579. jump(p1, i2, i4, p4)
  2580. """
  2581. preamble = """
  2582. [p1, i2, i3, p4]
  2583. guard_true(i3) [p1, p4]
  2584. i4 = int_neg(i2)
  2585. p2 = new_with_vtable(descr=nodesize)
  2586. setfield_gc(p2, p4, descr=nextdescr)
  2587. setfield_gc(p1, p2, descr=nextdescr)
  2588. i101 = same_as_i(i4)
  2589. jump(p1, i2, i4, p4, i101)
  2590. """
  2591. expected = """
  2592. [p1, i2, i4, p4, i5]
  2593. guard_true(i4) [p1, p4]
  2594. p2 = new_with_vtable(descr=nodesize)
  2595. setfield_gc(p2, p4, descr=nextdescr)
  2596. setfield_gc(p1, p2, descr=nextdescr)
  2597. jump(p1, i2, i5, p4, i5)
  2598. """
  2599. self.optimize_loop(ops, expected, preamble)
  2600. def test_bug_1(self):
  2601. ops = """
  2602. [i0, p1]
  2603. p4 = getfield_gc_r(p1, descr=nextdescr)
  2604. guard_nonnull(p4) []
  2605. escape_n(p4)
  2606. #
  2607. p2 = new_with_vtable(descr=nodesize)
  2608. p3 = escape_r()
  2609. setfield_gc(p2, p3, descr=nextdescr)
  2610. jump(i0, p2)
  2611. """
  2612. expected = """
  2613. [i0, p4]
  2614. guard_nonnull(p4) []
  2615. escape_n(p4)
  2616. #
  2617. p3 = escape_r()
  2618. jump(i0, p3)
  2619. """
  2620. self.optimize_loop(ops, expected)
  2621. def test_bug_2(self):
  2622. ops = """
  2623. [i0, p1]
  2624. p4 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  2625. guard_nonnull(p4) []
  2626. escape_n(p4)
  2627. #
  2628. p2 = new_array(1, descr=arraydescr2)
  2629. p3 = escape_r()
  2630. setarrayitem_gc(p2, 0, p3, descr=arraydescr2)
  2631. jump(i0, p2)
  2632. """
  2633. expected = """
  2634. [i0, p4]
  2635. guard_nonnull(p4) []
  2636. escape_n(p4)
  2637. #
  2638. p3 = escape_r()
  2639. jump(i0, p3)
  2640. """
  2641. self.optimize_loop(ops, expected,
  2642. jump_values=[None, self.array2ref])
  2643. def test_bug_3(self):
  2644. ops = """
  2645. [p1]
  2646. guard_nonnull(p1) []
  2647. guard_class(p1, ConstClass(node_vtable2)) []
  2648. p2 = getfield_gc_r(p1, descr=nextdescr)
  2649. guard_nonnull(ConstPtr(nodeaddr)) []
  2650. guard_class(p2, ConstClass(node_vtable)) []
  2651. p3 = getfield_gc_r(p1, descr=otherdescr)
  2652. guard_nonnull(ConstPtr(nodeaddr)) []
  2653. guard_class(p3, ConstClass(node_vtable)) []
  2654. setfield_gc(p3, p2, descr=nextdescr)
  2655. p1a = new_with_vtable(descr=nodesize2)
  2656. p2a = new_with_vtable(descr=nodesize)
  2657. p3a = new_with_vtable(descr=nodesize)
  2658. escape_n(p3a)
  2659. setfield_gc(p1a, p2a, descr=nextdescr)
  2660. setfield_gc(p1a, p3a, descr=otherdescr)
  2661. jump(p1a)
  2662. """
  2663. preamble = """
  2664. [p1]
  2665. guard_nonnull_class(p1, ConstClass(node_vtable2)) []
  2666. p2 = getfield_gc_r(p1, descr=nextdescr)
  2667. guard_class(p2, ConstClass(node_vtable)) []
  2668. p3 = getfield_gc_r(p1, descr=otherdescr)
  2669. guard_class(p3, ConstClass(node_vtable)) []
  2670. p3a = new_with_vtable(descr=nodesize)
  2671. setfield_gc(p3, p2, descr=nextdescr)
  2672. escape_n(p3a)
  2673. jump(p3a)
  2674. """
  2675. expected = """
  2676. [p3a]
  2677. # p1=p1a(next=p2a, other=p3a), p2()
  2678. # p2 = getfield_gc(p1, descr=nextdescr) # p2a
  2679. # p3 = getfield_gc(p1, descr=otherdescr)# p3a
  2680. # setfield_gc(p3, p2, descr=otherdescr) # p3a.other = p2a
  2681. # p1a = new_with_vtable(descr=nodesize2)
  2682. # p2a = new_with_vtable(descr=nodesize)
  2683. p3anew = new_with_vtable(descr=nodesize)
  2684. p2 = new_with_vtable(descr=nodesize)
  2685. setfield_gc(p3a, p2, descr=nextdescr) # p3a.other = p2a
  2686. escape_n(p3anew)
  2687. jump(p3anew)
  2688. """
  2689. self.optimize_loop(ops, expected, preamble)
  2690. def test_bug_3bis(self):
  2691. ops = """
  2692. [p1]
  2693. guard_nonnull(p1) []
  2694. guard_class(p1, ConstClass(node_vtable2)) []
  2695. p2 = getfield_gc_r(p1, descr=nextdescr)
  2696. guard_nonnull(ConstPtr(nodeaddr)) []
  2697. guard_class(p2, ConstClass(node_vtable)) []
  2698. p3 = getfield_gc_r(p1, descr=otherdescr)
  2699. guard_nonnull(ConstPtr(nodeaddr)) []
  2700. guard_class(p3, ConstClass(node_vtable)) []
  2701. p1a = new_with_vtable(descr=nodesize2)
  2702. p2a = new_with_vtable(descr=nodesize)
  2703. setfield_gc(p3, p2a, descr=otherdescr)
  2704. p3a = new_with_vtable(descr=nodesize)
  2705. escape_n(p3a)
  2706. setfield_gc(p1a, p2a, descr=nextdescr)
  2707. setfield_gc(p1a, p3a, descr=otherdescr)
  2708. jump(p1a)
  2709. """
  2710. preamble = """
  2711. [p1]
  2712. guard_nonnull_class(p1, ConstClass(node_vtable2)) []
  2713. p2 = getfield_gc_r(p1, descr=nextdescr)
  2714. guard_class(p2, ConstClass(node_vtable)) []
  2715. p3 = getfield_gc_r(p1, descr=otherdescr)
  2716. guard_class(p3, ConstClass(node_vtable)) []
  2717. # p1a = new_with_vtable(descr=nodesize2)
  2718. p3a = new_with_vtable(descr=nodesize)
  2719. p2a = new_with_vtable(descr=nodesize)
  2720. setfield_gc(p3, p2a, descr=otherdescr)
  2721. escape_n(p3a)
  2722. # setfield_gc(p1a, p2a, descr=nextdescr)
  2723. # setfield_gc(p1a, p3a, descr=otherdescr)
  2724. jump(p2a, p3a)
  2725. """
  2726. expected = """
  2727. [p2, p3]
  2728. p3a = new_with_vtable(descr=nodesize)
  2729. p2a = new_with_vtable(descr=nodesize)
  2730. setfield_gc(p3, p2a, descr=otherdescr)
  2731. escape_n(p3a)
  2732. jump(p2a, p3a)
  2733. """
  2734. self.optimize_loop(ops, expected, preamble)
  2735. def test_bug_4(self):
  2736. ops = """
  2737. [p9]
  2738. p30 = new_with_vtable(descr=nodesize)
  2739. setfield_gc(ConstPtr(myptr), p9, descr=nextdescr)
  2740. jump(p30)
  2741. """
  2742. preamble = """
  2743. [p9]
  2744. setfield_gc(ConstPtr(myptr), p9, descr=nextdescr)
  2745. jump()
  2746. """
  2747. expected = """
  2748. []
  2749. p30 = new_with_vtable(descr=nodesize)
  2750. setfield_gc(ConstPtr(myptr), p30, descr=nextdescr)
  2751. jump()
  2752. """
  2753. self.optimize_loop(ops, expected, preamble)
  2754. def test_bug_5(self):
  2755. ops = """
  2756. [p0]
  2757. i0 = escape_i()
  2758. i2 = getfield_gc_i(p0, descr=valuedescr)
  2759. i4 = int_add(i2, 1)
  2760. setfield_gc(p0, i4, descr=valuedescr)
  2761. guard_true(i0) []
  2762. i6 = getfield_gc_i(p0, descr=valuedescr)
  2763. i8 = int_sub(i6, 1)
  2764. setfield_gc(p0, i8, descr=valuedescr)
  2765. escape_n()
  2766. jump(p0)
  2767. """
  2768. expected = """
  2769. [p0]
  2770. i0 = escape_i()
  2771. i2 = getfield_gc_i(p0, descr=valuedescr)
  2772. i4 = int_add(i2, 1)
  2773. setfield_gc(p0, i4, descr=valuedescr)
  2774. guard_true(i0) []
  2775. setfield_gc(p0, i2, descr=valuedescr)
  2776. escape_n()
  2777. jump(p0)
  2778. """
  2779. self.optimize_loop(ops, expected)
  2780. def test_invalid_loop_1(self):
  2781. ops = """
  2782. [p1]
  2783. guard_isnull(p1) []
  2784. #
  2785. p2 = new_with_vtable(descr=nodesize)
  2786. jump(p2)
  2787. """
  2788. self.raises(InvalidLoop, self.optimize_loop, ops, "crash!")
  2789. def test_invalid_loop_2(self):
  2790. ops = """
  2791. [p1]
  2792. guard_class(p1, ConstClass(node_vtable2)) []
  2793. #
  2794. p2 = new_with_vtable(descr=nodesize)
  2795. escape_n(p2) # prevent it from staying Virtual
  2796. jump(p2)
  2797. """
  2798. self.raises(InvalidLoop, self.optimize_loop, ops, "crash!")
  2799. def test_invalid_loop_3(self):
  2800. ops = """
  2801. [p1]
  2802. p2 = getfield_gc_r(p1, descr=nextdescr)
  2803. guard_isnull(p2) []
  2804. #
  2805. p3 = new_with_vtable(descr=nodesize)
  2806. p4 = new_with_vtable(descr=nodesize)
  2807. setfield_gc(p3, p4, descr=nextdescr)
  2808. jump(p3)
  2809. """
  2810. self.raises(InvalidLoop, self.optimize_loop, ops, "crash!")
  2811. def test_invalid_loop_guard_value_of_virtual(self):
  2812. ops = """
  2813. [p1]
  2814. p2 = new_with_vtable(descr=nodesize)
  2815. guard_value(p2, ConstPtr(myptr)) []
  2816. jump(p2)
  2817. """
  2818. exc = self.raises(InvalidLoop, self.optimize_loop, ops, "crash!")
  2819. if exc:
  2820. assert "promote of a virtual" in exc.msg
  2821. def test_merge_guard_class_guard_value(self):
  2822. ops = """
  2823. [p1, i0, i1, i2, p2]
  2824. guard_class(p1, ConstClass(node_vtable)) [i0]
  2825. i3 = int_add(i1, i2)
  2826. guard_value(p1, ConstPtr(myptr)) [i1]
  2827. jump(p2, i0, i1, i3, p2)
  2828. """
  2829. preamble = """
  2830. [p1, i0, i1, i2, p2]
  2831. guard_value(p1, ConstPtr(myptr)) [i0]
  2832. i3 = int_add(i1, i2)
  2833. jump(p2, i0, i1, i3)
  2834. """
  2835. expected = """
  2836. [p2, i0, i1, i2]
  2837. guard_value(p2, ConstPtr(myptr)) [i0]
  2838. i3 = int_add(i1, i2)
  2839. jump(ConstPtr(myptr), i0, i1, i3)
  2840. """
  2841. self.optimize_loop(ops, expected, preamble)
  2842. def test_merge_guard_nonnull_guard_class(self):
  2843. ops = """
  2844. [p1, i0, i1, i2, p2]
  2845. guard_nonnull(p1) [i0]
  2846. i3 = int_add(i1, i2)
  2847. guard_class(p1, ConstClass(node_vtable)) [i1]
  2848. jump(p2, i0, i1, i3, p2)
  2849. """
  2850. preamble = """
  2851. [p1, i0, i1, i2, p2]
  2852. guard_nonnull_class(p1, ConstClass(node_vtable)) [i0]
  2853. i3 = int_add(i1, i2)
  2854. jump(p2, i0, i1, i3)
  2855. """
  2856. expected = """
  2857. [p2, i0, i1, i2]
  2858. guard_nonnull_class(p2, ConstClass(node_vtable)) [i0]
  2859. i3 = int_add(i1, i2)
  2860. jump(p2, i0, i1, i3)
  2861. """
  2862. self.optimize_loop(ops, expected, preamble)
  2863. #self.check_expanded_fail_descr("i0", rop.GUARD_NONNULL_CLASS)
  2864. def test_merge_guard_nonnull_guard_value(self):
  2865. ops = """
  2866. [p1, i0, i1, i2, p2]
  2867. guard_nonnull(p1) [i0]
  2868. i3 = int_add(i1, i2)
  2869. guard_value(p1, ConstPtr(myptr)) [i1]
  2870. jump(p2, i0, i1, i3, p2)
  2871. """
  2872. preamble = """
  2873. [p1, i0, i1, i2, p2]
  2874. guard_value(p1, ConstPtr(myptr)) [i0]
  2875. i3 = int_add(i1, i2)
  2876. jump(p2, i0, i1, i3)
  2877. """
  2878. expected = """
  2879. [p2, i0, i1, i2]
  2880. guard_value(p2, ConstPtr(myptr)) [i0]
  2881. i3 = int_add(i1, i2)
  2882. jump(ConstPtr(myptr), i0, i1, i3)
  2883. """
  2884. self.optimize_loop(ops, expected, preamble)
  2885. #self.check_expanded_fail_descr("i0", rop.GUARD_VALUE)
  2886. def test_merge_guard_nonnull_guard_class_guard_value(self):
  2887. ops = """
  2888. [p1, i0, i1, i2, p2]
  2889. guard_nonnull(p1) [i0]
  2890. i3 = int_add(i1, i2)
  2891. guard_class(p1, ConstClass(node_vtable)) [i2]
  2892. i4 = int_sub(i3, 1)
  2893. guard_value(p1, ConstPtr(myptr)) [i1]
  2894. jump(p2, i0, i1, i4, p2)
  2895. """
  2896. preamble = """
  2897. [p1, i0, i1, i2, p2]
  2898. guard_value(p1, ConstPtr(myptr)) [i0]
  2899. i3 = int_add(i1, i2)
  2900. i4 = int_sub(i3, 1)
  2901. jump(p2, i0, i1, i4)
  2902. """
  2903. expected = """
  2904. [p2, i0, i1, i2]
  2905. guard_value(p2, ConstPtr(myptr)) [i0]
  2906. i3 = int_add(i1, i2)
  2907. i4 = int_sub(i3, 1)
  2908. jump(ConstPtr(myptr), i0, i1, i4)
  2909. """
  2910. self.optimize_loop(ops, expected, preamble)
  2911. #self.check_expanded_fail_descr("i0", rop.GUARD_VALUE)
  2912. def test_invalid_guard_value_after_guard_class(self):
  2913. ops = """
  2914. [p1, i0, i1, i2, p2]
  2915. guard_class(p1, ConstClass(node_vtable)) [i0]
  2916. i3 = int_add(i1, i2)
  2917. guard_value(p1, NULL) [i1]
  2918. jump(p2, i0, i1, i3, p2)
  2919. """
  2920. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  2921. def test_invalid_guard_value_after_bounds(self):
  2922. ops = """
  2923. [i0]
  2924. i1 = int_gt(i0, 5)
  2925. guard_true(i1) []
  2926. guard_value(i0, 2) []
  2927. jump()
  2928. """
  2929. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  2930. def test_guard_class_oois(self):
  2931. ops = """
  2932. [p1]
  2933. guard_class(p1, ConstClass(node_vtable2)) []
  2934. i = instance_ptr_ne(ConstPtr(myptr), p1)
  2935. guard_true(i) []
  2936. jump(p1)
  2937. """
  2938. preamble = """
  2939. [p1]
  2940. guard_class(p1, ConstClass(node_vtable2)) []
  2941. jump(p1)
  2942. """
  2943. expected = """
  2944. [p1]
  2945. jump(p1)
  2946. """
  2947. self.optimize_loop(ops, expected, preamble)
  2948. def test_oois_of_itself(self):
  2949. ops = """
  2950. [p0]
  2951. p1 = getfield_gc_r(p0, descr=nextdescr)
  2952. p2 = getfield_gc_r(p0, descr=nextdescr)
  2953. i1 = ptr_eq(p1, p2)
  2954. guard_true(i1) []
  2955. i2 = ptr_ne(p1, p2)
  2956. guard_false(i2) []
  2957. jump(p0)
  2958. """
  2959. preamble = """
  2960. [p0]
  2961. p1 = getfield_gc_r(p0, descr=nextdescr)
  2962. jump(p0)
  2963. """
  2964. expected = """
  2965. [p0]
  2966. jump(p0)
  2967. """
  2968. self.optimize_loop(ops, expected, preamble)
  2969. def test_remove_multiple_add_1(self):
  2970. py.test.skip("disabled")
  2971. ops = """
  2972. [i0]
  2973. i1 = int_add(i0, 1)
  2974. i2 = int_add(i1, 2)
  2975. i3 = int_add(i2, 1)
  2976. jump(i3)
  2977. """
  2978. expected = """
  2979. [i0]
  2980. i1 = int_add(i0, 1)
  2981. i2 = int_add(i0, 3)
  2982. i3 = int_add(i0, 4)
  2983. jump(i3)
  2984. """
  2985. self.optimize_loop(ops, expected)
  2986. def test_remove_multiple_add_2(self):
  2987. py.test.skip("disabled")
  2988. ops = """
  2989. [i0]
  2990. i1 = int_add(i0, 1)
  2991. i2 = int_add(2, i1)
  2992. i3 = int_add(i2, 1)
  2993. i4 = int_mul(i3, 5)
  2994. i5 = int_add(5, i4)
  2995. i6 = int_add(1, i5)
  2996. i7 = int_add(i2, i6)
  2997. i8 = int_add(i7, 1)
  2998. jump(i8)
  2999. """
  3000. expected = """
  3001. [i0]
  3002. i1 = int_add(i0, 1)
  3003. i2 = int_add(i0, 3)
  3004. i3 = int_add(i0, 4)
  3005. i4 = int_mul(i3, 5)
  3006. i5 = int_add(5, i4)
  3007. i6 = int_add(i4, 6)
  3008. i7 = int_add(i2, i6)
  3009. i8 = int_add(i7, 1)
  3010. jump(i8)
  3011. """
  3012. self.optimize_loop(ops, expected)
  3013. def test_remove_multiple_add_3(self):
  3014. py.test.skip("disabled")
  3015. ops = """
  3016. [i0]
  3017. i1 = int_add(i0, %s)
  3018. i2 = int_add(i1, %s)
  3019. i3 = int_add(i0, %s)
  3020. i4 = int_add(i3, %s)
  3021. jump(i4)
  3022. """ % (sys.maxint - 1, sys.maxint - 2, -sys.maxint, -sys.maxint + 1)
  3023. expected = """
  3024. [i0]
  3025. i1 = int_add(i0, %s)
  3026. i2 = int_add(i0, %s)
  3027. i3 = int_add(i0, %s)
  3028. i4 = int_add(i0, %s)
  3029. jump(i4)
  3030. """ % (sys.maxint - 1, -5, -sys.maxint, 3)
  3031. self.optimize_loop(ops, expected)
  3032. def test_remove_duplicate_pure_op(self):
  3033. ops = """
  3034. [p1, p2]
  3035. i1 = ptr_eq(p1, p2)
  3036. i2 = ptr_eq(p1, p2)
  3037. i3 = int_add(i1, 1)
  3038. i3b = int_is_true(i3)
  3039. guard_true(i3b) []
  3040. i4 = int_add(i2, 1)
  3041. i4b = int_is_true(i4)
  3042. guard_true(i4b) []
  3043. escape_n(i3)
  3044. escape_n(i4)
  3045. guard_true(i1) []
  3046. guard_true(i2) []
  3047. jump(p1, p2)
  3048. """
  3049. preamble = """
  3050. [p1, p2]
  3051. i1 = ptr_eq(p1, p2)
  3052. i3 = int_add(i1, 1)
  3053. escape_n(i3)
  3054. escape_n(i3)
  3055. guard_true(i1) []
  3056. jump(p1, p2)
  3057. """
  3058. expected = """
  3059. [p1, p2]
  3060. escape_n(2)
  3061. escape_n(2)
  3062. jump(p1, p2)
  3063. """
  3064. self.optimize_loop(ops, expected, preamble)
  3065. def test_remove_duplicate_pure_op_with_descr(self):
  3066. ops = """
  3067. [p1]
  3068. i0 = arraylen_gc(p1, descr=arraydescr)
  3069. i1 = int_gt(i0, 0)
  3070. guard_true(i1) []
  3071. i2 = arraylen_gc(p1, descr=arraydescr)
  3072. i3 = int_gt(i0, 0)
  3073. guard_true(i3) []
  3074. jump(p1)
  3075. """
  3076. preamble = """
  3077. [p1]
  3078. i0 = arraylen_gc(p1, descr=arraydescr)
  3079. i1 = int_gt(i0, 0)
  3080. guard_true(i1) []
  3081. jump(p1)
  3082. """
  3083. expected = """
  3084. [p1]
  3085. jump(p1)
  3086. """
  3087. self.optimize_loop(ops, expected, preamble)
  3088. def test_remove_duplicate_pure_op_ovf(self):
  3089. ops = """
  3090. [i1]
  3091. i3 = int_add_ovf(i1, 1)
  3092. guard_no_overflow() []
  3093. i3b = int_is_true(i3)
  3094. guard_true(i3b) []
  3095. i4 = int_add_ovf(i1, 1)
  3096. guard_no_overflow() []
  3097. i4b = int_is_true(i4)
  3098. guard_true(i4b) []
  3099. escape_n(i3)
  3100. escape_n(i4)
  3101. jump(i1)
  3102. """
  3103. preamble = """
  3104. [i1]
  3105. i3 = int_add_ovf(i1, 1)
  3106. guard_no_overflow() []
  3107. i3b = int_is_true(i3)
  3108. guard_true(i3b) []
  3109. escape_n(i3)
  3110. escape_n(i3)
  3111. jump(i1, i3)
  3112. """
  3113. expected = """
  3114. [i1, i3]
  3115. escape_n(i3)
  3116. escape_n(i3)
  3117. jump(i1, i3)
  3118. """
  3119. self.optimize_loop(ops, expected, preamble)
  3120. def test_remove_duplicate_pure_op_ovf_with_lazy_setfield(self):
  3121. ops = """
  3122. [i1, p1]
  3123. i3 = int_add_ovf(i1, 1)
  3124. guard_no_overflow() []
  3125. i3b = int_is_true(i3)
  3126. guard_true(i3b) []
  3127. setfield_gc(p1, i1, descr=valuedescr)
  3128. i4 = int_add_ovf(i1, 1)
  3129. guard_no_overflow() []
  3130. i4b = int_is_true(i4)
  3131. guard_true(i4b) []
  3132. escape_n(i3)
  3133. escape_n(i4)
  3134. jump(i1, p1)
  3135. """
  3136. preamble = """
  3137. [i1, p1]
  3138. i3 = int_add_ovf(i1, 1)
  3139. guard_no_overflow() []
  3140. i3b = int_is_true(i3)
  3141. guard_true(i3b) []
  3142. setfield_gc(p1, i1, descr=valuedescr)
  3143. escape_n(i3)
  3144. escape_n(i3)
  3145. jump(i1, p1, i3)
  3146. """
  3147. expected = """
  3148. [i1, p1, i3]
  3149. setfield_gc(p1, i1, descr=valuedescr)
  3150. escape_n(i3)
  3151. escape_n(i3)
  3152. jump(i1, p1, i3)
  3153. """
  3154. self.optimize_loop(ops, expected, preamble)
  3155. def test_ovf_guard_in_short_preamble1(self):
  3156. ops = """
  3157. [p8, p11, i24]
  3158. p26 = new(descr=ssize)
  3159. setfield_gc(p26, i24, descr=adescr)
  3160. i34 = getfield_gc_i(p11, descr=abisdescr)
  3161. i35 = getfield_gc_i(p26, descr=adescr)
  3162. i36 = int_add_ovf(i34, i35)
  3163. guard_no_overflow() []
  3164. jump(p8, p11, i35)
  3165. """
  3166. expected = """
  3167. [p8, p11, i26]
  3168. jump(p8, p11, i26)
  3169. """
  3170. self.optimize_loop(ops, expected)
  3171. def test_ovf_guard_in_short_preamble2(self):
  3172. ops = """
  3173. [p8, p11, p12]
  3174. p16 = getfield_gc_r(p8, descr=nextdescr)
  3175. i17 = getfield_gc_i(p8, descr=valuedescr)
  3176. i19 = getfield_gc_i(p16, descr=valuedescr)
  3177. i20 = int_ge(i17, i19)
  3178. guard_false(i20) []
  3179. i21 = getfield_gc_i(p16, descr=chardescr)
  3180. i22 = getfield_gc_i(p16, descr=valuedescr)
  3181. i23 = int_mul(i17, i22)
  3182. i24 = int_add(i21, i23)
  3183. p26 = new(descr=ssize)
  3184. setfield_gc(p26, i24, descr=adescr)
  3185. i28 = int_add(i17, 1)
  3186. setfield_gc(p8, i28, descr=valuedescr)
  3187. i34 = getfield_gc_i(p11, descr=valuedescr3)
  3188. i35 = getfield_gc_i(p26, descr=adescr)
  3189. guard_nonnull(p12) []
  3190. i36 = int_add_ovf(i34, i35)
  3191. guard_no_overflow() []
  3192. p38 = new(descr=ssize)
  3193. setfield_gc(p38, i36, descr=adescr)
  3194. jump(p8, p11, p26)
  3195. """
  3196. expected = """
  3197. [p0, p1, i9, p3, i10, i7, i11]
  3198. i13 = getfield_gc_i(p3, descr=valuedescr)
  3199. i14 = int_ge(i10, i13)
  3200. guard_false(i14) []
  3201. i15 = int_mul(i10, i13)
  3202. i16 = int_add(i7, i15)
  3203. i17 = int_add(i10, 1)
  3204. setfield_gc(p0, i17, descr=valuedescr)
  3205. i18 = int_add_ovf(i11, i16)
  3206. guard_no_overflow() []
  3207. jump(p0, p1, i16, p3, i17, i7, i11)
  3208. """
  3209. self.optimize_loop(ops, expected,
  3210. jump_values=[None, None, self.tupleaddr])
  3211. def test_int_and_or_with_zero(self):
  3212. ops = """
  3213. [i0, i1]
  3214. i2 = int_and(i0, 0)
  3215. i3 = int_and(0, i2)
  3216. i4 = int_or(i2, i1)
  3217. i5 = int_or(i0, i3)
  3218. jump(i4, i5)
  3219. """
  3220. expected = """
  3221. [i0, i1]
  3222. jump(i1, i0)
  3223. """
  3224. self.optimize_loop(ops, expected)
  3225. def test_fold_partially_constant_add_sub(self):
  3226. ops = """
  3227. [i0]
  3228. i1 = int_sub(i0, 0)
  3229. jump(i1)
  3230. """
  3231. expected = """
  3232. [i0]
  3233. jump(i0)
  3234. """
  3235. self.optimize_loop(ops, expected)
  3236. ops = """
  3237. [i0]
  3238. i1 = int_add(i0, 0)
  3239. jump(i1)
  3240. """
  3241. expected = """
  3242. [i0]
  3243. jump(i0)
  3244. """
  3245. self.optimize_loop(ops, expected)
  3246. ops = """
  3247. [i0]
  3248. i1 = int_add(0, i0)
  3249. jump(i1)
  3250. """
  3251. expected = """
  3252. [i0]
  3253. jump(i0)
  3254. """
  3255. self.optimize_loop(ops, expected)
  3256. def test_fold_partially_constant_add_sub_ovf(self):
  3257. ops = """
  3258. [i0]
  3259. i1 = int_sub_ovf(i0, 0)
  3260. guard_no_overflow() []
  3261. jump(i1)
  3262. """
  3263. expected = """
  3264. [i0]
  3265. jump(i0)
  3266. """
  3267. self.optimize_loop(ops, expected)
  3268. ops = """
  3269. [i0]
  3270. i1 = int_add_ovf(i0, 0)
  3271. guard_no_overflow() []
  3272. jump(i1)
  3273. """
  3274. expected = """
  3275. [i0]
  3276. jump(i0)
  3277. """
  3278. self.optimize_loop(ops, expected)
  3279. ops = """
  3280. [i0]
  3281. i1 = int_add_ovf(0, i0)
  3282. guard_no_overflow() []
  3283. jump(i1)
  3284. """
  3285. expected = """
  3286. [i0]
  3287. jump(i0)
  3288. """
  3289. self.optimize_loop(ops, expected)
  3290. def test_fold_int_sub_ovf_xx(self):
  3291. ops = """
  3292. [i0]
  3293. i1 = int_sub_ovf(i0, i0)
  3294. guard_no_overflow() []
  3295. escape_n(i1)
  3296. jump(i1)
  3297. """
  3298. expected = """
  3299. []
  3300. escape_n(0)
  3301. jump()
  3302. """
  3303. self.optimize_loop(ops, expected)
  3304. def test_fold_partially_constant_shift(self):
  3305. ops = """
  3306. [i0]
  3307. i1 = int_lshift(i0, 0)
  3308. i2 = int_rshift(i1, 0)
  3309. i3 = int_eq(i2, i0)
  3310. guard_true(i3) []
  3311. jump(i2)
  3312. """
  3313. expected = """
  3314. [i0]
  3315. jump(i0)
  3316. """
  3317. self.optimize_loop(ops, expected)
  3318. def test_fold_partially_constant_uint_floordiv(self):
  3319. ops = """
  3320. [i0]
  3321. i1 = call_pure_i(321, i0, 1, descr=int_udiv_descr)
  3322. jump(i1)
  3323. """
  3324. expected = """
  3325. [i0]
  3326. jump(i0)
  3327. """
  3328. self.optimize_loop(ops, expected)
  3329. def test_fold_partially_constant_xor(self):
  3330. ops = """
  3331. [i0, i1]
  3332. i2 = int_xor(i0, 23)
  3333. i3 = int_xor(i1, 0)
  3334. jump(i2, i3)
  3335. """
  3336. expected = """
  3337. [i0, i1]
  3338. i2 = int_xor(i0, 23)
  3339. jump(i2, i1)
  3340. """
  3341. self.optimize_loop(ops, expected)
  3342. # ----------
  3343. def test_residual_call_does_not_invalidate_caches(self):
  3344. ops = """
  3345. [p1, p2]
  3346. i1 = getfield_gc_i(p1, descr=valuedescr)
  3347. i2 = call_i(i1, descr=nonwritedescr)
  3348. i3 = getfield_gc_i(p1, descr=valuedescr)
  3349. escape_n(i1)
  3350. escape_n(i3)
  3351. jump(p1, p2)
  3352. """
  3353. expected = """
  3354. [p1, p2]
  3355. i1 = getfield_gc_i(p1, descr=valuedescr)
  3356. i2 = call_i(i1, descr=nonwritedescr)
  3357. escape_n(i1)
  3358. escape_n(i1)
  3359. jump(p1, p2)
  3360. """
  3361. self.optimize_loop(ops, expected)
  3362. def test_residual_call_does_not_invalidate_immutable_caches(self):
  3363. ops = """
  3364. [p1]
  3365. i1 = getfield_gc_i(p1, descr=valuedescr3)
  3366. i2 = call_i(i1, descr=writevalue3descr)
  3367. i3 = getfield_gc_i(p1, descr=valuedescr3)
  3368. jump(p1)
  3369. """
  3370. expected_preamble = """
  3371. [p1]
  3372. i1 = getfield_gc_i(p1, descr=valuedescr3)
  3373. i2 = call_i(i1, descr=writevalue3descr)
  3374. jump(p1, i1)
  3375. """
  3376. expected = """
  3377. [p1, i1]
  3378. i2 = call_i(i1, descr=writevalue3descr)
  3379. jump(p1, i1)
  3380. """
  3381. self.optimize_loop(ops, expected, expected_preamble=expected_preamble)
  3382. def test_residual_call_invalidate_some_caches(self):
  3383. ops = """
  3384. [p1, p2]
  3385. i1 = getfield_gc_i(p1, descr=adescr)
  3386. i2 = getfield_gc_i(p1, descr=bdescr)
  3387. i3 = call_i(i1, descr=writeadescr)
  3388. i4 = getfield_gc_i(p1, descr=adescr)
  3389. i5 = getfield_gc_i(p1, descr=bdescr)
  3390. escape_n(i1)
  3391. escape_n(i2)
  3392. escape_n(i4)
  3393. escape_n(i5)
  3394. jump(p1, p2)
  3395. """
  3396. expected = """
  3397. [p1, p2]
  3398. i1 = getfield_gc_i(p1, descr=adescr)
  3399. i2 = getfield_gc_i(p1, descr=bdescr)
  3400. i3 = call_i(i1, descr=writeadescr)
  3401. i4 = getfield_gc_i(p1, descr=adescr)
  3402. escape_n(i1)
  3403. escape_n(i2)
  3404. escape_n(i4)
  3405. escape_n(i2)
  3406. jump(p1, p2)
  3407. """
  3408. self.optimize_loop(ops, expected)
  3409. def test_residual_call_invalidate_arrays(self):
  3410. ops = """
  3411. [p1, p2, i1]
  3412. p3 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  3413. p4 = getarrayitem_gc_r(p2, 1, descr=arraydescr2)
  3414. i3 = call_i(i1, descr=writeadescr)
  3415. p5 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  3416. p6 = getarrayitem_gc_r(p2, 1, descr=arraydescr2)
  3417. escape_n(p3)
  3418. escape_n(p4)
  3419. escape_n(p5)
  3420. escape_n(p6)
  3421. jump(p1, p2, i1)
  3422. """
  3423. expected = """
  3424. [p1, p2, i1]
  3425. p3 = getarrayitem_gc_r(p1, 0, descr=arraydescr2)
  3426. p4 = getarrayitem_gc_r(p2, 1, descr=arraydescr2)
  3427. i3 = call_i(i1, descr=writeadescr)
  3428. escape_n(p3)
  3429. escape_n(p4)
  3430. escape_n(p3)
  3431. escape_n(p4)
  3432. jump(p1, p2, i1)
  3433. """
  3434. self.optimize_loop(ops, expected)
  3435. def test_residual_call_invalidate_some_arrays(self):
  3436. ops = """
  3437. [p1, p2, i1]
  3438. p3 = getarrayitem_gc_r(p2, 0, descr=arraydescr2)
  3439. p4 = getarrayitem_gc_r(p2, 1, descr=arraydescr2)
  3440. i2 = getarrayitem_gc_i(p1, 1, descr=arraydescr)
  3441. i3 = call_i(i1, descr=writearraydescr)
  3442. p5 = getarrayitem_gc_r(p2, 0, descr=arraydescr2)
  3443. p6 = getarrayitem_gc_r(p2, 1, descr=arraydescr2)
  3444. i4 = getarrayitem_gc_i(p1, 1, descr=arraydescr)
  3445. escape_n(p3)
  3446. escape_n(p4)
  3447. escape_n(p5)
  3448. escape_n(p6)
  3449. escape_n(i2)
  3450. escape_n(i4)
  3451. jump(p1, p2, i1)
  3452. """
  3453. expected = """
  3454. [p1, p2, i1]
  3455. p3 = getarrayitem_gc_r(p2, 0, descr=arraydescr2)
  3456. p4 = getarrayitem_gc_r(p2, 1, descr=arraydescr2)
  3457. i2 = getarrayitem_gc_i(p1, 1, descr=arraydescr)
  3458. i3 = call_i(i1, descr=writearraydescr)
  3459. i4 = getarrayitem_gc_i(p1, 1, descr=arraydescr)
  3460. escape_n(p3)
  3461. escape_n(p4)
  3462. escape_n(p3)
  3463. escape_n(p4)
  3464. escape_n(i2)
  3465. escape_n(i4)
  3466. jump(p1, p2, i1)
  3467. """
  3468. self.optimize_loop(ops, expected)
  3469. def test_residual_call_invalidates_some_read_caches_1(self):
  3470. ops = """
  3471. [p1, i1, p2, i2]
  3472. setfield_gc(p1, i1, descr=valuedescr)
  3473. setfield_gc(p2, i2, descr=adescr)
  3474. i3 = call_i(i1, descr=readadescr)
  3475. setfield_gc(p1, i3, descr=valuedescr)
  3476. setfield_gc(p2, i3, descr=adescr)
  3477. jump(p1, i1, p2, i2)
  3478. """
  3479. expected = """
  3480. [p1, i1, p2, i2]
  3481. setfield_gc(p2, i2, descr=adescr)
  3482. i3 = call_i(i1, descr=readadescr)
  3483. setfield_gc(p2, i3, descr=adescr)
  3484. setfield_gc(p1, i3, descr=valuedescr)
  3485. jump(p1, i1, p2, i2)
  3486. """
  3487. self.optimize_loop(ops, expected)
  3488. def test_residual_call_invalidates_some_read_caches_2(self):
  3489. ops = """
  3490. [p1, i1, p2, i2]
  3491. setfield_gc(p1, i1, descr=valuedescr)
  3492. setfield_gc(p2, i2, descr=adescr)
  3493. i3 = call_i(i1, descr=writeadescr)
  3494. setfield_gc(p1, i3, descr=valuedescr)
  3495. setfield_gc(p2, i3, descr=adescr)
  3496. jump(p1, i1, p2, i2)
  3497. """
  3498. expected = """
  3499. [p1, i1, p2, i2]
  3500. setfield_gc(p2, i2, descr=adescr)
  3501. i3 = call_i(i1, descr=writeadescr)
  3502. setfield_gc(p2, i3, descr=adescr)
  3503. setfield_gc(p1, i3, descr=valuedescr)
  3504. jump(p1, i1, p2, i2)
  3505. """
  3506. self.optimize_loop(ops, expected)
  3507. def test_residual_call_invalidates_some_read_caches_3(self):
  3508. ops = """
  3509. [p1, i1, p2, i2]
  3510. setfield_gc(p2, i2, descr=adescr)
  3511. setfield_gc(p1, i1, descr=valuedescr)
  3512. i3 = call_i(i1, descr=plaincalldescr)
  3513. setfield_gc(p2, i3, descr=adescr)
  3514. setfield_gc(p1, i3, descr=valuedescr)
  3515. jump(p1, i1, p2, i2)
  3516. """
  3517. self.optimize_loop(ops, ops)
  3518. def test_call_assembler_invalidates_caches(self):
  3519. ops = '''
  3520. [p1, i1, i4]
  3521. setfield_gc(p1, i1, descr=valuedescr)
  3522. i3 = call_assembler_i(i1, descr=asmdescr)
  3523. setfield_gc(p1, i3, descr=valuedescr)
  3524. jump(p1, i4, i3)
  3525. '''
  3526. preamble = '''
  3527. [p1, i1, i4]
  3528. setfield_gc(p1, i1, descr=valuedescr)
  3529. i3 = call_assembler_i(i1, descr=asmdescr)
  3530. setfield_gc(p1, i3, descr=valuedescr)
  3531. jump(p1, i4, i3)
  3532. '''
  3533. self.optimize_loop(ops, ops, preamble)
  3534. def test_call_assembler_invalidates_heap_knowledge(self):
  3535. ops = '''
  3536. [p1, i1, i4]
  3537. setfield_gc(p1, i1, descr=valuedescr)
  3538. i3 = call_assembler_i(i1, descr=asmdescr)
  3539. setfield_gc(p1, i1, descr=valuedescr)
  3540. jump(p1, i4, i3)
  3541. '''
  3542. self.optimize_loop(ops, ops, ops)
  3543. def test_call_pure_invalidates_caches(self):
  3544. # CALL_PURE should still force the setfield_gc() to occur before it
  3545. ops = '''
  3546. [p1, i1, i4]
  3547. setfield_gc(p1, i1, descr=valuedescr)
  3548. i3 = call_pure_i(p1, descr=elidablecalldescr)
  3549. setfield_gc(p1, i3, descr=valuedescr)
  3550. jump(p1, i4, i3)
  3551. '''
  3552. expected = '''
  3553. [p1, i4, i3, i5]
  3554. setfield_gc(p1, i5, descr=valuedescr)
  3555. jump(p1, i3, i5, i5)
  3556. '''
  3557. preamble = '''
  3558. [p1, i1, i4]
  3559. setfield_gc(p1, i1, descr=valuedescr)
  3560. i3 = call_i(p1, descr=elidablecalldescr)
  3561. setfield_gc(p1, i3, descr=valuedescr)
  3562. ifoo = same_as_i(i3)
  3563. jump(p1, i4, i3, ifoo)
  3564. '''
  3565. self.optimize_loop(ops, expected, preamble)
  3566. def test_call_pure_invalidates_caches_2(self):
  3567. # same as test_call_pure_invalidates_caches, but with
  3568. # an EF_ELIDABLE_OR_MEMORYERROR, which can still be moved
  3569. # out of the main loop potentially into the short preamble
  3570. ops = '''
  3571. [p1, i1, i4]
  3572. setfield_gc(p1, i1, descr=valuedescr)
  3573. i3 = call_pure_i(p1, descr=elidable2calldescr)
  3574. guard_no_exception() []
  3575. setfield_gc(p1, i3, descr=valuedescr)
  3576. jump(p1, i4, i3)
  3577. '''
  3578. expected = '''
  3579. [p1, i4, i3, i5]
  3580. setfield_gc(p1, i5, descr=valuedescr)
  3581. jump(p1, i3, i5, i5)
  3582. '''
  3583. preamble = '''
  3584. [p1, i1, i4]
  3585. setfield_gc(p1, i1, descr=valuedescr)
  3586. i3 = call_i(p1, descr=elidable2calldescr)
  3587. guard_no_exception() []
  3588. setfield_gc(p1, i3, descr=valuedescr)
  3589. i147 = same_as_i(i3)
  3590. jump(p1, i4, i3, i147)
  3591. '''
  3592. self.optimize_loop(ops, expected, preamble)
  3593. def test_call_pure_can_raise(self):
  3594. # same as test_call_pure_invalidates_caches, but this time
  3595. # with an EF_ELIDABLE_CAN_RAISE, which *cannot* be moved
  3596. # out of the main loop: the problem is that it cannot be
  3597. # present in the short preamble, because nobody would catch
  3598. # the potential exception
  3599. ops = '''
  3600. [p1, i1, i4]
  3601. setfield_gc(p1, i1, descr=valuedescr)
  3602. i3 = call_pure_i(p1, descr=elidable3calldescr)
  3603. guard_no_exception() []
  3604. setfield_gc(p1, i3, descr=valuedescr)
  3605. jump(p1, i4, i3)
  3606. '''
  3607. expected = '''
  3608. [p1, i1, i4]
  3609. setfield_gc(p1, i1, descr=valuedescr)
  3610. i3 = call_i(p1, descr=elidable3calldescr)
  3611. guard_no_exception() []
  3612. setfield_gc(p1, i3, descr=valuedescr)
  3613. jump(p1, i4, i3)
  3614. '''
  3615. preamble = '''
  3616. [p1, i1, i4]
  3617. setfield_gc(p1, i1, descr=valuedescr)
  3618. i3 = call_i(p1, descr=elidable3calldescr)
  3619. guard_no_exception() []
  3620. setfield_gc(p1, i3, descr=valuedescr)
  3621. jump(p1, i4, i3)
  3622. '''
  3623. self.optimize_loop(ops, expected, preamble)
  3624. def test_call_pure_invalidates_heap_knowledge(self):
  3625. # CALL_PURE should still force the setfield_gc() to occur before it
  3626. ops = '''
  3627. [p1, i1, i4]
  3628. setfield_gc(p1, i1, descr=valuedescr)
  3629. i3 = call_pure_i(p1, descr=elidablecalldescr)
  3630. setfield_gc(p1, i1, descr=valuedescr)
  3631. jump(p1, i4, i3)
  3632. '''
  3633. expected = '''
  3634. [p1, i4, i3, i5]
  3635. setfield_gc(p1, i4, descr=valuedescr)
  3636. jump(p1, i3, i5, i5)
  3637. '''
  3638. preamble = '''
  3639. [p1, i1, i4]
  3640. setfield_gc(p1, i1, descr=valuedescr)
  3641. i3 = call_i(p1, descr=elidablecalldescr)
  3642. i151 = same_as_i(i3)
  3643. jump(p1, i4, i3, i151)
  3644. '''
  3645. self.optimize_loop(ops, expected, preamble)
  3646. def test_call_pure_constant_folding(self):
  3647. arg_consts = [ConstInt(i) for i in (123456, 4, 5, 6)]
  3648. call_pure_results = {tuple(arg_consts): ConstInt(42)}
  3649. ops = '''
  3650. [i0, i1, i2]
  3651. escape_n(i1)
  3652. escape_n(i2)
  3653. i3 = call_pure_i(123456, 4, 5, 6, descr=elidablecalldescr)
  3654. i4 = call_pure_i(123456, 4, i0, 6, descr=elidablecalldescr)
  3655. jump(i0, i3, i4)
  3656. '''
  3657. preamble = '''
  3658. [i0, i1, i2]
  3659. escape_n(i1)
  3660. escape_n(i2)
  3661. i4 = call_i(123456, 4, i0, 6, descr=elidablecalldescr)
  3662. i153 = same_as_i(i4)
  3663. jump(i0, i4, i153)
  3664. '''
  3665. expected = '''
  3666. [i0, i4, i5]
  3667. escape_n(42)
  3668. escape_n(i4)
  3669. jump(i0, i5, i5)
  3670. '''
  3671. self.optimize_loop(ops, expected, preamble, call_pure_results)
  3672. def test_call_pure_constant_folding_memoryerr(self):
  3673. ops = '''
  3674. [p0, i0]
  3675. escape_n(i0)
  3676. i3 = call_pure_i(123456, p0, descr=elidable2calldescr)
  3677. guard_no_exception() []
  3678. jump(p0, i3)
  3679. '''
  3680. preamble = '''
  3681. [p0, i0]
  3682. escape_n(i0)
  3683. i3 = call_i(123456, p0, descr=elidable2calldescr)
  3684. guard_no_exception() []
  3685. ifoo = same_as_i(i3)
  3686. jump(p0, i3, ifoo)
  3687. '''
  3688. expected = '''
  3689. [p0, i3, ifoo]
  3690. escape_n(i3)
  3691. jump(p0, ifoo, ifoo)
  3692. '''
  3693. self.optimize_loop(ops, expected, preamble)
  3694. def test_call_pure_constant_folding_exc(self):
  3695. # CALL_PURE may be followed by GUARD_NO_EXCEPTION
  3696. # we can't remove such call_pures from the loop,
  3697. # because the short preamble can't call them safely.
  3698. # We can still check that an all-constant call_pure is removed,
  3699. # and that duplicate call_pures are folded.
  3700. arg_consts = [ConstInt(i) for i in (123456, 4, 5, 6)]
  3701. call_pure_results = {tuple(arg_consts): ConstInt(42)}
  3702. ops = '''
  3703. [i0, i1, i2, i9]
  3704. escape_n(i1)
  3705. escape_n(i2)
  3706. escape_n(i9)
  3707. i3 = call_pure_i(123456, 4, 5, 6, descr=elidable3calldescr)
  3708. guard_no_exception() []
  3709. i4 = call_pure_i(123456, 4, i0, 6, descr=elidable3calldescr)
  3710. guard_no_exception() []
  3711. i5 = call_pure_i(123456, 4, i0, 6, descr=elidable3calldescr)
  3712. guard_no_exception() []
  3713. jump(i0, i3, i4, i5)
  3714. '''
  3715. preamble = '''
  3716. [i0, i1, i2, i9]
  3717. escape_n(i1)
  3718. escape_n(i2)
  3719. escape_n(i9)
  3720. i4 = call_i(123456, 4, i0, 6, descr=elidable3calldescr)
  3721. guard_no_exception() []
  3722. jump(i0, i4)
  3723. '''
  3724. expected = '''
  3725. [i0, i2]
  3726. escape_n(42)
  3727. escape_n(i2)
  3728. escape_n(i2)
  3729. i4 = call_i(123456, 4, i0, 6, descr=elidable3calldescr)
  3730. guard_no_exception() []
  3731. jump(i0, i4)
  3732. '''
  3733. self.optimize_loop(ops, expected, preamble, call_pure_results)
  3734. def test_call_pure_returning_virtual(self):
  3735. # XXX: This kind of loop invaraint call_pure will be forced
  3736. # both in the preamble and in the peeled loop
  3737. ops = '''
  3738. [p1, i1, i2]
  3739. p2 = call_pure_i(0, p1, i1, i2, descr=strslicedescr)
  3740. guard_no_exception() []
  3741. escape_n(p2)
  3742. jump(p1, i1, i2)
  3743. '''
  3744. preamble = '''
  3745. [p1, i1, i2]
  3746. i6 = int_sub(i2, i1)
  3747. p2 = newstr(i6)
  3748. copystrcontent(p1, p2, i1, 0, i6)
  3749. escape_n(p2)
  3750. jump(p1, i1, i2, i6)
  3751. '''
  3752. expected = '''
  3753. [p1, i1, i2, i6]
  3754. p2 = newstr(i6)
  3755. copystrcontent(p1, p2, i1, 0, i6)
  3756. escape_n(p2)
  3757. jump(p1, i1, i2, i6)
  3758. '''
  3759. self.optimize_loop(ops, expected, preamble)
  3760. # ----------
  3761. def test_vref_nonvirtual_nonescape(self):
  3762. ops = """
  3763. [p1]
  3764. p2 = virtual_ref(p1, 5)
  3765. virtual_ref_finish(p2, p1)
  3766. jump(p1)
  3767. """
  3768. expected = """
  3769. [p1]
  3770. p0 = force_token()
  3771. jump(p1)
  3772. """
  3773. self.optimize_loop(ops, expected, expected)
  3774. def test_vref_nonvirtual_escape(self):
  3775. ops = """
  3776. [p1]
  3777. p2 = virtual_ref(p1, 5)
  3778. escape_n(p2)
  3779. virtual_ref_finish(p2, p1)
  3780. jump(p1)
  3781. """
  3782. expected = """
  3783. [p1]
  3784. p0 = force_token()
  3785. p2 = new_with_vtable(descr=vref_descr)
  3786. setfield_gc(p2, p0, descr=virtualtokendescr)
  3787. setfield_gc(p2, NULL, descr=virtualforceddescr)
  3788. escape_n(p2)
  3789. setfield_gc(p2, NULL, descr=virtualtokendescr)
  3790. setfield_gc(p2, p1, descr=virtualforceddescr)
  3791. jump(p1)
  3792. """
  3793. # XXX we should optimize a bit more the case of a nonvirtual.
  3794. # in theory it is enough to just do 'p2 = p1'.
  3795. self.optimize_loop(ops, expected, expected)
  3796. def test_vref_virtual_1(self):
  3797. ops = """
  3798. [p0, i1]
  3799. #
  3800. p1 = new_with_vtable(descr=nodesize)
  3801. p1b = new_with_vtable(descr=nodesize)
  3802. setfield_gc(p1b, 252, descr=valuedescr)
  3803. setfield_gc(p1, p1b, descr=nextdescr)
  3804. #
  3805. p2 = virtual_ref(p1, 3)
  3806. setfield_gc(p0, p2, descr=nextdescr)
  3807. call_may_force_n(i1, descr=mayforcevirtdescr)
  3808. guard_not_forced() [i1]
  3809. virtual_ref_finish(p2, p1)
  3810. setfield_gc(p0, NULL, descr=nextdescr)
  3811. jump(p0, i1)
  3812. """
  3813. expected = """
  3814. [p0, i1]
  3815. p3 = force_token()
  3816. #
  3817. p2 = new_with_vtable(descr=vref_descr)
  3818. setfield_gc(p2, p3, descr=virtualtokendescr)
  3819. setfield_gc(p2, NULL, descr=virtualforceddescr)
  3820. setfield_gc(p0, p2, descr=nextdescr)
  3821. #
  3822. call_may_force_n(i1, descr=mayforcevirtdescr)
  3823. guard_not_forced() [i1]
  3824. #
  3825. setfield_gc(p0, NULL, descr=nextdescr)
  3826. setfield_gc(p2, NULL, descr=virtualtokendescr)
  3827. p1 = new_with_vtable(descr=nodesize)
  3828. p1b = new_with_vtable(descr=nodesize)
  3829. setfield_gc(p1b, 252, descr=valuedescr)
  3830. setfield_gc(p1, p1b, descr=nextdescr)
  3831. setfield_gc(p2, p1, descr=virtualforceddescr)
  3832. jump(p0, i1)
  3833. """
  3834. self.optimize_loop(ops, expected, expected)
  3835. def test_vref_virtual_2(self):
  3836. ops = """
  3837. [p0, i1]
  3838. #
  3839. p1 = new_with_vtable(descr=nodesize)
  3840. p1b = new_with_vtable(descr=nodesize)
  3841. setfield_gc(p1b, i1, descr=valuedescr)
  3842. setfield_gc(p1, p1b, descr=nextdescr)
  3843. #
  3844. p2 = virtual_ref(p1, 2)
  3845. setfield_gc(p0, p2, descr=nextdescr)
  3846. call_may_force_n(i1, descr=mayforcevirtdescr)
  3847. guard_not_forced() [p2, p1]
  3848. virtual_ref_finish(p2, p1)
  3849. setfield_gc(p0, NULL, descr=nextdescr)
  3850. jump(p0, i1)
  3851. """
  3852. expected = """
  3853. [p0, i1]
  3854. p3 = force_token()
  3855. #
  3856. p2 = new_with_vtable(descr=vref_descr)
  3857. setfield_gc(p2, p3, descr=virtualtokendescr)
  3858. setfield_gc(p2, NULL, descr=virtualforceddescr)
  3859. setfield_gc(p0, p2, descr=nextdescr)
  3860. #
  3861. call_may_force_n(i1, descr=mayforcevirtdescr)
  3862. guard_not_forced() [p2, i1]
  3863. #
  3864. setfield_gc(p0, NULL, descr=nextdescr)
  3865. setfield_gc(p2, NULL, descr=virtualtokendescr)
  3866. p1 = new_with_vtable(descr=nodesize)
  3867. p1b = new_with_vtable(descr=nodesize)
  3868. setfield_gc(p1b, i1, descr=valuedescr)
  3869. setfield_gc(p1, p1b, descr=nextdescr)
  3870. setfield_gc(p2, p1, descr=virtualforceddescr)
  3871. jump(p0, i1)
  3872. """
  3873. # the point of this test is that 'i1' should show up in the fail_args
  3874. # of 'guard_not_forced', because it was stored in the virtual 'p1b'.
  3875. self.optimize_loop(ops, expected)
  3876. #self.check_expanded_fail_descr('''p2, p1
  3877. # where p1 is a node_vtable, nextdescr=p1b
  3878. # where p1b is a node_vtable, valuedescr=i1
  3879. # ''', rop.GUARD_NOT_FORCED)
  3880. def test_vref_virtual_and_lazy_setfield(self):
  3881. ops = """
  3882. [p0, i1]
  3883. #
  3884. p1 = new_with_vtable(descr=nodesize)
  3885. p1b = new_with_vtable(descr=nodesize)
  3886. setfield_gc(p1b, i1, descr=valuedescr)
  3887. setfield_gc(p1, p1b, descr=nextdescr)
  3888. #
  3889. p2 = virtual_ref(p1, 2)
  3890. setfield_gc(p0, p2, descr=refdescr)
  3891. call_n(i1, descr=nonwritedescr)
  3892. guard_no_exception() [p2, p1]
  3893. virtual_ref_finish(p2, p1)
  3894. setfield_gc(p0, NULL, descr=refdescr)
  3895. escape_n()
  3896. jump(p0, i1)
  3897. """
  3898. preamble = """
  3899. [p0, i1]
  3900. p3 = force_token()
  3901. call_n(i1, descr=nonwritedescr)
  3902. guard_no_exception() [p3, i1, p0]
  3903. setfield_gc(p0, NULL, descr=refdescr)
  3904. escape_n()
  3905. jump(p0, i1)
  3906. """
  3907. expected = """
  3908. [p0, i1]
  3909. p3 = force_token()
  3910. call_n(i1, descr=nonwritedescr)
  3911. guard_no_exception() [p3, i1, p0]
  3912. setfield_gc(p0, NULL, descr=refdescr)
  3913. escape_n()
  3914. jump(p0, i1)
  3915. """
  3916. self.optimize_loop(ops, expected, preamble)
  3917. # the fail_args contain [p3, i1, p0]:
  3918. # - p3 is from the virtual expansion of p2
  3919. # - i1 is from the virtual expansion of p1
  3920. # - p0 is from the extra pendingfields
  3921. #self.loop.inputargs[0].value = self.nodeobjvalue
  3922. #self.check_expanded_fail_descr('''p2, p1
  3923. # p0.refdescr = p2
  3924. # where p2 is a jit_virtual_ref_vtable, virtualtokendescr=p3
  3925. # where p1 is a node_vtable, nextdescr=p1b
  3926. # where p1b is a node_vtable, valuedescr=i1
  3927. # ''', rop.GUARD_NO_EXCEPTION)
  3928. def test_vref_virtual_after_finish(self):
  3929. ops = """
  3930. [i1]
  3931. p1 = new_with_vtable(descr=nodesize)
  3932. p2 = virtual_ref(p1, 7)
  3933. escape_n(p2)
  3934. virtual_ref_finish(p2, p1)
  3935. call_may_force_n(i1, descr=mayforcevirtdescr)
  3936. guard_not_forced() []
  3937. jump(i1)
  3938. """
  3939. expected = """
  3940. [i1]
  3941. p3 = force_token()
  3942. p2 = new_with_vtable(descr=vref_descr)
  3943. setfield_gc(p2, p3, descr=virtualtokendescr)
  3944. setfield_gc(p2, NULL, descr=virtualforceddescr)
  3945. escape_n(p2)
  3946. p1 = new_with_vtable(descr=nodesize)
  3947. setfield_gc(p2, p1, descr=virtualforceddescr)
  3948. setfield_gc(p2, NULL, descr=virtualtokendescr)
  3949. call_may_force_n(i1, descr=mayforcevirtdescr)
  3950. guard_not_forced() []
  3951. jump(i1)
  3952. """
  3953. self.optimize_loop(ops, expected, expected)
  3954. def test_vref_nonvirtual_and_lazy_setfield(self):
  3955. ops = """
  3956. [i1, p1]
  3957. p2 = virtual_ref(p1, 23)
  3958. escape_n(p2)
  3959. virtual_ref_finish(p2, p1)
  3960. call_may_force_n(i1, descr=mayforcevirtdescr)
  3961. guard_not_forced() [i1]
  3962. jump(i1, p1)
  3963. """
  3964. expected = """
  3965. [i1, p1]
  3966. p3 = force_token()
  3967. p2 = new_with_vtable(descr=vref_descr)
  3968. setfield_gc(p2, p3, descr=virtualtokendescr)
  3969. setfield_gc(p2, NULL, descr=virtualforceddescr)
  3970. escape_n(p2)
  3971. setfield_gc(p2, p1, descr=virtualforceddescr)
  3972. setfield_gc(p2, NULL, descr=virtualtokendescr)
  3973. call_may_force_n(i1, descr=mayforcevirtdescr)
  3974. guard_not_forced() [i1]
  3975. jump(i1, p1)
  3976. """
  3977. self.optimize_loop(ops, expected, expected)
  3978. # ----------
  3979. def test_arraycopy_1(self):
  3980. ops = '''
  3981. [i0]
  3982. p1 = new_array(3, descr=arraydescr)
  3983. setarrayitem_gc(p1, 1, 1, descr=arraydescr)
  3984. p2 = new_array(3, descr=arraydescr)
  3985. setarrayitem_gc(p2, 1, 3, descr=arraydescr)
  3986. call_n(0, p1, p2, 1, 1, 2, descr=arraycopydescr)
  3987. i2 = getarrayitem_gc_i(p2, 1, descr=arraydescr)
  3988. jump(i2)
  3989. '''
  3990. expected = '''
  3991. []
  3992. jump()
  3993. '''
  3994. self.optimize_loop(ops, expected)
  3995. def test_arraycopy_2(self):
  3996. ops = '''
  3997. [i0]
  3998. p1 = new_array(3, descr=arraydescr)
  3999. p2 = new_array(3, descr=arraydescr)
  4000. setarrayitem_gc(p1, 0, i0, descr=arraydescr)
  4001. setarrayitem_gc(p2, 0, 3, descr=arraydescr)
  4002. call_n(0, p1, p2, 1, 1, 2, descr=arraycopydescr)
  4003. i2 = getarrayitem_gc_i(p2, 0, descr=arraydescr)
  4004. jump(i2)
  4005. '''
  4006. expected = '''
  4007. []
  4008. jump()
  4009. '''
  4010. self.optimize_loop(ops, expected)
  4011. def test_arraycopy_not_virtual(self):
  4012. ops = '''
  4013. []
  4014. p1 = new_array(3, descr=arraydescr)
  4015. p2 = new_array(3, descr=arraydescr)
  4016. setarrayitem_gc(p1, 2, 10, descr=arraydescr)
  4017. setarrayitem_gc(p2, 2, 13, descr=arraydescr)
  4018. call_n(0, p1, p2, 0, 0, 3, descr=arraycopydescr)
  4019. escape_n(p2)
  4020. jump()
  4021. '''
  4022. expected = '''
  4023. []
  4024. p2 = new_array(3, descr=arraydescr)
  4025. setarrayitem_gc(p2, 2, 10, descr=arraydescr)
  4026. escape_n(p2)
  4027. jump()
  4028. '''
  4029. self.optimize_loop(ops, expected)
  4030. def test_arraycopy_no_elem(self):
  4031. """ this was actually observed in the wild
  4032. """
  4033. ops = '''
  4034. [p1]
  4035. p0 = new_array(0, descr=arraydescr)
  4036. call_n(0, p0, p1, 0, 0, 0, descr=arraycopydescr)
  4037. jump(p1)
  4038. '''
  4039. expected = '''
  4040. [p1]
  4041. jump(p1)
  4042. '''
  4043. self.optimize_loop(ops, expected)
  4044. def test_arraycopy_dest_not_virtual(self):
  4045. ops = '''
  4046. []
  4047. p1 = new_array_clear(3, descr=arraydescr)
  4048. p2 = new_array(3, descr=arraydescr)
  4049. setarrayitem_gc(p1, 2, 10, descr=arraydescr)
  4050. setarrayitem_gc(p2, 2, 13, descr=arraydescr)
  4051. escape_n(p2)
  4052. call_n(0, p1, p2, 0, 0, 3, descr=arraycopydescr)
  4053. escape_n(p2)
  4054. jump()
  4055. '''
  4056. expected = '''
  4057. []
  4058. p2 = new_array(3, descr=arraydescr)
  4059. setarrayitem_gc(p2, 2, 13, descr=arraydescr)
  4060. escape_n(p2)
  4061. setarrayitem_gc(p2, 0, 0, descr=arraydescr)
  4062. setarrayitem_gc(p2, 1, 0, descr=arraydescr)
  4063. setarrayitem_gc(p2, 2, 10, descr=arraydescr)
  4064. escape_n(p2)
  4065. jump()
  4066. '''
  4067. self.optimize_loop(ops, expected)
  4068. def test_arraycopy_dest_not_virtual_too_long(self):
  4069. ops = '''
  4070. []
  4071. p1 = new_array(10, descr=arraydescr)
  4072. p2 = new_array(10, descr=arraydescr)
  4073. setarrayitem_gc(p1, 2, 10, descr=arraydescr)
  4074. setarrayitem_gc(p2, 2, 13, descr=arraydescr)
  4075. escape_n(p2)
  4076. call_n(0, p1, p2, 0, 0, 10, descr=arraycopydescr)
  4077. escape_n(p2)
  4078. jump()
  4079. '''
  4080. expected = '''
  4081. []
  4082. p2 = new_array(10, descr=arraydescr)
  4083. setarrayitem_gc(p2, 2, 13, descr=arraydescr)
  4084. escape_n(p2)
  4085. p1 = new_array(10, descr=arraydescr)
  4086. setarrayitem_gc(p1, 2, 10, descr=arraydescr)
  4087. call_n(0, p1, p2, 0, 0, 10, descr=arraycopydescr)
  4088. escape_n(p2)
  4089. jump()
  4090. '''
  4091. self.optimize_loop(ops, expected)
  4092. def test_bound_lt(self):
  4093. ops = """
  4094. [i0]
  4095. i1 = int_lt(i0, 4)
  4096. guard_true(i1) []
  4097. i2 = int_lt(i0, 5)
  4098. guard_true(i2) []
  4099. jump(i0)
  4100. """
  4101. preamble = """
  4102. [i0]
  4103. i1 = int_lt(i0, 4)
  4104. guard_true(i1) []
  4105. jump(i0)
  4106. """
  4107. expected = """
  4108. [i0]
  4109. jump(i0)
  4110. """
  4111. self.optimize_loop(ops, expected, preamble)
  4112. def test_bound_lt_noguard(self):
  4113. ops = """
  4114. [i0]
  4115. i1 = int_lt(i0, 4)
  4116. i2 = int_lt(i0, 5)
  4117. jump(i2)
  4118. """
  4119. preamble = """
  4120. [i0]
  4121. i1 = int_lt(i0, 4)
  4122. i2 = int_lt(i0, 5)
  4123. jump(i2)
  4124. """
  4125. expected = """
  4126. [i0]
  4127. jump(1)
  4128. """
  4129. self.optimize_loop(ops, expected, preamble)
  4130. def test_bound_lt_noopt(self):
  4131. ops = """
  4132. [i0]
  4133. i1 = int_lt(i0, 4)
  4134. guard_false(i1) []
  4135. i2 = int_lt(i0, 5)
  4136. guard_true(i2) []
  4137. jump(i0)
  4138. """
  4139. preamble = """
  4140. [i0]
  4141. i1 = int_lt(i0, 4)
  4142. guard_false(i1) []
  4143. i2 = int_lt(i0, 5)
  4144. guard_true(i2) []
  4145. jump()
  4146. """
  4147. expected = """
  4148. []
  4149. jump()
  4150. """
  4151. self.optimize_loop(ops, expected, preamble)
  4152. def test_bound_lt_rev(self):
  4153. ops = """
  4154. [i0]
  4155. i1 = int_lt(i0, 4)
  4156. guard_false(i1) []
  4157. i2 = int_gt(i0, 3)
  4158. guard_true(i2) []
  4159. jump(i0)
  4160. """
  4161. preamble = """
  4162. [i0]
  4163. i1 = int_lt(i0, 4)
  4164. guard_false(i1) []
  4165. jump(i0)
  4166. """
  4167. expected = """
  4168. [i0]
  4169. jump(i0)
  4170. """
  4171. self.optimize_loop(ops, expected, preamble)
  4172. def test_bound_lt_tripple(self):
  4173. ops = """
  4174. [i0]
  4175. i1 = int_lt(i0, 0)
  4176. guard_true(i1) []
  4177. i2 = int_lt(i0, 7)
  4178. guard_true(i2) []
  4179. i3 = int_lt(i0, 5)
  4180. guard_true(i3) []
  4181. jump(i0)
  4182. """
  4183. preamble = """
  4184. [i0]
  4185. i1 = int_lt(i0, 0)
  4186. guard_true(i1) []
  4187. jump(i0)
  4188. """
  4189. expected = """
  4190. [i0]
  4191. jump(i0)
  4192. """
  4193. self.optimize_loop(ops, expected, preamble)
  4194. def test_bound_lt_add(self):
  4195. ops = """
  4196. [i0]
  4197. i1 = int_lt(i0, 4)
  4198. guard_true(i1) []
  4199. i2 = int_add(i0, 10)
  4200. i3 = int_lt(i2, 15)
  4201. guard_true(i3) []
  4202. jump(i0)
  4203. """
  4204. preamble = """
  4205. [i0]
  4206. i1 = int_lt(i0, 4)
  4207. guard_true(i1) []
  4208. i2 = int_add(i0, 10)
  4209. jump(i0)
  4210. """
  4211. expected = """
  4212. [i0]
  4213. jump(i0)
  4214. """
  4215. self.optimize_loop(ops, expected, preamble)
  4216. def test_bound_lt_add_before(self):
  4217. ops = """
  4218. [i0]
  4219. i2 = int_add(i0, 10)
  4220. i3 = int_lt(i2, 15)
  4221. guard_true(i3) []
  4222. i1 = int_lt(i0, 6)
  4223. guard_true(i1) []
  4224. jump(i0)
  4225. """
  4226. preamble = """
  4227. [i0]
  4228. i2 = int_add(i0, 10)
  4229. i3 = int_lt(i2, 15)
  4230. guard_true(i3) []
  4231. jump(i0)
  4232. """
  4233. expected = """
  4234. [i0]
  4235. jump(i0)
  4236. """
  4237. self.optimize_loop(ops, expected, preamble)
  4238. def test_bound_lt_add_ovf(self):
  4239. ops = """
  4240. [i0]
  4241. i1 = int_lt(i0, 4)
  4242. guard_true(i1) []
  4243. i2 = int_add_ovf(i0, 10)
  4244. guard_no_overflow() []
  4245. i3 = int_lt(i2, 15)
  4246. guard_true(i3) []
  4247. jump(i0)
  4248. """
  4249. preamble = """
  4250. [i0]
  4251. i1 = int_lt(i0, 4)
  4252. guard_true(i1) []
  4253. i2 = int_add(i0, 10)
  4254. jump(i0)
  4255. """
  4256. expected = """
  4257. [i0]
  4258. jump(i0)
  4259. """
  4260. self.optimize_loop(ops, expected, preamble)
  4261. def test_bound_lt_add_ovf_before(self):
  4262. ops = """
  4263. [i0]
  4264. i2 = int_add_ovf(i0, 10)
  4265. guard_no_overflow() []
  4266. i3 = int_lt(i2, 15)
  4267. guard_true(i3) []
  4268. i1 = int_lt(i0, 6)
  4269. guard_true(i1) []
  4270. jump(i0)
  4271. """
  4272. preamble = """
  4273. [i0]
  4274. i2 = int_add_ovf(i0, 10)
  4275. guard_no_overflow() []
  4276. i3 = int_lt(i2, 15)
  4277. guard_true(i3) []
  4278. jump(i0)
  4279. """
  4280. expected = """
  4281. [i0]
  4282. jump(i0)
  4283. """
  4284. self.optimize_loop(ops, expected, preamble)
  4285. def test_bound_lt_sub1(self):
  4286. ops = """
  4287. [i0]
  4288. i1 = int_lt(i0, 4)
  4289. guard_true(i1) []
  4290. i2 = int_sub(i0, 10)
  4291. i3 = int_lt(i2, -5)
  4292. guard_true(i3) []
  4293. jump(i0)
  4294. """
  4295. preamble = """
  4296. [i0]
  4297. i1 = int_lt(i0, 4)
  4298. guard_true(i1) []
  4299. i2 = int_sub(i0, 10)
  4300. i3 = int_lt(i2, -5)
  4301. guard_true(i3) []
  4302. jump(i0)
  4303. """
  4304. expected = """
  4305. [i0]
  4306. jump(i0)
  4307. """
  4308. self.optimize_loop(ops, expected, preamble)
  4309. def test_bound_lt_sub2(self):
  4310. ops = """
  4311. [i0]
  4312. i1 = int_lt(i0, 4)
  4313. guard_true(i1) []
  4314. i1p = int_gt(i0, -4)
  4315. guard_true(i1p) []
  4316. i2 = int_sub(i0, 10)
  4317. i3 = int_lt(i2, -5)
  4318. guard_true(i3) []
  4319. jump(i0)
  4320. """
  4321. preamble = """
  4322. [i0]
  4323. i1 = int_lt(i0, 4)
  4324. guard_true(i1) []
  4325. i1p = int_gt(i0, -4)
  4326. guard_true(i1p) []
  4327. i2 = int_sub(i0, 10)
  4328. jump(i0)
  4329. """
  4330. expected = """
  4331. [i0]
  4332. jump(i0)
  4333. """
  4334. self.optimize_loop(ops, expected, preamble)
  4335. def test_bound_lt_sub_before(self):
  4336. ops = """
  4337. [i0]
  4338. i2 = int_sub(i0, 10)
  4339. i3 = int_lt(i2, -5)
  4340. guard_true(i3) []
  4341. i1 = int_lt(i0, 5)
  4342. guard_true(i1) []
  4343. jump(i0)
  4344. """
  4345. preamble = """
  4346. [i0]
  4347. i2 = int_sub(i0, 10)
  4348. i3 = int_lt(i2, -5)
  4349. guard_true(i3) []
  4350. jump(i0)
  4351. """
  4352. expected = """
  4353. [i0]
  4354. jump(i0)
  4355. """
  4356. self.optimize_loop(ops, expected, preamble)
  4357. def test_bound_ltle(self):
  4358. ops = """
  4359. [i0]
  4360. i1 = int_lt(i0, 4)
  4361. guard_true(i1) []
  4362. i2 = int_le(i0, 3)
  4363. guard_true(i2) []
  4364. jump(i0)
  4365. """
  4366. preamble = """
  4367. [i0]
  4368. i1 = int_lt(i0, 4)
  4369. guard_true(i1) []
  4370. jump(i0)
  4371. """
  4372. expected = """
  4373. [i0]
  4374. jump(i0)
  4375. """
  4376. self.optimize_loop(ops, expected, preamble)
  4377. def test_bound_lelt(self):
  4378. ops = """
  4379. [i0]
  4380. i1 = int_le(i0, 4)
  4381. guard_true(i1) []
  4382. i2 = int_lt(i0, 5)
  4383. guard_true(i2) []
  4384. jump(i0)
  4385. """
  4386. preamble = """
  4387. [i0]
  4388. i1 = int_le(i0, 4)
  4389. guard_true(i1) []
  4390. jump(i0)
  4391. """
  4392. expected = """
  4393. [i0]
  4394. jump(i0)
  4395. """
  4396. self.optimize_loop(ops, expected, preamble)
  4397. def test_bound_gt(self):
  4398. ops = """
  4399. [i0]
  4400. i1 = int_gt(i0, 5)
  4401. guard_true(i1) []
  4402. i2 = int_gt(i0, 4)
  4403. guard_true(i2) []
  4404. jump(i0)
  4405. """
  4406. preamble = """
  4407. [i0]
  4408. i1 = int_gt(i0, 5)
  4409. guard_true(i1) []
  4410. jump(i0)
  4411. """
  4412. expected = """
  4413. [i0]
  4414. jump(i0)
  4415. """
  4416. self.optimize_loop(ops, expected, preamble)
  4417. def test_bound_gtge(self):
  4418. ops = """
  4419. [i0]
  4420. i1 = int_gt(i0, 5)
  4421. guard_true(i1) []
  4422. i2 = int_ge(i0, 6)
  4423. guard_true(i2) []
  4424. jump(i0)
  4425. """
  4426. preamble = """
  4427. [i0]
  4428. i1 = int_gt(i0, 5)
  4429. guard_true(i1) []
  4430. jump(i0)
  4431. """
  4432. expected = """
  4433. [i0]
  4434. jump(i0)
  4435. """
  4436. self.optimize_loop(ops, expected, preamble)
  4437. def test_bound_gegt(self):
  4438. ops = """
  4439. [i0]
  4440. i1 = int_ge(i0, 5)
  4441. guard_true(i1) []
  4442. i2 = int_gt(i0, 4)
  4443. guard_true(i2) []
  4444. jump(i0)
  4445. """
  4446. preamble = """
  4447. [i0]
  4448. i1 = int_ge(i0, 5)
  4449. guard_true(i1) []
  4450. jump(i0)
  4451. """
  4452. expected = """
  4453. [i0]
  4454. jump(i0)
  4455. """
  4456. self.optimize_loop(ops, expected, preamble)
  4457. def test_bound_ovf(self):
  4458. ops = """
  4459. [i0]
  4460. i1 = int_ge(i0, 0)
  4461. guard_true(i1) []
  4462. i2 = int_lt(i0, 10)
  4463. guard_true(i2) []
  4464. i3 = int_add_ovf(i0, 1)
  4465. guard_no_overflow() []
  4466. jump(i3)
  4467. """
  4468. preamble = """
  4469. [i0]
  4470. i1 = int_ge(i0, 0)
  4471. guard_true(i1) []
  4472. i2 = int_lt(i0, 10)
  4473. guard_true(i2) []
  4474. i3 = int_add(i0, 1)
  4475. jump(i3)
  4476. """
  4477. expected = """
  4478. [i0]
  4479. i2 = int_lt(i0, 10)
  4480. guard_true(i2) []
  4481. i3 = int_add(i0, 1)
  4482. jump(i3)
  4483. """
  4484. self.optimize_loop(ops, expected, preamble)
  4485. def test_bound_arraylen(self):
  4486. ops = """
  4487. [i0, p0]
  4488. p1 = new_array(i0, descr=gcarraydescr)
  4489. i1 = arraylen_gc(p1, descr=gcarraydescr)
  4490. i2 = int_gt(i1, -1)
  4491. guard_true(i2) []
  4492. setarrayitem_gc(p0, 0, p1, descr=gcarraydescr)
  4493. jump(i0, p0)
  4494. """
  4495. # The dead arraylen_gc will be eliminated by the backend.
  4496. expected = """
  4497. [i0, p0]
  4498. p1 = new_array(i0, descr=gcarraydescr)
  4499. i1 = arraylen_gc(p1, descr=gcarraydescr)
  4500. setarrayitem_gc(p0, 0, p1, descr=gcarraydescr)
  4501. jump(i0, p0)
  4502. """
  4503. self.optimize_loop(ops, expected)
  4504. def test_bound_arraylen_2(self):
  4505. ops = """
  4506. [i0, p0]
  4507. p1 = new_array(i0, descr=gcarraydescr)
  4508. setarrayitem_gc(p1, 3, p1, descr=gcarraydescr)
  4509. i1 = arraylen_gc(p1)
  4510. i2 = int_gt(i1, 2)
  4511. guard_true(i2) []
  4512. setarrayitem_gc(p1, 0, p0, descr=gcarraydescr)
  4513. jump(i0, p0)
  4514. """
  4515. # The dead arraylen_gc will be eliminated by the backend.
  4516. expected = """
  4517. [i0, p0]
  4518. p1 = new_array(i0, descr=gcarraydescr)
  4519. i1 = arraylen_gc(p1)
  4520. setarrayitem_gc(p1, 0, p0, descr=gcarraydescr)
  4521. setarrayitem_gc(p1, 3, p1, descr=gcarraydescr)
  4522. jump(i0, p0)
  4523. """
  4524. self.optimize_loop(ops, expected)
  4525. def test_bound_strlen(self):
  4526. ops = """
  4527. [p0]
  4528. i0 = strlen(p0)
  4529. i1 = int_ge(i0, 0)
  4530. guard_true(i1) []
  4531. jump(p0)
  4532. """
  4533. preamble = """
  4534. [p0]
  4535. i0 = strlen(p0)
  4536. jump(p0)
  4537. """
  4538. expected = """
  4539. [p0]
  4540. jump(p0)
  4541. """
  4542. self.optimize_strunicode_loop(ops, expected, preamble)
  4543. def test_bound_force_ge_zero(self):
  4544. ops = """
  4545. [p0]
  4546. i0 = arraylen_gc(p0, descr=arraydescr)
  4547. i1 = int_force_ge_zero(i0)
  4548. escape_n(i1)
  4549. jump(p0)
  4550. """
  4551. preamble = """
  4552. [p0]
  4553. i0 = arraylen_gc(p0, descr=arraydescr)
  4554. escape_n(i0)
  4555. jump(p0, i0)
  4556. """
  4557. expected = """
  4558. [p0, i0]
  4559. escape_n(i0)
  4560. jump(p0, i0)
  4561. """
  4562. self.optimize_loop(ops, expected, preamble)
  4563. def test_addsub_const(self):
  4564. ops = """
  4565. [i0]
  4566. i1 = int_add(i0, 1)
  4567. i2 = int_sub(i1, 1)
  4568. i3 = int_add(i2, 1)
  4569. i4 = int_mul(i2, i3)
  4570. jump(i4)
  4571. """
  4572. expected = """
  4573. [i0]
  4574. i1 = int_add(i0, 1)
  4575. i4 = int_mul(i0, i1)
  4576. jump(i4)
  4577. """
  4578. self.optimize_loop(ops, expected)
  4579. def test_addsub_int(self):
  4580. ops = """
  4581. [i0, i10]
  4582. i1 = int_add(i0, i10)
  4583. i2 = int_sub(i1, i10)
  4584. i3 = int_add(i2, i10)
  4585. i4 = int_add(i2, i3)
  4586. jump(i4, i10)
  4587. """
  4588. expected = """
  4589. [i0, i10]
  4590. i1 = int_add(i0, i10)
  4591. i4 = int_add(i0, i1)
  4592. jump(i4, i10)
  4593. """
  4594. self.optimize_loop(ops, expected)
  4595. def test_addsub_int2(self):
  4596. ops = """
  4597. [i0, i10]
  4598. i1 = int_add(i10, i0)
  4599. i2 = int_sub(i1, i10)
  4600. i3 = int_add(i10, i2)
  4601. i4 = int_add(i2, i3)
  4602. jump(i4, i10)
  4603. """
  4604. expected = """
  4605. [i0, i10]
  4606. i1 = int_add(i10, i0)
  4607. i4 = int_add(i0, i1)
  4608. jump(i4, i10)
  4609. """
  4610. self.optimize_loop(ops, expected)
  4611. def test_add_sub_ovf(self):
  4612. ops = """
  4613. [i1]
  4614. i2 = int_add_ovf(i1, 1)
  4615. guard_no_overflow() []
  4616. i3 = int_sub_ovf(i2, 1)
  4617. guard_no_overflow() []
  4618. escape_n(i3)
  4619. jump(i2)
  4620. """
  4621. expected = """
  4622. [i1]
  4623. i2 = int_add_ovf(i1, 1)
  4624. guard_no_overflow() []
  4625. escape_n(i1)
  4626. jump(i2)
  4627. """
  4628. self.optimize_loop(ops, expected)
  4629. def test_add_sub_ovf_second_operation_regular(self):
  4630. py.test.skip("Smalltalk would like this to pass")
  4631. # This situation occurs in Smalltalk because it uses 1-based indexing.
  4632. # The below code is equivalent to a loop over an array.
  4633. ops = """
  4634. [i1]
  4635. i2 = int_sub(i1, 1)
  4636. escape_n(i2)
  4637. i3 = int_add_ovf(i1, 1)
  4638. guard_no_overflow() []
  4639. jump(i3)
  4640. """
  4641. preamble = """
  4642. [i1]
  4643. i2 = int_sub(i1, 1)
  4644. escape_n(i2)
  4645. i3 = int_add_ovf(i1, 1)
  4646. guard_no_overflow() []
  4647. jump(i3, i1)
  4648. """
  4649. expected = """
  4650. [i1, i2]
  4651. escape_n(i2)
  4652. i3 = int_add_ovf(i1, 1)
  4653. guard_no_overflow() []
  4654. jump(i3, i1)
  4655. """
  4656. self.optimize_loop(ops, expected, preamble)
  4657. def test_add_sub_ovf_virtual_unroll(self):
  4658. ops = """
  4659. [p15]
  4660. i886 = getfield_gc_i(p15, descr=valuedescr)
  4661. i888 = int_sub_ovf(i886, 1)
  4662. guard_no_overflow() []
  4663. escape_n(i888)
  4664. i4360 = getfield_gc_i(p15, descr=valuedescr)
  4665. i4362 = int_add_ovf(i4360, 1)
  4666. guard_no_overflow() []
  4667. i4360p = int_sub_ovf(i4362, 1)
  4668. guard_no_overflow() []
  4669. p4364 = new_with_vtable(descr=nodesize)
  4670. setfield_gc(p4364, i4362, descr=valuedescr)
  4671. jump(p4364)
  4672. """
  4673. expected = """
  4674. [i0]
  4675. i1 = int_sub_ovf(i0, 1)
  4676. guard_no_overflow() []
  4677. escape_n(i1)
  4678. i2 = int_add_ovf(i0, 1)
  4679. guard_no_overflow() []
  4680. jump(i2)
  4681. """
  4682. self.optimize_loop(ops, expected)
  4683. def test_framestackdepth_overhead(self):
  4684. ops = """
  4685. [p0, i22]
  4686. i1 = getfield_gc_i(p0, descr=valuedescr)
  4687. i2 = int_gt(i1, i22)
  4688. guard_false(i2) []
  4689. i3 = int_add(i1, 1)
  4690. setfield_gc(p0, i3, descr=valuedescr)
  4691. i4 = int_sub(i3, 1)
  4692. setfield_gc(p0, i4, descr=valuedescr)
  4693. i5 = int_gt(i4, i22)
  4694. guard_false(i5) []
  4695. i6 = int_add(i4, 1)
  4696. p331 = force_token()
  4697. i7 = int_sub(i6, 1)
  4698. setfield_gc(p0, i7, descr=valuedescr)
  4699. jump(p0, i22)
  4700. """
  4701. expected = """
  4702. [p0, i22]
  4703. p331 = force_token()
  4704. jump(p0, i22)
  4705. """
  4706. self.optimize_loop(ops, expected)
  4707. def test_setgetfield_raw(self):
  4708. ops = """
  4709. [p4, p7, i30]
  4710. p16 = getfield_gc_r(p4, descr=nextdescr)
  4711. guard_value(p16, ConstPtr(myptr), descr=<Guard3>) []
  4712. i1 = getfield_raw_i(p7, descr=nextdescr)
  4713. i2 = int_add(i1, i30)
  4714. setfield_raw(p7, 7, descr=nextdescr)
  4715. setfield_raw(p7, i2, descr=nextdescr)
  4716. jump(p4, p7, i30)
  4717. """
  4718. expected = """
  4719. [p4, p7, i30]
  4720. i1 = getfield_raw_i(p7, descr=nextdescr)
  4721. i2 = int_add(i1, i30)
  4722. setfield_raw(p7, 7, descr=nextdescr)
  4723. setfield_raw(p7, i2, descr=nextdescr)
  4724. jump(p4, p7, i30)
  4725. """
  4726. self.optimize_loop(ops, expected, ops)
  4727. def test_setgetarrayitem_raw(self):
  4728. ops = """
  4729. [p4, i7, i30]
  4730. p16 = getfield_gc_r(p4, descr=otherdescr)
  4731. guard_value(p16, ConstPtr(myptr), descr=<Guard3>) []
  4732. i1 = getarrayitem_raw_i(i7, 1, descr=arraydescr)
  4733. i2 = int_add(i1, i30)
  4734. setarrayitem_raw(i7, 1, 7, descr=arraydescr)
  4735. setarrayitem_raw(i7, 1, i2, descr=arraydescr)
  4736. jump(p4, i7, i30)
  4737. """
  4738. expected = """
  4739. [p4, i7, i30]
  4740. i1 = getarrayitem_raw_i(i7, 1, descr=arraydescr)
  4741. i2 = int_add(i1, i30)
  4742. setarrayitem_raw(i7, 1, 7, descr=arraydescr)
  4743. setarrayitem_raw(i7, 1, i2, descr=arraydescr)
  4744. jump(p4, i7, i30)
  4745. """
  4746. self.optimize_loop(ops, expected, ops)
  4747. def test_pure(self):
  4748. ops = """
  4749. [p42]
  4750. p53 = getfield_gc_r(ConstPtr(myptr3), descr=nextdescr3)
  4751. p59 = getfield_gc_r(p53, descr=valuedescr3)
  4752. i61 = call_i(1, p59, descr=nonwritedescr)
  4753. jump(p42)
  4754. """
  4755. expected = """
  4756. [p42]
  4757. i61 = call_i(1, 7, descr=nonwritedescr)
  4758. jump(p42)
  4759. """
  4760. self.optimize_loop(ops, expected)
  4761. def test_complains_getfieldpure_setfield(self):
  4762. from rpython.jit.metainterp.optimizeopt.heap import BogusImmutableField
  4763. py.test.skip("disabled for now")
  4764. ops = """
  4765. [p3]
  4766. p1 = escape_r()
  4767. p2 = getfield_gc_r(p1, descr=nextdescr)
  4768. setfield_gc(p1, p3, descr=nextdescr)
  4769. jump(p3)
  4770. """
  4771. self.raises(BogusImmutableField, self.optimize_loop, ops, "crash!")
  4772. def test_dont_complains_different_field(self):
  4773. ops = """
  4774. [p3]
  4775. p1 = escape_r()
  4776. p2 = getfield_gc_r(p1, descr=nextdescr3)
  4777. setfield_gc(p1, p3, descr=otherdescr)
  4778. escape_n(p2)
  4779. jump(p3)
  4780. """
  4781. expected = """
  4782. [p3]
  4783. p1 = escape_r()
  4784. p2 = getfield_gc_r(p1, descr=nextdescr3)
  4785. setfield_gc(p1, p3, descr=otherdescr)
  4786. escape_n(p2)
  4787. jump(p3)
  4788. """
  4789. self.optimize_loop(ops, expected)
  4790. def test_dont_complains_different_object(self):
  4791. ops = """
  4792. []
  4793. p1 = escape_r()
  4794. p2 = getfield_gc_r(p1, descr=nextdescr)
  4795. p3 = escape_r()
  4796. setfield_gc(p3, p1, descr=nextdescr)
  4797. jump()
  4798. """
  4799. self.optimize_loop(ops, ops)
  4800. def test_getfield_guard_const(self):
  4801. ops = """
  4802. [p0]
  4803. p20 = getfield_gc_r(p0, descr=nextdescr)
  4804. guard_nonnull(p20) []
  4805. guard_class(p20, ConstClass(node_vtable)) []
  4806. guard_class(p20, ConstClass(node_vtable)) []
  4807. p23 = getfield_gc_r(p20, descr=valuedescr)
  4808. guard_isnull(p23) []
  4809. guard_class(p20, ConstClass(node_vtable)) []
  4810. guard_value(p20, ConstPtr(myptr)) []
  4811. p37 = getfield_gc_r(p0, descr=nextdescr)
  4812. guard_nonnull(p37) []
  4813. guard_class(p37, ConstClass(node_vtable)) []
  4814. guard_class(p37, ConstClass(node_vtable)) []
  4815. p40 = getfield_gc_r(p37, descr=valuedescr)
  4816. guard_isnull(p40) []
  4817. guard_class(p37, ConstClass(node_vtable)) []
  4818. guard_value(p37, ConstPtr(myptr)) []
  4819. p64 = call_may_force_r(p23, p40, descr=plaincalldescr)
  4820. jump(p0)
  4821. """
  4822. expected = """
  4823. [p0]
  4824. p20 = getfield_gc_r(p0, descr=nextdescr)
  4825. guard_value(p20, ConstPtr(myptr)) []
  4826. p23 = getfield_gc_r(p20, descr=valuedescr)
  4827. guard_isnull(p23) []
  4828. p64 = call_may_force_r(NULL, NULL, descr=plaincalldescr)
  4829. jump(p0)
  4830. """
  4831. self.optimize_loop(ops, expected, expected)
  4832. def test_getfield_guard_const_preamble(self):
  4833. ops = """
  4834. [p0]
  4835. p01 = getfield_gc_r(p0, descr=nextdescr)
  4836. p02 = getfield_gc_r(p01, descr=valuedescr)
  4837. guard_value(p01, ConstPtr(myptr)) []
  4838. p11 = getfield_gc_r(p0, descr=nextdescr)
  4839. p12 = getfield_gc_r(p11, descr=valuedescr)
  4840. guard_value(p11, ConstPtr(myptr)) []
  4841. p64 = call_may_force_r(p02, p12, descr=plaincalldescr)
  4842. p21 = getfield_gc_r(p0, descr=nextdescr)
  4843. p22 = getfield_gc_r(p21, descr=valuedescr)
  4844. guard_value(p21, ConstPtr(myptr)) []
  4845. p31 = getfield_gc_r(p0, descr=nextdescr)
  4846. p32 = getfield_gc_r(p31, descr=valuedescr)
  4847. guard_value(p31, ConstPtr(myptr)) []
  4848. p65 = call_may_force_r(p22, p32, descr=plaincalldescr)
  4849. jump(p0)
  4850. """
  4851. expected = """
  4852. [p0]
  4853. p01 = getfield_gc_r(p0, descr=nextdescr)
  4854. p02 = getfield_gc_r(p01, descr=valuedescr)
  4855. guard_value(p01, ConstPtr(myptr)) []
  4856. p64 = call_may_force_r(p02, p02, descr=plaincalldescr)
  4857. p21 = getfield_gc_r(p0, descr=nextdescr)
  4858. p22 = getfield_gc_r(p21, descr=valuedescr)
  4859. guard_value(p21, ConstPtr(myptr)) []
  4860. p65 = call_may_force_r(p22, p22, descr=plaincalldescr)
  4861. jump(p0)
  4862. """
  4863. self.optimize_loop(ops, expected, expected)
  4864. def test_addsub_ovf(self):
  4865. ops = """
  4866. [i0]
  4867. i1 = int_add_ovf(i0, 10)
  4868. guard_no_overflow() []
  4869. i2 = int_sub_ovf(i1, 5)
  4870. guard_no_overflow() []
  4871. jump(i2)
  4872. """
  4873. expected = """
  4874. [i0]
  4875. i1 = int_add_ovf(i0, 10)
  4876. guard_no_overflow() []
  4877. i2 = int_sub(i1, 5)
  4878. jump(i2)
  4879. """
  4880. self.optimize_loop(ops, expected)
  4881. def test_subadd_ovf(self):
  4882. ops = """
  4883. [i0]
  4884. i1 = int_sub_ovf(i0, 10)
  4885. guard_no_overflow() []
  4886. i2 = int_add_ovf(i1, 5)
  4887. guard_no_overflow() []
  4888. jump(i2)
  4889. """
  4890. expected = """
  4891. [i0]
  4892. i1 = int_sub_ovf(i0, 10)
  4893. guard_no_overflow() []
  4894. i2 = int_add(i1, 5)
  4895. jump(i2)
  4896. """
  4897. self.optimize_loop(ops, expected)
  4898. def test_bound_and(self):
  4899. ops = """
  4900. []
  4901. i0 = escape_i()
  4902. i1 = int_and(i0, 255)
  4903. i2 = int_lt(i1, 500)
  4904. guard_true(i2) []
  4905. i3 = int_le(i1, 255)
  4906. guard_true(i3) []
  4907. i4 = int_gt(i1, -1)
  4908. guard_true(i4) []
  4909. i5 = int_ge(i1, 0)
  4910. guard_true(i5) []
  4911. i6 = int_lt(i1, 0)
  4912. guard_false(i6) []
  4913. i7 = int_le(i1, -1)
  4914. guard_false(i7) []
  4915. i8 = int_gt(i1, 255)
  4916. guard_false(i8) []
  4917. i9 = int_ge(i1, 500)
  4918. guard_false(i9) []
  4919. i12 = int_lt(i1, 100)
  4920. guard_true(i12) []
  4921. i13 = int_le(i1, 90)
  4922. guard_true(i13) []
  4923. i14 = int_gt(i1, 10)
  4924. guard_true(i14) []
  4925. i15 = int_ge(i1, 20)
  4926. guard_true(i15) []
  4927. jump()
  4928. """
  4929. expected = """
  4930. []
  4931. i0 = escape_i()
  4932. i1 = int_and(i0, 255)
  4933. i12 = int_lt(i1, 100)
  4934. guard_true(i12) []
  4935. i13 = int_le(i1, 90)
  4936. guard_true(i13) []
  4937. i14 = int_gt(i1, 10)
  4938. guard_true(i14) []
  4939. i15 = int_ge(i1, 20)
  4940. guard_true(i15) []
  4941. jump()
  4942. """
  4943. self.optimize_loop(ops, expected)
  4944. def test_bound_xor(self):
  4945. ops = """
  4946. [i0, i1, i2]
  4947. it1 = int_ge(i1, 0)
  4948. guard_true(it1) []
  4949. it2 = int_gt(i2, 0)
  4950. guard_true(it2) []
  4951. ix1 = int_xor(i0, i0)
  4952. ix1t = int_ge(ix1, 0)
  4953. guard_true(ix1t) []
  4954. ix2 = int_xor(i0, i1)
  4955. ix2t = int_ge(ix2, 0)
  4956. guard_true(ix2t) []
  4957. ix3 = int_xor(i1, i0)
  4958. ix3t = int_ge(ix3, 0)
  4959. guard_true(ix3t) []
  4960. ix4 = int_xor(i1, i2)
  4961. ix4t = int_ge(ix4, 0)
  4962. guard_true(ix4t) []
  4963. jump(i0, i1, i2)
  4964. """
  4965. preamble = """
  4966. [i0, i1, i2]
  4967. it1 = int_ge(i1, 0)
  4968. guard_true(it1) []
  4969. it2 = int_gt(i2, 0)
  4970. guard_true(it2) []
  4971. ix2 = int_xor(i0, i1)
  4972. ix2t = int_ge(ix2, 0)
  4973. guard_true(ix2t) []
  4974. ix3 = int_xor(i1, i0)
  4975. ix3t = int_ge(ix3, 0)
  4976. guard_true(ix3t) []
  4977. ix4 = int_xor(i1, i2)
  4978. jump(i0, i1, i2)
  4979. """
  4980. expected = """
  4981. [i0, i1, i2]
  4982. jump(i0, i1, i2)
  4983. """
  4984. self.optimize_loop(ops, expected, preamble)
  4985. def test_bound_floordiv(self):
  4986. ops = """
  4987. [i0, i1, i2]
  4988. it1 = int_ge(i1, 0)
  4989. guard_true(it1) []
  4990. it2 = int_gt(i2, 0)
  4991. guard_true(it2) []
  4992. ix2 = call_pure_i(321, i0, i1, descr=int_py_div_descr)
  4993. ix2t = int_ge(ix2, 0)
  4994. guard_true(ix2t) []
  4995. ix3 = call_pure_i(321, i1, i0, descr=int_py_div_descr)
  4996. ix3t = int_ge(ix3, 0)
  4997. guard_true(ix3t) []
  4998. ix4 = call_pure_i(321, i1, i2, descr=int_py_div_descr)
  4999. ix4t = int_ge(ix4, 0)
  5000. guard_true(ix4t) []
  5001. jump(i0, i1, i2)
  5002. """
  5003. preamble = """
  5004. [i0, i1, i2]
  5005. it1 = int_ge(i1, 0)
  5006. guard_true(it1) []
  5007. it2 = int_gt(i2, 0)
  5008. guard_true(it2) []
  5009. ix2 = call_i(321, i0, i1, descr=int_py_div_descr)
  5010. ix2t = int_ge(ix2, 0)
  5011. guard_true(ix2t) []
  5012. ix3 = call_i(321, i1, i0, descr=int_py_div_descr)
  5013. ix3t = int_ge(ix3, 0)
  5014. guard_true(ix3t) []
  5015. ix4 = call_i(321, i1, i2, descr=int_py_div_descr)
  5016. # <== the check that ix4 is nonnegative was removed
  5017. jump(i0, i1, i2)
  5018. """
  5019. expected = """
  5020. [i0, i1, i2]
  5021. jump(i0, i1, i2)
  5022. """
  5023. self.optimize_loop(ops, expected, preamble)
  5024. def test_bound_int_is_zero(self):
  5025. ops = """
  5026. [i1, i2a, i2b, i2c]
  5027. i3 = int_is_zero(i1)
  5028. i4 = int_gt(i2a, 7)
  5029. guard_true(i4) []
  5030. i5 = int_is_zero(i2a)
  5031. guard_false(i5) []
  5032. i6 = int_le(i2b, -7)
  5033. guard_true(i6) []
  5034. i7 = int_is_zero(i2b)
  5035. guard_false(i7) []
  5036. i8 = int_gt(i2c, -7)
  5037. guard_true(i8) []
  5038. i9 = int_is_zero(i2c)
  5039. jump(i1, i2a, i2b, i2c)
  5040. """
  5041. preamble = """
  5042. [i1, i2a, i2b, i2c]
  5043. i3 = int_is_zero(i1)
  5044. i4 = int_gt(i2a, 7)
  5045. guard_true(i4) []
  5046. i6 = int_le(i2b, -7)
  5047. guard_true(i6) []
  5048. i8 = int_gt(i2c, -7)
  5049. guard_true(i8) []
  5050. i9 = int_is_zero(i2c)
  5051. jump(i1, i2a, i2b, i2c)
  5052. """
  5053. expected = """
  5054. [i0, i1, i2, i3]
  5055. jump(i0, i1, i2, i3)
  5056. """
  5057. self.optimize_loop(ops, expected, preamble)
  5058. def test_division_to_rshift(self):
  5059. ops = """
  5060. [i1, i2]
  5061. i3 = call_pure_i(321, i1, i2, descr=int_py_div_descr)
  5062. i4 = call_pure_i(322, 2, i2, descr=int_py_div_descr)
  5063. i6 = call_pure_i(323, 3, i2, descr=int_py_div_descr)
  5064. i8 = call_pure_i(324, 4, i2, descr=int_py_div_descr)
  5065. i9b = call_pure_i(325, i1, -2, descr=int_py_div_descr)
  5066. i9c = call_pure_i(326, i1, -1, descr=int_py_div_descr)
  5067. i10 = call_pure_i(327, i1, 0, descr=int_py_div_descr)
  5068. i11 = call_pure_i(328, i1, 1, descr=int_py_div_descr)
  5069. i5 = call_pure_i(329, i1, 2, descr=int_py_div_descr)
  5070. i9 = call_pure_i(331, i1, 4, descr=int_py_div_descr)
  5071. jump(i5, i9)
  5072. """
  5073. expected = """
  5074. [i1, i2]
  5075. i3 = call_i(321, i1, i2, descr=int_py_div_descr)
  5076. i4 = call_i(322, 2, i2, descr=int_py_div_descr)
  5077. i6 = call_i(323, 3, i2, descr=int_py_div_descr)
  5078. i8 = call_i(324, 4, i2, descr=int_py_div_descr)
  5079. i9b = call_i(325, i1, -2, descr=int_py_div_descr)
  5080. i9c = call_i(326, i1, -1, descr=int_py_div_descr)
  5081. i10 = call_i(327, i1, 0, descr=int_py_div_descr)
  5082. # i11 = i1
  5083. i5 = int_rshift(i1, 1)
  5084. i9 = int_rshift(i1, 2)
  5085. jump(i5, i9)
  5086. """
  5087. self.optimize_loop(ops, expected)
  5088. def test_division_to_mul_high_nonneg(self):
  5089. from rpython.jit.metainterp.optimizeopt.intdiv import magic_numbers
  5090. for divisor in [3, 5, 12]:
  5091. kk, ii = magic_numbers(divisor)
  5092. ops = """
  5093. [i1]
  5094. i3 = int_ge(i1, 0)
  5095. guard_true(i3) []
  5096. i2 = call_pure_i(321, i1, %d, descr=int_py_div_descr)
  5097. jump(i2)
  5098. """ % divisor
  5099. expected = """
  5100. [i1]
  5101. i4 = uint_mul_high(i1, %d)
  5102. i2 = uint_rshift(i4, %d)
  5103. jump(i2)
  5104. """ % (intmask(kk), ii)
  5105. self.optimize_loop(ops, expected)
  5106. def test_division_to_mul_high(self):
  5107. from rpython.jit.metainterp.optimizeopt.intdiv import magic_numbers
  5108. for divisor in [3, 5, 12]:
  5109. kk, ii = magic_numbers(divisor)
  5110. ops = """
  5111. [i1]
  5112. i2 = call_pure_i(321, i1, %d, descr=int_py_div_descr)
  5113. jump(i2)
  5114. """ % divisor
  5115. expected = """
  5116. [i1]
  5117. i3 = int_rshift(i1, %d)
  5118. i4 = int_xor(i1, i3)
  5119. i5 = uint_mul_high(i4, %d)
  5120. i6 = uint_rshift(i5, %d)
  5121. i2 = int_xor(i6, i3)
  5122. jump(i2)
  5123. """ % (63 if sys.maxint > 2**32 else 31, intmask(kk), ii)
  5124. self.optimize_loop(ops, expected)
  5125. def test_mul_to_lshift(self):
  5126. ops = """
  5127. [i1, i2]
  5128. i3 = int_mul(i1, 2)
  5129. i4 = int_mul(2, i2)
  5130. i5 = int_mul(i1, 32)
  5131. i6 = int_mul(i1, i2)
  5132. jump(i5, i6)
  5133. """
  5134. expected = """
  5135. [i1, i2]
  5136. i3 = int_lshift(i1, 1)
  5137. i4 = int_lshift(i2, 1)
  5138. i5 = int_lshift(i1, 5)
  5139. i6 = int_mul(i1, i2)
  5140. jump(i5, i6)
  5141. """
  5142. self.optimize_loop(ops, expected)
  5143. def test_lshift_rshift(self):
  5144. ops = """
  5145. [i1, i2, i2b, i1b]
  5146. i3 = int_lshift(i1, i2)
  5147. i4 = int_rshift(i3, i2)
  5148. i5 = int_lshift(i1, 2)
  5149. i6 = int_rshift(i5, 2)
  5150. i6t= int_eq(i6, i1)
  5151. guard_true(i6t) []
  5152. i7 = int_lshift(i1, 100)
  5153. i8 = int_rshift(i7, 100)
  5154. i9 = int_lt(i1b, 100)
  5155. guard_true(i9) []
  5156. i10 = int_gt(i1b, -100)
  5157. guard_true(i10) []
  5158. i13 = int_lshift(i1b, i2)
  5159. i14 = int_rshift(i13, i2)
  5160. i15 = int_lshift(i1b, 2)
  5161. i16 = int_rshift(i15, 2)
  5162. i17 = int_lshift(i1b, 100)
  5163. i18 = int_rshift(i17, 100)
  5164. i19 = int_eq(i1b, i16)
  5165. guard_true(i19) []
  5166. i20 = int_ne(i1b, i16)
  5167. guard_false(i20) []
  5168. jump(i2, i3, i1b, i2b)
  5169. """
  5170. expected = """
  5171. [i1, i2, i2b, i1b]
  5172. i3 = int_lshift(i1, i2)
  5173. i4 = int_rshift(i3, i2)
  5174. i5 = int_lshift(i1, 2)
  5175. i6 = int_rshift(i5, 2)
  5176. i6t= int_eq(i6, i1)
  5177. guard_true(i6t) []
  5178. i7 = int_lshift(i1, 100)
  5179. i8 = int_rshift(i7, 100)
  5180. i9 = int_lt(i1b, 100)
  5181. guard_true(i9) []
  5182. i10 = int_gt(i1b, -100)
  5183. guard_true(i10) []
  5184. i13 = int_lshift(i1b, i2)
  5185. i14 = int_rshift(i13, i2)
  5186. i15 = int_lshift(i1b, 2)
  5187. i17 = int_lshift(i1b, 100)
  5188. i18 = int_rshift(i17, 100)
  5189. jump(i2, i3, i1b, i2b)
  5190. """
  5191. self.optimize_loop(ops, expected)
  5192. def test_int_div_1(self):
  5193. ops = """
  5194. [i0]
  5195. i1 = call_pure_i(321, i0, 1, descr=int_py_div_descr)
  5196. jump(i1)
  5197. """
  5198. expected = """
  5199. [i0]
  5200. jump(i0)
  5201. """
  5202. self.optimize_loop(ops, expected)
  5203. ops = """
  5204. [i0]
  5205. i1 = call_pure_i(321, 0, i0, descr=int_py_div_descr)
  5206. escape_n(i1)
  5207. jump(i0)
  5208. """
  5209. expected = """
  5210. [i0]
  5211. escape_n(0)
  5212. jump(i0)
  5213. """
  5214. self.optimize_loop(ops, expected)
  5215. def test_division_bound_bug(self):
  5216. ops = """
  5217. [i4]
  5218. i1 = int_ge(i4, -50)
  5219. guard_true(i1) []
  5220. i2 = int_le(i4, -40)
  5221. guard_true(i2) []
  5222. # here, -50 <= i4 <= -40
  5223. i5 = call_pure_i(321, i4, 30, descr=int_py_div_descr)
  5224. # here, we know that that i5 == -2 (Python-style handling of negatives)
  5225. escape_n(i5)
  5226. jump(i4)
  5227. """
  5228. expected = """
  5229. [i4, i5]
  5230. escape_n(-2)
  5231. jump(i4, -2)
  5232. """
  5233. self.optimize_loop(ops, expected)
  5234. def test_subsub_ovf(self):
  5235. ops = """
  5236. [i0]
  5237. i1 = int_sub_ovf(1, i0)
  5238. guard_no_overflow() []
  5239. i2 = int_gt(i1, 1)
  5240. guard_true(i2) []
  5241. i3 = int_sub_ovf(1, i0)
  5242. guard_no_overflow() []
  5243. i4 = int_gt(i3, 1)
  5244. guard_true(i4) []
  5245. jump(i0)
  5246. """
  5247. preamble = """
  5248. [i0]
  5249. i1 = int_sub_ovf(1, i0)
  5250. guard_no_overflow() []
  5251. i2 = int_gt(i1, 1)
  5252. guard_true(i2) []
  5253. jump(i0)
  5254. """
  5255. expected = """
  5256. [i0]
  5257. jump(i0)
  5258. """
  5259. self.optimize_loop(ops, expected, preamble)
  5260. def test_bound_eq(self):
  5261. ops = """
  5262. []
  5263. i0 = escape_i()
  5264. i1 = escape_i()
  5265. i2 = int_le(i0, 4)
  5266. guard_true(i2) []
  5267. i3 = int_eq(i0, i1)
  5268. guard_true(i3) []
  5269. i4 = int_lt(i1, 5)
  5270. guard_true(i4) []
  5271. jump()
  5272. """
  5273. expected = """
  5274. []
  5275. i0 = escape_i()
  5276. i1 = escape_i()
  5277. i2 = int_le(i0, 4)
  5278. guard_true(i2) []
  5279. i3 = int_eq(i0, i1)
  5280. guard_true(i3) []
  5281. jump()
  5282. """
  5283. self.optimize_loop(ops, expected)
  5284. def test_bound_eq_const(self):
  5285. ops = """
  5286. []
  5287. i0 = escape_i()
  5288. i1 = int_eq(i0, 7)
  5289. guard_true(i1) []
  5290. i2 = int_add(i0, 3)
  5291. escape_n(i2)
  5292. jump()
  5293. """
  5294. expected = """
  5295. []
  5296. i0 = escape_i()
  5297. i1 = int_eq(i0, 7)
  5298. guard_true(i1) []
  5299. escape_n(10)
  5300. jump()
  5301. """
  5302. self.optimize_loop(ops, expected)
  5303. def test_bound_eq_const_not(self):
  5304. ops = """
  5305. [i0]
  5306. i1 = int_eq(i0, 7)
  5307. guard_false(i1) []
  5308. i2 = int_add(i0, 3)
  5309. jump(i2)
  5310. """
  5311. expected = """
  5312. [i0]
  5313. i1 = int_eq(i0, 7)
  5314. guard_false(i1) []
  5315. i2 = int_add(i0, 3)
  5316. jump(i2)
  5317. """
  5318. self.optimize_loop(ops, expected)
  5319. def test_bound_ne_const(self):
  5320. ops = """
  5321. [i0]
  5322. i1 = int_ne(i0, 7)
  5323. guard_false(i1) []
  5324. i2 = int_add(i0, 3)
  5325. jump(i2)
  5326. """
  5327. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  5328. def test_bound_ne_const_not(self):
  5329. ops = """
  5330. [i0]
  5331. i1 = int_ne(i0, 7)
  5332. guard_true(i1) []
  5333. i2 = int_add(i0, 3)
  5334. jump(i2)
  5335. """
  5336. expected = """
  5337. [i0]
  5338. i1 = int_ne(i0, 7)
  5339. guard_true(i1) []
  5340. i2 = int_add(i0, 3)
  5341. jump(i2)
  5342. """
  5343. self.optimize_loop(ops, expected)
  5344. def test_bound_ltne(self):
  5345. ops = """
  5346. [i0, i1]
  5347. i2 = int_lt(i0, 7)
  5348. guard_true(i2) []
  5349. i3 = int_ne(i0, 10)
  5350. guard_true(i2) []
  5351. jump(i0, i1)
  5352. """
  5353. preamble = """
  5354. [i0, i1]
  5355. i2 = int_lt(i0, 7)
  5356. guard_true(i2) []
  5357. jump(i0, i1)
  5358. """
  5359. expected = """
  5360. [i0, i1]
  5361. jump(i0, i1)
  5362. """
  5363. self.optimize_loop(ops, expected, preamble)
  5364. def test_bound_lege_const(self):
  5365. ops = """
  5366. [i0]
  5367. i1 = int_ge(i0, 7)
  5368. guard_true(i1) []
  5369. i2 = int_le(i0, 7)
  5370. guard_true(i2) []
  5371. i3 = int_add(i0, 3)
  5372. jump(i3)
  5373. """
  5374. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  5375. def test_bound_lshift(self):
  5376. ops = """
  5377. [i0, i1, i1b, i2, i3]
  5378. i4 = int_lt(i1, 7)
  5379. guard_true(i4) []
  5380. i4b = int_lt(i1b, 7)
  5381. guard_true(i4b) []
  5382. i4c = int_ge(i1b, 0)
  5383. guard_true(i4c) []
  5384. i5 = int_lt(i3, 2)
  5385. guard_true(i5) []
  5386. i6 = int_ge(i3, 0)
  5387. guard_true(i6) []
  5388. i7 = int_lshift(i1, i3)
  5389. i8 = int_le(i7, 14)
  5390. guard_true(i8) []
  5391. i8b = int_lshift(i1, i2)
  5392. i9 = int_le(i8b, 14)
  5393. guard_true(i9) []
  5394. i10 = int_lshift(i0, i3)
  5395. i11 = int_le(i10, 14)
  5396. guard_true(i11) []
  5397. i12 = int_lt(i0, 15)
  5398. guard_true(i12) []
  5399. i13 = int_lshift(i1b, i3)
  5400. i14 = int_le(i13, 14)
  5401. guard_true(i14) []
  5402. i15 = int_lshift(i1b, i2)
  5403. i16 = int_le(i15, 14)
  5404. guard_true(i16) []
  5405. jump(i0, i1, i1b, i2, i3)
  5406. """
  5407. preamble = """
  5408. [i0, i1, i1b, i2, i3]
  5409. i4 = int_lt(i1, 7)
  5410. guard_true(i4) []
  5411. i4b = int_lt(i1b, 7)
  5412. guard_true(i4b) []
  5413. i4c = int_ge(i1b, 0)
  5414. guard_true(i4c) []
  5415. i5 = int_lt(i3, 2)
  5416. guard_true(i5) []
  5417. i6 = int_ge(i3, 0)
  5418. guard_true(i6) []
  5419. i7 = int_lshift(i1, i3)
  5420. i8 = int_le(i7, 14)
  5421. guard_true(i8) []
  5422. i8b = int_lshift(i1, i2)
  5423. i9 = int_le(i8b, 14)
  5424. guard_true(i9) []
  5425. i10 = int_lshift(i0, i3)
  5426. i11 = int_le(i10, 14)
  5427. guard_true(i11) []
  5428. i13 = int_lshift(i1b, i3)
  5429. i15 = int_lshift(i1b, i2)
  5430. i16 = int_le(i15, 14)
  5431. guard_true(i16) []
  5432. jump(i0, i1, i1b, i2, i3)
  5433. """
  5434. expected = """
  5435. [i0, i1, i1b, i2, i3]
  5436. jump(i0, i1, i1b, i2, i3)
  5437. """
  5438. self.optimize_loop(ops, expected, preamble)
  5439. def test_bound_rshift(self):
  5440. ops = """
  5441. [i0, i1, i1b, i2, i3]
  5442. i4 = int_lt(i1, 7)
  5443. guard_true(i4) []
  5444. i4b = int_lt(i1b, 7)
  5445. guard_true(i4b) []
  5446. i4c = int_ge(i1b, 0)
  5447. guard_true(i4c) []
  5448. i5 = int_lt(i3, 2)
  5449. guard_true(i5) []
  5450. i6 = int_ge(i3, 0)
  5451. guard_true(i6) []
  5452. i7 = int_rshift(i1, i3)
  5453. i8 = int_le(i7, 14)
  5454. guard_true(i8) []
  5455. i8b = int_rshift(i1, i2)
  5456. i9 = int_le(i8b, 14)
  5457. guard_true(i9) []
  5458. i10 = int_rshift(i0, i3)
  5459. i11 = int_le(i10, 14)
  5460. guard_true(i11) []
  5461. i12 = int_lt(i0, 25)
  5462. guard_true(i12) []
  5463. i13 = int_rshift(i1b, i3)
  5464. i14 = int_le(i13, 14)
  5465. guard_true(i14) []
  5466. i15 = int_rshift(i1b, i2)
  5467. i16 = int_le(i15, 14)
  5468. guard_true(i16) []
  5469. jump(i0, i1, i1b, i2, i3)
  5470. """
  5471. preamble = """
  5472. [i0, i1, i1b, i2, i3]
  5473. i4 = int_lt(i1, 7)
  5474. guard_true(i4) []
  5475. i4b = int_lt(i1b, 7)
  5476. guard_true(i4b) []
  5477. i4c = int_ge(i1b, 0)
  5478. guard_true(i4c) []
  5479. i5 = int_lt(i3, 2)
  5480. guard_true(i5) []
  5481. i6 = int_ge(i3, 0)
  5482. guard_true(i6) []
  5483. i7 = int_rshift(i1, i3)
  5484. i8b = int_rshift(i1, i2)
  5485. i9 = int_le(i8b, 14)
  5486. guard_true(i9) []
  5487. i10 = int_rshift(i0, i3)
  5488. i11 = int_le(i10, 14)
  5489. guard_true(i11) []
  5490. i12 = int_lt(i0, 25)
  5491. guard_true(i12) []
  5492. i13 = int_rshift(i1b, i3)
  5493. i15 = int_rshift(i1b, i2)
  5494. i16 = int_le(i15, 14)
  5495. guard_true(i16) []
  5496. jump(i0, i1, i1b, i2, i3)
  5497. """
  5498. expected = """
  5499. [i0, i1, i1b, i2, i3]
  5500. jump(i0, i1, i1b, i2, i3)
  5501. """
  5502. self.optimize_loop(ops, expected, preamble)
  5503. def test_bound_dont_backpropagate_rshift(self):
  5504. ops = """
  5505. [i0]
  5506. i3 = int_rshift(i0, 1)
  5507. i5 = int_eq(i3, 1)
  5508. guard_true(i5) []
  5509. i11 = int_add(i0, 1)
  5510. jump(i11)
  5511. """
  5512. self.optimize_loop(ops, ops, ops)
  5513. def test_bound_backpropagate_int_signext(self):
  5514. ops = """
  5515. []
  5516. i0 = escape_i()
  5517. i1 = int_signext(i0, 1)
  5518. i2 = int_eq(i0, i1)
  5519. guard_true(i2) []
  5520. i3 = int_le(i0, 127) # implied by equality with int_signext
  5521. guard_true(i3) []
  5522. i5 = int_gt(i0, -129) # implied by equality with int_signext
  5523. guard_true(i5) []
  5524. jump()
  5525. """
  5526. expected = """
  5527. []
  5528. i0 = escape_i()
  5529. i1 = int_signext(i0, 1)
  5530. i2 = int_eq(i0, i1)
  5531. guard_true(i2) []
  5532. jump()
  5533. """
  5534. self.optimize_loop(ops, expected)
  5535. def test_bound_backpropagate_int_signext_2(self):
  5536. ops = """
  5537. []
  5538. i0 = escape_i()
  5539. i1 = int_signext(i0, 1)
  5540. i2 = int_eq(i0, i1)
  5541. guard_true(i2) []
  5542. i3 = int_le(i0, 126) # false for i1 == 127
  5543. guard_true(i3) []
  5544. i5 = int_gt(i0, -128) # false for i1 == -128
  5545. guard_true(i5) []
  5546. jump()
  5547. """
  5548. self.optimize_loop(ops, ops)
  5549. def test_mul_ovf(self):
  5550. ops = """
  5551. [i0, i1]
  5552. i2 = int_and(i0, 255)
  5553. i3 = int_lt(i1, 5)
  5554. guard_true(i3) []
  5555. i4 = int_gt(i1, -10)
  5556. guard_true(i4) []
  5557. i5 = int_mul_ovf(i2, i1)
  5558. guard_no_overflow() []
  5559. i6 = int_lt(i5, -2550)
  5560. guard_false(i6) []
  5561. i7 = int_ge(i5, 1276)
  5562. guard_false(i7) []
  5563. i8 = int_gt(i5, 126)
  5564. guard_true(i8) []
  5565. jump(i0, i1)
  5566. """
  5567. preamble = """
  5568. [i0, i1]
  5569. i2 = int_and(i0, 255)
  5570. i3 = int_lt(i1, 5)
  5571. guard_true(i3) []
  5572. i4 = int_gt(i1, -10)
  5573. guard_true(i4) []
  5574. i5 = int_mul(i2, i1)
  5575. i8 = int_gt(i5, 126)
  5576. guard_true(i8) []
  5577. jump(i0, i1)
  5578. """
  5579. expected = """
  5580. [i0, i1]
  5581. jump(i0, i1)
  5582. """
  5583. self.optimize_loop(ops, expected, preamble)
  5584. def test_mul_ovf_before(self):
  5585. ops = """
  5586. [i0, i1]
  5587. i2 = int_and(i0, 255)
  5588. i22 = int_add(i2, 1)
  5589. i3 = int_mul_ovf(i22, i1)
  5590. guard_no_overflow() []
  5591. i4 = int_lt(i3, 10)
  5592. guard_true(i4) []
  5593. i5 = int_gt(i3, 2)
  5594. guard_true(i5) []
  5595. i6 = int_lt(i1, 0)
  5596. guard_false(i6) []
  5597. jump(i0, i1)
  5598. """
  5599. preamble = """
  5600. [i0, i1]
  5601. i2 = int_and(i0, 255)
  5602. i22 = int_add(i2, 1)
  5603. i3 = int_mul_ovf(i22, i1)
  5604. guard_no_overflow() []
  5605. i4 = int_lt(i3, 10)
  5606. guard_true(i4) []
  5607. i5 = int_gt(i3, 2)
  5608. guard_true(i5) []
  5609. jump(i0, i1)
  5610. """
  5611. expected = """
  5612. [i0, i1]
  5613. jump(i0, i1)
  5614. """
  5615. self.optimize_loop(ops, expected, preamble)
  5616. def test_sub_ovf_before(self):
  5617. ops = """
  5618. [i0, i1]
  5619. i2 = int_and(i0, 255)
  5620. i3 = int_sub_ovf(i2, i1)
  5621. guard_no_overflow() []
  5622. i4 = int_le(i3, 10)
  5623. guard_true(i4) []
  5624. i5 = int_ge(i3, 2)
  5625. guard_true(i5) []
  5626. i6 = int_lt(i1, -10)
  5627. guard_false(i6) []
  5628. i7 = int_gt(i1, 253)
  5629. guard_false(i7) []
  5630. jump(i0, i1)
  5631. """
  5632. preamble = """
  5633. [i0, i1]
  5634. i2 = int_and(i0, 255)
  5635. i3 = int_sub_ovf(i2, i1)
  5636. guard_no_overflow() []
  5637. i4 = int_le(i3, 10)
  5638. guard_true(i4) []
  5639. i5 = int_ge(i3, 2)
  5640. guard_true(i5) []
  5641. jump(i0, i1)
  5642. """
  5643. expected = """
  5644. [i0, i1]
  5645. jump(i0, i1)
  5646. """
  5647. self.optimize_loop(ops, expected, preamble)
  5648. def test_invariant_ovf(self):
  5649. ops = """
  5650. [i0, i1, i10, i11, i20, i21]
  5651. i2 = int_add_ovf(i0, i1)
  5652. guard_no_overflow() []
  5653. i3 = int_sub_ovf(i0, i1)
  5654. guard_no_overflow() []
  5655. i4 = int_mul_ovf(i0, i1)
  5656. guard_no_overflow() []
  5657. escape_n(i2)
  5658. escape_n(i3)
  5659. escape_n(i4)
  5660. i24 = int_mul_ovf(i10, i11)
  5661. guard_no_overflow() []
  5662. i23 = int_sub_ovf(i10, i11)
  5663. guard_no_overflow() []
  5664. i22 = int_add_ovf(i10, i11)
  5665. guard_no_overflow() []
  5666. jump(i0, i1, i20, i21, i20, i21)
  5667. """
  5668. expected = """
  5669. [i0, i1, i10, i11, i2, i3, i4]
  5670. escape_n(i2)
  5671. escape_n(i3)
  5672. escape_n(i4)
  5673. i24 = int_mul_ovf(i10, i11)
  5674. guard_no_overflow() []
  5675. i23 = int_sub_ovf(i10, i11)
  5676. guard_no_overflow() []
  5677. i22 = int_add_ovf(i10, i11)
  5678. guard_no_overflow() []
  5679. jump(i0, i1, i10, i11, i2, i3, i4)
  5680. """
  5681. self.optimize_loop(ops, expected)
  5682. def test_value_proven_to_be_constant_after_two_iterations(self):
  5683. ops = """
  5684. [p0, p1, p2, p3, i4, p5, i6, p7, p8, p9, p14]
  5685. guard_value(i4, 3) []
  5686. guard_class(p9, ConstClass(node_vtable)) []
  5687. guard_class(p9, ConstClass(node_vtable)) []
  5688. p22 = getfield_gc_r(p9, descr=inst_w_seq)
  5689. guard_nonnull(p22) []
  5690. i23 = getfield_gc_i(p9, descr=inst_index)
  5691. p24 = getfield_gc_r(p22, descr=inst_w_list)
  5692. guard_isnull(p24) []
  5693. i25 = getfield_gc_i(p22, descr=inst_length)
  5694. i26 = int_ge(i23, i25)
  5695. guard_true(i26) []
  5696. setfield_gc(p9, ConstPtr(myptr), descr=inst_w_seq)
  5697. guard_nonnull(p14) []
  5698. guard_class(p14, 17273920) []
  5699. guard_class(p14, 17273920) []
  5700. p75 = new_with_vtable(descr=nodesize)
  5701. setfield_gc(p75, p14, descr=inst_w_seq)
  5702. setfield_gc(p75, 0, descr=inst_index)
  5703. guard_class(p75, ConstClass(node_vtable)) []
  5704. guard_class(p75, ConstClass(node_vtable)) []
  5705. p79 = getfield_gc_r(p75, descr=inst_w_seq)
  5706. guard_nonnull(p79) []
  5707. i80 = getfield_gc_i(p75, descr=inst_index)
  5708. p81 = getfield_gc_r(p79, descr=inst_w_list)
  5709. guard_isnull(p81) []
  5710. i82 = getfield_gc_i(p79, descr=inst_length)
  5711. i83 = int_ge(i80, i82)
  5712. guard_false(i83) []
  5713. i84 = getfield_gc_i(p79, descr=inst_start)
  5714. i85 = getfield_gc_i(p79, descr=inst_step)
  5715. i86 = int_mul(i80, i85)
  5716. i87 = int_add(i84, i86)
  5717. i91 = int_add(i80, 1)
  5718. setfield_gc(p75, i91, descr=inst_index)
  5719. p110 = same_as_r(ConstPtr(myptr))
  5720. i112 = same_as_i(3)
  5721. i114 = same_as_i(39)
  5722. jump(p0, p1, p110, p3, i112, p5, i114, p7, p8, p75, p14)
  5723. """
  5724. expected = """
  5725. [p0, p1, p3, p5, p7, p8, p14, i82]
  5726. i115 = int_ge(1, i82)
  5727. guard_true(i115) []
  5728. jump(p0, p1, p3, p5, p7, p8, p14, 1)
  5729. """
  5730. self.optimize_loop(ops, expected)
  5731. def test_let_getfield_kill_setfields(self):
  5732. ops = """
  5733. [p0]
  5734. p1 = getfield_gc_r(p0, descr=nextdescr)
  5735. setfield_gc(p0, p1, descr=nextdescr)
  5736. setfield_gc(p0, p1, descr=nextdescr)
  5737. setfield_gc(p0, p0, descr=nextdescr)
  5738. jump(p0)
  5739. """
  5740. preamble = """
  5741. [p0]
  5742. p1 = getfield_gc_r(p0, descr=nextdescr)
  5743. setfield_gc(p0, p0, descr=nextdescr)
  5744. jump(p0)
  5745. """
  5746. expected = """
  5747. [p0]
  5748. p1 = getfield_gc_r(p0, descr=nextdescr) # to be killed by the backend
  5749. setfield_gc(p0, p0, descr=nextdescr)
  5750. jump(p0)
  5751. """
  5752. self.optimize_loop(ops, expected, preamble)
  5753. def test_let_getfield_kill_chained_setfields(self):
  5754. ops = """
  5755. [p0]
  5756. p1 = getfield_gc_r(p0, descr=valuedescr)
  5757. setfield_gc(p0, p0, descr=valuedescr)
  5758. setfield_gc(p0, p1, descr=valuedescr)
  5759. setfield_gc(p0, p1, descr=valuedescr)
  5760. jump(p0)
  5761. """
  5762. preamble = """
  5763. [p0]
  5764. p1 = getfield_gc_r(p0, descr=valuedescr)
  5765. jump(p0)
  5766. """
  5767. expected = """
  5768. [p0]
  5769. jump(p0)
  5770. """
  5771. self.optimize_loop(ops, expected, preamble)
  5772. def test_immutable_not(self):
  5773. ops = """
  5774. []
  5775. p0 = new_with_vtable(descr=noimmut_descr)
  5776. setfield_gc(p0, 42, descr=noimmut_intval)
  5777. escape_n(p0)
  5778. jump()
  5779. """
  5780. self.optimize_loop(ops, ops)
  5781. def test_immutable_variable(self):
  5782. ops = """
  5783. [i0]
  5784. p0 = new_with_vtable(descr=immut_descr)
  5785. setfield_gc(p0, i0, descr=immut_intval)
  5786. escape_n(p0)
  5787. jump(i0)
  5788. """
  5789. self.optimize_loop(ops, ops)
  5790. def test_immutable_incomplete(self):
  5791. ops = """
  5792. []
  5793. p0 = new_with_vtable(descr=immut_descr)
  5794. escape_n(p0)
  5795. jump()
  5796. """
  5797. self.optimize_loop(ops, ops)
  5798. def test_immutable_constantfold(self):
  5799. ops = """
  5800. []
  5801. p0 = new_with_vtable(descr=immut_descr)
  5802. setfield_gc(p0, 1242, descr=immut_intval)
  5803. escape_n(p0)
  5804. jump()
  5805. """
  5806. from rpython.rtyper.lltypesystem import lltype, llmemory
  5807. class IntObj1242(object):
  5808. _TYPE = llmemory.GCREF.TO
  5809. def __eq__(self, other):
  5810. return other.container.intval == 1242
  5811. def _normalizedcontainer(self):
  5812. return self
  5813. self.namespace['intobj1242'] = lltype._ptr(llmemory.GCREF,
  5814. IntObj1242())
  5815. expected = """
  5816. []
  5817. escape_n(ConstPtr(intobj1242))
  5818. jump()
  5819. """
  5820. self.optimize_loop(ops, expected)
  5821. # ----------
  5822. ops = """
  5823. [p1]
  5824. p0 = new_with_vtable(descr=ptrobj_immut_descr)
  5825. setfield_gc(p0, p1, descr=immut_ptrval)
  5826. escape_n(p0)
  5827. jump(p1)
  5828. """
  5829. self.optimize_loop(ops, ops)
  5830. # ----------
  5831. ops = """
  5832. []
  5833. p0 = new_with_vtable(descr=ptrobj_immut_descr)
  5834. p1 = new_with_vtable(descr=immut_descr)
  5835. setfield_gc(p1, 1242, descr=immut_intval)
  5836. setfield_gc(p0, p1, descr=immut_ptrval)
  5837. escape_n(p0)
  5838. jump()
  5839. """
  5840. class PtrObj1242(object):
  5841. _TYPE = llmemory.GCREF.TO
  5842. def __eq__(slf, other):
  5843. if slf is other:
  5844. return 1
  5845. p1 = other.container.ptrval
  5846. p1cast = lltype.cast_pointer(lltype.Ptr(self.INTOBJ_IMMUT), p1)
  5847. return p1cast.intval == 1242
  5848. def _normalizedcontainer(self):
  5849. return self
  5850. self.namespace['ptrobj1242'] = lltype._ptr(llmemory.GCREF,
  5851. PtrObj1242())
  5852. expected = """
  5853. []
  5854. escape_n(ConstPtr(ptrobj1242))
  5855. jump()
  5856. """
  5857. self.optimize_loop(ops, expected)
  5858. def test_bug_unroll_with_immutables(self):
  5859. ops = """
  5860. [p0]
  5861. i2 = getfield_gc_i(p0, descr=immut_intval)
  5862. p1 = new_with_vtable(descr=immut_descr)
  5863. setfield_gc(p1, 1242, descr=immut_intval)
  5864. jump(p1)
  5865. """
  5866. preamble = """
  5867. [p0]
  5868. i2 = getfield_gc_i(p0, descr=immut_intval)
  5869. jump()
  5870. """
  5871. expected = """
  5872. []
  5873. jump()
  5874. """
  5875. self.optimize_loop(ops, expected, preamble, jump_values=
  5876. [self.immutaddr])
  5877. def test_immutable_constantfold_recursive(self):
  5878. ops = """
  5879. []
  5880. p0 = new_with_vtable(descr=ptrobj_immut_descr)
  5881. setfield_gc(p0, p0, descr=immut_ptrval)
  5882. escape_n(p0)
  5883. jump()
  5884. """
  5885. from rpython.rtyper.lltypesystem import lltype, llmemory
  5886. class PtrObjSelf(object):
  5887. _TYPE = llmemory.GCREF.TO
  5888. def __eq__(slf, other):
  5889. if slf is other:
  5890. return 1
  5891. p1 = other.container.ptrval
  5892. p1cast = lltype.cast_pointer(lltype.Ptr(self.PTROBJ_IMMUT), p1)
  5893. return p1cast.ptrval == p1
  5894. def _normalizedcontainer(self):
  5895. return self
  5896. self.namespace['ptrobjself'] = lltype._ptr(llmemory.GCREF,
  5897. PtrObjSelf())
  5898. expected = """
  5899. []
  5900. escape_n(ConstPtr(ptrobjself))
  5901. jump()
  5902. """
  5903. self.optimize_loop(ops, expected)
  5904. #
  5905. ops = """
  5906. []
  5907. p0 = new_with_vtable(descr=ptrobj_immut_descr)
  5908. p1 = new_with_vtable(descr=ptrobj_immut_descr)
  5909. setfield_gc(p0, p1, descr=immut_ptrval)
  5910. setfield_gc(p1, p0, descr=immut_ptrval)
  5911. escape_n(p0)
  5912. jump()
  5913. """
  5914. class PtrObjSelf2(object):
  5915. _TYPE = llmemory.GCREF.TO
  5916. def __eq__(slf, other):
  5917. if slf is other:
  5918. return 1
  5919. p1 = other.container.ptrval
  5920. p1cast = lltype.cast_pointer(lltype.Ptr(self.PTROBJ_IMMUT), p1)
  5921. p2 = p1cast.ptrval
  5922. assert p2 != p1
  5923. p2cast = lltype.cast_pointer(lltype.Ptr(self.PTROBJ_IMMUT), p2)
  5924. return p2cast.ptrval == p1
  5925. def _normalizedcontainer(self):
  5926. return self
  5927. self.namespace['ptrobjself2'] = lltype._ptr(llmemory.GCREF,
  5928. PtrObjSelf2())
  5929. expected = """
  5930. []
  5931. escape_n(ConstPtr(ptrobjself2))
  5932. jump()
  5933. """
  5934. self.optimize_loop(ops, expected)
  5935. # ----------
  5936. def optimize_strunicode_loop(self, ops, optops, preamble):
  5937. # check with the arguments passed in
  5938. self.optimize_loop(ops, optops, preamble)
  5939. # check with replacing 'str' with 'unicode' everywhere
  5940. def r(s):
  5941. return s.replace('str', 'unicode').replace('s"', 'u"')
  5942. self.optimize_loop(r(ops), r(optops), r(preamble))
  5943. def test_newstr_1(self):
  5944. ops = """
  5945. [i0]
  5946. p1 = newstr(1)
  5947. strsetitem(p1, 0, i0)
  5948. i1 = strgetitem(p1, 0)
  5949. jump(i1)
  5950. """
  5951. expected = """
  5952. [i0]
  5953. jump(i0)
  5954. """
  5955. self.optimize_strunicode_loop(ops, expected, expected)
  5956. def test_newstr_2(self):
  5957. ops = """
  5958. [i0, i1]
  5959. p1 = newstr(2)
  5960. strsetitem(p1, 0, i0)
  5961. strsetitem(p1, 1, i1)
  5962. i2 = strgetitem(p1, 1)
  5963. i3 = strgetitem(p1, 0)
  5964. jump(i2, i3)
  5965. """
  5966. expected = """
  5967. [i0, i1]
  5968. jump(i1, i0)
  5969. """
  5970. self.optimize_strunicode_loop(ops, expected, expected)
  5971. def test_newstr_toobig(self):
  5972. ops = """
  5973. [i0]
  5974. p1 = newstr(101)
  5975. strsetitem(p1, 0, i0)
  5976. i3 = strgetitem(p1, 0)
  5977. jump(i3)
  5978. """
  5979. self.optimize_strunicode_loop(ops, ops, ops)
  5980. def test_str_slice_bug(self):
  5981. ops = """
  5982. []
  5983. p1066 = newstr(8)
  5984. escape_n(p1066) # should initialize the string's content
  5985. p1134 = call_pure_r(0, p1066, 0, 4, descr=strslicedescr)
  5986. escape_n(p1134)
  5987. jump()
  5988. """
  5989. expected = """
  5990. []
  5991. p1 = newstr(8)
  5992. escape_n(p1)
  5993. p2 = newstr(4)
  5994. copystrcontent(p1, p2, 0, 0, 4)
  5995. escape_n(p2)
  5996. jump()
  5997. """
  5998. self.optimize_strunicode_loop(ops, expected, expected)
  5999. # XXX Should some of the call's below now be call_pure?
  6000. def test_str_concat_1(self):
  6001. ops = """
  6002. [p1, p2]
  6003. p3 = call_r(0, p1, p2, descr=strconcatdescr)
  6004. jump(p2, p3)
  6005. """
  6006. preamble = """
  6007. [p1, p2]
  6008. i1 = strlen(p1)
  6009. i2 = strlen(p2)
  6010. i3 = int_add(i1, i2)
  6011. p3 = newstr(i3)
  6012. copystrcontent(p1, p3, 0, 0, i1)
  6013. copystrcontent(p2, p3, 0, i1, i2)
  6014. jump(p2, p3, i2)
  6015. """
  6016. expected = """
  6017. [p1, p2, i1]
  6018. i2 = strlen(p2)
  6019. i3 = int_add(i1, i2)
  6020. p3 = newstr(i3)
  6021. copystrcontent(p1, p3, 0, 0, i1)
  6022. copystrcontent(p2, p3, 0, i1, i2)
  6023. jump(p2, p3, i2)
  6024. """
  6025. self.optimize_strunicode_loop(ops, expected, preamble)
  6026. def test_str_concat_vstr2_str(self):
  6027. ops = """
  6028. [i0, i1, p2]
  6029. p1 = newstr(2)
  6030. strsetitem(p1, 0, i0)
  6031. strsetitem(p1, 1, i1)
  6032. p3 = call_r(0, p1, p2, descr=strconcatdescr)
  6033. jump(i1, i0, p3)
  6034. """
  6035. expected = """
  6036. [i0, i1, p2]
  6037. i2 = strlen(p2)
  6038. i3 = int_add(2, i2)
  6039. p3 = newstr(i3)
  6040. strsetitem(p3, 0, i0)
  6041. strsetitem(p3, 1, i1)
  6042. copystrcontent(p2, p3, 0, 2, i2)
  6043. jump(i1, i0, p3)
  6044. """
  6045. self.optimize_strunicode_loop(ops, expected, expected)
  6046. def test_str_concat_str_vstr2(self):
  6047. ops = """
  6048. [i0, i1, p2]
  6049. p1 = newstr(2)
  6050. strsetitem(p1, 0, i0)
  6051. strsetitem(p1, 1, i1)
  6052. p3 = call_r(0, p2, p1, descr=strconcatdescr)
  6053. jump(i1, i0, p3)
  6054. """
  6055. expected = """
  6056. [i0, i1, p2]
  6057. i2 = strlen(p2)
  6058. i3 = int_add(i2, 2)
  6059. p3 = newstr(i3)
  6060. copystrcontent(p2, p3, 0, 0, i2)
  6061. strsetitem(p3, i2, i0)
  6062. i5 = int_add(i2, 1)
  6063. strsetitem(p3, i5, i1)
  6064. i6 = int_add(i5, 1) # will be killed by the backend
  6065. jump(i1, i0, p3)
  6066. """
  6067. self.optimize_strunicode_loop(ops, expected, expected)
  6068. def test_str_concat_str_str_str(self):
  6069. ops = """
  6070. [p1, p2, p3]
  6071. p4 = call_r(0, p1, p2, descr=strconcatdescr)
  6072. p5 = call_r(0, p4, p3, descr=strconcatdescr)
  6073. jump(p2, p3, p5)
  6074. """
  6075. preamble = """
  6076. [p1, p2, p3]
  6077. i1 = strlen(p1)
  6078. i2 = strlen(p2)
  6079. i12 = int_add(i1, i2)
  6080. i3 = strlen(p3)
  6081. i123 = int_add(i12, i3)
  6082. p5 = newstr(i123)
  6083. copystrcontent(p1, p5, 0, 0, i1)
  6084. copystrcontent(p2, p5, 0, i1, i2)
  6085. copystrcontent(p3, p5, 0, i12, i3)
  6086. jump(p2, p3, p5, i2, i3)
  6087. """
  6088. expected = """
  6089. [p1, p2, p3, i1, i2]
  6090. i12 = int_add(i1, i2)
  6091. i3 = strlen(p3)
  6092. i123 = int_add(i12, i3)
  6093. p5 = newstr(i123)
  6094. copystrcontent(p1, p5, 0, 0, i1)
  6095. copystrcontent(p2, p5, 0, i1, i2)
  6096. copystrcontent(p3, p5, 0, i12, i3)
  6097. jump(p2, p3, p5, i2, i3)
  6098. """
  6099. self.optimize_strunicode_loop(ops, expected, preamble)
  6100. def test_str_concat_str_cstr1(self):
  6101. ops = """
  6102. [p2]
  6103. p3 = call_r(0, p2, s"x", descr=strconcatdescr)
  6104. jump(p3)
  6105. """
  6106. expected = """
  6107. [p2]
  6108. i2 = strlen(p2)
  6109. i3 = int_add(i2, 1)
  6110. p3 = newstr(i3)
  6111. copystrcontent(p2, p3, 0, 0, i2)
  6112. strsetitem(p3, i2, 120) # == ord('x')
  6113. jump(p3)
  6114. """
  6115. self.optimize_strunicode_loop(ops, expected, expected)
  6116. def test_str_concat_consts(self):
  6117. ops = """
  6118. []
  6119. p1 = same_as_r(s"ab")
  6120. p2 = same_as_r(s"cde")
  6121. p3 = call_r(0, p1, p2, descr=strconcatdescr)
  6122. escape_n(p3)
  6123. jump()
  6124. """
  6125. expected = """
  6126. []
  6127. escape_n(s"abcde")
  6128. jump()
  6129. """
  6130. self.optimize_strunicode_loop(ops, expected, expected)
  6131. def test_str_concat_optimize_fully_initialized(self):
  6132. ops = """
  6133. [i0, i1]
  6134. p1 = newstr(2)
  6135. strsetitem(p1, 0, i0)
  6136. strsetitem(p1, 1, i1)
  6137. escape_n(p1)
  6138. p3 = call_pure_r(0, p1, p1, descr=strconcatdescr)
  6139. escape_n(p3)
  6140. jump(i0, i1)
  6141. """
  6142. expected = """
  6143. [i0, i1]
  6144. p1 = newstr(2)
  6145. strsetitem(p1, 0, i0)
  6146. strsetitem(p1, 1, i1)
  6147. escape_n(p1)
  6148. p3 = newstr(4)
  6149. strsetitem(p3, 0, i0)
  6150. strsetitem(p3, 1, i1)
  6151. strsetitem(p3, 2, i0)
  6152. strsetitem(p3, 3, i1)
  6153. escape_n(p3)
  6154. jump(i0, i1)
  6155. """
  6156. self.optimize_strunicode_loop(ops, expected, expected)
  6157. def test_str_concat_cant_optimize_partialy_uninitialized(self):
  6158. ops = """
  6159. [i0]
  6160. p1 = newstr(2)
  6161. strsetitem(p1, 0, i0) # p1[1] is set by the escape below
  6162. escape_n(p1)
  6163. p3 = call_pure_r(0, p1, p1, descr=strconcatdescr)
  6164. escape_n(p3)
  6165. jump(i0)
  6166. """
  6167. expected = """
  6168. [i0]
  6169. p1 = newstr(2)
  6170. strsetitem(p1, 0, i0)
  6171. escape_n(p1)
  6172. p3 = newstr(4)
  6173. strsetitem(p3, 0, i0)
  6174. i1 = strgetitem(p1, 1)
  6175. strsetitem(p3, 1, i1)
  6176. strsetitem(p3, 2, i0)
  6177. strsetitem(p3, 3, i1)
  6178. escape_n(p3)
  6179. jump(i0)
  6180. """
  6181. self.optimize_strunicode_loop(ops, expected, expected)
  6182. def test_str_slice_len_surviving1(self):
  6183. ops = """
  6184. [p1, i1, i2, i3]
  6185. escape_n(i3)
  6186. p2 = call_r(0, p1, i1, i2, descr=strslicedescr)
  6187. i4 = strlen(p2)
  6188. jump(p1, i1, i2, i4)
  6189. """
  6190. preamble = """
  6191. [p1, i1, i2, i3]
  6192. escape_n(i3)
  6193. i4 = int_sub(i2, i1)
  6194. i5 = same_as_i(i4)
  6195. jump(p1, i1, i2, i4, i5)
  6196. """
  6197. expected = """
  6198. [p1, i1, i2, i3, i5]
  6199. escape_n(i3)
  6200. jump(p1, i1, i2, i5, i5)
  6201. """
  6202. self.optimize_strunicode_loop(ops, expected, preamble)
  6203. def test_str_slice_len_surviving2(self):
  6204. ops = """
  6205. [p1, i1, i2, p2]
  6206. i5 = getfield_gc_i(p2, descr=valuedescr)
  6207. escape_n(i5)
  6208. p3 = call_r(0, p1, i1, i2, descr=strslicedescr)
  6209. i4 = strlen(p3)
  6210. setfield_gc(p2, i4, descr=valuedescr)
  6211. jump(p1, i1, i2, p2)
  6212. """
  6213. preamble = """
  6214. [p1, i1, i2, p2]
  6215. i5 = getfield_gc_i(p2, descr=valuedescr)
  6216. escape_n(i5)
  6217. i4 = int_sub(i2, i1)
  6218. setfield_gc(p2, i4, descr=valuedescr)
  6219. i8 = same_as_i(i4)
  6220. jump(p1, i1, i2, p2, i8, i4)
  6221. """
  6222. expected = """
  6223. [p1, i1, i2, p2, i5, i6]
  6224. escape_n(i5)
  6225. setfield_gc(p2, i6, descr=valuedescr)
  6226. jump(p1, i1, i2, p2, i6, i6)
  6227. """
  6228. self.optimize_strunicode_loop(ops, expected, preamble)
  6229. def test_str_slice_1(self):
  6230. ops = """
  6231. [p1, i1, i2]
  6232. p2 = call_r(0, p1, i1, i2, descr=strslicedescr)
  6233. jump(p2, i1, i2)
  6234. """
  6235. preamble = """
  6236. [p1, i1, i2]
  6237. i3 = int_sub(i2, i1)
  6238. p2 = newstr(i3)
  6239. copystrcontent(p1, p2, i1, 0, i3)
  6240. jump(p2, i1, i2, i3)
  6241. """
  6242. expected = """
  6243. [p1, i1, i2, i3]
  6244. p2 = newstr(i3)
  6245. copystrcontent(p1, p2, i1, 0, i3)
  6246. jump(p2, i1, i2, i3)
  6247. """
  6248. self.optimize_strunicode_loop(ops, expected, preamble)
  6249. def test_str_slice_2(self):
  6250. ops = """
  6251. [p1, i2]
  6252. p2 = call_r(0, p1, 0, i2, descr=strslicedescr)
  6253. jump(p2, i2)
  6254. """
  6255. expected = """
  6256. [p1, i2]
  6257. p2 = newstr(i2)
  6258. copystrcontent(p1, p2, 0, 0, i2)
  6259. jump(p2, i2)
  6260. """
  6261. self.optimize_strunicode_loop(ops, expected, expected)
  6262. def test_str_slice_3(self):
  6263. ops = """
  6264. [p1, i1, i2, i3, i4]
  6265. p2 = call_r(0, p1, i1, i2, descr=strslicedescr)
  6266. p3 = call_r(0, p2, i3, i4, descr=strslicedescr)
  6267. jump(p3, i1, i2, i3, i4)
  6268. """
  6269. preamble = """
  6270. [p1, i1, i2, i3, i4]
  6271. i0 = int_sub(i2, i1) # killed by the backend
  6272. i5 = int_sub(i4, i3)
  6273. i6 = int_add(i1, i3)
  6274. p3 = newstr(i5)
  6275. copystrcontent(p1, p3, i6, 0, i5)
  6276. jump(p3, i1, i2, i3, i4, i5, i6)
  6277. """
  6278. expected = """
  6279. [p1, i1, i2, i3, i4, i5, i6]
  6280. p3 = newstr(i5)
  6281. copystrcontent(p1, p3, i6, 0, i5)
  6282. jump(p3, i1, i2, i3, i4, i5, i6)
  6283. """
  6284. self.optimize_strunicode_loop(ops, expected, preamble)
  6285. def test_str_slice_getitem1(self):
  6286. ops = """
  6287. [p1, i1, i2, i3]
  6288. p2 = call_r(0, p1, i1, i2, descr=strslicedescr)
  6289. i4 = strgetitem(p2, i3)
  6290. escape_n(i4)
  6291. jump(p1, i1, i2, i3)
  6292. """
  6293. preamble = """
  6294. [p1, i1, i2, i3]
  6295. i6 = int_sub(i2, i1) # killed by the backend
  6296. i5 = int_add(i1, i3)
  6297. i4 = strgetitem(p1, i5)
  6298. escape_n(i4)
  6299. jump(p1, i1, i2, i3, i4)
  6300. """
  6301. expected = """
  6302. [p1, i1, i2, i3, i4]
  6303. escape_n(i4)
  6304. jump(p1, i1, i2, i3, i4)
  6305. """
  6306. self.optimize_strunicode_loop(ops, expected, preamble)
  6307. def test_str_slice_plain(self):
  6308. ops = """
  6309. [i3, i4]
  6310. p1 = newstr(2)
  6311. strsetitem(p1, 0, i3)
  6312. strsetitem(p1, 1, i4)
  6313. p2 = call_r(0, p1, 1, 2, descr=strslicedescr)
  6314. i5 = strgetitem(p2, 0)
  6315. escape_n(i5)
  6316. jump(i3, i4)
  6317. """
  6318. expected = """
  6319. [i3, i4]
  6320. escape_n(i4)
  6321. jump(i3, i4)
  6322. """
  6323. self.optimize_strunicode_loop(ops, expected, expected)
  6324. def test_str_slice_concat(self):
  6325. ops = """
  6326. [p1, i1, i2, p2]
  6327. p3 = call_r(0, p1, i1, i2, descr=strslicedescr)
  6328. p4 = call_r(0, p3, p2, descr=strconcatdescr)
  6329. jump(p4, i1, i2, p2)
  6330. """
  6331. preamble = """
  6332. [p1, i1, i2, p2]
  6333. i3 = int_sub(i2, i1) # length of p3
  6334. i4 = strlen(p2)
  6335. i5 = int_add(i3, i4)
  6336. p4 = newstr(i5)
  6337. copystrcontent(p1, p4, i1, 0, i3)
  6338. copystrcontent(p2, p4, 0, i3, i4)
  6339. jump(p4, i1, i2, p2, i5, i3, i4)
  6340. """
  6341. expected = """
  6342. [p1, i1, i2, p2, i5, i3, i4]
  6343. p4 = newstr(i5)
  6344. copystrcontent(p1, p4, i1, 0, i3)
  6345. copystrcontent(p2, p4, 0, i3, i4)
  6346. jump(p4, i1, i2, p2, i5, i3, i4)
  6347. """
  6348. self.optimize_strunicode_loop(ops, expected, preamble)
  6349. def test_strgetitem_bounds(self):
  6350. ops = """
  6351. [p0, i0]
  6352. i1 = strgetitem(p0, i0)
  6353. i10 = strgetitem(p0, i0)
  6354. i2 = int_lt(i1, 256)
  6355. guard_true(i2) []
  6356. i3 = int_ge(i1, 0)
  6357. guard_true(i3) []
  6358. jump(p0, i0)
  6359. """
  6360. expected = """
  6361. [p0, i0]
  6362. jump(p0, i0)
  6363. """
  6364. self.optimize_loop(ops, expected)
  6365. def test_unicodegetitem_bounds(self):
  6366. ops = """
  6367. [p0, i0]
  6368. i1 = unicodegetitem(p0, i0)
  6369. i10 = unicodegetitem(p0, i0)
  6370. i2 = int_lt(i1, 0)
  6371. guard_false(i2) []
  6372. jump(p0, i0)
  6373. """
  6374. expected = """
  6375. [p0, i0]
  6376. jump(p0, i0)
  6377. """
  6378. self.optimize_loop(ops, expected)
  6379. def test_strlen_positive(self):
  6380. ops = """
  6381. [p0]
  6382. i0 = strlen(p0)
  6383. i1 = int_ge(i0, 0)
  6384. guard_true(i1) []
  6385. i2 = int_gt(i0, -1)
  6386. guard_true(i2) []
  6387. jump(p0)
  6388. """
  6389. expected = """
  6390. [p0]
  6391. jump(p0)
  6392. """
  6393. self.optimize_loop(ops, expected)
  6394. def test_strlen_repeated(self):
  6395. ops = """
  6396. [p0]
  6397. i0 = strlen(p0)
  6398. i1 = strlen(p0)
  6399. i2 = int_eq(i0, i1)
  6400. guard_true(i2) []
  6401. jump(p0)
  6402. """
  6403. expected = """
  6404. [p0]
  6405. jump(p0)
  6406. """
  6407. self.optimize_loop(ops, expected)
  6408. # ----------
  6409. def optimize_strunicode_loop_extradescrs(self, ops, optops, preamble):
  6410. self.optimize_strunicode_loop(ops, optops, preamble)
  6411. def test_str_equal_noop1(self):
  6412. ops = """
  6413. [p1, p2]
  6414. i0 = call_i(0, p1, p2, descr=strequaldescr)
  6415. escape_n(i0)
  6416. jump(p1, p2)
  6417. """
  6418. self.optimize_strunicode_loop_extradescrs(ops, ops, ops)
  6419. def test_str_equal_noop2(self):
  6420. ops = """
  6421. [p1, p2, p3]
  6422. p4 = call_r(0, p1, p2, descr=strconcatdescr)
  6423. i0 = call_i(0, p3, p4, descr=strequaldescr)
  6424. escape_n(i0)
  6425. jump(p1, p2, p3)
  6426. """
  6427. preamble = """
  6428. [p1, p2, p3]
  6429. i1 = strlen(p1)
  6430. i2 = strlen(p2)
  6431. i3 = int_add(i1, i2)
  6432. p4 = newstr(i3)
  6433. copystrcontent(p1, p4, 0, 0, i1)
  6434. copystrcontent(p2, p4, 0, i1, i2)
  6435. i0 = call_i(0, p3, p4, descr=strequaldescr)
  6436. escape_n(i0)
  6437. jump(p1, p2, p3, i3, i1, i2)
  6438. """
  6439. expected = """
  6440. [p1, p2, p3, i3, i1, i2]
  6441. p4 = newstr(i3)
  6442. copystrcontent(p1, p4, 0, 0, i1)
  6443. copystrcontent(p2, p4, 0, i1, i2)
  6444. i0 = call_i(0, p3, p4, descr=strequaldescr)
  6445. escape_n(i0)
  6446. jump(p1, p2, p3, i3, i1, i2)
  6447. """
  6448. self.optimize_strunicode_loop_extradescrs(ops, expected,
  6449. preamble)
  6450. def test_str_equal_slice1(self):
  6451. ops = """
  6452. [p1, i1, i2, p3]
  6453. p4 = call_r(0, p1, i1, i2, descr=strslicedescr)
  6454. i0 = call_i(0, p4, p3, descr=strequaldescr)
  6455. escape_n(i0)
  6456. jump(p1, i1, i2, p3)
  6457. """
  6458. preamble = """
  6459. [p1, i1, i2, p3]
  6460. i3 = int_sub(i2, i1)
  6461. i0 = call_i(0, p1, i1, i3, p3, descr=streq_slice_checknull_descr)
  6462. escape_n(i0)
  6463. jump(p1, i1, i2, p3, i3)
  6464. """
  6465. expected = """
  6466. [p1, i1, i2, p3, i3]
  6467. i0 = call_i(0, p1, i1, i3, p3, descr=streq_slice_checknull_descr)
  6468. escape_n(i0)
  6469. jump(p1, i1, i2, p3, i3)
  6470. """
  6471. self.optimize_strunicode_loop_extradescrs(ops, expected,
  6472. preamble)
  6473. def test_str_equal_slice2(self):
  6474. ops = """
  6475. [p1, i1, i2, p3]
  6476. p4 = call_r(0, p1, i1, i2, descr=strslicedescr)
  6477. i0 = call_i(0, p3, p4, descr=strequaldescr)
  6478. escape_n(i0)
  6479. jump(p1, i1, i2, p3)
  6480. """
  6481. preamble = """
  6482. [p1, i1, i2, p3]
  6483. i4 = int_sub(i2, i1)
  6484. i0 = call_i(0, p1, i1, i4, p3, descr=streq_slice_checknull_descr)
  6485. escape_n(i0)
  6486. jump(p1, i1, i2, p3, i4)
  6487. """
  6488. expected = """
  6489. [p1, i1, i2, p3, i4]
  6490. i0 = call_i(0, p1, i1, i4, p3, descr=streq_slice_checknull_descr)
  6491. escape_n(i0)
  6492. jump(p1, i1, i2, p3, i4)
  6493. """
  6494. self.optimize_strunicode_loop_extradescrs(ops, expected,
  6495. preamble)
  6496. def test_str_equal_slice3(self):
  6497. ops = """
  6498. [p1, i1, i2, p3]
  6499. guard_nonnull(p3) []
  6500. p4 = call_r(0, p1, i1, i2, descr=strslicedescr)
  6501. i0 = call_i(0, p3, p4, descr=strequaldescr)
  6502. escape_n(i0)
  6503. jump(p1, i1, i2, p3)
  6504. """
  6505. expected = """
  6506. [p1, i1, i2, p3, i4]
  6507. i0 = call_i(0, p1, i1, i4, p3, descr=streq_slice_nonnull_descr)
  6508. escape_n(i0)
  6509. jump(p1, i1, i2, p3, i4)
  6510. """
  6511. preamble = """
  6512. [p1, i1, i2, p3]
  6513. guard_nonnull(p3) []
  6514. i4 = int_sub(i2, i1)
  6515. i0 = call_i(0, p1, i1, i4, p3, descr=streq_slice_nonnull_descr)
  6516. escape_n(i0)
  6517. jump(p1, i1, i2, p3, i4)
  6518. """
  6519. self.optimize_strunicode_loop_extradescrs(ops,
  6520. expected, preamble)
  6521. def test_str_equal_slice4(self):
  6522. ops = """
  6523. [p1, i1, i2]
  6524. p3 = call_r(0, p1, i1, i2, descr=strslicedescr)
  6525. i0 = call_i(0, p3, s"x", descr=strequaldescr)
  6526. escape_n(i0)
  6527. jump(p1, i1, i2)
  6528. """
  6529. preamble = """
  6530. [p1, i1, i2]
  6531. i3 = int_sub(i2, i1)
  6532. i0 = call_i(0, p1, i1, i3, 120, descr=streq_slice_char_descr)
  6533. escape_n(i0)
  6534. jump(p1, i1, i2, i3)
  6535. """
  6536. expected = """
  6537. [p1, i1, i2, i3]
  6538. i0 = call_i(0, p1, i1, i3, 120, descr=streq_slice_char_descr)
  6539. escape_n(i0)
  6540. jump(p1, i1, i2, i3)
  6541. """
  6542. self.optimize_strunicode_loop_extradescrs(ops, expected,
  6543. preamble)
  6544. def test_str_equal_slice5(self):
  6545. ops = """
  6546. [p1, i1, i2, i3]
  6547. p4 = call_r(0, p1, i1, i2, descr=strslicedescr)
  6548. p5 = newstr(1)
  6549. strsetitem(p5, 0, i3)
  6550. i0 = call_i(0, p5, p4, descr=strequaldescr)
  6551. escape_n(i0)
  6552. jump(p1, i1, i2, i3)
  6553. """
  6554. preamble = """
  6555. [p1, i1, i2, i3]
  6556. i4 = int_sub(i2, i1)
  6557. i0 = call_i(0, p1, i1, i4, i3, descr=streq_slice_char_descr)
  6558. escape_n(i0)
  6559. jump(p1, i1, i2, i3, i4)
  6560. """
  6561. expected = """
  6562. [p1, i1, i2, i3, i4]
  6563. i0 = call_i(0, p1, i1, i4, i3, descr=streq_slice_char_descr)
  6564. escape_n(i0)
  6565. jump(p1, i1, i2, i3, i4)
  6566. """
  6567. self.optimize_strunicode_loop_extradescrs(ops, expected,
  6568. preamble)
  6569. def test_str_equal_none1(self):
  6570. ops = """
  6571. [p1]
  6572. i0 = call_i(0, p1, NULL, descr=strequaldescr)
  6573. escape_n(i0)
  6574. jump(p1)
  6575. """
  6576. preamble = """
  6577. [p1]
  6578. i0 = ptr_eq(p1, NULL)
  6579. escape_n(i0)
  6580. jump(p1, i0)
  6581. """
  6582. expected = """
  6583. [p1, i0]
  6584. escape_n(i0)
  6585. jump(p1, i0)
  6586. """
  6587. self.optimize_strunicode_loop_extradescrs(ops, expected, preamble)
  6588. def test_str_equal_none2(self):
  6589. ops = """
  6590. [p1]
  6591. i0 = call_i(0, NULL, p1, descr=strequaldescr)
  6592. escape_n(i0)
  6593. jump(p1)
  6594. """
  6595. preamble = """
  6596. [p1]
  6597. i0 = ptr_eq(p1, NULL)
  6598. escape_n(i0)
  6599. jump(p1, i0)
  6600. """
  6601. expected = """
  6602. [p1, i0]
  6603. escape_n(i0)
  6604. jump(p1, i0)
  6605. """
  6606. self.optimize_strunicode_loop_extradescrs(ops, expected, preamble)
  6607. def test_str_equal_nonnull1(self):
  6608. ops = """
  6609. [p1]
  6610. guard_nonnull(p1) []
  6611. i0 = call_i(0, p1, s"hello world", descr=strequaldescr)
  6612. escape_n(i0)
  6613. jump(p1)
  6614. """
  6615. expected = """
  6616. [p1]
  6617. i0 = call_i(0, p1, s"hello world", descr=streq_nonnull_descr)
  6618. escape_n(i0)
  6619. jump(p1)
  6620. """
  6621. preamble = """
  6622. [p1]
  6623. guard_nonnull(p1) []
  6624. i0 = call_i(0, p1, s"hello world", descr=streq_nonnull_descr)
  6625. escape_n(i0)
  6626. jump(p1)
  6627. """
  6628. self.optimize_strunicode_loop_extradescrs(ops, expected, preamble)
  6629. def test_str_equal_nonnull2(self):
  6630. ops = """
  6631. [p1]
  6632. guard_nonnull(p1) []
  6633. i0 = call_i(0, p1, s"", descr=strequaldescr)
  6634. escape_n(i0)
  6635. jump(p1)
  6636. """
  6637. expected = """
  6638. [p1, i0]
  6639. escape_n(i0)
  6640. jump(p1, i0)
  6641. """
  6642. preamble = """
  6643. [p1]
  6644. guard_nonnull(p1) []
  6645. i1 = strlen(p1)
  6646. i0 = int_eq(i1, 0)
  6647. escape_n(i0)
  6648. jump(p1, i0)
  6649. """
  6650. self.optimize_strunicode_loop_extradescrs(ops, expected, preamble)
  6651. def test_str_equal_nonnull3(self):
  6652. ops = """
  6653. [p1]
  6654. guard_nonnull(p1) []
  6655. i0 = call_i(0, p1, s"x", descr=strequaldescr)
  6656. escape_n(i0)
  6657. jump(p1)
  6658. """
  6659. expected = """
  6660. [p1]
  6661. i0 = call_i(0, p1, 120, descr=streq_nonnull_char_descr)
  6662. escape_n(i0)
  6663. jump(p1)
  6664. """
  6665. preamble = """
  6666. [p1]
  6667. guard_nonnull(p1) []
  6668. i0 = call_i(0, p1, 120, descr=streq_nonnull_char_descr)
  6669. escape_n(i0)
  6670. jump(p1)
  6671. """
  6672. self.optimize_strunicode_loop_extradescrs(ops, expected, preamble)
  6673. def test_str_equal_nonnull4(self):
  6674. ops = """
  6675. [p1, p2]
  6676. p4 = call_r(0, p1, p2, descr=strconcatdescr)
  6677. i0 = call_i(0, s"hello world", p4, descr=strequaldescr)
  6678. escape_n(i0)
  6679. jump(p1, p2)
  6680. """
  6681. preamble = """
  6682. [p1, p2]
  6683. i1 = strlen(p1)
  6684. i2 = strlen(p2)
  6685. i3 = int_add(i1, i2)
  6686. p4 = newstr(i3)
  6687. copystrcontent(p1, p4, 0, 0, i1)
  6688. copystrcontent(p2, p4, 0, i1, i2)
  6689. i0 = call_i(0, s"hello world", p4, descr=streq_nonnull_descr)
  6690. escape_n(i0)
  6691. jump(p1, p2, i3, i1, i2)
  6692. """
  6693. expected = """
  6694. [p1, p2, i3, i1, i2]
  6695. p4 = newstr(i3)
  6696. copystrcontent(p1, p4, 0, 0, i1)
  6697. copystrcontent(p2, p4, 0, i1, i2)
  6698. i0 = call_i(0, s"hello world", p4, descr=streq_nonnull_descr)
  6699. escape_n(i0)
  6700. jump(p1, p2, i3, i1, i2)
  6701. """
  6702. self.optimize_strunicode_loop_extradescrs(ops, expected, preamble)
  6703. def test_str_equal_chars0(self):
  6704. ops = """
  6705. [i1]
  6706. p1 = newstr(0)
  6707. i0 = call_i(0, p1, s"", descr=strequaldescr)
  6708. escape_n(i0)
  6709. jump(i1)
  6710. """
  6711. expected = """
  6712. [i1]
  6713. escape_n(1)
  6714. jump(i1)
  6715. """
  6716. self.optimize_strunicode_loop_extradescrs(ops, expected, expected)
  6717. def test_str_equal_chars1(self):
  6718. ops = """
  6719. [i1]
  6720. p1 = newstr(1)
  6721. strsetitem(p1, 0, i1)
  6722. i0 = call_i(0, p1, s"x", descr=strequaldescr)
  6723. escape_n(i0)
  6724. jump(i1)
  6725. """
  6726. preamble = """
  6727. [i1]
  6728. i0 = int_eq(i1, 120) # ord('x')
  6729. escape_n(i0)
  6730. jump(i1, i0)
  6731. """
  6732. expected = """
  6733. [i1, i0]
  6734. escape_n(i0)
  6735. jump(i1, i0)
  6736. """
  6737. self.optimize_strunicode_loop_extradescrs(ops, expected, preamble)
  6738. def test_str_equal_nonconst(self):
  6739. ops = """
  6740. [i1, i2]
  6741. p1 = newstr(1)
  6742. strsetitem(p1, 0, i1)
  6743. p2 = newstr(1)
  6744. strsetitem(p2, 0, i2)
  6745. i0 = call_i(0, p1, p2, descr=strequaldescr)
  6746. escape_n(i0)
  6747. jump(i1, i2)
  6748. """
  6749. preamble = """
  6750. [i1, i2]
  6751. i0 = int_eq(i1, i2)
  6752. escape_n(i0)
  6753. jump(i1, i2, i0)
  6754. """
  6755. expected = """
  6756. [i1, i2, i0]
  6757. escape_n(i0)
  6758. jump(i1, i2, i0)
  6759. """
  6760. self.optimize_strunicode_loop_extradescrs(ops, expected, preamble)
  6761. def test_str_equal_chars2(self):
  6762. ops = """
  6763. [i1, i2]
  6764. p1 = newstr(2)
  6765. strsetitem(p1, 0, i1)
  6766. strsetitem(p1, 1, i2)
  6767. i0 = call_i(0, p1, s"xy", descr=strequaldescr)
  6768. escape_n(i0)
  6769. jump(i1, i2)
  6770. """
  6771. expected = """
  6772. [i1, i2]
  6773. p1 = newstr(2)
  6774. strsetitem(p1, 0, i1)
  6775. strsetitem(p1, 1, i2)
  6776. i0 = call_i(0, p1, s"xy", descr=streq_lengthok_descr)
  6777. escape_n(i0)
  6778. jump(i1, i2)
  6779. """
  6780. self.optimize_strunicode_loop_extradescrs(ops, expected, expected)
  6781. def test_str_equal_chars3(self):
  6782. ops = """
  6783. [p1]
  6784. i0 = call_i(0, s"x", p1, descr=strequaldescr)
  6785. escape_n(i0)
  6786. jump(p1)
  6787. """
  6788. expected = """
  6789. [p1]
  6790. i0 = call_i(0, p1, 120, descr=streq_checknull_char_descr)
  6791. escape_n(i0)
  6792. jump(p1)
  6793. """
  6794. self.optimize_strunicode_loop_extradescrs(ops, expected, expected)
  6795. def test_str_equal_lengthmismatch1(self):
  6796. ops = """
  6797. [i1]
  6798. p1 = newstr(1)
  6799. strsetitem(p1, 0, i1)
  6800. i0 = call_i(0, s"xy", p1, descr=strequaldescr)
  6801. escape_n(i0)
  6802. jump(i1)
  6803. """
  6804. expected = """
  6805. [i1]
  6806. escape_n(0)
  6807. jump(i1)
  6808. """
  6809. self.optimize_strunicode_loop_extradescrs(ops, expected, expected)
  6810. def test_str2unicode_constant(self):
  6811. ops = """
  6812. []
  6813. escape_n(1213)
  6814. p0 = call_r(0, "xy", descr=s2u_descr) # string -> unicode
  6815. guard_no_exception() []
  6816. escape_n(p0)
  6817. jump()
  6818. """
  6819. expected = """
  6820. []
  6821. escape_n(1213)
  6822. escape_n(u"xy")
  6823. jump()
  6824. """
  6825. self.optimize_strunicode_loop_extradescrs(ops, expected, expected)
  6826. def test_str2unicode_nonconstant(self):
  6827. ops = """
  6828. [p0]
  6829. p1 = call_r(0, p0, descr=s2u_descr) # string -> unicode
  6830. guard_no_exception() []
  6831. escape_n(p1)
  6832. jump(p1)
  6833. """
  6834. self.optimize_strunicode_loop_extradescrs(ops, ops, ops)
  6835. # more generally, supporting non-constant but virtual cases is
  6836. # not obvious, because of the exception UnicodeDecodeError that
  6837. # can be raised by ll_str2unicode()
  6838. def test_record_exact_class(self):
  6839. ops = """
  6840. [p0]
  6841. p1 = getfield_gc_r(p0, descr=nextdescr)
  6842. record_exact_class(p1, ConstClass(node_vtable))
  6843. guard_class(p1, ConstClass(node_vtable)) []
  6844. jump(p1)
  6845. """
  6846. expected = """
  6847. [p0]
  6848. p1 = getfield_gc_r(p0, descr=nextdescr)
  6849. jump(p1)
  6850. """
  6851. self.optimize_loop(ops, expected)
  6852. def test_quasi_immut(self):
  6853. ops = """
  6854. [p0, p1, i0]
  6855. quasiimmut_field(p0, descr=quasiimmutdescr)
  6856. guard_not_invalidated() []
  6857. i1 = getfield_gc_i(p0, descr=quasifielddescr)
  6858. escape_n(i1)
  6859. jump(p1, p0, i1)
  6860. """
  6861. expected = """
  6862. [p0, p1, i0]
  6863. i1 = getfield_gc_i(p0, descr=quasifielddescr)
  6864. escape_n(i1)
  6865. jump(p1, p0, i1)
  6866. """
  6867. self.optimize_loop(ops, expected)
  6868. def test_quasi_immut_2(self):
  6869. ops = """
  6870. []
  6871. quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr)
  6872. guard_not_invalidated() []
  6873. i1 = getfield_gc_i(ConstPtr(quasiptr), descr=quasifielddescr)
  6874. escape_n(i1)
  6875. jump()
  6876. """
  6877. expected = """
  6878. []
  6879. guard_not_invalidated() []
  6880. escape_n(-4247)
  6881. jump()
  6882. """
  6883. self.optimize_loop(ops, expected, expected)
  6884. def test_remove_extra_guards_not_invalidated(self):
  6885. ops = """
  6886. [i0]
  6887. guard_not_invalidated() []
  6888. guard_not_invalidated() []
  6889. i1 = int_add(i0, 1)
  6890. guard_not_invalidated() []
  6891. guard_not_invalidated() []
  6892. jump(i1)
  6893. """
  6894. expected = """
  6895. [i0]
  6896. guard_not_invalidated() []
  6897. i1 = int_add(i0, 1)
  6898. jump(i1)
  6899. """
  6900. self.optimize_loop(ops, expected)
  6901. def test_call_may_force_invalidated_guards(self):
  6902. ops = """
  6903. [i0]
  6904. guard_not_invalidated() []
  6905. call_may_force_n(i0, descr=mayforcevirtdescr)
  6906. guard_not_invalidated() []
  6907. jump(i0)
  6908. """
  6909. expected = """
  6910. [i0]
  6911. guard_not_invalidated() []
  6912. call_may_force_n(i0, descr=mayforcevirtdescr)
  6913. guard_not_invalidated() []
  6914. jump(i0)
  6915. """
  6916. self.optimize_loop(ops, expected)
  6917. def test_call_may_force_invalidated_guards_reload(self):
  6918. ops = """
  6919. [i0a, i0b]
  6920. quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr)
  6921. guard_not_invalidated() []
  6922. i1 = getfield_gc_i(ConstPtr(quasiptr), descr=quasifielddescr)
  6923. call_may_force_n(i0b, descr=mayforcevirtdescr)
  6924. quasiimmut_field(ConstPtr(quasiptr), descr=quasiimmutdescr)
  6925. guard_not_invalidated() []
  6926. i2 = getfield_gc_i(ConstPtr(quasiptr), descr=quasifielddescr)
  6927. i3 = escape_i(i1)
  6928. i4 = escape_i(i2)
  6929. jump(i3, i4)
  6930. """
  6931. expected = """
  6932. [i0a, i0b]
  6933. guard_not_invalidated() []
  6934. call_may_force_n(i0b, descr=mayforcevirtdescr)
  6935. guard_not_invalidated() []
  6936. i3 = escape_i(-4247)
  6937. i4 = escape_i(-4247)
  6938. jump(i3, i4)
  6939. """
  6940. self.optimize_loop(ops, expected)
  6941. def test_call_may_force_invalidated_guards_virtual(self):
  6942. ops = """
  6943. [i0a, i0b]
  6944. p = new(descr=quasisize)
  6945. setfield_gc(p, 421, descr=quasifielddescr)
  6946. quasiimmut_field(p, descr=quasiimmutdescr)
  6947. guard_not_invalidated() []
  6948. i1 = getfield_gc_i(p, descr=quasifielddescr)
  6949. call_may_force_n(i0b, descr=mayforcevirtdescr)
  6950. quasiimmut_field(p, descr=quasiimmutdescr)
  6951. guard_not_invalidated() []
  6952. i2 = getfield_gc_i(p, descr=quasifielddescr)
  6953. i3 = escape_i(i1)
  6954. i4 = escape_i(i2)
  6955. jump(i3, i4)
  6956. """
  6957. expected = """
  6958. [i0a, i0b]
  6959. call_may_force_n(i0b, descr=mayforcevirtdescr)
  6960. i3 = escape_i(421)
  6961. i4 = escape_i(421)
  6962. jump(i3, i4)
  6963. """
  6964. self.optimize_loop(ops, expected)
  6965. def test_constant_getfield1(self):
  6966. ops = """
  6967. [p1, p187, i184]
  6968. p188 = getarrayitem_gc_r(p187, 42, descr=gcarraydescr)
  6969. guard_value(p188, ConstPtr(myptr)) []
  6970. p25 = getfield_gc_r(ConstPtr(myptr), descr=otherdescr)
  6971. jump(p25, p187, i184)
  6972. """
  6973. preamble = """
  6974. [p1, p187, i184]
  6975. p188 = getarrayitem_gc_r(p187, 42, descr=gcarraydescr)
  6976. guard_value(p188, ConstPtr(myptr)) []
  6977. p25 = getfield_gc_r(ConstPtr(myptr), descr=otherdescr)
  6978. p5 = same_as_r(p25)
  6979. jump(p25, p187, i184, p5)
  6980. """
  6981. short = """
  6982. [p1, p187, i184]
  6983. guard_nonnull(p187) []
  6984. guard_gc_type(p187, ConstInt(gcarraydescr_tid)) []
  6985. i10 = arraylen_gc(p187, descr=gcarraydescr)
  6986. i11 = int_ge(i10, 43)
  6987. guard_true(i11) []
  6988. p188 = getarrayitem_gc_r(p187, 42, descr=gcarraydescr)
  6989. guard_value(p188, ConstPtr(myptr)) []
  6990. p25 = getfield_gc_r(ConstPtr(myptr), descr=otherdescr)
  6991. jump(p25)
  6992. """
  6993. expected = """
  6994. [p25, p187, i184, p189]
  6995. ifoo = arraylen_gc(p187, descr=gcarraydescr) # killed by backend
  6996. jump(p189, p187, i184, p189)
  6997. """
  6998. self.optimize_loop(ops, expected, preamble, expected_short=short)
  6999. def test_constant_getfield1bis(self):
  7000. ops = """
  7001. [p1, p187, i184]
  7002. p188 = getarrayitem_gc_r(p187, 42, descr=gcarraydescr)
  7003. guard_value(p188, ConstPtr(myptr)) []
  7004. p25 = getfield_gc_r(ConstPtr(myptr), descr=otherdescr)
  7005. p26 = call_r(p25, descr=nonwritedescr)
  7006. jump(p26, p187, i184)
  7007. """
  7008. expected = """
  7009. [p24, p187, i184, p25]
  7010. p26 = call_r(p25, descr=nonwritedescr)
  7011. ifoo = arraylen_gc(p187, descr=gcarraydescr) # killed
  7012. jump(p26, p187, i184, p25)
  7013. """
  7014. self.optimize_loop(ops, expected)
  7015. def test_constant_getfield2(self):
  7016. ops = """
  7017. [p19]
  7018. p22 = getfield_gc_r(p19, descr=otherdescr)
  7019. guard_value(p19, ConstPtr(myptr)) []
  7020. jump(p19)
  7021. """
  7022. expected = """
  7023. []
  7024. jump()
  7025. """
  7026. self.optimize_loop(ops, expected)
  7027. def test_constant_getfield3(self):
  7028. ops = """
  7029. [p19, p20, p21]
  7030. p22 = getfield_gc_r(p19, descr=otherdescr)
  7031. guard_value(p19, ConstPtr(myptr)) []
  7032. p23 = getfield_gc_r(ConstPtr(myptr), descr=otherdescr)
  7033. jump(p20, p21, p21)
  7034. """
  7035. expected = """
  7036. [p20, p21]
  7037. p22 = getfield_gc_r(p20, descr=otherdescr)
  7038. guard_value(p20, ConstPtr(myptr)) []
  7039. jump(p21, p21)
  7040. """
  7041. self.optimize_loop(ops, expected)
  7042. def test_constant_getfield4(self):
  7043. ops = """
  7044. [p19, p20, p21]
  7045. p22 = getfield_gc_r(p19, descr=otherdescr)
  7046. p23 = getfield_gc_r(ConstPtr(myptr), descr=otherdescr)
  7047. guard_value(p19, ConstPtr(myptr)) []
  7048. jump(p20, p21, p21)
  7049. """
  7050. expected = """
  7051. [p20, p21]
  7052. p22 = getfield_gc_r(p20, descr=otherdescr)
  7053. guard_value(p20, ConstPtr(myptr)) []
  7054. jump(p21, p21)
  7055. """
  7056. self.optimize_loop(ops, expected)
  7057. def test_constnats_among_virtual_fileds(self):
  7058. ops = """
  7059. [p19, p20, p21]
  7060. p1 = getfield_gc_r(p20, descr=valuedescr)
  7061. p2 = getfield_gc_r(p1, descr=otherdescr)
  7062. pv = new_with_vtable(descr=nodesize)
  7063. setfield_gc(pv, p19, descr=valuedescr)
  7064. p22 = getfield_gc_r(p19, descr=otherdescr)
  7065. guard_value(p19, ConstPtr(myptr)) []
  7066. p23 = getfield_gc_r(ConstPtr(myptr), descr=otherdescr)
  7067. jump(p21, pv, p21)
  7068. """
  7069. expected = """
  7070. [p20]
  7071. p22 = getfield_gc_r(p20, descr=otherdescr)
  7072. guard_value(p20, ConstPtr(myptr)) []
  7073. jump(ConstPtr(myptr))
  7074. """
  7075. self.optimize_loop(ops, expected)
  7076. def test_dont_cache_setfields(self):
  7077. # Naivly caching the last two getfields here would specialize
  7078. # the loop to the state where the first two getfields return
  7079. # the same value. That state would need to be guarded for
  7080. # in the short preamble. Instead we make sure to keep the
  7081. # results of the two getfields as separate boxes.
  7082. ops = """
  7083. [p0, p1, ii, ii2]
  7084. i1 = getfield_gc_i(p0, descr=valuedescr)
  7085. i2 = getfield_gc_i(p1, descr=chardescr)
  7086. i3 = int_add(i1, i2)
  7087. setfield_gc(p0, ii, descr=valuedescr)
  7088. setfield_gc(p1, ii, descr=chardescr)
  7089. i4 = getfield_gc_i(p0, descr=valuedescr)
  7090. i5 = getfield_gc_i(p1, descr=chardescr)
  7091. jump(p0, p1, ii2, ii)
  7092. """
  7093. preamble = """
  7094. [p0, p1, ii, ii2]
  7095. i1 = getfield_gc_i(p0, descr=valuedescr)
  7096. i2 = getfield_gc_i(p1, descr=chardescr)
  7097. i3 = int_add(i1, i2)
  7098. setfield_gc(p0, ii, descr=valuedescr)
  7099. setfield_gc(p1, ii, descr=chardescr)
  7100. i10 = same_as_i(ii)
  7101. i11 = same_as_i(ii)
  7102. jump(p0, p1, ii2, ii, i10, i11)
  7103. """
  7104. expected = """
  7105. [p0, p1, i1, i2, i7, i8]
  7106. i3 = int_add(i7, i8)
  7107. setfield_gc(p0, i1, descr=valuedescr)
  7108. setfield_gc(p1, i1, descr=chardescr)
  7109. jump(p0, p1, i2, i1, i1, i1)
  7110. """
  7111. self.optimize_loop(ops, expected, preamble)
  7112. def test_dont_specialize_on_boxes_equal(self):
  7113. ops = """
  7114. [p0, p1, p3, ii, ii2]
  7115. i1 = getfield_gc_i(p0, descr=valuedescr)
  7116. i2 = getfield_gc_i(p1, descr=chardescr)
  7117. setfield_gc(p3, i1, descr=adescr)
  7118. setfield_gc(p3, i2, descr=abisdescr)
  7119. i4 = int_eq(i1, i2)
  7120. guard_true(i4) []
  7121. i5 = int_gt(ii, 42)
  7122. guard_true(i5) []
  7123. jump(p0, p1, p3, ii2, ii)
  7124. """
  7125. expected = """
  7126. [p0, p1, p3, ii, ii2, i1, i2]
  7127. setfield_gc(p3, i1, descr=abisdescr)
  7128. setfield_gc(p3, i2, descr=adescr)
  7129. i5 = int_gt(ii, 42)
  7130. guard_true(i5) []
  7131. jump(p0, p1, p3, ii2, ii, i1, i2)
  7132. """
  7133. self.optimize_loop(ops, expected)
  7134. def test_lazy_setfield_forced_by_jump_needing_additionall_inputargs(self):
  7135. ops = """
  7136. [p0, p3]
  7137. i1 = getfield_gc_i(p0, descr=valuedescr)
  7138. setfield_gc(p3, i1, descr=otherdescr)
  7139. jump(p0, p3)
  7140. """
  7141. expected = """
  7142. [p0, p3, i1]
  7143. setfield_gc(p3, i1, descr=otherdescr)
  7144. jump(p0, p3, i1)
  7145. """
  7146. self.optimize_loop(ops, expected)
  7147. def test_guards_before_getfields_in_short_preamble(self):
  7148. ops = """
  7149. [p0]
  7150. guard_nonnull_class(p0, ConstClass(node_vtable)) []
  7151. p1 = getfield_gc_r(p0, descr=nextdescr)
  7152. guard_nonnull_class(p1, ConstClass(node_vtable)) []
  7153. p2 = getfield_gc_r(p1, descr=nextdescr)
  7154. guard_nonnull_class(p2, ConstClass(node_vtable)) []
  7155. jump(p0)
  7156. """
  7157. expected = """
  7158. [p0, p1]
  7159. jump(p0, p1)
  7160. """
  7161. short = """
  7162. [p0]
  7163. guard_nonnull(p0) []
  7164. guard_is_object(p0) []
  7165. guard_class(p0, ConstClass(node_vtable)) []
  7166. p1 = getfield_gc_r(p0, descr=nextdescr)
  7167. guard_nonnull(p1) []
  7168. guard_is_object(p1) []
  7169. guard_class(p1, ConstClass(node_vtable)) []
  7170. p2 = getfield_gc_r(p1, descr=nextdescr)
  7171. guard_nonnull(p2) []
  7172. guard_is_object(p2) []
  7173. guard_class(p2, ConstClass(node_vtable)) []
  7174. jump(p1)
  7175. """
  7176. self.optimize_loop(ops, expected, expected_short=short)
  7177. def test_forced_virtual_pure_getfield(self):
  7178. ops = """
  7179. [p0]
  7180. p1 = getfield_gc_r(p0, descr=valuedescr3)
  7181. jump(p1)
  7182. """
  7183. self.optimize_loop(ops, ops)
  7184. ops = """
  7185. [p0]
  7186. p1 = new_with_vtable(descr=nodesize3)
  7187. setfield_gc(p1, p0, descr=valuedescr3)
  7188. escape_n(p1)
  7189. p2 = getfield_gc_r(p1, descr=valuedescr3)
  7190. escape_n(p2)
  7191. jump(p0)
  7192. """
  7193. expected = """
  7194. [p0]
  7195. p1 = new_with_vtable(descr=nodesize3)
  7196. setfield_gc(p1, p0, descr=valuedescr3)
  7197. escape_n(p1)
  7198. escape_n(p0)
  7199. jump(p0)
  7200. """
  7201. self.optimize_loop(ops, expected)
  7202. def test_setarrayitem_lazy(self):
  7203. ops = """
  7204. [i0, i1]
  7205. p0 = escape_r()
  7206. i2 = escape_i()
  7207. p1 = new_with_vtable(descr=nodesize)
  7208. setarrayitem_gc(p0, 2, p1, descr=arraydescr)
  7209. guard_true(i2) []
  7210. setarrayitem_gc(p0, 2, p0, descr=arraydescr)
  7211. jump(i0, i1)
  7212. """
  7213. expected = """
  7214. [i0, i1]
  7215. p0 = escape_r()
  7216. i2 = escape_i()
  7217. guard_true(i2) [p0]
  7218. setarrayitem_gc(p0, 2, p0, descr=arraydescr)
  7219. jump(i0, i1)
  7220. """
  7221. self.optimize_loop(ops, expected)
  7222. def test_force_virtualizable_virtual(self):
  7223. ops = """
  7224. [i0]
  7225. p1 = new_with_vtable(descr=nodesize)
  7226. cond_call(1, 123, p1, descr=clear_vable)
  7227. jump(i0)
  7228. """
  7229. expected = """
  7230. [i0]
  7231. jump(i0)
  7232. """
  7233. self.optimize_loop(ops, expected)
  7234. def test_setgetfield_counter(self):
  7235. ops = """
  7236. [p1]
  7237. i2 = getfield_gc_i(p1, descr=valuedescr)
  7238. i3 = int_add(i2, 1)
  7239. setfield_gc(p1, i3, descr=valuedescr)
  7240. jump(p1)
  7241. """
  7242. expected = """
  7243. [p1, i1]
  7244. i2 = int_add(i1, 1)
  7245. setfield_gc(p1, i2, descr=valuedescr)
  7246. jump(p1, i2)
  7247. """
  7248. self.optimize_loop(ops, expected)
  7249. def test_loopinvariant_strlen(self):
  7250. ops = """
  7251. [p9]
  7252. i843 = strlen(p9)
  7253. call_n(i843, descr=nonwritedescr)
  7254. jump(p9)
  7255. """
  7256. preamble = """
  7257. [p9]
  7258. i843 = strlen(p9)
  7259. call_n(i843, descr=nonwritedescr)
  7260. jump(p9, i843)
  7261. """
  7262. short = """
  7263. [p9]
  7264. guard_nonnull(p9) []
  7265. i843 = strlen(p9)
  7266. i848 = int_ge(i843, 0)
  7267. guard_true(i848)[]
  7268. jump(i843)
  7269. """
  7270. expected = """
  7271. [p9, i2]
  7272. call_n(i2, descr=nonwritedescr)
  7273. jump(p9, i2)
  7274. """
  7275. self.optimize_loop(ops, expected, preamble, expected_short=short)
  7276. def test_loopinvariant_strlen_with_bound(self):
  7277. ops = """
  7278. [p9]
  7279. i843 = strlen(p9)
  7280. i1 = int_gt(i843, 7)
  7281. guard_true(i1) []
  7282. call_n(i843, descr=nonwritedescr)
  7283. jump(p9)
  7284. """
  7285. expected = """
  7286. [p9, i2]
  7287. call_n(i2, descr=nonwritedescr)
  7288. jump(p9, i2)
  7289. """
  7290. self.optimize_loop(ops, expected)
  7291. def test_loopinvariant_strgetitem(self):
  7292. ops = """
  7293. [p9, i1]
  7294. i843 = strgetitem(p9, i1)
  7295. call_n(i843, descr=nonwritedescr)
  7296. jump(p9, i1)
  7297. """
  7298. expected = """
  7299. [p9, i1, i843]
  7300. call_n(i843, descr=nonwritedescr)
  7301. jump(p9, i1, i843)
  7302. """
  7303. self.optimize_loop(ops, expected)
  7304. def test_loopinvariant_unicodelen(self):
  7305. ops = """
  7306. [p9]
  7307. i843 = unicodelen(p9)
  7308. call_n(i843, descr=nonwritedescr)
  7309. jump(p9)
  7310. """
  7311. expected = """
  7312. [p9, i2]
  7313. call_n(i2, descr=nonwritedescr)
  7314. jump(p9, i2)
  7315. """
  7316. self.optimize_loop(ops, expected)
  7317. def test_loopinvariant_unicodegetitem(self):
  7318. ops = """
  7319. [p9, i1]
  7320. i843 = unicodegetitem(p9, i1)
  7321. call_n(i843, descr=nonwritedescr)
  7322. jump(p9, i1)
  7323. """
  7324. expected = """
  7325. [p9, i1, i843]
  7326. call_n(i843, descr=nonwritedescr)
  7327. jump(p9, i1, i843)
  7328. """
  7329. self.optimize_loop(ops, expected)
  7330. def test_loopinvariant_arraylen(self):
  7331. ops = """
  7332. [p9]
  7333. i843 = arraylen_gc(p9, descr=arraydescr)
  7334. call_n(i843, descr=nonwritedescr)
  7335. jump(p9)
  7336. """
  7337. expected = """
  7338. [p9, i2]
  7339. call_n(i2, descr=nonwritedescr)
  7340. jump(p9, i2)
  7341. """
  7342. self.optimize_loop(ops, expected)
  7343. def test_loopinvariant_getarrayitem(self):
  7344. ops = """
  7345. [p0]
  7346. p1 = getfield_gc_r(p0, descr=nextdescr)
  7347. p2 = getarrayitem_gc_r(p1, 7, descr=gcarraydescr)
  7348. call_n(p2, descr=nonwritedescr)
  7349. jump(p0)
  7350. """
  7351. short = """
  7352. [p0]
  7353. guard_nonnull(p0) []
  7354. guard_is_object(p0) []
  7355. guard_subclass(p0, ConstClass(node_vtable)) []
  7356. p1 = getfield_gc_r(p0, descr=nextdescr)
  7357. guard_nonnull(p1) []
  7358. guard_gc_type(p1, ConstInt(gcarraydescr_tid)) []
  7359. i1 = arraylen_gc(p1, descr=gcarraydescr)
  7360. i2 = int_ge(i1, 8)
  7361. guard_true(i2) []
  7362. p2 = getarrayitem_gc_r(p1, 7, descr=gcarraydescr)
  7363. jump(p1, p2)
  7364. """
  7365. expected = """
  7366. [p0, p1, p2]
  7367. call_n(p2, descr=nonwritedescr)
  7368. i3 = arraylen_gc(p1, descr=gcarraydescr) # Should be killed by backend
  7369. jump(p0, p1, p2)
  7370. """
  7371. self.optimize_loop(ops, expected, expected_short=short)
  7372. def test_duplicated_virtual(self):
  7373. ops = """
  7374. [p1, p2]
  7375. p3 = new_with_vtable(descr=nodesize)
  7376. jump(p3, p3)
  7377. """
  7378. expected = """
  7379. []
  7380. jump()
  7381. """
  7382. self.optimize_loop(ops, expected)
  7383. def test_duplicated_aliased_virtual(self):
  7384. ops = """
  7385. [p1, p2]
  7386. p3 = new_with_vtable(descr=nodesize)
  7387. setfield_gc(p3, p3, descr=nextdescr)
  7388. p4 = getfield_gc_r(p3, descr=nextdescr)
  7389. jump(p3, p4)
  7390. """
  7391. expected = """
  7392. []
  7393. jump()
  7394. """
  7395. self.optimize_loop(ops, expected)
  7396. def test_imported_aliased_virtual_in_failargs(self):
  7397. ops = """
  7398. [p1, p2, i0]
  7399. i2 = int_lt(i0, 10)
  7400. guard_true(i2) [p1, p2]
  7401. p3 = new_with_vtable(descr=nodesize)
  7402. setfield_gc(p3, p3, descr=nextdescr)
  7403. p4 = getfield_gc_r(p3, descr=nextdescr)
  7404. i1 = int_add(i0, 1)
  7405. jump(p3, p4, i1)
  7406. """
  7407. expected = """
  7408. [i0]
  7409. i2 = int_lt(i0, 10)
  7410. guard_true(i2) []
  7411. i1 = int_add(i0, 1)
  7412. jump(i1)
  7413. """
  7414. self.optimize_loop(ops, expected)
  7415. def test_chained_virtuals(self):
  7416. ops = """
  7417. [p0, p1]
  7418. p2 = new_with_vtable(descr=nodesize)
  7419. p3 = new_with_vtable(descr=nodesize)
  7420. setfield_gc(p2, p3, descr=nextdescr)
  7421. jump(p2, p3)
  7422. """
  7423. expected = """
  7424. []
  7425. jump()
  7426. """
  7427. self.optimize_loop(ops, expected)
  7428. def test_arraylen_bound(self):
  7429. ops = """
  7430. [p1, i]
  7431. p2 = getarrayitem_gc_r(p1, 7, descr=arraydescr)
  7432. i1 = arraylen_gc(p1)
  7433. i2 = int_ge(i1, 8)
  7434. guard_true(i2) []
  7435. jump(p2, i2)
  7436. """
  7437. expected = """
  7438. [p1]
  7439. p2 = getarrayitem_gc_r(p1, 7, descr=arraydescr)
  7440. i1 = arraylen_gc(p1)
  7441. jump(p2)
  7442. """
  7443. self.optimize_loop(ops, expected)
  7444. def test_loopinvariant_getarrayitem_gc_pure(self):
  7445. ops = """
  7446. [p9, i1]
  7447. i843 = getarrayitem_gc_pure_i(p9, i1, descr=arrayimmutdescr)
  7448. call_n(i843, descr=nonwritedescr)
  7449. jump(p9, i1)
  7450. """
  7451. expected = """
  7452. [p9, i1, i843]
  7453. call_n(i843, descr=nonwritedescr)
  7454. ifoo = arraylen_gc(p9, descr=arrayimmutdescr)
  7455. jump(p9, i1, i843)
  7456. """
  7457. self.optimize_loop(ops, expected)
  7458. def test_loopinvariant_constant_getarrayitem_pure(self):
  7459. ops = """
  7460. [p0]
  7461. p1 = getfield_gc_r(p0, descr=nextdescr)
  7462. p2 = getarrayitem_gc_r(p1, 7, descr=gcarraydescr)
  7463. call_n(p2, descr=nonwritedescr)
  7464. jump(p0)
  7465. """
  7466. short = """
  7467. [p0]
  7468. guard_nonnull(p0) []
  7469. guard_is_object(p0) []
  7470. guard_subclass(p0, ConstClass(node_vtable)) []
  7471. p1 = getfield_gc_r(p0, descr=nextdescr)
  7472. guard_nonnull(p1) []
  7473. guard_gc_type(p1, ConstInt(gcarraydescr_tid)) []
  7474. i1 = arraylen_gc(p1, descr=gcarraydescr)
  7475. i2 = int_ge(i1, 8)
  7476. guard_true(i2) []
  7477. p2 = getarrayitem_gc_r(p1, 7, descr=gcarraydescr)
  7478. jump(p1, p2)
  7479. """
  7480. expected = """
  7481. [p0, p1, p2]
  7482. call_n(p2, descr=nonwritedescr)
  7483. i3 = arraylen_gc(p1, descr=gcarraydescr) # Should be killed by backend
  7484. jump(p0, p1, p2)
  7485. """
  7486. self.optimize_loop(ops, expected, expected_short=short)
  7487. def test_loopinvariant_constant_strgetitem(self):
  7488. ops = """
  7489. [p0]
  7490. p1 = getfield_gc_r(p0, descr=nextdescr)
  7491. i22 = strgetitem(p1, 7)
  7492. call_n(i22, descr=nonwritedescr)
  7493. jump(p0)
  7494. """
  7495. short = """
  7496. [p0]
  7497. guard_nonnull(p0) []
  7498. guard_is_object(p0) []
  7499. guard_subclass(p0, ConstClass(node_vtable)) []
  7500. p1 = getfield_gc_r(p0, descr=nextdescr)
  7501. guard_nonnull(p1) []
  7502. i1 = strlen(p1)
  7503. i2 = int_ge(i1, 8)
  7504. guard_true(i2) []
  7505. i22 = strgetitem(p1, 7, descr=<GcPtrArrayDescr>)
  7506. i8 = int_ge(i22, 0)
  7507. guard_true(i8) []
  7508. i9 = int_le(i22, 255)
  7509. guard_true(i9) []
  7510. jump(i22, p1)
  7511. """
  7512. expected = """
  7513. [p0, i22, p1]
  7514. call_n(i22, descr=nonwritedescr)
  7515. i3 = strlen(p1) # Should be killed by backend
  7516. jump(p0, i22, p1)
  7517. """
  7518. self.optimize_loop(ops, expected, expected_short=short)
  7519. def test_loopinvariant_constant_unicodegetitem(self):
  7520. ops = """
  7521. [p0]
  7522. p1 = getfield_gc_r(p0, descr=nextdescr)
  7523. i22 = unicodegetitem(p1, 7)
  7524. call_n(i22, descr=nonwritedescr)
  7525. jump(p0)
  7526. """
  7527. short = """
  7528. [p0]
  7529. guard_nonnull(p0) []
  7530. guard_is_object(p0) []
  7531. guard_subclass(p0, ConstClass(node_vtable)) []
  7532. p1 = getfield_gc_r(p0, descr=nextdescr)
  7533. guard_nonnull(p1) []
  7534. i1 = unicodelen(p1)
  7535. i2 = int_ge(i1, 8)
  7536. guard_true(i2) []
  7537. i22 = unicodegetitem(p1, 7, descr=<GcPtrArrayDescr>)
  7538. i8 = int_ge(i22, 0)
  7539. guard_true(i8) []
  7540. jump(i22, p1)
  7541. """
  7542. expected = """
  7543. [p0, i22, p1]
  7544. call_n(i22, descr=nonwritedescr)
  7545. i3 = unicodelen(p1) # Should be killed by backend
  7546. jump(p0, i22, p1)
  7547. """
  7548. self.optimize_loop(ops, expected, expected_short=short)
  7549. def test_propagate_virtual_arraylen(self):
  7550. ops = """
  7551. [p0]
  7552. p404 = new_array(2, descr=arraydescr)
  7553. p403 = new_array(3, descr=arraydescr)
  7554. i405 = arraylen_gc(p404, descr=arraydescr)
  7555. i406 = arraylen_gc(p403, descr=arraydescr)
  7556. i407 = int_add_ovf(i405, i406)
  7557. guard_no_overflow() []
  7558. call_n(i407, descr=nonwritedescr)
  7559. jump(p0)
  7560. """
  7561. expected = """
  7562. [p0]
  7563. call_n(5, descr=nonwritedescr)
  7564. jump(p0)
  7565. """
  7566. self.optimize_loop(ops, expected)
  7567. def test_propagate_virtual_strunicodelen(self):
  7568. ops = """
  7569. [p0]
  7570. p404 = newstr(2)
  7571. p403 = newunicode(3)
  7572. i405 = strlen(p404)
  7573. i406 = unicodelen(p403)
  7574. i407 = int_add_ovf(i405, i406)
  7575. guard_no_overflow() []
  7576. call_n(i407, descr=nonwritedescr)
  7577. jump(p0)
  7578. """
  7579. expected = """
  7580. [p0]
  7581. call_n(5, descr=nonwritedescr)
  7582. jump(p0)
  7583. """
  7584. self.optimize_loop(ops, expected)
  7585. def test_keep_getfields_and_inputargs_separate(self):
  7586. ops = """
  7587. [p0]
  7588. call_n(p0, descr=nonwritedescr)
  7589. p1 = getfield_gc_r(ConstPtr(myptr), descr=nextdescr)
  7590. call_n(p1, descr=writeadescr)
  7591. jump(p1)
  7592. """
  7593. expected = """
  7594. [p0, p1]
  7595. call_n(p0, descr=nonwritedescr)
  7596. call_n(p1, descr=writeadescr)
  7597. jump(p1, p1)
  7598. """
  7599. self.optimize_loop(ops, expected)
  7600. def test_value_guard_arraylen_reused(self):
  7601. ops = """
  7602. [p0, p1]
  7603. p10 = getfield_gc_r(p0, descr=nextdescr)
  7604. p11 = getfield_gc_r(p1, descr=nextdescr)
  7605. i1 = arraylen_gc(p10, descr=arraydescr)
  7606. i13 = getarrayitem_gc_i(p11, 1, descr=arraydescr)
  7607. call_n(i1, descr=nonwritedescr)
  7608. jump(p1, p0)
  7609. """
  7610. expected = """
  7611. [p0, p1, p10, p11]
  7612. i1 = arraylen_gc(p10, descr=arraydescr)
  7613. i13 = getarrayitem_gc_i(p11, 1, descr=arraydescr)
  7614. call_n(i1, descr=nonwritedescr)
  7615. jump(p1, p0, p11, p10)
  7616. """
  7617. self.optimize_loop(ops, expected)
  7618. def test_cache_constant_setfield(self):
  7619. ops = """
  7620. [p5]
  7621. i10 = getfield_gc_i(p5, descr=valuedescr)
  7622. call_n(i10, descr=nonwritedescr)
  7623. setfield_gc(p5, 1, descr=valuedescr)
  7624. jump(p5)
  7625. """
  7626. preamble = """
  7627. [p5]
  7628. i10 = getfield_gc_i(p5, descr=valuedescr)
  7629. call_n(i10, descr=nonwritedescr)
  7630. setfield_gc(p5, 1, descr=valuedescr)
  7631. jump(p5)
  7632. """
  7633. short = """
  7634. [p0]
  7635. guard_nonnull(p0) []
  7636. guard_is_object(p0) []
  7637. guard_subclass(p0, ConstClass(node_vtable)) []
  7638. i0 = getfield_gc_i(p0, descr=valuedescr)
  7639. guard_value(i0, 1) []
  7640. jump()
  7641. """
  7642. expected = """
  7643. [p5]
  7644. call_n(1, descr=nonwritedescr)
  7645. jump(p5)
  7646. """
  7647. self.optimize_loop(ops, expected, preamble, expected_short=short)
  7648. def test_dont_mixup_equal_boxes(self):
  7649. ops = """
  7650. [p8]
  7651. i9 = getfield_gc_i(p8, descr=valuedescr3)
  7652. i10 = int_gt(i9, 0)
  7653. guard_true(i10) []
  7654. i29 = int_lshift(i9, 1)
  7655. i30 = int_rshift(i29, 1)
  7656. i40 = int_ne(i30, i9)
  7657. guard_false(i40) []
  7658. jump(p8)
  7659. """
  7660. expected = """
  7661. [p8]
  7662. jump(p8)
  7663. """
  7664. self.optimize_loop(ops, expected)
  7665. def test_specialized_to_cached_constant_guard(self):
  7666. ops = """
  7667. [p9]
  7668. i16 = getfield_gc_i(p9, descr=valuedescr)
  7669. i17 = int_is_true(i16)
  7670. guard_false(i17) []
  7671. call_assembler_n(i17, descr=asmdescr)
  7672. i18 = getfield_gc_i(p9, descr=valuedescr)
  7673. guard_value(i18, 0) []
  7674. jump(p9)
  7675. """
  7676. expected = """
  7677. [p9]
  7678. call_assembler_n(0, descr=asmdescr)
  7679. i18 = getfield_gc_i(p9, descr=valuedescr)
  7680. guard_value(i18, 0) []
  7681. jump(p9)
  7682. """
  7683. self.optimize_loop(ops, expected)
  7684. def test_specialized_to_cached_constant_setfield(self):
  7685. ops = """
  7686. [p9]
  7687. i16 = getfield_gc_i(p9, descr=valuedescr)
  7688. i17 = int_is_true(i16)
  7689. guard_false(i17) []
  7690. call_assembler_n(i17, descr=asmdescr)
  7691. i18 = setfield_gc(p9, 0, descr=valuedescr)
  7692. jump(p9)
  7693. """
  7694. expected = """
  7695. [p9]
  7696. call_assembler_n(0, descr=asmdescr)
  7697. i18 = setfield_gc(p9, 0, descr=valuedescr)
  7698. jump(p9)
  7699. """
  7700. self.optimize_loop(ops, expected)
  7701. def test_cached_equal_fields(self):
  7702. ops = """
  7703. [p5, p6]
  7704. i10 = getfield_gc_i(p5, descr=valuedescr)
  7705. i11 = getfield_gc_i(p6, descr=chardescr)
  7706. call_n(i10, i11, descr=nonwritedescr)
  7707. setfield_gc(p6, i10, descr=chardescr)
  7708. jump(p5, p6)
  7709. """
  7710. expected = """
  7711. [p5, p6, i10, i11]
  7712. call_n(i10, i11, descr=nonwritedescr)
  7713. setfield_gc(p6, i10, descr=chardescr)
  7714. jump(p5, p6, i10, i10)
  7715. """
  7716. self.optimize_loop(ops, expected)
  7717. def test_cached_pure_func_of_equal_fields(self):
  7718. ops = """
  7719. [p5, p6]
  7720. i10 = getfield_gc_i(p5, descr=valuedescr)
  7721. i11 = getfield_gc_i(p6, descr=chardescr)
  7722. i12 = int_add(i10, 7)
  7723. i13 = int_add(i11, 7)
  7724. call_n(i12, i13, descr=nonwritedescr)
  7725. setfield_gc(p6, i10, descr=chardescr)
  7726. jump(p5, p6)
  7727. """
  7728. expected = """
  7729. [p5, p6, i14, i12]
  7730. i13 = int_add(i14, 7)
  7731. call_n(i13, i12, descr=nonwritedescr)
  7732. setfield_gc(p6, i14, descr=chardescr)
  7733. jump(p5, p6, i14, i13)
  7734. """
  7735. self.optimize_loop(ops, expected)
  7736. def test_forced_counter(self):
  7737. # XXX: VIRTUALHEAP (see above)
  7738. py.test.skip("would be fixed by make heap optimizer aware of virtual setfields")
  7739. ops = """
  7740. [p5, p8]
  7741. i9 = getfield_gc_i(p5, descr=valuedescr)
  7742. call_n(i9, descr=nonwritedescr)
  7743. i11 = getfield_gc_i(p8, descr=valuedescr)
  7744. i13 = int_add_ovf(i11, 1)
  7745. guard_no_overflow() []
  7746. p22 = new_with_vtable(descr=nodesize)
  7747. setfield_gc(p22, i13, descr=valuedescr)
  7748. setfield_gc(ConstPtr(myptr), p22, descr=adescr)
  7749. jump(p22, p22)
  7750. """
  7751. expected = """
  7752. [p8, i9]
  7753. call_n(i9, descr=nonwritedescr)
  7754. i13 = int_add_ovf(i9, 1)
  7755. guard_no_overflow() []
  7756. p22 = new_with_vtable(descr=nodesize)
  7757. setfield_gc(p22, i13, descr=valuedescr)
  7758. setfield_gc(ConstPtr(myptr), p22, descr=adescr)
  7759. jump(p22, i13)
  7760. """
  7761. self.optimize_loop(ops, expected)
  7762. def test_constptr_samebox_getfield_setfield(self):
  7763. ops = """
  7764. [p0]
  7765. p10 = getfield_gc_r(ConstPtr(myptr), descr=valuedescr)
  7766. call_n(p10, descr=nonwritedescr)
  7767. setfield_gc(ConstPtr(myptr), p10, descr=valuedescr)
  7768. jump(p0)
  7769. """
  7770. expected = """
  7771. [p0, p10]
  7772. call_n(p10, descr=nonwritedescr)
  7773. jump(p0, p10)
  7774. """
  7775. self.optimize_loop(ops, expected)
  7776. def test_constptr_constptr_getfield_setfield(self):
  7777. ops = """
  7778. [p0]
  7779. p10 = getfield_gc_r(ConstPtr(myptr), descr=otherdescr)
  7780. guard_value(p10, ConstPtr(myptrb)) []
  7781. call_n(p10, descr=nonwritedescr)
  7782. setfield_gc(ConstPtr(myptr), ConstPtr(myptrb), descr=otherdescr)
  7783. jump(p0)
  7784. """
  7785. expected = """
  7786. [p0]
  7787. call_n(ConstPtr(myptrb), descr=nonwritedescr)
  7788. jump(p0)
  7789. """
  7790. self.optimize_loop(ops, expected)
  7791. def test_box_samebox_getfield_setfield(self):
  7792. ops = """
  7793. [p0]
  7794. p10 = getfield_gc_r(p0, descr=valuedescr)
  7795. call_n(p10, descr=nonwritedescr)
  7796. setfield_gc(p0, p10, descr=valuedescr)
  7797. jump(p0)
  7798. """
  7799. expected = """
  7800. [p0, p10]
  7801. call_n(p10, descr=nonwritedescr)
  7802. jump(p0, p10)
  7803. """
  7804. self.optimize_loop(ops, expected)
  7805. def test_box_constptr_getfield_setfield(self):
  7806. ops = """
  7807. [p0]
  7808. p10 = getfield_gc_r(p0, descr=otherdescr)
  7809. guard_value(p10, ConstPtr(myptrb)) []
  7810. call_n(p10, descr=nonwritedescr)
  7811. setfield_gc(p0, ConstPtr(myptrb), descr=otherdescr)
  7812. jump(p0)
  7813. """
  7814. expected = """
  7815. [p0]
  7816. call_n(ConstPtr(myptrb), descr=nonwritedescr)
  7817. jump(p0)
  7818. """
  7819. self.optimize_loop(ops, expected)
  7820. def test_import_constants_when_folding_pure_operations(self):
  7821. ops = """
  7822. [p0]
  7823. f1 = getfield_gc_f(p0, descr=floatdescr)
  7824. f2 = float_abs(f1)
  7825. call_n(7.0, descr=nonwritedescr)
  7826. setfield_gc(p0, -7.0, descr=floatdescr)
  7827. jump(p0)
  7828. """
  7829. expected = """
  7830. [p0]
  7831. call_n(7.0, descr=nonwritedescr)
  7832. jump(p0)
  7833. """
  7834. self.optimize_loop(ops, expected)
  7835. def test_exploding_duplication(self):
  7836. py.test.skip("maybe we want to revisit this guy, but in the new model"
  7837. " it fails for same_as reasons")
  7838. ops = """
  7839. [i1, i2]
  7840. i3 = int_add(i1, i1)
  7841. i4 = int_add(i3, i3)
  7842. i5 = int_add(i4, i4)
  7843. i6 = int_add(i5, i5)
  7844. call_n(i6, descr=nonwritedescr)
  7845. jump(i1, i3)
  7846. """
  7847. expected = """
  7848. [i1, i2, i3, i4]
  7849. call_n(i3, descr=nonwritedescr)
  7850. jump(i1, i2, i3, i4)
  7851. """
  7852. short = """
  7853. [i1, i2]
  7854. i3 = int_add(i1, i1)
  7855. i4 = int_add(i3, i3)
  7856. i5 = int_add(i4, i4)
  7857. i6 = int_add(i5, i5)
  7858. jump(i6, i3)
  7859. """
  7860. self.optimize_loop(ops, expected, expected_short=short)
  7861. def test_prioritize_getfield1(self):
  7862. py.test.skip("we no longer do it, and while unfortunate I don't think it's that relevant")
  7863. ops = """
  7864. [p1, p2]
  7865. i1 = getfield_gc_i(p1, descr=valuedescr)
  7866. setfield_gc(p2, i1, descr=nextdescr)
  7867. i2 = int_neg(i1)
  7868. call_n(i2, descr=nonwritedescr)
  7869. jump(p1, p2)
  7870. """
  7871. expected = """
  7872. [p1, p2, i2, i1]
  7873. call_n(i2, descr=nonwritedescr)
  7874. setfield_gc(p2, i1, descr=nextdescr)
  7875. jump(p1, p2, i2, i1)
  7876. """
  7877. self.optimize_loop(ops, expected)
  7878. def test_prioritize_getfield2(self):
  7879. # Same as previous, but with descrs intercahnged which means
  7880. # that the getfield is discovered first when looking for
  7881. # potential short boxes during tests
  7882. ops = """
  7883. [p1, p2]
  7884. i1 = getfield_gc_i(p1, descr=nextdescr)
  7885. setfield_gc(p2, i1, descr=valuedescr)
  7886. i2 = int_neg(i1)
  7887. call_n(i2, descr=nonwritedescr)
  7888. jump(p1, p2)
  7889. """
  7890. expected = """
  7891. [p1, p2, i2, i1]
  7892. call_n(i2, descr=nonwritedescr)
  7893. setfield_gc(p2, i1, descr=valuedescr)
  7894. jump(p1, p2, i2, i1)
  7895. """
  7896. self.optimize_loop(ops, expected)
  7897. def test_heap_cache_forced_virtuals(self):
  7898. ops = """
  7899. [i1, i2, p0]
  7900. p1 = new(descr=ssize)
  7901. setfield_gc(p1, i1, descr=adescr)
  7902. setfield_gc(p1, i2, descr=bdescr)
  7903. call_n(p0, p1, descr=writeadescr)
  7904. i3 = getfield_gc_i(p1, descr=adescr)
  7905. i4 = getfield_gc_i(p1, descr=bdescr)
  7906. jump(i3, i4, p0)
  7907. """
  7908. expected = """
  7909. [i1, i2, p0]
  7910. p1 = new(descr=ssize)
  7911. setfield_gc(p1, i1, descr=adescr)
  7912. call_n(p0, p1, descr=writeadescr)
  7913. i3 = getfield_gc_i(p1, descr=adescr)
  7914. setfield_gc(p1, i2, descr=bdescr)
  7915. jump(i3, i2, p0)
  7916. """
  7917. self.optimize_loop(ops, expected)
  7918. def test_setarrayitem_followed_by_arraycopy(self):
  7919. ops = """
  7920. [p1, p2]
  7921. setarrayitem_gc(p1, 2, 10, descr=arraydescr)
  7922. setarrayitem_gc(p2, 3, 13, descr=arraydescr)
  7923. call_n(0, p1, p2, 0, 0, 10, descr=arraycopydescr)
  7924. jump(p1, p2)
  7925. """
  7926. self.optimize_loop(ops, ops)
  7927. def test_setarrayitem_followed_by_arraycopy_2(self):
  7928. ops = """
  7929. [i1, i2]
  7930. p1 = new_array(i1, descr=arraydescr)
  7931. setarrayitem_gc(p1, 0, i2, descr=arraydescr)
  7932. p3 = new_array(5, descr=arraydescr)
  7933. call_n(0, p1, p3, 0, 1, 1, descr=arraycopydescr)
  7934. i4 = getarrayitem_gc_i(p3, 1, descr=arraydescr)
  7935. jump(i1, i4)
  7936. """
  7937. expected = """
  7938. [i1, i2]
  7939. # operations are not all removed because this new_array() is var-sized
  7940. p1 = new_array(i1, descr=arraydescr)
  7941. setarrayitem_gc(p1, 0, i2, descr=arraydescr)
  7942. jump(i1, i2)
  7943. """
  7944. self.optimize_loop(ops, expected)
  7945. def test_heap_cache_virtuals_forced_by_delayed_setfield(self):
  7946. py.test.skip('not yet supoprted')
  7947. ops = """
  7948. [i1, p0]
  7949. p1 = new(descr=ssize)
  7950. setfield_gc(p1, i1, descr=valuedescr)
  7951. setfield_gc(p0, p1, descr=adescr)
  7952. call_n(p0, descr=writeadescr)
  7953. i2 = getfield_gc_i(p1, descr=valuedescr)
  7954. jump(i2, p0)
  7955. """
  7956. expected = """
  7957. [i1, p0]
  7958. p1 = new(descr=ssize)
  7959. setfield_gc(p1, i1, descr=valuedescr)
  7960. setfield_gc(p0, p1, descr=adescr)
  7961. call_n(p0, descr=writeadescr)
  7962. jump(i1, p0)
  7963. """
  7964. self.optimize_loop(ops, expected)
  7965. def test_repeated_constant_setfield_mixed_with_guard(self):
  7966. ops = """
  7967. [p22, p18]
  7968. setfield_gc(p22, 2, descr=valuedescr)
  7969. guard_nonnull_class(p18, ConstClass(node_vtable)) []
  7970. setfield_gc(p22, 2, descr=valuedescr)
  7971. jump(p22, p18)
  7972. """
  7973. preamble = """
  7974. [p22, p18]
  7975. setfield_gc(p22, 2, descr=valuedescr)
  7976. guard_nonnull_class(p18, ConstClass(node_vtable)) []
  7977. jump(p22, p18)
  7978. """
  7979. short = """
  7980. [p22, p18]
  7981. guard_nonnull(p22) []
  7982. guard_is_object(p22) []
  7983. guard_subclass(p22, ConstClass(node_vtable)) []
  7984. i1 = getfield_gc_i(p22, descr=valuedescr)
  7985. guard_value(i1, 2) []
  7986. jump()
  7987. """
  7988. expected = """
  7989. [p22, p18]
  7990. jump(p22, p18)
  7991. """
  7992. self.optimize_loop(ops, expected, preamble, expected_short=short)
  7993. def test_repeated_setfield_mixed_with_guard(self):
  7994. ops = """
  7995. [p22, p18, i1]
  7996. i2 = getfield_gc_i(p22, descr=valuedescr)
  7997. call_n(i2, descr=nonwritedescr)
  7998. setfield_gc(p22, i1, descr=valuedescr)
  7999. guard_nonnull_class(p18, ConstClass(node_vtable)) []
  8000. setfield_gc(p22, i1, descr=valuedescr)
  8001. jump(p22, p18, i1)
  8002. """
  8003. preamble = """
  8004. [p22, p18, i1]
  8005. i2 = getfield_gc_i(p22, descr=valuedescr)
  8006. call_n(i2, descr=nonwritedescr)
  8007. setfield_gc(p22, i1, descr=valuedescr)
  8008. guard_nonnull_class(p18, ConstClass(node_vtable)) []
  8009. i10 = same_as_i(i1)
  8010. jump(p22, p18, i1, i10)
  8011. """
  8012. short = """
  8013. [p22, p18, i1]
  8014. guard_nonnull(p22) []
  8015. guard_is_object(p22) []
  8016. guard_subclass(p22, ConstClass(node_vtable)) []
  8017. i2 = getfield_gc_i(p22, descr=valuedescr)
  8018. jump(i2)
  8019. """
  8020. expected = """
  8021. [p22, p18, i1, i2]
  8022. call_n(i2, descr=nonwritedescr)
  8023. setfield_gc(p22, i1, descr=valuedescr)
  8024. jump(p22, p18, i1, i1)
  8025. """
  8026. self.optimize_loop(ops, expected, preamble, expected_short=short)
  8027. def test_cache_setfield_across_loop_boundaries(self):
  8028. ops = """
  8029. [p1]
  8030. p2 = getfield_gc_r(p1, descr=nextdescr)
  8031. guard_nonnull_class(p2, ConstClass(node_vtable)) []
  8032. call_n(p2, descr=nonwritedescr)
  8033. p3 = new_with_vtable(descr=nodesize)
  8034. setfield_gc(p1, p3, descr=nextdescr)
  8035. jump(p1)
  8036. """
  8037. expected = """
  8038. [p1, p2]
  8039. call_n(p2, descr=nonwritedescr)
  8040. p3 = new_with_vtable(descr=nodesize)
  8041. setfield_gc(p1, p3, descr=nextdescr)
  8042. jump(p1, p3)
  8043. """
  8044. self.optimize_loop(ops, expected)
  8045. def test_cache_setarrayitem_across_loop_boundaries(self):
  8046. ops = """
  8047. [p1]
  8048. p2 = getarrayitem_gc_r(p1, 3, descr=gcarraydescr)
  8049. guard_nonnull_class(p2, ConstClass(node_vtable)) []
  8050. call_n(p2, descr=nonwritedescr)
  8051. p3 = new_with_vtable(descr=nodesize)
  8052. setarrayitem_gc(p1, 3, p3, descr=gcarraydescr)
  8053. jump(p1)
  8054. """
  8055. expected = """
  8056. [p1, p2]
  8057. call_n(p2, descr=nonwritedescr)
  8058. ifoo = arraylen_gc(p1, descr=gcarraydescr) # killed
  8059. p3 = new_with_vtable(descr=nodesize)
  8060. setarrayitem_gc(p1, 3, p3, descr=gcarraydescr)
  8061. jump(p1, p3)
  8062. """
  8063. self.optimize_loop(ops, expected)
  8064. def test_setarrayitem_p0_p0(self):
  8065. ops = """
  8066. [i0, i1]
  8067. p0 = escape_r()
  8068. setarrayitem_gc(p0, 2, p0, descr=arraydescr)
  8069. jump(i0, i1)
  8070. """
  8071. expected = """
  8072. [i0, i1]
  8073. p0 = escape_r()
  8074. setarrayitem_gc(p0, 2, p0, descr=arraydescr)
  8075. jump(i0, i1)
  8076. """
  8077. self.optimize_loop(ops, expected)
  8078. def test_setfield_p0_p0(self):
  8079. ops = """
  8080. [i0, i1]
  8081. p0 = escape_r()
  8082. setfield_gc(p0, p0, descr=nextdescr)
  8083. jump(i0, i1)
  8084. """
  8085. expected = """
  8086. [i0, i1]
  8087. p0 = escape_r()
  8088. setfield_gc(p0, p0, descr=nextdescr)
  8089. jump(i0, i1)
  8090. """
  8091. self.optimize_loop(ops, expected)
  8092. def test_setfield_p0_p1_p0(self):
  8093. ops = """
  8094. [i0, i1]
  8095. p0 = escape_r()
  8096. p1 = escape_r()
  8097. setfield_gc(p0, p1, descr=adescr)
  8098. setfield_gc(p1, p0, descr=bdescr)
  8099. jump(i0, i1)
  8100. """
  8101. expected = """
  8102. [i0, i1]
  8103. p0 = escape_r()
  8104. p1 = escape_r()
  8105. setfield_gc(p1, p0, descr=bdescr)
  8106. setfield_gc(p0, p1, descr=adescr)
  8107. jump(i0, i1)
  8108. """
  8109. self.optimize_loop(ops, expected)
  8110. def test_setinteriorfield_should_not_clear_cache(self):
  8111. ops = """
  8112. [i0, p0]
  8113. i2 = getfield_gc_i(p0, descr=adescr)
  8114. i3 = call_i(i2, descr=nonwritedescr)
  8115. setinteriorfield_raw(i0, i2, i3)
  8116. jump(i0, p0)
  8117. """
  8118. expected = """
  8119. [i0, p0, i2]
  8120. i3 = call_i(i2, descr=nonwritedescr)
  8121. setinteriorfield_raw(i0, i2, i3)
  8122. jump(i0, p0, i2)
  8123. """
  8124. self.optimize_loop(ops, expected)
  8125. def test_constant_failargs(self):
  8126. ops = """
  8127. [p1, i2, i3]
  8128. setfield_gc(p1, ConstPtr(myptr), descr=nextdescr)
  8129. p16 = getfield_gc_r(p1, descr=nextdescr)
  8130. guard_true(i2) [p16, i3]
  8131. jump(p1, i3, i2)
  8132. """
  8133. preamble = """
  8134. [p1, i2, i3]
  8135. setfield_gc(p1, ConstPtr(myptr), descr=nextdescr)
  8136. guard_true(i2) [i3]
  8137. jump(p1, i3)
  8138. """
  8139. expected = """
  8140. [p1, i3]
  8141. guard_true(i3) []
  8142. jump(p1, 1)
  8143. """
  8144. self.optimize_loop(ops, expected, preamble)
  8145. def test_issue1048(self):
  8146. ops = """
  8147. [p1, i2, i3]
  8148. p16 = getfield_gc_r(p1, descr=nextdescr)
  8149. guard_true(i2) [p16]
  8150. setfield_gc(p1, ConstPtr(myptr), descr=nextdescr)
  8151. jump(p1, i3, i2)
  8152. """
  8153. expected = """
  8154. [p1, i3]
  8155. guard_true(i3) []
  8156. jump(p1, 1)
  8157. """
  8158. self.optimize_loop(ops, expected)
  8159. def test_issue1048_ok(self):
  8160. ops = """
  8161. [p1, i2, i3]
  8162. p16 = getfield_gc_r(p1, descr=nextdescr)
  8163. call_n(p16, descr=nonwritedescr)
  8164. guard_true(i2) [p16]
  8165. setfield_gc(p1, ConstPtr(myptr), descr=nextdescr)
  8166. jump(p1, i3, i2)
  8167. """
  8168. expected = """
  8169. [p1, i3]
  8170. call_n(ConstPtr(myptr), descr=nonwritedescr)
  8171. guard_true(i3) []
  8172. jump(p1, 1)
  8173. """
  8174. self.optimize_loop(ops, expected)
  8175. def test_issue1080_infinitie_loop_virtual(self):
  8176. # Same comment as the following test_issue1080_infinitie_loop_simple
  8177. ops = """
  8178. [p10]
  8179. p52 = getfield_gc_r(p10, descr=nextdescr) # inst_storage
  8180. p54 = getarrayitem_gc_r(p52, 0, descr=arraydescr)
  8181. p69 = getfield_gc_r(p54, descr=otherdescr) # inst_w_function
  8182. quasiimmut_field(p69, descr=quasiimmutdescr)
  8183. guard_not_invalidated() []
  8184. p71 = getfield_gc_r(p69, descr=quasifielddescr) # inst_code
  8185. guard_value(p71, -4247) []
  8186. p106 = new_with_vtable(descr=nodesize)
  8187. p108 = new_array(3, descr=arraydescr)
  8188. p110 = new_with_vtable(descr=nodesize)
  8189. setfield_gc(p110, ConstPtr(myptrb), descr=otherdescr) # inst_w_function
  8190. setarrayitem_gc(p108, 0, p110, descr=arraydescr)
  8191. setfield_gc(p106, p108, descr=nextdescr) # inst_storage
  8192. jump(p106)
  8193. """
  8194. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8195. def test_issue1080_infinitie_loop_simple(self):
  8196. # 'quasiimmutdescr' is a QuasiImmutDescr initialized with the
  8197. # 'quasibox' as the quasi-immutable instance. We close the loop
  8198. # with ConstPtr(myptr), i.e. a different pointer. The test checks
  8199. # that the resulting loop is invalid.
  8200. ops = """
  8201. [p69]
  8202. quasiimmut_field(p69, descr=quasiimmutdescr)
  8203. guard_not_invalidated() []
  8204. p71 = getfield_gc_r(p69, descr=quasifielddescr) # inst_code
  8205. guard_value(p71, -4247) []
  8206. jump(ConstPtr(myptr))
  8207. """
  8208. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8209. def test_only_strengthen_guard_if_class_matches(self):
  8210. ops = """
  8211. [p1]
  8212. guard_class(p1, ConstClass(node_vtable2)) []
  8213. guard_value(p1, ConstPtr(myptr)) []
  8214. jump(p1)
  8215. """
  8216. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8217. def test_only_strengthen_guard_if_class_matches_2(self):
  8218. ops = """
  8219. [p1]
  8220. guard_class(p1, ConstClass(node_vtable2)) []
  8221. guard_value(p1, ConstPtr(myptr)) []
  8222. jump(p1)
  8223. """
  8224. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8225. def test_cond_call_with_a_constant(self):
  8226. ops = """
  8227. [p1]
  8228. cond_call(1, 123, p1, descr=plaincalldescr)
  8229. jump(p1)
  8230. """
  8231. expected = """
  8232. [p1]
  8233. call_n(123, p1, descr=plaincalldescr)
  8234. jump(p1)
  8235. """
  8236. self.optimize_loop(ops, expected)
  8237. def test_cond_call_with_a_constant_2(self):
  8238. ops = """
  8239. [p1]
  8240. cond_call(0, 123, p1, descr=plaincalldescr)
  8241. jump(p1)
  8242. """
  8243. expected = """
  8244. [p1]
  8245. jump(p1)
  8246. """
  8247. self.optimize_loop(ops, expected)
  8248. def test_hippyvm_unroll_bug(self):
  8249. ops = """
  8250. [p0, i1, i2]
  8251. i3 = int_add(i1, 1)
  8252. i4 = int_eq(i3, i2)
  8253. setfield_gc(p0, i4, descr=valuedescr)
  8254. jump(p0, i3, i2)
  8255. """
  8256. self.optimize_loop(ops, ops)
  8257. def test_unroll_failargs(self):
  8258. ops = """
  8259. [p0, i1]
  8260. p1 = getfield_gc_r(p0, descr=valuedescr)
  8261. i2 = int_add(i1, 1)
  8262. i3 = int_le(i2, 13)
  8263. guard_true(i3) [p1]
  8264. jump(p0, i2)
  8265. """
  8266. expected = """
  8267. [p0, i1, p1]
  8268. i2 = int_add(i1, 1)
  8269. i3 = int_le(i2, 13)
  8270. guard_true(i3) [p1]
  8271. jump(p0, i2, p1)
  8272. """
  8273. preamble = """
  8274. [p0, i1]
  8275. p1 = getfield_gc_r(p0, descr=valuedescr)
  8276. i2 = int_add(i1, 1)
  8277. i3 = int_le(i2, 13)
  8278. guard_true(i3) [p1]
  8279. jump(p0, i2, p1)
  8280. """
  8281. self.optimize_loop(ops, expected, preamble)
  8282. def test_unroll_two_boxes_used_differently(self):
  8283. ops = """
  8284. [p0, i0, i2]
  8285. i1 = int_add(i0, 1)
  8286. i3 = int_add(i1, i2)
  8287. i4 = getfield_gc_i(p0, descr=valuedescr)
  8288. escape_n(i4)
  8289. setfield_gc(p0, i1, descr=valuedescr)
  8290. jump(p0, i0, i3)
  8291. """
  8292. preamble = """
  8293. [p0, i0, i2]
  8294. i1 = int_add(i0, 1)
  8295. i3 = int_add(i1, i2)
  8296. i4 = getfield_gc_i(p0, descr=valuedescr)
  8297. escape_n(i4)
  8298. setfield_gc(p0, i1, descr=valuedescr)
  8299. ii = same_as_i(i1)
  8300. jump(p0, i0, i3, i1, ii)
  8301. """
  8302. expected = """
  8303. [p0, i0, i2, i4, i5]
  8304. i3 = int_add(i4, i2)
  8305. escape_n(i5)
  8306. setfield_gc(p0, i4, descr=valuedescr)
  8307. jump(p0, i0, i3, i4, i4)
  8308. """
  8309. self.optimize_loop(ops, expected, preamble)
  8310. def test_loop_variant_mul1(self):
  8311. ops = """
  8312. [i3, i4, i5]
  8313. i6 = int_mul(i5, i5)
  8314. i7 = int_add(i4, i6)
  8315. i9 = int_add(i5, 1)
  8316. i10 = int_mul(i9, i9)
  8317. i11 = int_add(i7, i10)
  8318. i13 = int_sub(i3, 1)
  8319. i15 = int_gt(i13, 0)
  8320. guard_true(i15) []
  8321. jump(i13, i11, i9)
  8322. """
  8323. expected = """
  8324. [i8, i7, i5, i6]
  8325. i10 = int_add(i7, i6)
  8326. i11 = int_add(i5, 1)
  8327. i12 = int_mul(i11, i11)
  8328. i13 = int_add(i10, i12)
  8329. i14 = int_sub(i8, 1)
  8330. i15 = int_gt(i14, 0)
  8331. guard_true(i15) []
  8332. jump(i14, i13, i11, i12)
  8333. """
  8334. expected_short = """
  8335. [i16, i17, i18]
  8336. i19 = int_mul(i18, i18)
  8337. jump(i19)
  8338. """
  8339. self.optimize_loop(ops, expected, expected_short=expected_short)
  8340. def test_cached_arrayitem_write_descr(self):
  8341. ops = """
  8342. [p0, p1, i0]
  8343. setarrayitem_gc(p0, 0, i0, descr=arraydescr)
  8344. ifoo = call_i(descr=writearraydescr)
  8345. i1 = getarrayitem_gc_i(p1, 0, descr=arraydescr)
  8346. jump(p0, p1, i1)
  8347. """
  8348. self.optimize_loop(ops, ops)
  8349. def test_pass_both_short_preamble_and_arg(self):
  8350. ops = """
  8351. [i0, i1]
  8352. i2 = int_add(i0, 1)
  8353. jump(i0, i2)
  8354. """
  8355. expected = """
  8356. [i0, i1, i2]
  8357. jump(i0, i2, i2)
  8358. """
  8359. preamble = """
  8360. [i0, i1]
  8361. i2 = int_add(i0, 1)
  8362. i3 = same_as_i(i2)
  8363. jump(i0, i2, i3)
  8364. """
  8365. self.optimize_loop(ops, expected, preamble)
  8366. def test_raw_buffer_in_preamble(self):
  8367. ops = """
  8368. [i1]
  8369. i0 = call_i(123, 10, descr=raw_malloc_descr)
  8370. guard_no_exception() []
  8371. jump(i0)
  8372. """
  8373. expected = """
  8374. [i1]
  8375. i0 = call_i(123, 10, descr=raw_malloc_descr)
  8376. check_memory_error(i0)
  8377. jump(i0)
  8378. """
  8379. self.optimize_loop(ops, expected)
  8380. def test_raw_buffer_int_is_true(self):
  8381. ops = """
  8382. [iinp]
  8383. i0 = call_i(123, 10, descr=raw_malloc_descr)
  8384. guard_no_exception() []
  8385. i1 = int_is_true(i0)
  8386. guard_true(i1) []
  8387. i2 = int_is_zero(i0)
  8388. guard_false(i2) []
  8389. jump(i0)
  8390. """
  8391. expected = """
  8392. [i2]
  8393. i0 = call_i(123, 10, descr=raw_malloc_descr)
  8394. check_memory_error(i0)
  8395. jump(i0)
  8396. """
  8397. self.optimize_loop(ops, expected)
  8398. def test_virtual_back_and_forth(self):
  8399. ops = """
  8400. [p0]
  8401. p1 = getfield_gc_r(p0, descr=nextdescr3)
  8402. ptemp = new_with_vtable(descr=nodesize)
  8403. setfield_gc(ptemp, p1, descr=nextdescr)
  8404. p2 = getfield_gc_r(ptemp, descr=nextdescr)
  8405. ix = getarrayitem_gc_pure_i(p2, 0, descr=arrayimmutdescr)
  8406. pfoo = getfield_gc_r(ptemp, descr=nextdescr)
  8407. guard_value(pfoo, ConstPtr(immutarray)) []
  8408. ifoo = int_add(ix, 13)
  8409. escape_n(ix)
  8410. jump(p0)
  8411. """
  8412. expected = """
  8413. [p0]
  8414. escape_n(0)
  8415. jump(p0)
  8416. """
  8417. self.optimize_loop(ops, expected)
  8418. def test_guard_value_const_virtualstate(self):
  8419. ops = """
  8420. [p0, i0]
  8421. p1 = new_with_vtable(descr=nodesize)
  8422. setfield_gc(p1, i0, descr=valuedescr)
  8423. guard_value(i0, 13) []
  8424. i1 = getfield_gc_i(p1, descr=valuedescr)
  8425. jump(p1, i1)
  8426. """
  8427. expected = """
  8428. []
  8429. jump()
  8430. """
  8431. self.optimize_loop(ops, expected)
  8432. def test_constant_float_pure(self):
  8433. ops = """
  8434. [p0]
  8435. f0 = getarrayitem_gc_pure_f(p0, 3, descr=floatarrayimmutdescr)
  8436. guard_value(f0, 1.03) []
  8437. jump(p0)
  8438. """
  8439. expected = """
  8440. [p0]
  8441. ifoo = arraylen_gc(p0, descr=floatarrayimmutdescr)
  8442. jump(p0)
  8443. """
  8444. self.optimize_loop(ops, expected)
  8445. def test_resume_forced_raw_ptr(self):
  8446. ops = """
  8447. [i0]
  8448. i = call_i('malloc', 10, descr=raw_malloc_descr)
  8449. guard_no_exception() []
  8450. is = int_add(i, 8)
  8451. escape_n(i)
  8452. i1 = int_add(i0, 1)
  8453. i2 = int_lt(i1, 100)
  8454. guard_true(i2) [is]
  8455. call_n('free', i, descr=raw_free_descr)
  8456. jump(i1)
  8457. """
  8458. expected = """
  8459. [i0]
  8460. i = call_i('malloc', 10, descr=raw_malloc_descr)
  8461. check_memory_error(i)
  8462. escape_n(i)
  8463. i1 = int_add(i0, 1)
  8464. i2 = int_lt(i1, 100)
  8465. guard_true(i2) [i]
  8466. call_n('free', i, descr=raw_free_descr)
  8467. jump(i1)
  8468. """
  8469. self.optimize_loop(ops, expected)
  8470. def test_virtual_with_floats(self):
  8471. ops = """
  8472. [p1, i1]
  8473. p0 = new_with_vtable(descr=nodesize)
  8474. i2 = int_add(i1, 1)
  8475. setfield_gc(p0, 0.0000, descr=floatdescr)
  8476. setfield_gc(p0, i2, descr=valuedescr)
  8477. jump(p0, i2)
  8478. """
  8479. expected = """
  8480. [i1]
  8481. i2 = int_add(i1, 1)
  8482. jump(i2)
  8483. """
  8484. self.optimize_loop(ops, expected)
  8485. def test_same_as_preserves_info_in_the_preamble(self):
  8486. ops = """
  8487. [p0, p1, i1]
  8488. i2 = int_add(i1, 1)
  8489. setfield_gc(p0, i2, descr=valuedescr)
  8490. i = int_le(i2, 13)
  8491. guard_true(i) []
  8492. if00 = getfield_gc_i(p0, descr=valuedescr)
  8493. icheck = int_le(if00, 13)
  8494. guard_true(icheck) []
  8495. jump(p0, p1, i1)
  8496. """
  8497. expected = """
  8498. [p0, p1, i1, i2]
  8499. setfield_gc(p0, i2, descr=valuedescr)
  8500. jump(p0, p1, i1, i2)
  8501. """
  8502. self.optimize_loop(ops, expected)
  8503. def test_same_as_preserves_info_in_the_preamble_2(self):
  8504. ops = """
  8505. [i0, p0]
  8506. ifoo = getfield_gc_i(p0, descr=valuedescr)
  8507. icheck = int_lt(ifoo, 13)
  8508. guard_true(icheck) []
  8509. i1 = int_add(i0, 1)
  8510. i2 = int_lt(i1, 13)
  8511. guard_true(i2) []
  8512. setfield_gc(p0, i1, descr=valuedescr)
  8513. jump(i0, p0)
  8514. """
  8515. expected = """
  8516. [i0, p0, i4]
  8517. setfield_gc(p0, i4, descr=valuedescr)
  8518. jump(i0, p0, i4)
  8519. """
  8520. self.optimize_loop(ops, expected)
  8521. def test_pending_setfield_delayed_malloc(self):
  8522. ops = """
  8523. [i0, p0]
  8524. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  8525. guard_no_exception() []
  8526. setarrayitem_raw(i2, 0, 13, descr=rawarraydescr)
  8527. setfield_gc(p0, i2, descr=valuedescr)
  8528. i1 = int_add(i0, 1)
  8529. i3 = int_lt(i1, 10)
  8530. guard_true(i3) []
  8531. setfield_gc(p0, 0, descr=valuedescr)
  8532. jump(i1, p0)
  8533. """
  8534. expected = """
  8535. [i0, p0]
  8536. i1 = int_add(i0, 1)
  8537. i3 = int_lt(i1, 10)
  8538. guard_true(i3) [p0]
  8539. jump(i1, p0)
  8540. """
  8541. self.optimize_loop(ops, expected)
  8542. def test_raw_buffer_ptr_info_intbounds_bug(self):
  8543. ops = """
  8544. []
  8545. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  8546. guard_no_exception() []
  8547. guard_value(i2, 12345) []
  8548. jump()
  8549. """
  8550. expected = """
  8551. []
  8552. i2 = call_i('malloc', 10, descr=raw_malloc_descr)
  8553. check_memory_error(i2)
  8554. guard_value(i2, 12345) []
  8555. jump()
  8556. """
  8557. # getting InvalidLoop would be a good idea, too.
  8558. # (this test was written to show it would previously crash)
  8559. self.optimize_loop(ops, expected)
  8560. def test_unroll_constant_null_1(self):
  8561. ops = """
  8562. [p0, i1]
  8563. i2 = int_gt(i1, 0)
  8564. guard_true(i2) []
  8565. i4 = getfield_gc_i(p0, descr=valuedescr)
  8566. i3 = int_sub(i1, 1)
  8567. jump(NULL, i3)
  8568. """
  8569. # may either raise InvalidLoop or compile; it's a rare case
  8570. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8571. def test_unroll_constant_null_2(self):
  8572. ops = """
  8573. [p0, i1]
  8574. i2 = int_gt(i1, 0)
  8575. guard_true(i2) []
  8576. setfield_gc(p0, i1, descr=valuedescr)
  8577. i3 = int_sub(i1, 1)
  8578. jump(NULL, i3)
  8579. """
  8580. # may either raise InvalidLoop or compile; it's a rare case
  8581. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8582. def test_unroll_constant_null_3(self):
  8583. ops = """
  8584. [p0, i1]
  8585. i2 = int_gt(i1, 0)
  8586. guard_true(i2) []
  8587. i4 = getarrayitem_gc_i(p0, 5, descr=arraydescr)
  8588. i3 = int_sub(i1, 1)
  8589. jump(NULL, i3)
  8590. """
  8591. # may either raise InvalidLoop or compile; it's a rare case
  8592. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8593. def test_unroll_constant_null_4(self):
  8594. ops = """
  8595. [p0, i1]
  8596. i2 = int_gt(i1, 0)
  8597. guard_true(i2) []
  8598. setarrayitem_gc(p0, 5, i1, descr=arraydescr)
  8599. i3 = int_sub(i1, 1)
  8600. jump(NULL, i3)
  8601. """
  8602. # may either raise InvalidLoop or compile; it's a rare case
  8603. self.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8604. def test_unroll_constant_null_5(self):
  8605. ops = """
  8606. [p0, i1]
  8607. i2 = int_gt(i1, 0)
  8608. guard_true(i2) []
  8609. i4 = getarrayitem_gc_i(p0, i1, descr=arraydescr)
  8610. i3 = int_sub(i1, 1)
  8611. jump(NULL, i3)
  8612. """
  8613. expected = """
  8614. [i1]
  8615. i2 = int_gt(i1, 0)
  8616. guard_true(i2) []
  8617. i4 = getarrayitem_gc_i(NULL, i1, descr=arraydescr)
  8618. i3 = int_sub(i1, 1)
  8619. jump(i3)
  8620. """
  8621. # may either raise InvalidLoop or compile; it's a rare case
  8622. self.optimize_loop(ops, expected)
  8623. def test_unroll_constant_null_6(self):
  8624. ops = """
  8625. [p0, i1]
  8626. i2 = int_gt(i1, 0)
  8627. guard_true(i2) []
  8628. setarrayitem_gc(p0, i1, i1, descr=arraydescr)
  8629. i3 = int_sub(i1, 1)
  8630. jump(NULL, i3)
  8631. """
  8632. expected = """
  8633. [i1]
  8634. i2 = int_gt(i1, 0)
  8635. guard_true(i2) []
  8636. setarrayitem_gc(NULL, i1, i1, descr=arraydescr)
  8637. i3 = int_sub(i1, 1)
  8638. jump(i3)
  8639. """
  8640. # may either raise InvalidLoop or compile; it's a rare case
  8641. self.optimize_loop(ops, expected)
  8642. def test_unroll_pure_on_bogus_object_1(self):
  8643. ops = """
  8644. [p0, i1]
  8645. i2 = int_gt(i1, 0)
  8646. guard_true(i2) []
  8647. getfield_gc_i(p0, descr=valuedescr3)
  8648. i3 = int_sub(i1, 1)
  8649. jump(NULL, i3)
  8650. """
  8651. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8652. def test_unroll_pure_on_bogus_object_2(self):
  8653. ops = """
  8654. [p0, i1]
  8655. i2 = int_gt(i1, 0)
  8656. guard_true(i2) []
  8657. getfield_gc_i(p0, descr=valuedescr3)
  8658. i3 = int_sub(i1, 1)
  8659. jump(ConstPtr(myptr2), i3)
  8660. """
  8661. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8662. def test_unroll_pure_on_bogus_object_3(self):
  8663. ops = """
  8664. [p0, i1]
  8665. i2 = int_gt(i1, 0)
  8666. guard_true(i2) []
  8667. getarrayitem_gc_pure_i(p0, 5, descr=arraydescr)
  8668. i3 = int_sub(i1, 1)
  8669. jump(NULL, i3)
  8670. """
  8671. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8672. def test_unroll_pure_on_bogus_object_4(self):
  8673. ops = """
  8674. [p0, i1]
  8675. i2 = int_gt(i1, 0)
  8676. guard_true(i2) []
  8677. getarrayitem_gc_pure_i(p0, 5, descr=arraydescr)
  8678. i3 = int_sub(i1, 1)
  8679. jump(ConstPtr(myptr3), i3)
  8680. """
  8681. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8682. def test_unroll_pure_on_bogus_object_5(self):
  8683. ops = """
  8684. [p0, i1]
  8685. i2 = int_gt(i1, 0)
  8686. guard_true(i2) []
  8687. getarrayitem_gc_pure_i(p0, 125, descr=arraydescr)
  8688. i3 = int_sub(i1, 1)
  8689. jump(ConstPtr(arrayref), i3) # too short, length < 126!
  8690. """
  8691. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8692. def test_unroll_pure_on_bogus_object_6(self):
  8693. ops = """
  8694. [i0, i1]
  8695. i2 = int_gt(i1, 0)
  8696. guard_true(i2) []
  8697. getarrayitem_gc_pure_i(ConstPtr(arrayref), i0, descr=arraydescr)
  8698. i3 = int_sub(i1, 1)
  8699. jump(125, i3) # arrayref is too short, length < 126!
  8700. """
  8701. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8702. def test_unroll_pure_on_bogus_object_7(self):
  8703. ops = """
  8704. [i0, i1]
  8705. i2 = int_gt(i1, 0)
  8706. guard_true(i2) []
  8707. getarrayitem_gc_pure_i(ConstPtr(arrayref), i0, descr=arraydescr)
  8708. i3 = int_sub(i1, 1)
  8709. jump(-1, i3) # cannot access array item -1!
  8710. """
  8711. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8712. def test_unroll_pure_on_bogus_object_8(self):
  8713. ops = """
  8714. [p0, i1]
  8715. i2 = int_gt(i1, 0)
  8716. guard_true(i2) []
  8717. i4 = strgetitem(p0, 125)
  8718. i3 = int_sub(i1, 1)
  8719. jump(NULL, i3)
  8720. """
  8721. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8722. def test_unroll_pure_on_bogus_object_9(self):
  8723. ops = """
  8724. [p0, i1]
  8725. i2 = int_gt(i1, 0)
  8726. guard_true(i2) []
  8727. i4 = strgetitem(p0, 125)
  8728. i3 = int_sub(i1, 1)
  8729. jump(ConstPtr(myptr), i3) # not a string at all
  8730. """
  8731. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8732. def test_unroll_pure_on_bogus_object_9_unicode(self):
  8733. ops = """
  8734. [p0, i1]
  8735. i2 = int_gt(i1, 0)
  8736. guard_true(i2) []
  8737. i4 = unicodegetitem(p0, 125)
  8738. i3 = int_sub(i1, 1)
  8739. jump(ConstPtr(myptr), i3) # not a unicode at all
  8740. """
  8741. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8742. def test_unroll_pure_on_bogus_object_10(self):
  8743. ops = """
  8744. [i0, i1]
  8745. i2 = int_gt(i1, 0)
  8746. guard_true(i2) []
  8747. i4 = strgetitem("foobar", i0)
  8748. i3 = int_sub(i1, 1)
  8749. jump(125, i3) # string is too short!
  8750. """
  8751. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8752. def test_unroll_pure_on_bogus_object_11(self):
  8753. ops = """
  8754. [i0, i1]
  8755. i2 = int_gt(i1, 0)
  8756. guard_true(i2) []
  8757. i4 = strgetitem("foobar", i0)
  8758. i3 = int_sub(i1, 1)
  8759. jump(-1, i3) # cannot access character -1!
  8760. """
  8761. py.test.raises(InvalidLoop, self.optimize_loop, ops, ops)
  8762. def test_virtual_array_length_discovered_constant_1(self):
  8763. ops = """
  8764. []
  8765. i1 = escape_i()
  8766. guard_value(i1, 5) []
  8767. p1 = new_array_clear(i1, descr=arraydescr3)
  8768. escape_n(p1)
  8769. jump()
  8770. """
  8771. expected = """
  8772. []
  8773. i1 = escape_i()
  8774. guard_value(i1, 5) []
  8775. p1 = new_array_clear(5, descr=arraydescr3) # 'i1' => '5'
  8776. escape_n(p1)
  8777. jump()
  8778. """
  8779. self.optimize_loop(ops, expected)
  8780. def test_virtual_array_length_discovered_constant_2(self):
  8781. ops = """
  8782. [p0]
  8783. escape_n(p0)
  8784. i1 = escape_i()
  8785. guard_value(i1, 5) []
  8786. p1 = new_array_clear(i1, descr=arraydescr3)
  8787. jump(p1)
  8788. """
  8789. expected = """
  8790. []
  8791. p1 = new_array_clear(5, descr=arraydescr3)
  8792. escape_n(p1)
  8793. i1 = escape_i()
  8794. guard_value(i1, 5) []
  8795. jump()
  8796. """
  8797. a = lltype.malloc(lltype.GcArray(lltype.Ptr(self.NODE3)), 5, zero=True)
  8798. self.optimize_loop(ops, expected, jump_values=[a])
  8799. def test_large_number_of_immutable_references(self):
  8800. ops = """
  8801. [p0]
  8802. i0 = getfield_gc_i(p0, descr=bigadescr)
  8803. i1 = getfield_gc_i(p0, descr=bigbdescr)
  8804. i2 = getfield_gc_i(p0, descr=bigcdescr)
  8805. i3 = getfield_gc_i(p0, descr=bigddescr)
  8806. i4 = getfield_gc_i(p0, descr=bigedescr)
  8807. i5 = getfield_gc_i(p0, descr=bigfdescr)
  8808. i6 = getfield_gc_i(p0, descr=biggdescr)
  8809. i7 = getfield_gc_i(p0, descr=bighdescr)
  8810. i8 = getfield_gc_i(p0, descr=bigidescr)
  8811. i9 = getfield_gc_i(p0, descr=bigjdescr)
  8812. i10 = getfield_gc_i(p0, descr=bigkdescr)
  8813. i11 = getfield_gc_i(p0, descr=bigldescr)
  8814. i12 = getfield_gc_i(p0, descr=bigmdescr)
  8815. i13 = getfield_gc_i(p0, descr=bigndescr)
  8816. i14 = getfield_gc_i(p0, descr=bigodescr)
  8817. i15 = getfield_gc_i(p0, descr=bigpdescr)
  8818. i16 = getfield_gc_i(p0, descr=bigqdescr)
  8819. i17 = getfield_gc_i(p0, descr=bigrdescr)
  8820. i18 = getfield_gc_i(p0, descr=bigsdescr)
  8821. i19 = getfield_gc_i(p0, descr=bigtdescr)
  8822. i20 = getfield_gc_i(p0, descr=bigudescr)
  8823. i21 = getfield_gc_i(p0, descr=bigvdescr)
  8824. i22 = getfield_gc_i(p0, descr=bigwdescr)
  8825. i23 = getfield_gc_i(p0, descr=bigxdescr)
  8826. i24 = getfield_gc_i(p0, descr=bigydescr)
  8827. i25 = getfield_gc_i(p0, descr=bigzdescr)
  8828. i27 = getfield_gc_i(p0, descr=bigbdescr)
  8829. i28 = getfield_gc_i(p0, descr=bigcdescr)
  8830. i29 = getfield_gc_i(p0, descr=bigddescr)
  8831. i30 = getfield_gc_i(p0, descr=bigedescr)
  8832. i31 = getfield_gc_i(p0, descr=bigfdescr)
  8833. i32 = getfield_gc_i(p0, descr=biggdescr)
  8834. i33 = getfield_gc_i(p0, descr=bighdescr)
  8835. i34 = getfield_gc_i(p0, descr=bigidescr)
  8836. i35 = getfield_gc_i(p0, descr=bigjdescr)
  8837. i36 = getfield_gc_i(p0, descr=bigkdescr)
  8838. i37 = getfield_gc_i(p0, descr=bigldescr)
  8839. i38 = getfield_gc_i(p0, descr=bigmdescr)
  8840. i39 = getfield_gc_i(p0, descr=bigndescr)
  8841. i40 = getfield_gc_i(p0, descr=bigodescr)
  8842. i41 = getfield_gc_i(p0, descr=bigpdescr)
  8843. i42 = getfield_gc_i(p0, descr=bigqdescr)
  8844. i43 = getfield_gc_i(p0, descr=bigrdescr)
  8845. i44 = getfield_gc_i(p0, descr=bigsdescr)
  8846. i45 = getfield_gc_i(p0, descr=bigtdescr)
  8847. i46 = getfield_gc_i(p0, descr=bigudescr)
  8848. i47 = getfield_gc_i(p0, descr=bigvdescr)
  8849. i48 = getfield_gc_i(p0, descr=bigwdescr)
  8850. i49 = getfield_gc_i(p0, descr=bigxdescr)
  8851. i50 = getfield_gc_i(p0, descr=bigydescr)
  8852. i51 = getfield_gc_i(p0, descr=bigzdescr)
  8853. i26 = getfield_gc_i(p0, descr=bigadescr)
  8854. i99 = int_add(i26, i51)
  8855. escape_i(i27)
  8856. escape_i(i28)
  8857. escape_i(i29)
  8858. escape_i(i30)
  8859. escape_i(i31)
  8860. escape_i(i32)
  8861. escape_i(i33)
  8862. escape_i(i34)
  8863. escape_i(i35)
  8864. escape_i(i36)
  8865. escape_i(i37)
  8866. escape_i(i38)
  8867. escape_i(i39)
  8868. escape_i(i40)
  8869. escape_i(i41)
  8870. escape_i(i42)
  8871. escape_i(i43)
  8872. escape_i(i44)
  8873. escape_i(i45)
  8874. escape_i(i46)
  8875. escape_i(i47)
  8876. escape_i(i48)
  8877. escape_i(i49)
  8878. escape_i(i50)
  8879. escape_i(i51)
  8880. escape_i(i26)
  8881. escape_i(i99)
  8882. jump(p0)
  8883. """
  8884. expected = """
  8885. [p0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,i21,i22,i23,i24,i25,i0,i99]
  8886. escape_i(i1)
  8887. escape_i(i2)
  8888. escape_i(i3)
  8889. escape_i(i4)
  8890. escape_i(i5)
  8891. escape_i(i6)
  8892. escape_i(i7)
  8893. escape_i(i8)
  8894. escape_i(i9)
  8895. escape_i(i10)
  8896. escape_i(i11)
  8897. escape_i(i12)
  8898. escape_i(i13)
  8899. escape_i(i14)
  8900. escape_i(i15)
  8901. escape_i(i16)
  8902. escape_i(i17)
  8903. escape_i(i18)
  8904. escape_i(i19)
  8905. escape_i(i20)
  8906. escape_i(i21)
  8907. escape_i(i22)
  8908. escape_i(i23)
  8909. escape_i(i24)
  8910. escape_i(i25)
  8911. escape_i(i0)
  8912. escape_i(i99)
  8913. jump(p0,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16,i17,i18,i19,i20,i21,i22,i23,i24,i25,i0,i99)
  8914. """
  8915. self.optimize_loop(ops, expected)
  8916. class TestLLtype(OptimizeOptTest, LLtypeMixin):
  8917. pass