PageRenderTime 78ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

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

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