PageRenderTime 42ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/glavoie/pypy
Python | 5066 lines | 5038 code | 19 blank | 9 comment | 9 complexity | 9c3fab02a76ef2bb849fa0f9fadb02e4 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
  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. class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
  4744. pass
  4745. ##class TestOOtype(BaseTestOptimizeBasic, OOtypeMixin):
  4746. ## def test_instanceof(self):
  4747. ## ops = """
  4748. ## [i0]
  4749. ## p0 = new_with_vtable(ConstClass(node_vtable))
  4750. ## i1 = instanceof(p0, descr=nodesize)
  4751. ## jump(i1)
  4752. ## """
  4753. ## expected = """
  4754. ## [i0]
  4755. ## jump(1)
  4756. ## """
  4757. ## self.optimize_loop(ops, expected)
  4758. ## def test_instanceof_guard_class(self):
  4759. ## ops = """
  4760. ## [i0, p0]
  4761. ## guard_class(p0, ConstClass(node_vtable)) []
  4762. ## i1 = instanceof(p0, descr=nodesize)
  4763. ## jump(i1, p0)
  4764. ## """
  4765. ## expected = """
  4766. ## [i0, p0]
  4767. ## guard_class(p0, ConstClass(node_vtable)) []
  4768. ## jump(1, p0)
  4769. ## """
  4770. ## self.optimize_loop(ops, expected)