PageRenderTime 43ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/varialus/jyjy
Python | 5121 lines | 5093 code | 19 blank | 9 comment | 9 complexity | 53e4e24f0c9d27e43ed9071c9e55ef60 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_no_elem(self):
  3056. """ this was actually observed in the wild
  3057. """
  3058. ops = '''
  3059. [p1]
  3060. p0 = new_array(0, descr=arraydescr)
  3061. call(0, p0, p1, 0, 0, 0, descr=arraycopydescr)
  3062. jump(p1)
  3063. '''
  3064. expected = '''
  3065. [p1]
  3066. jump(p1)
  3067. '''
  3068. self.optimize_loop(ops, expected)
  3069. def test_bound_lt(self):
  3070. ops = """
  3071. [i0]
  3072. i1 = int_lt(i0, 4)
  3073. guard_true(i1) []
  3074. i2 = int_lt(i0, 5)
  3075. guard_true(i2) []
  3076. jump(i0)
  3077. """
  3078. expected = """
  3079. [i0]
  3080. i1 = int_lt(i0, 4)
  3081. guard_true(i1) []
  3082. jump(i0)
  3083. """
  3084. self.optimize_loop(ops, expected)
  3085. def test_bound_lt_noguard(self):
  3086. ops = """
  3087. [i0]
  3088. i1 = int_lt(i0, 4)
  3089. i2 = int_lt(i0, 5)
  3090. jump(i2)
  3091. """
  3092. expected = """
  3093. [i0]
  3094. i1 = int_lt(i0, 4)
  3095. i2 = int_lt(i0, 5)
  3096. jump(i2)
  3097. """
  3098. self.optimize_loop(ops, expected)
  3099. def test_bound_lt_noopt(self):
  3100. ops = """
  3101. [i0]
  3102. i1 = int_lt(i0, 4)
  3103. guard_false(i1) []
  3104. i2 = int_lt(i0, 5)
  3105. guard_true(i2) []
  3106. jump(i0)
  3107. """
  3108. expected = """
  3109. [i0]
  3110. i1 = int_lt(i0, 4)
  3111. guard_false(i1) []
  3112. i2 = int_lt(i0, 5)
  3113. guard_true(i2) []
  3114. jump(4)
  3115. """
  3116. self.optimize_loop(ops, expected)
  3117. def test_bound_lt_rev(self):
  3118. ops = """
  3119. [i0]
  3120. i1 = int_lt(i0, 4)
  3121. guard_false(i1) []
  3122. i2 = int_gt(i0, 3)
  3123. guard_true(i2) []
  3124. jump(i0)
  3125. """
  3126. expected = """
  3127. [i0]
  3128. i1 = int_lt(i0, 4)
  3129. guard_false(i1) []
  3130. jump(i0)
  3131. """
  3132. self.optimize_loop(ops, expected)
  3133. def test_bound_lt_tripple(self):
  3134. ops = """
  3135. [i0]
  3136. i1 = int_lt(i0, 0)
  3137. guard_true(i1) []
  3138. i2 = int_lt(i0, 7)
  3139. guard_true(i2) []
  3140. i3 = int_lt(i0, 5)
  3141. guard_true(i3) []
  3142. jump(i0)
  3143. """
  3144. expected = """
  3145. [i0]
  3146. i1 = int_lt(i0, 0)
  3147. guard_true(i1) []
  3148. jump(i0)
  3149. """
  3150. self.optimize_loop(ops, expected)
  3151. def test_bound_lt_add(self):
  3152. ops = """
  3153. [i0]
  3154. i1 = int_lt(i0, 4)
  3155. guard_true(i1) []
  3156. i2 = int_add(i0, 10)
  3157. i3 = int_lt(i2, 15)
  3158. guard_true(i3) []
  3159. jump(i0)
  3160. """
  3161. expected = """
  3162. [i0]
  3163. i1 = int_lt(i0, 4)
  3164. guard_true(i1) []
  3165. i2 = int_add(i0, 10)
  3166. jump(i0)
  3167. """
  3168. self.optimize_loop(ops, expected)
  3169. def test_bound_lt_add_before(self):
  3170. ops = """
  3171. [i0]
  3172. i2 = int_add(i0, 10)
  3173. i3 = int_lt(i2, 15)
  3174. guard_true(i3) []
  3175. i1 = int_lt(i0, 6)
  3176. guard_true(i1) []
  3177. jump(i0)
  3178. """
  3179. expected = """
  3180. [i0]
  3181. i2 = int_add(i0, 10)
  3182. i3 = int_lt(i2, 15)
  3183. guard_true(i3) []
  3184. jump(i0)
  3185. """
  3186. self.optimize_loop(ops, expected)
  3187. def test_bound_lt_add_ovf(self):
  3188. ops = """
  3189. [i0]
  3190. i1 = int_lt(i0, 4)
  3191. guard_true(i1) []
  3192. i2 = int_add_ovf(i0, 10)
  3193. guard_no_overflow() []
  3194. i3 = int_lt(i2, 15)
  3195. guard_true(i3) []
  3196. jump(i0)
  3197. """
  3198. expected = """
  3199. [i0]
  3200. i1 = int_lt(i0, 4)
  3201. guard_true(i1) []
  3202. i2 = int_add(i0, 10)
  3203. jump(i0)
  3204. """
  3205. self.optimize_loop(ops, expected)
  3206. def test_bound_lt_add_ovf_before(self):
  3207. ops = """
  3208. [i0]
  3209. i2 = int_add_ovf(i0, 10)
  3210. guard_no_overflow() []
  3211. i3 = int_lt(i2, 15)
  3212. guard_true(i3) []
  3213. i1 = int_lt(i0, 6)
  3214. guard_true(i1) []
  3215. jump(i0)
  3216. """
  3217. expected = """
  3218. [i0]
  3219. i2 = int_add_ovf(i0, 10)
  3220. guard_no_overflow() []
  3221. i3 = int_lt(i2, 15)
  3222. guard_true(i3) []
  3223. jump(i0)
  3224. """
  3225. self.optimize_loop(ops, expected)
  3226. def test_bound_lt_sub(self):
  3227. ops = """
  3228. [i0]
  3229. i1 = int_lt(i0, 4)
  3230. guard_true(i1) []
  3231. i1p = int_gt(i0, -4)
  3232. guard_true(i1p) []
  3233. i2 = int_sub(i0, 10)
  3234. i3 = int_lt(i2, -5)
  3235. guard_true(i3) []
  3236. jump(i0)
  3237. """
  3238. expected = """
  3239. [i0]
  3240. i1 = int_lt(i0, 4)
  3241. guard_true(i1) []
  3242. i1p = int_gt(i0, -4)
  3243. guard_true(i1p) []
  3244. i2 = int_sub(i0, 10)
  3245. jump(i0)
  3246. """
  3247. self.optimize_loop(ops, expected)
  3248. def test_bound_lt_sub_before(self):
  3249. ops = """
  3250. [i0]
  3251. i2 = int_sub(i0, 10)
  3252. i3 = int_lt(i2, -5)
  3253. guard_true(i3) []
  3254. i1 = int_lt(i0, 5)
  3255. guard_true(i1) []
  3256. jump(i0)
  3257. """
  3258. expected = """
  3259. [i0]
  3260. i2 = int_sub(i0, 10)
  3261. i3 = int_lt(i2, -5)
  3262. guard_true(i3) []
  3263. jump(i0)
  3264. """
  3265. self.optimize_loop(ops, expected)
  3266. def test_bound_ltle(self):
  3267. ops = """
  3268. [i0]
  3269. i1 = int_lt(i0, 4)
  3270. guard_true(i1) []
  3271. i2 = int_le(i0, 3)
  3272. guard_true(i2) []
  3273. jump(i0)
  3274. """
  3275. expected = """
  3276. [i0]
  3277. i1 = int_lt(i0, 4)
  3278. guard_true(i1) []
  3279. jump(i0)
  3280. """
  3281. self.optimize_loop(ops, expected)
  3282. def test_bound_lelt(self):
  3283. ops = """
  3284. [i0]
  3285. i1 = int_le(i0, 4)
  3286. guard_true(i1) []
  3287. i2 = int_lt(i0, 5)
  3288. guard_true(i2) []
  3289. jump(i0)
  3290. """
  3291. expected = """
  3292. [i0]
  3293. i1 = int_le(i0, 4)
  3294. guard_true(i1) []
  3295. jump(i0)
  3296. """
  3297. self.optimize_loop(ops, expected)
  3298. def test_bound_gt(self):
  3299. ops = """
  3300. [i0]
  3301. i1 = int_gt(i0, 5)
  3302. guard_true(i1) []
  3303. i2 = int_gt(i0, 4)
  3304. guard_true(i2) []
  3305. jump(i0)
  3306. """
  3307. expected = """
  3308. [i0]
  3309. i1 = int_gt(i0, 5)
  3310. guard_true(i1) []
  3311. jump(i0)
  3312. """
  3313. self.optimize_loop(ops, expected)
  3314. def test_bound_gtge(self):
  3315. ops = """
  3316. [i0]
  3317. i1 = int_gt(i0, 5)
  3318. guard_true(i1) []
  3319. i2 = int_ge(i0, 6)
  3320. guard_true(i2) []
  3321. jump(i0)
  3322. """
  3323. expected = """
  3324. [i0]
  3325. i1 = int_gt(i0, 5)
  3326. guard_true(i1) []
  3327. jump(i0)
  3328. """
  3329. self.optimize_loop(ops, expected)
  3330. def test_bound_gegt(self):
  3331. ops = """
  3332. [i0]
  3333. i1 = int_ge(i0, 5)
  3334. guard_true(i1) []
  3335. i2 = int_gt(i0, 4)
  3336. guard_true(i2) []
  3337. jump(i0)
  3338. """
  3339. expected = """
  3340. [i0]
  3341. i1 = int_ge(i0, 5)
  3342. guard_true(i1) []
  3343. jump(i0)
  3344. """
  3345. self.optimize_loop(ops, expected)
  3346. def test_bound_ovf(self):
  3347. ops = """
  3348. [i0]
  3349. i1 = int_ge(i0, 0)
  3350. guard_true(i1) []
  3351. i2 = int_lt(i0, 10)
  3352. guard_true(i2) []
  3353. i3 = int_add_ovf(i0, 1)
  3354. guard_no_overflow() []
  3355. jump(i3)
  3356. """
  3357. expected = """
  3358. [i0]
  3359. i1 = int_ge(i0, 0)
  3360. guard_true(i1) []
  3361. i2 = int_lt(i0, 10)
  3362. guard_true(i2) []
  3363. i3 = int_add(i0, 1)
  3364. jump(i3)
  3365. """
  3366. self.optimize_loop(ops, expected)
  3367. def test_bound_arraylen(self):
  3368. ops = """
  3369. [i0, p0]
  3370. p1 = new_array(i0, descr=arraydescr)
  3371. i1 = arraylen_gc(p1)
  3372. i2 = int_gt(i1, -1)
  3373. guard_true(i2) []
  3374. setarrayitem_gc(p0, 0, p1)
  3375. jump(i0, p0)
  3376. """
  3377. # The dead arraylen_gc will be eliminated by the backend.
  3378. expected = """
  3379. [i0, p0]
  3380. p1 = new_array(i0, descr=arraydescr)
  3381. i1 = arraylen_gc(p1)
  3382. setarrayitem_gc(p0, 0, p1)
  3383. jump(i0, p0)
  3384. """
  3385. self.optimize_loop(ops, expected)
  3386. def test_bound_strlen(self):
  3387. ops = """
  3388. [p0]
  3389. i0 = strlen(p0)
  3390. i1 = int_ge(i0, 0)
  3391. guard_true(i1) []
  3392. jump(p0)
  3393. """
  3394. # The dead strlen will be eliminated be the backend.
  3395. expected = """
  3396. [p0]
  3397. i0 = strlen(p0)
  3398. jump(p0)
  3399. """
  3400. self.optimize_strunicode_loop(ops, expected)
  3401. def test_addsub_const(self):
  3402. ops = """
  3403. [i0]
  3404. i1 = int_add(i0, 1)
  3405. i2 = int_sub(i1, 1)
  3406. i3 = int_add(i2, 1)
  3407. i4 = int_mul(i2, i3)
  3408. jump(i4)
  3409. """
  3410. expected = """
  3411. [i0]
  3412. i1 = int_add(i0, 1)
  3413. i4 = int_mul(i0, i1)
  3414. jump(i4)
  3415. """
  3416. self.optimize_loop(ops, expected)
  3417. def test_addsub_int(self):
  3418. ops = """
  3419. [i0, i10]
  3420. i1 = int_add(i0, i10)
  3421. i2 = int_sub(i1, i10)
  3422. i3 = int_add(i2, i10)
  3423. i4 = int_add(i2, i3)
  3424. jump(i4, i10)
  3425. """
  3426. expected = """
  3427. [i0, i10]
  3428. i1 = int_add(i0, i10)
  3429. i4 = int_add(i0, i1)
  3430. jump(i4, i10)
  3431. """
  3432. self.optimize_loop(ops, expected)
  3433. def test_addsub_int2(self):
  3434. ops = """
  3435. [i0, i10]
  3436. i1 = int_add(i10, i0)
  3437. i2 = int_sub(i1, i10)
  3438. i3 = int_add(i10, i2)
  3439. i4 = int_add(i2, i3)
  3440. jump(i4, i10)
  3441. """
  3442. expected = """
  3443. [i0, i10]
  3444. i1 = int_add(i10, i0)
  3445. i4 = int_add(i0, i1)
  3446. jump(i4, i10)
  3447. """
  3448. self.optimize_loop(ops, expected)
  3449. def test_framestackdepth_overhead(self):
  3450. ops = """
  3451. [p0, i22]
  3452. i1 = getfield_gc(p0, descr=valuedescr)
  3453. i2 = int_gt(i1, i22)
  3454. guard_false(i2) []
  3455. i3 = int_add(i1, 1)
  3456. setfield_gc(p0, i3, descr=valuedescr)
  3457. i4 = int_sub(i3, 1)
  3458. setfield_gc(p0, i4, descr=valuedescr)
  3459. i5 = int_gt(i4, i22)
  3460. guard_false(i5) []
  3461. i6 = int_add(i4, 1)
  3462. i331 = force_token()
  3463. i7 = int_sub(i6, 1)
  3464. setfield_gc(p0, i7, descr=valuedescr)
  3465. jump(p0, i22)
  3466. """
  3467. expected = """
  3468. [p0, i22]
  3469. i1 = getfield_gc(p0, descr=valuedescr)
  3470. i2 = int_gt(i1, i22)
  3471. guard_false(i2) []
  3472. i3 = int_add(i1, 1)
  3473. i331 = force_token()
  3474. jump(p0, i22)
  3475. """
  3476. self.optimize_loop(ops, expected)
  3477. def test_addsub_ovf(self):
  3478. ops = """
  3479. [i0]
  3480. i1 = int_add_ovf(i0, 10)
  3481. guard_no_overflow() []
  3482. i2 = int_sub_ovf(i1, 5)
  3483. guard_no_overflow() []
  3484. jump(i2)
  3485. """
  3486. expected = """
  3487. [i0]
  3488. i1 = int_add_ovf(i0, 10)
  3489. guard_no_overflow() []
  3490. i2 = int_sub(i1, 5)
  3491. jump(i2)
  3492. """
  3493. self.optimize_loop(ops, expected)
  3494. def test_subadd_ovf(self):
  3495. ops = """
  3496. [i0]
  3497. i1 = int_sub_ovf(i0, 10)
  3498. guard_no_overflow() []
  3499. i2 = int_add_ovf(i1, 5)
  3500. guard_no_overflow() []
  3501. jump(i2)
  3502. """
  3503. expected = """
  3504. [i0]
  3505. i1 = int_sub_ovf(i0, 10)
  3506. guard_no_overflow() []
  3507. i2 = int_add(i1, 5)
  3508. jump(i2)
  3509. """
  3510. self.optimize_loop(ops, expected)
  3511. def test_bound_and(self):
  3512. ops = """
  3513. [i0]
  3514. i1 = int_and(i0, 255)
  3515. i2 = int_lt(i1, 500)
  3516. guard_true(i2) []
  3517. i3 = int_le(i1, 255)
  3518. guard_true(i3) []
  3519. i4 = int_gt(i1, -1)
  3520. guard_true(i4) []
  3521. i5 = int_ge(i1, 0)
  3522. guard_true(i5) []
  3523. i6 = int_lt(i1, 0)
  3524. guard_false(i6) []
  3525. i7 = int_le(i1, -1)
  3526. guard_false(i7) []
  3527. i8 = int_gt(i1, 255)
  3528. guard_false(i8) []
  3529. i9 = int_ge(i1, 500)
  3530. guard_false(i9) []
  3531. i12 = int_lt(i1, 100)
  3532. guard_true(i12) []
  3533. i13 = int_le(i1, 90)
  3534. guard_true(i13) []
  3535. i14 = int_gt(i1, 10)
  3536. guard_true(i14) []
  3537. i15 = int_ge(i1, 20)
  3538. guard_true(i15) []
  3539. jump(i1)
  3540. """
  3541. expected = """
  3542. [i0]
  3543. i1 = int_and(i0, 255)
  3544. i12 = int_lt(i1, 100)
  3545. guard_true(i12) []
  3546. i13 = int_le(i1, 90)
  3547. guard_true(i13) []
  3548. i14 = int_gt(i1, 10)
  3549. guard_true(i14) []
  3550. i15 = int_ge(i1, 20)
  3551. guard_true(i15) []
  3552. jump(i1)
  3553. """
  3554. self.optimize_loop(ops, expected)
  3555. def test_subsub_ovf(self):
  3556. ops = """
  3557. [i0]
  3558. i1 = int_sub_ovf(1, i0)
  3559. guard_no_overflow() []
  3560. i2 = int_gt(i1, 1)
  3561. guard_true(i2) []
  3562. i3 = int_sub_ovf(1, i0)
  3563. guard_no_overflow() []
  3564. i4 = int_gt(i3, 1)
  3565. guard_true(i4) []
  3566. jump(i0)
  3567. """
  3568. expected = """
  3569. [i0]
  3570. i1 = int_sub_ovf(1, i0)
  3571. guard_no_overflow() []
  3572. i2 = int_gt(i1, 1)
  3573. guard_true(i2) []
  3574. jump(i0)
  3575. """
  3576. self.optimize_loop(ops, expected)
  3577. def test_bound_eq(self):
  3578. ops = """
  3579. [i0, i1]
  3580. i2 = int_le(i0, 4)
  3581. guard_true(i2) []
  3582. i3 = int_eq(i0, i1)
  3583. guard_true(i3) []
  3584. i4 = int_lt(i1, 5)
  3585. guard_true(i4) []
  3586. jump(i0, i1)
  3587. """
  3588. expected = """
  3589. [i0, i1]
  3590. i2 = int_le(i0, 4)
  3591. guard_true(i2) []
  3592. i3 = int_eq(i0, i1)
  3593. guard_true(i3) []
  3594. jump(i0, i1)
  3595. """
  3596. self.optimize_loop(ops, expected)
  3597. def test_bound_eq_const(self):
  3598. ops = """
  3599. [i0]
  3600. i1 = int_eq(i0, 7)
  3601. guard_true(i1) []
  3602. i2 = int_add(i0, 3)
  3603. jump(i2)
  3604. """
  3605. expected = """
  3606. [i0]
  3607. i1 = int_eq(i0, 7)
  3608. guard_true(i1) []
  3609. jump(10)
  3610. """
  3611. self.optimize_loop(ops, expected)
  3612. def test_bound_eq_const_not(self):
  3613. ops = """
  3614. [i0]
  3615. i1 = int_eq(i0, 7)
  3616. guard_false(i1) []
  3617. i2 = int_add(i0, 3)
  3618. jump(i2)
  3619. """
  3620. expected = """
  3621. [i0]
  3622. i1 = int_eq(i0, 7)
  3623. guard_false(i1) []
  3624. i2 = int_add(i0, 3)
  3625. jump(i2)
  3626. """
  3627. self.optimize_loop(ops, expected)
  3628. def test_bound_ne_const(self):
  3629. ops = """
  3630. [i0]
  3631. i1 = int_ne(i0, 7)
  3632. guard_false(i1) []
  3633. i2 = int_add(i0, 3)
  3634. jump(i2)
  3635. """
  3636. expected = """
  3637. [i0]
  3638. i1 = int_ne(i0, 7)
  3639. guard_false(i1) []
  3640. jump(10)
  3641. """
  3642. self.optimize_loop(ops, expected)
  3643. def test_bound_ne_const_not(self):
  3644. ops = """
  3645. [i0]
  3646. i1 = int_ne(i0, 7)
  3647. guard_true(i1) []
  3648. i2 = int_add(i0, 3)
  3649. jump(i2)
  3650. """
  3651. expected = """
  3652. [i0]
  3653. i1 = int_ne(i0, 7)
  3654. guard_true(i1) []
  3655. i2 = int_add(i0, 3)
  3656. jump(i2)
  3657. """
  3658. self.optimize_loop(ops, expected)
  3659. def test_bound_ltne(self):
  3660. ops = """
  3661. [i0, i1]
  3662. i2 = int_lt(i0, 7)
  3663. guard_true(i2) []
  3664. i3 = int_ne(i0, 10)
  3665. guard_true(i2) []
  3666. jump(i0, i1)
  3667. """
  3668. expected = """
  3669. [i0, i1]
  3670. i2 = int_lt(i0, 7)
  3671. guard_true(i2) []
  3672. jump(i0, i1)
  3673. """
  3674. self.optimize_loop(ops, expected)
  3675. def test_bound_lege_const(self):
  3676. ops = """
  3677. [i0]
  3678. i1 = int_ge(i0, 7)
  3679. guard_true(i1) []
  3680. i2 = int_le(i0, 7)
  3681. guard_true(i2) []
  3682. i3 = int_add(i0, 3)
  3683. jump(i3)
  3684. """
  3685. expected = """
  3686. [i0]
  3687. i1 = int_ge(i0, 7)
  3688. guard_true(i1) []
  3689. i2 = int_le(i0, 7)
  3690. guard_true(i2) []
  3691. jump(10)
  3692. """
  3693. self.optimize_loop(ops, expected)
  3694. def test_mul_ovf(self):
  3695. ops = """
  3696. [i0, i1]
  3697. i2 = int_and(i0, 255)
  3698. i3 = int_lt(i1, 5)
  3699. guard_true(i3) []
  3700. i4 = int_gt(i1, -10)
  3701. guard_true(i4) []
  3702. i5 = int_mul_ovf(i2, i1)
  3703. guard_no_overflow() []
  3704. i6 = int_lt(i5, -2550)
  3705. guard_false(i6) []
  3706. i7 = int_ge(i5, 1276)
  3707. guard_false(i7) []
  3708. i8 = int_gt(i5, 126)
  3709. guard_true(i8) []
  3710. jump(i0, i1)
  3711. """
  3712. expected = """
  3713. [i0, i1]
  3714. i2 = int_and(i0, 255)
  3715. i3 = int_lt(i1, 5)
  3716. guard_true(i3) []
  3717. i4 = int_gt(i1, -10)
  3718. guard_true(i4) []
  3719. i5 = int_mul(i2, i1)
  3720. i8 = int_gt(i5, 126)
  3721. guard_true(i8) []
  3722. jump(i0, i1)
  3723. """
  3724. self.optimize_loop(ops, expected)
  3725. def test_mul_ovf_before(self):
  3726. ops = """
  3727. [i0, i1]
  3728. i2 = int_and(i0, 255)
  3729. i22 = int_add(i2, 1)
  3730. i3 = int_mul_ovf(i22, i1)
  3731. guard_no_overflow() []
  3732. i4 = int_lt(i3, 10)
  3733. guard_true(i4) []
  3734. i5 = int_gt(i3, 2)
  3735. guard_true(i5) []
  3736. i6 = int_lt(i1, 0)
  3737. guard_false(i6) []
  3738. jump(i0, i1)
  3739. """
  3740. expected = """
  3741. [i0, i1]
  3742. i2 = int_and(i0, 255)
  3743. i22 = int_add(i2, 1)
  3744. i3 = int_mul_ovf(i22, i1)
  3745. guard_no_overflow() []
  3746. i4 = int_lt(i3, 10)
  3747. guard_true(i4) []
  3748. i5 = int_gt(i3, 2)
  3749. guard_true(i5) []
  3750. jump(i0, i1)
  3751. """
  3752. self.optimize_loop(ops, expected)
  3753. def test_sub_ovf_before(self):
  3754. ops = """
  3755. [i0, i1]
  3756. i2 = int_and(i0, 255)
  3757. i3 = int_sub_ovf(i2, i1)
  3758. guard_no_overflow() []
  3759. i4 = int_le(i3, 10)
  3760. guard_true(i4) []
  3761. i5 = int_ge(i3, 2)
  3762. guard_true(i5) []
  3763. i6 = int_lt(i1, -10)
  3764. guard_false(i6) []
  3765. i7 = int_gt(i1, 253)
  3766. guard_false(i7) []
  3767. jump(i0, i1)
  3768. """
  3769. expected = """
  3770. [i0, i1]
  3771. i2 = int_and(i0, 255)
  3772. i3 = int_sub_ovf(i2, i1)
  3773. guard_no_overflow() []
  3774. i4 = int_le(i3, 10)
  3775. guard_true(i4) []
  3776. i5 = int_ge(i3, 2)
  3777. guard_true(i5) []
  3778. jump(i0, i1)
  3779. """
  3780. self.optimize_loop(ops, expected)
  3781. # ----------
  3782. def optimize_strunicode_loop(self, ops, optops):
  3783. # check with the arguments passed in
  3784. self.optimize_loop(ops, optops)
  3785. # check with replacing 'str' with 'unicode' everywhere
  3786. self.optimize_loop(ops.replace('str','unicode').replace('s"', 'u"'),
  3787. optops.replace('str','unicode').replace('s"', 'u"'))
  3788. def test_newstr_1(self):
  3789. ops = """
  3790. [i0]
  3791. p1 = newstr(1)
  3792. strsetitem(p1, 0, i0)
  3793. i1 = strgetitem(p1, 0)
  3794. jump(i1)
  3795. """
  3796. expected = """
  3797. [i0]
  3798. jump(i0)
  3799. """
  3800. self.optimize_strunicode_loop(ops, expected)
  3801. def test_newstr_2(self):
  3802. ops = """
  3803. [i0, i1]
  3804. p1 = newstr(2)
  3805. strsetitem(p1, 0, i0)
  3806. strsetitem(p1, 1, i1)
  3807. i2 = strgetitem(p1, 1)
  3808. i3 = strgetitem(p1, 0)
  3809. jump(i2, i3)
  3810. """
  3811. expected = """
  3812. [i0, i1]
  3813. jump(i1, i0)
  3814. """
  3815. self.optimize_strunicode_loop(ops, expected)
  3816. def test_str_concat_1(self):
  3817. ops = """
  3818. [p1, p2]
  3819. p3 = call(0, p1, p2, descr=strconcatdescr)
  3820. jump(p2, p3)
  3821. """
  3822. expected = """
  3823. [p1, p2]
  3824. i1 = strlen(p1)
  3825. i2 = strlen(p2)
  3826. i3 = int_add(i1, i2)
  3827. p3 = newstr(i3)
  3828. copystrcontent(p1, p3, 0, 0, i1)
  3829. copystrcontent(p2, p3, 0, i1, i2)
  3830. jump(p2, p3)
  3831. """
  3832. self.optimize_strunicode_loop(ops, expected)
  3833. def test_str_concat_vstr2_str(self):
  3834. ops = """
  3835. [i0, i1, p2]
  3836. p1 = newstr(2)
  3837. strsetitem(p1, 0, i0)
  3838. strsetitem(p1, 1, i1)
  3839. p3 = call(0, p1, p2, descr=strconcatdescr)
  3840. jump(i1, i0, p3)
  3841. """
  3842. expected = """
  3843. [i0, i1, p2]
  3844. i2 = strlen(p2)
  3845. i3 = int_add(2, i2)
  3846. p3 = newstr(i3)
  3847. strsetitem(p3, 0, i0)
  3848. strsetitem(p3, 1, i1)
  3849. copystrcontent(p2, p3, 0, 2, i2)
  3850. jump(i1, i0, p3)
  3851. """
  3852. self.optimize_strunicode_loop(ops, expected)
  3853. def test_str_concat_str_vstr2(self):
  3854. ops = """
  3855. [i0, i1, p2]
  3856. p1 = newstr(2)
  3857. strsetitem(p1, 0, i0)
  3858. strsetitem(p1, 1, i1)
  3859. p3 = call(0, p2, p1, descr=strconcatdescr)
  3860. jump(i1, i0, p3)
  3861. """
  3862. expected = """
  3863. [i0, i1, p2]
  3864. i2 = strlen(p2)
  3865. i3 = int_add(i2, 2)
  3866. p3 = newstr(i3)
  3867. copystrcontent(p2, p3, 0, 0, i2)
  3868. strsetitem(p3, i2, i0)
  3869. i5 = int_add(i2, 1)
  3870. strsetitem(p3, i5, i1)
  3871. i6 = int_add(i5, 1) # will be killed by the backend
  3872. jump(i1, i0, p3)
  3873. """
  3874. self.optimize_strunicode_loop(ops, expected)
  3875. def test_str_concat_str_str_str(self):
  3876. ops = """
  3877. [p1, p2, p3]
  3878. p4 = call(0, p1, p2, descr=strconcatdescr)
  3879. p5 = call(0, p4, p3, descr=strconcatdescr)
  3880. jump(p2, p3, p5)
  3881. """
  3882. expected = """
  3883. [p1, p2, p3]
  3884. i1 = strlen(p1)
  3885. i2 = strlen(p2)
  3886. i12 = int_add(i1, i2)
  3887. i3 = strlen(p3)
  3888. i123 = int_add(i12, i3)
  3889. p5 = newstr(i123)
  3890. copystrcontent(p1, p5, 0, 0, i1)
  3891. copystrcontent(p2, p5, 0, i1, i2)
  3892. copystrcontent(p3, p5, 0, i12, i3)
  3893. jump(p2, p3, p5)
  3894. """
  3895. self.optimize_strunicode_loop(ops, expected)
  3896. def test_str_concat_str_cstr1(self):
  3897. ops = """
  3898. [p2]
  3899. p3 = call(0, p2, s"x", descr=strconcatdescr)
  3900. jump(p3)
  3901. """
  3902. expected = """
  3903. [p2]
  3904. i2 = strlen(p2)
  3905. i3 = int_add(i2, 1)
  3906. p3 = newstr(i3)
  3907. copystrcontent(p2, p3, 0, 0, i2)
  3908. strsetitem(p3, i2, 120) # == ord('x')
  3909. jump(p3)
  3910. """
  3911. self.optimize_strunicode_loop(ops, expected)
  3912. def test_str_concat_consts(self):
  3913. ops = """
  3914. []
  3915. p1 = same_as(s"ab")
  3916. p2 = same_as(s"cde")
  3917. p3 = call(0, p1, p2, descr=strconcatdescr)
  3918. escape(p3)
  3919. jump()
  3920. """
  3921. expected = """
  3922. []
  3923. escape(s"abcde")
  3924. jump()
  3925. """
  3926. self.optimize_strunicode_loop(ops, expected)
  3927. def test_str_concat_constant_lengths(self):
  3928. ops = """
  3929. [i0]
  3930. p0 = newstr(1)
  3931. strsetitem(p0, 0, i0)
  3932. p1 = newstr(0)
  3933. p2 = call(0, p0, p1, descr=strconcatdescr)
  3934. i1 = call(0, p2, p0, descr=strequaldescr)
  3935. finish(i1)
  3936. """
  3937. expected = """
  3938. [i0]
  3939. finish(1)
  3940. """
  3941. self.optimize_strunicode_loop(ops, expected)
  3942. def test_str_concat_constant_lengths_2(self):
  3943. ops = """
  3944. [i0]
  3945. p0 = newstr(0)
  3946. p1 = newstr(1)
  3947. strsetitem(p1, 0, i0)
  3948. p2 = call(0, p0, p1, descr=strconcatdescr)
  3949. i1 = call(0, p2, p1, descr=strequaldescr)
  3950. finish(i1)
  3951. """
  3952. expected = """
  3953. [i0]
  3954. finish(1)
  3955. """
  3956. self.optimize_strunicode_loop(ops, expected)
  3957. def test_str_slice_1(self):
  3958. ops = """
  3959. [p1, i1, i2]
  3960. p2 = call(0, p1, i1, i2, descr=strslicedescr)
  3961. jump(p2, i1, i2)
  3962. """
  3963. expected = """
  3964. [p1, i1, i2]
  3965. i3 = int_sub(i2, i1)
  3966. p2 = newstr(i3)
  3967. copystrcontent(p1, p2, i1, 0, i3)
  3968. jump(p2, i1, i2)
  3969. """
  3970. self.optimize_strunicode_loop(ops, expected)
  3971. def test_str_slice_2(self):
  3972. ops = """
  3973. [p1, i2]
  3974. p2 = call(0, p1, 0, i2, descr=strslicedescr)
  3975. jump(p2, i2)
  3976. """
  3977. expected = """
  3978. [p1, i2]
  3979. p2 = newstr(i2)
  3980. copystrcontent(p1, p2, 0, 0, i2)
  3981. jump(p2, i2)
  3982. """
  3983. self.optimize_strunicode_loop(ops, expected)
  3984. def test_str_slice_3(self):
  3985. ops = """
  3986. [p1, i1, i2, i3, i4]
  3987. p2 = call(0, p1, i1, i2, descr=strslicedescr)
  3988. p3 = call(0, p2, i3, i4, descr=strslicedescr)
  3989. jump(p3, i1, i2, i3, i4)
  3990. """
  3991. expected = """
  3992. [p1, i1, i2, i3, i4]
  3993. i0 = int_sub(i2, i1) # killed by the backend
  3994. i5 = int_sub(i4, i3)
  3995. i6 = int_add(i1, i3)
  3996. p3 = newstr(i5)
  3997. copystrcontent(p1, p3, i6, 0, i5)
  3998. jump(p3, i1, i2, i3, i4)
  3999. """
  4000. self.optimize_strunicode_loop(ops, expected)
  4001. def test_str_slice_getitem1(self):
  4002. ops = """
  4003. [p1, i1, i2, i3]
  4004. p2 = call(0, p1, i1, i2, descr=strslicedescr)
  4005. i4 = strgetitem(p2, i3)
  4006. escape(i4)
  4007. jump(p1, i1, i2, i3)
  4008. """
  4009. expected = """
  4010. [p1, i1, i2, i3]
  4011. i6 = int_sub(i2, i1) # killed by the backend
  4012. i5 = int_add(i1, i3)
  4013. i4 = strgetitem(p1, i5)
  4014. escape(i4)
  4015. jump(p1, i1, i2, i3)
  4016. """
  4017. self.optimize_strunicode_loop(ops, expected)
  4018. def test_str_slice_plain(self):
  4019. ops = """
  4020. [i3, i4]
  4021. p1 = newstr(2)
  4022. strsetitem(p1, 0, i3)
  4023. strsetitem(p1, 1, i4)
  4024. p2 = call(0, p1, 1, 2, descr=strslicedescr)
  4025. i5 = strgetitem(p2, 0)
  4026. escape(i5)
  4027. jump(i3, i4)
  4028. """
  4029. expected = """
  4030. [i3, i4]
  4031. escape(i4)
  4032. jump(i3, i4)
  4033. """
  4034. self.optimize_strunicode_loop(ops, expected)
  4035. def test_str_slice_concat(self):
  4036. ops = """
  4037. [p1, i1, i2, p2]
  4038. p3 = call(0, p1, i1, i2, descr=strslicedescr)
  4039. p4 = call(0, p3, p2, descr=strconcatdescr)
  4040. jump(p4, i1, i2, p2)
  4041. """
  4042. expected = """
  4043. [p1, i1, i2, p2]
  4044. i3 = int_sub(i2, i1) # length of p3
  4045. i4 = strlen(p2)
  4046. i5 = int_add(i3, i4)
  4047. p4 = newstr(i5)
  4048. copystrcontent(p1, p4, i1, 0, i3)
  4049. copystrcontent(p2, p4, 0, i3, i4)
  4050. jump(p4, i1, i2, p2)
  4051. """
  4052. self.optimize_strunicode_loop(ops, expected)
  4053. def test_str_slice_plain_virtual(self):
  4054. ops = """
  4055. []
  4056. p0 = newstr(11)
  4057. copystrcontent(s"hello world", p0, 0, 0, 11)
  4058. p1 = call(0, p0, 0, 5, descr=strslicedescr)
  4059. finish(p1)
  4060. """
  4061. expected = """
  4062. []
  4063. p0 = newstr(11)
  4064. copystrcontent(s"hello world", p0, 0, 0, 11)
  4065. # Eventually this should just return s"hello", but ATM this test is
  4066. # just verifying that it doesn't return "\0\0\0\0\0", so being
  4067. # slightly underoptimized is ok.
  4068. p1 = newstr(5)
  4069. copystrcontent(p0, p1, 0, 0, 5)
  4070. finish(p1)
  4071. """
  4072. self.optimize_strunicode_loop(ops, expected)
  4073. # ----------
  4074. def optimize_strunicode_loop_extradescrs(self, ops, optops):
  4075. class FakeCallInfoCollection:
  4076. def callinfo_for_oopspec(self, oopspecindex):
  4077. calldescrtype = type(LLtypeMixin.strequaldescr)
  4078. effectinfotype = type(LLtypeMixin.strequaldescr.get_extra_info())
  4079. for value in LLtypeMixin.__dict__.values():
  4080. if isinstance(value, calldescrtype):
  4081. extra = value.get_extra_info()
  4082. if (extra and isinstance(extra, effectinfotype) and
  4083. extra.oopspecindex == oopspecindex):
  4084. # returns 0 for 'func' in this test
  4085. return value, 0
  4086. raise AssertionError("not found: oopspecindex=%d" %
  4087. oopspecindex)
  4088. #
  4089. self.callinfocollection = FakeCallInfoCollection()
  4090. self.optimize_strunicode_loop(ops, optops)
  4091. def test_str_equal_noop1(self):
  4092. ops = """
  4093. [p1, p2]
  4094. i0 = call(0, p1, p2, descr=strequaldescr)
  4095. escape(i0)
  4096. jump(p1, p2)
  4097. """
  4098. self.optimize_strunicode_loop_extradescrs(ops, ops)
  4099. def test_str_equal_noop2(self):
  4100. ops = """
  4101. [p1, p2, p3]
  4102. p4 = call(0, p1, p2, descr=strconcatdescr)
  4103. i0 = call(0, p3, p4, descr=strequaldescr)
  4104. escape(i0)
  4105. jump(p1, p2, p3)
  4106. """
  4107. expected = """
  4108. [p1, p2, p3]
  4109. i1 = strlen(p1)
  4110. i2 = strlen(p2)
  4111. i3 = int_add(i1, i2)
  4112. p4 = newstr(i3)
  4113. copystrcontent(p1, p4, 0, 0, i1)
  4114. copystrcontent(p2, p4, 0, i1, i2)
  4115. i0 = call(0, p3, p4, descr=strequaldescr)
  4116. escape(i0)
  4117. jump(p1, p2, p3)
  4118. """
  4119. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4120. def test_str_equal_slice1(self):
  4121. ops = """
  4122. [p1, i1, i2, p3]
  4123. p4 = call(0, p1, i1, i2, descr=strslicedescr)
  4124. i0 = call(0, p4, p3, descr=strequaldescr)
  4125. escape(i0)
  4126. jump(p1, i1, i2, p3)
  4127. """
  4128. expected = """
  4129. [p1, i1, i2, p3]
  4130. i3 = int_sub(i2, i1)
  4131. i0 = call(0, p1, i1, i3, p3, descr=streq_slice_checknull_descr)
  4132. escape(i0)
  4133. jump(p1, i1, i2, p3)
  4134. """
  4135. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4136. def test_str_equal_slice2(self):
  4137. ops = """
  4138. [p1, i1, i2, p3]
  4139. p4 = call(0, p1, i1, i2, descr=strslicedescr)
  4140. i0 = call(0, p3, p4, descr=strequaldescr)
  4141. escape(i0)
  4142. jump(p1, i1, i2, p3)
  4143. """
  4144. expected = """
  4145. [p1, i1, i2, p3]
  4146. i4 = int_sub(i2, i1)
  4147. i0 = call(0, p1, i1, i4, p3, descr=streq_slice_checknull_descr)
  4148. escape(i0)
  4149. jump(p1, i1, i2, p3)
  4150. """
  4151. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4152. def test_str_equal_slice3(self):
  4153. ops = """
  4154. [p1, i1, i2, p3]
  4155. guard_nonnull(p3) []
  4156. p4 = call(0, p1, i1, i2, descr=strslicedescr)
  4157. i0 = call(0, p3, p4, descr=strequaldescr)
  4158. escape(i0)
  4159. jump(p1, i1, i2, p3)
  4160. """
  4161. expected = """
  4162. [p1, i1, i2, p3]
  4163. guard_nonnull(p3) []
  4164. i4 = int_sub(i2, i1)
  4165. i0 = call(0, p1, i1, i4, p3, descr=streq_slice_nonnull_descr)
  4166. escape(i0)
  4167. jump(p1, i1, i2, p3)
  4168. """
  4169. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4170. def test_str_equal_slice4(self):
  4171. ops = """
  4172. [p1, i1, i2]
  4173. p3 = call(0, p1, i1, i2, descr=strslicedescr)
  4174. i0 = call(0, p3, s"x", descr=strequaldescr)
  4175. escape(i0)
  4176. jump(p1, i1, i2)
  4177. """
  4178. expected = """
  4179. [p1, i1, i2]
  4180. i3 = int_sub(i2, i1)
  4181. i0 = call(0, p1, i1, i3, 120, descr=streq_slice_char_descr)
  4182. escape(i0)
  4183. jump(p1, i1, i2)
  4184. """
  4185. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4186. def test_str_equal_slice5(self):
  4187. ops = """
  4188. [p1, i1, i2, i3]
  4189. p4 = call(0, p1, i1, i2, descr=strslicedescr)
  4190. p5 = newstr(1)
  4191. strsetitem(p5, 0, i3)
  4192. i0 = call(0, p5, p4, descr=strequaldescr)
  4193. escape(i0)
  4194. jump(p1, i1, i2, i3)
  4195. """
  4196. expected = """
  4197. [p1, i1, i2, i3]
  4198. i4 = int_sub(i2, i1)
  4199. i0 = call(0, p1, i1, i4, i3, descr=streq_slice_char_descr)
  4200. escape(i0)
  4201. jump(p1, i1, i2, i3)
  4202. """
  4203. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4204. def test_str_equal_none1(self):
  4205. ops = """
  4206. [p1]
  4207. i0 = call(0, p1, NULL, descr=strequaldescr)
  4208. escape(i0)
  4209. jump(p1)
  4210. """
  4211. expected = """
  4212. [p1]
  4213. i0 = ptr_eq(p1, NULL)
  4214. escape(i0)
  4215. jump(p1)
  4216. """
  4217. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4218. def test_str_equal_none2(self):
  4219. ops = """
  4220. [p1]
  4221. i0 = call(0, NULL, p1, descr=strequaldescr)
  4222. escape(i0)
  4223. jump(p1)
  4224. """
  4225. expected = """
  4226. [p1]
  4227. i0 = ptr_eq(p1, NULL)
  4228. escape(i0)
  4229. jump(p1)
  4230. """
  4231. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4232. def test_str_equal_nonnull1(self):
  4233. ops = """
  4234. [p1]
  4235. guard_nonnull(p1) []
  4236. i0 = call(0, p1, s"hello world", descr=strequaldescr)
  4237. escape(i0)
  4238. jump(p1)
  4239. """
  4240. expected = """
  4241. [p1]
  4242. guard_nonnull(p1) []
  4243. i0 = call(0, p1, s"hello world", descr=streq_nonnull_descr)
  4244. escape(i0)
  4245. jump(p1)
  4246. """
  4247. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4248. def test_str_equal_nonnull2(self):
  4249. ops = """
  4250. [p1]
  4251. guard_nonnull(p1) []
  4252. i0 = call(0, p1, s"", descr=strequaldescr)
  4253. escape(i0)
  4254. jump(p1)
  4255. """
  4256. expected = """
  4257. [p1]
  4258. guard_nonnull(p1) []
  4259. i1 = strlen(p1)
  4260. i0 = int_eq(i1, 0)
  4261. escape(i0)
  4262. jump(p1)
  4263. """
  4264. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4265. def test_str_equal_nonnull3(self):
  4266. ops = """
  4267. [p1]
  4268. guard_nonnull(p1) []
  4269. i0 = call(0, p1, s"x", descr=strequaldescr)
  4270. escape(i0)
  4271. jump(p1)
  4272. """
  4273. expected = """
  4274. [p1]
  4275. guard_nonnull(p1) []
  4276. i0 = call(0, p1, 120, descr=streq_nonnull_char_descr)
  4277. escape(i0)
  4278. jump(p1)
  4279. """
  4280. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4281. def test_str_equal_nonnull4(self):
  4282. ops = """
  4283. [p1, p2]
  4284. p4 = call(0, p1, p2, descr=strconcatdescr)
  4285. i0 = call(0, s"hello world", p4, descr=strequaldescr)
  4286. escape(i0)
  4287. jump(p1, p2)
  4288. """
  4289. expected = """
  4290. [p1, p2]
  4291. i1 = strlen(p1)
  4292. i2 = strlen(p2)
  4293. i3 = int_add(i1, i2)
  4294. p4 = newstr(i3)
  4295. copystrcontent(p1, p4, 0, 0, i1)
  4296. copystrcontent(p2, p4, 0, i1, i2)
  4297. i0 = call(0, s"hello world", p4, descr=streq_nonnull_descr)
  4298. escape(i0)
  4299. jump(p1, p2)
  4300. """
  4301. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4302. def test_str_equal_chars0(self):
  4303. ops = """
  4304. [i1]
  4305. p1 = newstr(0)
  4306. i0 = call(0, p1, s"", descr=strequaldescr)
  4307. escape(i0)
  4308. jump(i1)
  4309. """
  4310. expected = """
  4311. [i1]
  4312. escape(1)
  4313. jump(i1)
  4314. """
  4315. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4316. def test_str_equal_chars1(self):
  4317. ops = """
  4318. [i1]
  4319. p1 = newstr(1)
  4320. strsetitem(p1, 0, i1)
  4321. i0 = call(0, p1, s"x", descr=strequaldescr)
  4322. escape(i0)
  4323. jump(i1)
  4324. """
  4325. expected = """
  4326. [i1]
  4327. i0 = int_eq(i1, 120) # ord('x')
  4328. escape(i0)
  4329. jump(i1)
  4330. """
  4331. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4332. def test_str_equal_chars2(self):
  4333. ops = """
  4334. [i1, i2]
  4335. p1 = newstr(2)
  4336. strsetitem(p1, 0, i1)
  4337. strsetitem(p1, 1, i2)
  4338. i0 = call(0, p1, s"xy", descr=strequaldescr)
  4339. escape(i0)
  4340. jump(i1, i2)
  4341. """
  4342. expected = """
  4343. [i1, i2]
  4344. p1 = newstr(2)
  4345. strsetitem(p1, 0, i1)
  4346. strsetitem(p1, 1, i2)
  4347. i0 = call(0, p1, s"xy", descr=streq_lengthok_descr)
  4348. escape(i0)
  4349. jump(i1, i2)
  4350. """
  4351. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4352. def test_str_equal_chars3(self):
  4353. ops = """
  4354. [p1]
  4355. i0 = call(0, s"x", p1, descr=strequaldescr)
  4356. escape(i0)
  4357. jump(p1)
  4358. """
  4359. expected = """
  4360. [p1]
  4361. i0 = call(0, p1, 120, descr=streq_checknull_char_descr)
  4362. escape(i0)
  4363. jump(p1)
  4364. """
  4365. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4366. def test_str_equal_lengthmismatch1(self):
  4367. ops = """
  4368. [i1]
  4369. p1 = newstr(1)
  4370. strsetitem(p1, 0, i1)
  4371. i0 = call(0, s"xy", p1, descr=strequaldescr)
  4372. escape(i0)
  4373. jump(i1)
  4374. """
  4375. expected = """
  4376. [i1]
  4377. escape(0)
  4378. jump(i1)
  4379. """
  4380. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4381. def test_str2unicode_constant(self):
  4382. ops = """
  4383. []
  4384. p0 = call(0, "xy", descr=s2u_descr) # string -> unicode
  4385. escape(p0)
  4386. jump()
  4387. """
  4388. expected = """
  4389. []
  4390. escape(u"xy")
  4391. jump()
  4392. """
  4393. self.optimize_strunicode_loop_extradescrs(ops, expected)
  4394. def test_str2unicode_nonconstant(self):
  4395. ops = """
  4396. [p0]
  4397. p1 = call(0, p0, descr=s2u_descr) # string -> unicode
  4398. escape(p1)
  4399. jump(p1)
  4400. """
  4401. self.optimize_strunicode_loop_extradescrs(ops, ops)
  4402. # more generally, supporting non-constant but virtual cases is
  4403. # not obvious, because of the exception UnicodeDecodeError that
  4404. # can be raised by ll_str2unicode()
  4405. def test_strgetitem_repeated(self):
  4406. ops = """
  4407. [p0, i0]
  4408. i1 = strgetitem(p0, i0)
  4409. i2 = strgetitem(p0, i0)
  4410. i3 = int_eq(i1, i2)
  4411. guard_true(i3) []
  4412. escape(i2)
  4413. jump(p0, i0)
  4414. """
  4415. expected = """
  4416. [p0, i0]
  4417. i1 = strgetitem(p0, i0)
  4418. escape(i1)
  4419. jump(p0, i0)
  4420. """
  4421. self.optimize_strunicode_loop(ops, expected)
  4422. def test_int_is_true_bounds(self):
  4423. ops = """
  4424. [p0]
  4425. i0 = strlen(p0)
  4426. i1 = int_is_true(i0)
  4427. guard_true(i1) []
  4428. i2 = int_ge(0, i0)
  4429. guard_false(i2) []
  4430. jump(p0)
  4431. """
  4432. expected = """
  4433. [p0]
  4434. i0 = strlen(p0)
  4435. i1 = int_is_true(i0)
  4436. guard_true(i1) []
  4437. jump(p0)
  4438. """
  4439. self.optimize_strunicode_loop(ops, expected)
  4440. def test_strslice_subtraction_folds(self):
  4441. ops = """
  4442. [p0, i0]
  4443. i1 = int_add(i0, 1)
  4444. p1 = call(0, p0, i0, i1, descr=strslicedescr)
  4445. escape(p1)
  4446. jump(p0, i1)
  4447. """
  4448. expected = """
  4449. [p0, i0]
  4450. i1 = int_add(i0, 1)
  4451. p1 = newstr(1)
  4452. i2 = strgetitem(p0, i0)
  4453. strsetitem(p1, 0, i2)
  4454. escape(p1)
  4455. jump(p0, i1)
  4456. """
  4457. self.optimize_strunicode_loop(ops, expected)
  4458. def test_float_mul_reversed(self):
  4459. ops = """
  4460. [f0, f1]
  4461. f2 = float_mul(f0, f1)
  4462. f3 = float_mul(f1, f0)
  4463. jump(f2, f3)
  4464. """
  4465. expected = """
  4466. [f0, f1]
  4467. f2 = float_mul(f0, f1)
  4468. jump(f2, f2)
  4469. """
  4470. self.optimize_loop(ops, expected)
  4471. def test_null_char_str(self):
  4472. ops = """
  4473. [p0]
  4474. p1 = newstr(4)
  4475. setfield_gc(p0, p1, descr=valuedescr)
  4476. jump(p0)
  4477. """
  4478. # It used to be the case that this would have a series of
  4479. # strsetitem(p1, idx, 0), which was silly because memory is 0 filled
  4480. # when allocated.
  4481. expected = """
  4482. [p0]
  4483. p1 = newstr(4)
  4484. setfield_gc(p0, p1, descr=valuedescr)
  4485. jump(p0)
  4486. """
  4487. self.optimize_strunicode_loop(ops, expected)
  4488. def test_newstr_strlen(self):
  4489. ops = """
  4490. [i0]
  4491. p0 = newstr(i0)
  4492. escape(p0)
  4493. i1 = strlen(p0)
  4494. i2 = int_add(i1, 1)
  4495. jump(i2)
  4496. """
  4497. expected = """
  4498. [i0]
  4499. p0 = newstr(i0)
  4500. escape(p0)
  4501. i1 = int_add(i0, 1)
  4502. jump(i1)
  4503. """
  4504. self.optimize_strunicode_loop(ops, expected)
  4505. def test_intmod_bounds(self):
  4506. ops = """
  4507. [i0, i1]
  4508. i2 = int_mod(i0, 12)
  4509. i3 = int_gt(i2, 12)
  4510. guard_false(i3) []
  4511. i4 = int_lt(i2, -12)
  4512. guard_false(i4) []
  4513. i5 = int_mod(i1, -12)
  4514. i6 = int_lt(i5, -12)
  4515. guard_false(i6) []
  4516. i7 = int_gt(i5, 12)
  4517. guard_false(i7) []
  4518. jump(i2, i5)
  4519. """
  4520. expected = """
  4521. [i0, i1]
  4522. i2 = int_mod(i0, 12)
  4523. i5 = int_mod(i1, -12)
  4524. jump(i2, i5)
  4525. """
  4526. self.optimize_loop(ops, expected)
  4527. # This the sequence of resoperations that is generated for a Python
  4528. # app-level int % int. When the modulus is constant and when i0
  4529. # is known non-negative it should be optimized to a single int_mod.
  4530. ops = """
  4531. [i0]
  4532. i5 = int_ge(i0, 0)
  4533. guard_true(i5) []
  4534. i1 = int_mod(i0, 42)
  4535. i2 = int_rshift(i1, %d)
  4536. i3 = int_and(42, i2)
  4537. i4 = int_add(i1, i3)
  4538. finish(i4)
  4539. """ % (LONG_BIT-1)
  4540. expected = """
  4541. [i0]
  4542. i5 = int_ge(i0, 0)
  4543. guard_true(i5) []
  4544. i1 = int_mod(i0, 42)
  4545. finish(i1)
  4546. """
  4547. self.optimize_loop(ops, expected)
  4548. # 'n % power-of-two' can be turned into int_and(); at least that's
  4549. # easy to do now if n is known to be non-negative.
  4550. ops = """
  4551. [i0]
  4552. i5 = int_ge(i0, 0)
  4553. guard_true(i5) []
  4554. i1 = int_mod(i0, 8)
  4555. i2 = int_rshift(i1, %d)
  4556. i3 = int_and(42, i2)
  4557. i4 = int_add(i1, i3)
  4558. finish(i4)
  4559. """ % (LONG_BIT-1)
  4560. expected = """
  4561. [i0]
  4562. i5 = int_ge(i0, 0)
  4563. guard_true(i5) []
  4564. i1 = int_and(i0, 7)
  4565. finish(i1)
  4566. """
  4567. self.optimize_loop(ops, expected)
  4568. # Of course any 'maybe-negative % power-of-two' can be turned into
  4569. # int_and(), but that's a bit harder to detect here because it turns
  4570. # into several operations, and of course it is wrong to just turn
  4571. # int_mod(i0, 16) into int_and(i0, 15).
  4572. ops = """
  4573. [i0]
  4574. i1 = int_mod(i0, 16)
  4575. i2 = int_rshift(i1, %d)
  4576. i3 = int_and(16, i2)
  4577. i4 = int_add(i1, i3)
  4578. finish(i4)
  4579. """ % (LONG_BIT-1)
  4580. expected = """
  4581. [i0]
  4582. i4 = int_and(i0, 15)
  4583. finish(i4)
  4584. """
  4585. py.test.skip("harder")
  4586. self.optimize_loop(ops, expected)
  4587. def test_intmod_bounds_bug1(self):
  4588. ops = """
  4589. [i0]
  4590. i1 = int_mod(i0, %d)
  4591. i2 = int_eq(i1, 0)
  4592. guard_false(i2) []
  4593. finish()
  4594. """ % (-(1<<(LONG_BIT-1)),)
  4595. self.optimize_loop(ops, ops)
  4596. def test_bounded_lazy_setfield(self):
  4597. ops = """
  4598. [p0, i0]
  4599. i1 = int_gt(i0, 2)
  4600. guard_true(i1) []
  4601. setarrayitem_gc(p0, 0, 3)
  4602. setarrayitem_gc(p0, 2, 4)
  4603. setarrayitem_gc(p0, i0, 15)
  4604. i2 = getarrayitem_gc(p0, 2)
  4605. jump(p0, i2)
  4606. """
  4607. # Remove the getarrayitem_gc, because we know that p[i0] does not alias
  4608. # p0[2]
  4609. expected = """
  4610. [p0, i0]
  4611. i1 = int_gt(i0, 2)
  4612. guard_true(i1) []
  4613. setarrayitem_gc(p0, i0, 15)
  4614. setarrayitem_gc(p0, 0, 3)
  4615. setarrayitem_gc(p0, 2, 4)
  4616. jump(p0, 4)
  4617. """
  4618. self.optimize_loop(ops, expected)
  4619. def test_empty_copystrunicontent(self):
  4620. ops = """
  4621. [p0, p1, i0, i2, i3]
  4622. i4 = int_eq(i3, 0)
  4623. guard_true(i4) []
  4624. copystrcontent(p0, p1, i0, i2, i3)
  4625. jump(p0, p1, i0, i2, i3)
  4626. """
  4627. expected = """
  4628. [p0, p1, i0, i2, i3]
  4629. i4 = int_eq(i3, 0)
  4630. guard_true(i4) []
  4631. jump(p0, p1, i0, i2, 0)
  4632. """
  4633. self.optimize_strunicode_loop(ops, expected)
  4634. def test_empty_copystrunicontent_virtual(self):
  4635. ops = """
  4636. [p0]
  4637. p1 = newstr(23)
  4638. copystrcontent(p0, p1, 0, 0, 0)
  4639. jump(p0)
  4640. """
  4641. expected = """
  4642. [p0]
  4643. jump(p0)
  4644. """
  4645. self.optimize_strunicode_loop(ops, expected)
  4646. def test_forced_virtuals_aliasing(self):
  4647. ops = """
  4648. [i0, i1]
  4649. p0 = new(descr=ssize)
  4650. p1 = new(descr=ssize)
  4651. escape(p0)
  4652. escape(p1)
  4653. setfield_gc(p0, i0, descr=adescr)
  4654. setfield_gc(p1, i1, descr=adescr)
  4655. i2 = getfield_gc(p0, descr=adescr)
  4656. jump(i2, i2)
  4657. """
  4658. expected = """
  4659. [i0, i1]
  4660. p0 = new(descr=ssize)
  4661. escape(p0)
  4662. p1 = new(descr=ssize)
  4663. escape(p1)
  4664. setfield_gc(p0, i0, descr=adescr)
  4665. setfield_gc(p1, i1, descr=adescr)
  4666. jump(i0, i0)
  4667. """
  4668. py.test.skip("not implemented")
  4669. # setfields on things that used to be virtual still can't alias each
  4670. # other
  4671. self.optimize_loop(ops, expected)
  4672. def test_plain_virtual_string_copy_content(self):
  4673. ops = """
  4674. [i1]
  4675. p0 = newstr(6)
  4676. copystrcontent(s"hello!", p0, 0, 0, 6)
  4677. p1 = call(0, p0, s"abc123", descr=strconcatdescr)
  4678. i0 = strgetitem(p1, i1)
  4679. finish(i0)
  4680. """
  4681. expected = """
  4682. [i1]
  4683. p0 = newstr(6)
  4684. copystrcontent(s"hello!", p0, 0, 0, 6)
  4685. p1 = newstr(12)
  4686. copystrcontent(p0, p1, 0, 0, 6)
  4687. copystrcontent(s"abc123", p1, 0, 6, 6)
  4688. i0 = strgetitem(p1, i1)
  4689. finish(i0)
  4690. """
  4691. self.optimize_strunicode_loop(ops, expected)
  4692. def test_plain_virtual_string_copy_content_2(self):
  4693. ops = """
  4694. []
  4695. p0 = newstr(6)
  4696. copystrcontent(s"hello!", p0, 0, 0, 6)
  4697. p1 = call(0, p0, s"abc123", descr=strconcatdescr)
  4698. i0 = strgetitem(p1, 0)
  4699. finish(i0)
  4700. """
  4701. expected = """
  4702. []
  4703. p0 = newstr(6)
  4704. copystrcontent(s"hello!", p0, 0, 0, 6)
  4705. i0 = strgetitem(p0, 0)
  4706. finish(i0)
  4707. """
  4708. self.optimize_strunicode_loop(ops, expected)
  4709. def test_ptr_eq_str_constant(self):
  4710. ops = """
  4711. []
  4712. i0 = ptr_eq(s"abc", s"\x00")
  4713. finish(i0)
  4714. """
  4715. expected = """
  4716. []
  4717. finish(0)
  4718. """
  4719. self.optimize_loop(ops, expected)
  4720. def test_known_equal_ints(self):
  4721. py.test.skip("in-progress")
  4722. ops = """
  4723. [i0, i1, i2, p0]
  4724. i3 = int_eq(i0, i1)
  4725. guard_true(i3) []
  4726. i4 = int_lt(i2, i0)
  4727. guard_true(i4) []
  4728. i5 = int_lt(i2, i1)
  4729. guard_true(i5) []
  4730. i6 = getarrayitem_gc(p0, i2)
  4731. finish(i6)
  4732. """
  4733. expected = """
  4734. [i0, i1, i2, p0]
  4735. i3 = int_eq(i0, i1)
  4736. guard_true(i3) []
  4737. i4 = int_lt(i2, i0)
  4738. guard_true(i4) []
  4739. i6 = getarrayitem_gc(p0, i3)
  4740. finish(i6)
  4741. """
  4742. self.optimize_loop(ops, expected)
  4743. def test_str_copy_virtual(self):
  4744. ops = """
  4745. [i0]
  4746. p0 = newstr(8)
  4747. strsetitem(p0, 0, i0)
  4748. strsetitem(p0, 1, i0)
  4749. strsetitem(p0, 2, i0)
  4750. strsetitem(p0, 3, i0)
  4751. strsetitem(p0, 4, i0)
  4752. strsetitem(p0, 5, i0)
  4753. strsetitem(p0, 6, i0)
  4754. strsetitem(p0, 7, i0)
  4755. p1 = newstr(12)
  4756. copystrcontent(p0, p1, 0, 0, 8)
  4757. strsetitem(p1, 8, 3)
  4758. strsetitem(p1, 9, 0)
  4759. strsetitem(p1, 10, 0)
  4760. strsetitem(p1, 11, 0)
  4761. finish(p1)
  4762. """
  4763. expected = """
  4764. [i0]
  4765. p1 = newstr(12)
  4766. strsetitem(p1, 0, i0)
  4767. strsetitem(p1, 1, i0)
  4768. strsetitem(p1, 2, i0)
  4769. strsetitem(p1, 3, i0)
  4770. strsetitem(p1, 4, i0)
  4771. strsetitem(p1, 5, i0)
  4772. strsetitem(p1, 6, i0)
  4773. strsetitem(p1, 7, i0)
  4774. strsetitem(p1, 8, 3)
  4775. finish(p1)
  4776. """
  4777. self.optimize_strunicode_loop(ops, expected)
  4778. def test_call_pure_vstring_const(self):
  4779. py.test.skip("implement me")
  4780. ops = """
  4781. []
  4782. p0 = newstr(3)
  4783. strsetitem(p0, 0, 97)
  4784. strsetitem(p0, 1, 98)
  4785. strsetitem(p0, 2, 99)
  4786. i0 = call_pure(123, p0, descr=nonwritedescr)
  4787. finish(i0)
  4788. """
  4789. expected = """
  4790. []
  4791. finish(5)
  4792. """
  4793. call_pure_results = {
  4794. (ConstInt(123), get_const_ptr_for_string("abc"),): ConstInt(5),
  4795. }
  4796. self.optimize_loop(ops, expected, call_pure_results)
  4797. class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
  4798. pass
  4799. ##class TestOOtype(BaseTestOptimizeBasic, OOtypeMixin):
  4800. ## def test_instanceof(self):
  4801. ## ops = """
  4802. ## [i0]
  4803. ## p0 = new_with_vtable(ConstClass(node_vtable))
  4804. ## i1 = instanceof(p0, descr=nodesize)
  4805. ## jump(i1)
  4806. ## """
  4807. ## expected = """
  4808. ## [i0]
  4809. ## jump(1)
  4810. ## """
  4811. ## self.optimize_loop(ops, expected)
  4812. ## def test_instanceof_guard_class(self):
  4813. ## ops = """
  4814. ## [i0, p0]
  4815. ## guard_class(p0, ConstClass(node_vtable)) []
  4816. ## i1 = instanceof(p0, descr=nodesize)
  4817. ## jump(i1, p0)
  4818. ## """
  4819. ## expected = """
  4820. ## [i0, p0]
  4821. ## guard_class(p0, ConstClass(node_vtable)) []
  4822. ## jump(1, p0)
  4823. ## """
  4824. ## self.optimize_loop(ops, expected)