PageRenderTime 73ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

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

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