PageRenderTime 41ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/jit/backend/x86/test/test_regalloc.py

https://bitbucket.org/pypy/pypy/
Python | 694 lines | 657 code | 35 blank | 2 comment | 12 complexity | e62766430acb07534dfcf6c9eee2d861 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """ Tests for register allocation for common constructs
  2. """
  3. import py
  4. from pypy.jit.metainterp.history import BoxInt, ConstInt,\
  5. BoxPtr, ConstPtr, BasicFailDescr, JitCellToken, TargetToken
  6. from pypy.jit.metainterp.resoperation import rop, ResOperation
  7. from pypy.jit.backend.llsupport.descr import GcCache
  8. from pypy.jit.backend.detect_cpu import getcpuclass
  9. from pypy.jit.backend.x86.regalloc import RegAlloc, X86RegisterManager,\
  10. is_comparison_or_ovf_op
  11. from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64
  12. from pypy.jit.tool.oparser import parse
  13. from pypy.rpython.lltypesystem import lltype, llmemory, rffi
  14. from pypy.rpython.annlowlevel import llhelper
  15. from pypy.rpython.lltypesystem import rclass, rstr
  16. from pypy.jit.codewriter import longlong
  17. from pypy.jit.codewriter.effectinfo import EffectInfo
  18. from pypy.jit.backend.x86.rx86 import *
  19. def test_is_comparison_or_ovf_op():
  20. assert not is_comparison_or_ovf_op(rop.INT_ADD)
  21. assert is_comparison_or_ovf_op(rop.INT_ADD_OVF)
  22. assert is_comparison_or_ovf_op(rop.INT_EQ)
  23. CPU = getcpuclass()
  24. class MockGcDescr(GcCache):
  25. def get_funcptr_for_new(self):
  26. return 123
  27. get_funcptr_for_newarray = get_funcptr_for_new
  28. get_funcptr_for_newstr = get_funcptr_for_new
  29. get_funcptr_for_newunicode = get_funcptr_for_new
  30. def rewrite_assembler(self, cpu, operations):
  31. pass
  32. class MockAssembler(object):
  33. gcrefs = None
  34. _float_constants = None
  35. def __init__(self, cpu=None, gc_ll_descr=None):
  36. self.movs = []
  37. self.performs = []
  38. self.lea = []
  39. if cpu is None:
  40. cpu = CPU(None, None)
  41. cpu.setup_once()
  42. self.cpu = cpu
  43. if gc_ll_descr is None:
  44. gc_ll_descr = MockGcDescr(False)
  45. self.cpu.gc_ll_descr = gc_ll_descr
  46. def dump(self, *args):
  47. pass
  48. def regalloc_mov(self, from_loc, to_loc):
  49. self.movs.append((from_loc, to_loc))
  50. def regalloc_perform(self, op, arglocs, resloc):
  51. self.performs.append((op, arglocs, resloc))
  52. def regalloc_perform_discard(self, op, arglocs):
  53. self.performs.append((op, arglocs))
  54. def load_effective_addr(self, *args):
  55. self.lea.append(args)
  56. def fill_regs(regalloc, cls=BoxInt):
  57. allboxes = []
  58. for reg in X86RegisterManager.all_regs:
  59. box = cls()
  60. allboxes.append(box)
  61. regalloc.rm.try_allocate_reg()
  62. return allboxes
  63. class RegAllocForTests(RegAlloc):
  64. position = 0
  65. def _compute_next_usage(self, v, _):
  66. return -1
  67. class BaseTestRegalloc(object):
  68. cpu = CPU(None, None)
  69. cpu.setup_once()
  70. def raising_func(i):
  71. if i:
  72. raise LLException(zero_division_error,
  73. zero_division_value)
  74. FPTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Void))
  75. raising_fptr = llhelper(FPTR, raising_func)
  76. zero_division_tp, zero_division_value = cpu.get_zero_division_error()
  77. zd_addr = cpu.cast_int_to_adr(zero_division_tp)
  78. zero_division_error = llmemory.cast_adr_to_ptr(zd_addr,
  79. lltype.Ptr(rclass.OBJECT_VTABLE))
  80. raising_calldescr = cpu.calldescrof(FPTR.TO, FPTR.TO.ARGS, FPTR.TO.RESULT,
  81. EffectInfo.MOST_GENERAL)
  82. targettoken = TargetToken()
  83. targettoken2 = TargetToken()
  84. fdescr1 = BasicFailDescr(1)
  85. fdescr2 = BasicFailDescr(2)
  86. fdescr3 = BasicFailDescr(3)
  87. def setup_method(self, meth):
  88. self.targettoken._x86_loop_code = 0
  89. self.targettoken2._x86_loop_code = 0
  90. def f1(x):
  91. return x+1
  92. def f2(x, y):
  93. return x*y
  94. def f10(*args):
  95. assert len(args) == 10
  96. return sum(args)
  97. F1PTR = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
  98. F2PTR = lltype.Ptr(lltype.FuncType([lltype.Signed]*2, lltype.Signed))
  99. F10PTR = lltype.Ptr(lltype.FuncType([lltype.Signed]*10, lltype.Signed))
  100. f1ptr = llhelper(F1PTR, f1)
  101. f2ptr = llhelper(F2PTR, f2)
  102. f10ptr = llhelper(F10PTR, f10)
  103. f1_calldescr = cpu.calldescrof(F1PTR.TO, F1PTR.TO.ARGS, F1PTR.TO.RESULT,
  104. EffectInfo.MOST_GENERAL)
  105. f2_calldescr = cpu.calldescrof(F2PTR.TO, F2PTR.TO.ARGS, F2PTR.TO.RESULT,
  106. EffectInfo.MOST_GENERAL)
  107. f10_calldescr= cpu.calldescrof(F10PTR.TO, F10PTR.TO.ARGS, F10PTR.TO.RESULT,
  108. EffectInfo.MOST_GENERAL)
  109. namespace = locals().copy()
  110. type_system = 'lltype'
  111. def parse(self, s, boxkinds=None):
  112. return parse(s, self.cpu, self.namespace,
  113. type_system=self.type_system,
  114. boxkinds=boxkinds)
  115. def interpret(self, ops, args, run=True):
  116. loop = self.parse(ops)
  117. looptoken = JitCellToken()
  118. self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
  119. arguments = []
  120. for arg in args:
  121. if isinstance(arg, int):
  122. arguments.append(arg)
  123. elif isinstance(arg, float):
  124. arg = longlong.getfloatstorage(arg)
  125. arguments.append(arg)
  126. else:
  127. assert isinstance(lltype.typeOf(arg), lltype.Ptr)
  128. llgcref = lltype.cast_opaque_ptr(llmemory.GCREF, arg)
  129. arguments.append(llgcref)
  130. loop._jitcelltoken = looptoken
  131. if run:
  132. self.cpu.execute_token(looptoken, *arguments)
  133. return loop
  134. def prepare_loop(self, ops):
  135. loop = self.parse(ops)
  136. regalloc = RegAlloc(self.cpu.assembler, False)
  137. regalloc.prepare_loop(loop.inputargs, loop.operations,
  138. loop.original_jitcell_token, [])
  139. return regalloc
  140. def getint(self, index):
  141. return self.cpu.get_latest_value_int(index)
  142. def getfloat(self, index):
  143. return self.cpu.get_latest_value_float(index)
  144. def getints(self, end):
  145. return [self.cpu.get_latest_value_int(index) for
  146. index in range(0, end)]
  147. def getfloats(self, end):
  148. return [longlong.getrealfloat(self.cpu.get_latest_value_float(index))
  149. for index in range(0, end)]
  150. def getptr(self, index, T):
  151. gcref = self.cpu.get_latest_value_ref(index)
  152. return lltype.cast_opaque_ptr(T, gcref)
  153. def attach_bridge(self, ops, loop, guard_op_index, **kwds):
  154. guard_op = loop.operations[guard_op_index]
  155. assert guard_op.is_guard()
  156. bridge = self.parse(ops, **kwds)
  157. assert ([box.type for box in bridge.inputargs] ==
  158. [box.type for box in guard_op.getfailargs()])
  159. faildescr = guard_op.getdescr()
  160. self.cpu.compile_bridge(faildescr, bridge.inputargs, bridge.operations,
  161. loop._jitcelltoken)
  162. return bridge
  163. def run(self, loop, *arguments):
  164. return self.cpu.execute_token(loop._jitcelltoken, *arguments)
  165. class TestRegallocSimple(BaseTestRegalloc):
  166. def test_simple_loop(self):
  167. ops = '''
  168. [i0]
  169. label(i0, descr=targettoken)
  170. i1 = int_add(i0, 1)
  171. i2 = int_lt(i1, 20)
  172. guard_true(i2) [i1]
  173. jump(i1, descr=targettoken)
  174. '''
  175. self.interpret(ops, [0])
  176. assert self.getint(0) == 20
  177. def test_two_loops_and_a_bridge(self):
  178. ops = '''
  179. [i0, i1, i2, i3]
  180. label(i0, i1, i2, i3, descr=targettoken)
  181. i4 = int_add(i0, 1)
  182. i5 = int_lt(i4, 20)
  183. guard_true(i5) [i4, i1, i2, i3]
  184. jump(i4, i1, i2, i3, descr=targettoken)
  185. '''
  186. loop = self.interpret(ops, [0, 0, 0, 0])
  187. ops2 = '''
  188. [i5, i6, i7, i8]
  189. label(i5, descr=targettoken2)
  190. i1 = int_add(i5, 1)
  191. i3 = int_add(i1, 1)
  192. i4 = int_add(i3, 1)
  193. i2 = int_lt(i4, 30)
  194. guard_true(i2) [i4]
  195. jump(i4, descr=targettoken2)
  196. '''
  197. loop2 = self.interpret(ops2, [0, 0, 0, 0])
  198. bridge_ops = '''
  199. [i4]
  200. jump(i4, i4, i4, i4, descr=targettoken)
  201. '''
  202. bridge = self.attach_bridge(bridge_ops, loop2, 5)
  203. self.run(loop2, 0, 0, 0, 0)
  204. assert self.getint(0) == 31
  205. assert self.getint(1) == 30
  206. assert self.getint(2) == 30
  207. assert self.getint(3) == 30
  208. def test_pointer_arg(self):
  209. ops = '''
  210. [i0, p0]
  211. label(i0, p0, descr=targettoken)
  212. i1 = int_add(i0, 1)
  213. i2 = int_lt(i1, 10)
  214. guard_true(i2) [p0]
  215. jump(i1, p0, descr=targettoken)
  216. '''
  217. S = lltype.GcStruct('S')
  218. ptr = lltype.malloc(S)
  219. self.cpu.clear_latest_values(2)
  220. self.interpret(ops, [0, ptr])
  221. assert self.getptr(0, lltype.Ptr(S)) == ptr
  222. def test_exception_bridge_no_exception(self):
  223. ops = '''
  224. [i0]
  225. i1 = same_as(1)
  226. call(ConstClass(raising_fptr), i0, descr=raising_calldescr)
  227. guard_exception(ConstClass(zero_division_error)) [i1]
  228. finish(0)
  229. '''
  230. bridge_ops = '''
  231. [i3]
  232. i2 = same_as(2)
  233. guard_no_exception() [i2]
  234. finish(1)
  235. '''
  236. loop = self.interpret(ops, [0])
  237. assert self.getint(0) == 1
  238. bridge = self.attach_bridge(bridge_ops, loop, 2)
  239. self.run(loop, 0)
  240. assert self.getint(0) == 1
  241. def test_inputarg_unused(self):
  242. ops = '''
  243. [i0]
  244. finish(1)
  245. '''
  246. self.interpret(ops, [0])
  247. # assert did not explode
  248. def test_nested_guards(self):
  249. ops = '''
  250. [i0, i1]
  251. guard_true(i0) [i0, i1]
  252. finish(4)
  253. '''
  254. bridge_ops = '''
  255. [i0, i1]
  256. guard_true(i0) [i0, i1]
  257. finish(3)
  258. '''
  259. loop = self.interpret(ops, [0, 10])
  260. assert self.getint(0) == 0
  261. assert self.getint(1) == 10
  262. bridge = self.attach_bridge(bridge_ops, loop, 0)
  263. self.run(loop, 0, 10)
  264. assert self.getint(0) == 0
  265. assert self.getint(1) == 10
  266. def test_nested_unused_arg(self):
  267. ops = '''
  268. [i0, i1]
  269. guard_true(i0) [i0, i1]
  270. finish(1)
  271. '''
  272. loop = self.interpret(ops, [0, 1])
  273. assert self.getint(0) == 0
  274. bridge_ops = '''
  275. [i0, i1]
  276. finish(1, 2)
  277. '''
  278. self.attach_bridge(bridge_ops, loop, 0)
  279. self.run(loop, 0, 1)
  280. def test_spill_for_constant(self):
  281. ops = '''
  282. [i0, i1, i2, i3]
  283. label(i0, i1, i2, i3, descr=targettoken)
  284. i4 = int_add(3, i1)
  285. i5 = int_lt(i4, 30)
  286. guard_true(i5) [i0, i4, i2, i3]
  287. jump(1, i4, 3, 4, descr=targettoken)
  288. '''
  289. self.interpret(ops, [0, 0, 0, 0])
  290. assert self.getints(4) == [1, 30, 3, 4]
  291. def test_spill_for_constant_lshift(self):
  292. ops = '''
  293. [i0, i2, i1, i3]
  294. label(i0, i2, i1, i3, descr=targettoken)
  295. i4 = int_lshift(1, i1)
  296. i5 = int_add(1, i1)
  297. i6 = int_lt(i5, 30)
  298. guard_true(i6) [i4, i5, i2, i3]
  299. jump(i4, 3, i5, 4, descr=targettoken)
  300. '''
  301. self.interpret(ops, [0, 0, 0, 0])
  302. assert self.getints(4) == [1<<29, 30, 3, 4]
  303. ops = '''
  304. [i0, i1, i2, i3]
  305. label(i0, i1, i2, i3, descr=targettoken)
  306. i4 = int_lshift(1, i1)
  307. i5 = int_add(1, i1)
  308. i6 = int_lt(i5, 30)
  309. guard_true(i6) [i4, i5, i2, i3]
  310. jump(i4, i5, 3, 4, descr=targettoken)
  311. '''
  312. self.interpret(ops, [0, 0, 0, 0])
  313. assert self.getints(4) == [1<<29, 30, 3, 4]
  314. ops = '''
  315. [i0, i3, i1, i2]
  316. label(i0, i3, i1, i2, descr=targettoken)
  317. i4 = int_lshift(1, i1)
  318. i5 = int_add(1, i1)
  319. i6 = int_lt(i5, 30)
  320. guard_true(i6) [i4, i5, i2, i3]
  321. jump(i4, 4, i5, 3, descr=targettoken)
  322. '''
  323. self.interpret(ops, [0, 0, 0, 0])
  324. assert self.getints(4) == [1<<29, 30, 3, 4]
  325. def test_result_selected_reg_via_neg(self):
  326. ops = '''
  327. [i0, i1, i2, i3]
  328. label(i0, i1, i2, i3, descr=targettoken)
  329. i6 = int_neg(i2)
  330. i7 = int_add(1, i1)
  331. i4 = int_lt(i7, 10)
  332. guard_true(i4) [i0, i6, i7]
  333. jump(1, i7, i2, i6, descr=targettoken)
  334. '''
  335. self.interpret(ops, [0, 0, 3, 0])
  336. assert self.getints(3) == [1, -3, 10]
  337. def test_compare_memory_result_survives(self):
  338. ops = '''
  339. [i0, i1, i2, i3]
  340. label(i0, i1, i2, i3, descr=targettoken)
  341. i4 = int_lt(i0, i1)
  342. i5 = int_add(i3, 1)
  343. i6 = int_lt(i5, 30)
  344. guard_true(i6) [i4]
  345. jump(i0, i1, i4, i5, descr=targettoken)
  346. '''
  347. self.interpret(ops, [0, 10, 0, 0])
  348. assert self.getint(0) == 1
  349. def test_jump_different_args(self):
  350. ops = '''
  351. [i0, i15, i16, i18, i1, i2, i3]
  352. label(i0, i15, i16, i18, i1, i2, i3, descr=targettoken)
  353. i4 = int_add(i3, 1)
  354. i5 = int_lt(i4, 20)
  355. guard_true(i5) [i2, i1]
  356. jump(i0, i18, i15, i16, i2, i1, i4, descr=targettoken)
  357. '''
  358. self.interpret(ops, [0, 1, 2, 3, 0, 0, 0])
  359. def test_op_result_unused(self):
  360. ops = '''
  361. [i0, i1]
  362. i2 = int_add(i0, i1)
  363. finish(0)
  364. '''
  365. self.interpret(ops, [0, 0])
  366. def test_guard_value_two_boxes(self):
  367. ops = '''
  368. [i0, i1, i2, i3, i4, i5, i6, i7]
  369. guard_value(i6, i1) [i0, i2, i3, i4, i5, i6]
  370. finish(i0, i2, i3, i4, i5, i6)
  371. '''
  372. self.interpret(ops, [0, 0, 0, 0, 0, 0, 0, 0])
  373. assert self.getint(0) == 0
  374. def test_bug_wrong_stack_adj(self):
  375. ops = '''
  376. [i0, i1, i2, i3, i4, i5, i6, i7, i8]
  377. i9 = same_as(0)
  378. guard_true(i0) [i9, i0, i1, i2, i3, i4, i5, i6, i7, i8]
  379. finish(1, i0, i1, i2, i3, i4, i5, i6, i7, i8)
  380. '''
  381. loop = self.interpret(ops, [0, 1, 2, 3, 4, 5, 6, 7, 8])
  382. assert self.getint(0) == 0
  383. bridge_ops = '''
  384. [i9, i0, i1, i2, i3, i4, i5, i6, i7, i8]
  385. call(ConstClass(raising_fptr), 0, descr=raising_calldescr)
  386. finish(i0, i1, i2, i3, i4, i5, i6, i7, i8)
  387. '''
  388. self.attach_bridge(bridge_ops, loop, 1)
  389. self.run(loop, 0, 1, 2, 3, 4, 5, 6, 7, 8)
  390. assert self.getints(9) == range(9)
  391. def test_loopargs(self):
  392. ops = """
  393. [i0, i1, i2, i3]
  394. i4 = int_add(i0, i1)
  395. jump(i4, i1, i2, i3)
  396. """
  397. regalloc = self.prepare_loop(ops)
  398. if IS_X86_64:
  399. assert len(regalloc.rm.reg_bindings) == 4
  400. assert len(regalloc.fm.bindings) == 0
  401. else:
  402. assert len(regalloc.rm.reg_bindings) == 0
  403. assert len(regalloc.fm.bindings) == 4
  404. class TestRegallocCompOps(BaseTestRegalloc):
  405. def test_cmp_op_0(self):
  406. ops = '''
  407. [i0, i3]
  408. i1 = same_as(1)
  409. i2 = int_lt(i0, 100)
  410. guard_true(i3) [i1, i2]
  411. finish(0, i2)
  412. '''
  413. self.interpret(ops, [0, 1])
  414. assert self.getint(0) == 0
  415. class TestRegallocMoreRegisters(BaseTestRegalloc):
  416. cpu = BaseTestRegalloc.cpu
  417. targettoken = TargetToken()
  418. S = lltype.GcStruct('S', ('field', lltype.Char))
  419. fielddescr = cpu.fielddescrof(S, 'field')
  420. A = lltype.GcArray(lltype.Char)
  421. arraydescr = cpu.arraydescrof(A)
  422. namespace = locals().copy()
  423. def test_int_is_true(self):
  424. ops = '''
  425. [i0, i1, i2, i3, i4, i5, i6, i7]
  426. i10 = int_is_true(i0)
  427. i11 = int_is_true(i1)
  428. i12 = int_is_true(i2)
  429. i13 = int_is_true(i3)
  430. i14 = int_is_true(i4)
  431. i15 = int_is_true(i5)
  432. i16 = int_is_true(i6)
  433. i17 = int_is_true(i7)
  434. finish(i10, i11, i12, i13, i14, i15, i16, i17)
  435. '''
  436. self.interpret(ops, [0, 42, 12, 0, 13, 0, 0, 3333])
  437. assert self.getints(8) == [0, 1, 1, 0, 1, 0, 0, 1]
  438. def test_comparison_ops(self):
  439. ops = '''
  440. [i0, i1, i2, i3, i4, i5, i6]
  441. i10 = int_lt(i0, i1)
  442. i11 = int_le(i2, i3)
  443. i12 = int_ge(i4, i5)
  444. i13 = int_eq(i5, i6)
  445. i14 = int_gt(i6, i2)
  446. i15 = int_ne(i2, i6)
  447. finish(i10, i11, i12, i13, i14, i15)
  448. '''
  449. self.interpret(ops, [0, 1, 2, 3, 4, 5, 6])
  450. assert self.getints(6) == [1, 1, 0, 0, 1, 1]
  451. def test_strsetitem(self):
  452. ops = '''
  453. [p0, i]
  454. strsetitem(p0, 1, i)
  455. finish()
  456. '''
  457. llstr = rstr.mallocstr(10)
  458. self.interpret(ops, [llstr, ord('a')])
  459. assert llstr.chars[1] == 'a'
  460. def test_setfield_char(self):
  461. ops = '''
  462. [p0, i]
  463. setfield_gc(p0, i, descr=fielddescr)
  464. finish()
  465. '''
  466. s = lltype.malloc(self.S)
  467. self.interpret(ops, [s, ord('a')])
  468. assert s.field == 'a'
  469. def test_setarrayitem_gc(self):
  470. ops = '''
  471. [p0, i]
  472. setarrayitem_gc(p0, 1, i, descr=arraydescr)
  473. finish()
  474. '''
  475. s = lltype.malloc(self.A, 3)
  476. self.interpret(ops, [s, ord('a')])
  477. assert s[1] == 'a'
  478. def test_division_optimized(self):
  479. ops = '''
  480. [i7, i6]
  481. label(i7, i6, descr=targettoken)
  482. i18 = int_floordiv(i7, i6)
  483. i19 = int_xor(i7, i6)
  484. i21 = int_lt(i19, 0)
  485. i22 = int_mod(i7, i6)
  486. i23 = int_is_true(i22)
  487. i24 = int_eq(i6, 4)
  488. guard_false(i24) [i18]
  489. jump(i18, i6, descr=targettoken)
  490. '''
  491. self.interpret(ops, [10, 4])
  492. assert self.getint(0) == 2
  493. # FIXME: Verify that i19 - i23 are removed
  494. class TestRegallocFloats(BaseTestRegalloc):
  495. def test_float_add(self):
  496. ops = '''
  497. [f0, f1]
  498. f2 = float_add(f0, f1)
  499. finish(f2, f0, f1)
  500. '''
  501. self.interpret(ops, [3.0, 1.5])
  502. assert self.getfloats(3) == [4.5, 3.0, 1.5]
  503. def test_float_adds_stack(self):
  504. ops = '''
  505. [f0, f1, f2, f3, f4, f5, f6, f7, f8]
  506. f9 = float_add(f0, f1)
  507. f10 = float_add(f8, 3.5)
  508. finish(f9, f10, f2, f3, f4, f5, f6, f7, f8)
  509. '''
  510. self.interpret(ops, [0.1, .2, .3, .4, .5, .6, .7, .8, .9])
  511. assert self.getfloats(9) == [.1+.2, .9+3.5, .3, .4, .5, .6, .7, .8, .9]
  512. def test_lt_const(self):
  513. ops = '''
  514. [f0]
  515. i1 = float_lt(3.5, f0)
  516. finish(i1)
  517. '''
  518. self.interpret(ops, [0.1])
  519. assert self.getint(0) == 0
  520. def test_bug_float_is_true_stack(self):
  521. # NB. float_is_true no longer exists. Unsure if keeping this test
  522. # makes sense any more.
  523. ops = '''
  524. [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9]
  525. i0 = float_ne(f0, 0.0)
  526. i1 = float_ne(f1, 0.0)
  527. i2 = float_ne(f2, 0.0)
  528. i3 = float_ne(f3, 0.0)
  529. i4 = float_ne(f4, 0.0)
  530. i5 = float_ne(f5, 0.0)
  531. i6 = float_ne(f6, 0.0)
  532. i7 = float_ne(f7, 0.0)
  533. i8 = float_ne(f8, 0.0)
  534. i9 = float_ne(f9, 0.0)
  535. finish(i0, i1, i2, i3, i4, i5, i6, i7, i8, i9)
  536. '''
  537. loop = self.interpret(ops, [0.0, .1, .2, .3, .4, .5, .6, .7, .8, .9])
  538. assert self.getints(9) == [0, 1, 1, 1, 1, 1, 1, 1, 1]
  539. class TestRegAllocCallAndStackDepth(BaseTestRegalloc):
  540. def expected_param_depth(self, num_args):
  541. # Assumes the arguments are all non-float
  542. if IS_X86_32:
  543. return num_args
  544. elif IS_X86_64:
  545. return max(num_args - 6, 0)
  546. def test_one_call(self):
  547. ops = '''
  548. [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  549. i10 = call(ConstClass(f1ptr), i0, descr=f1_calldescr)
  550. finish(i10, i1, i2, i3, i4, i5, i6, i7, i8, i9)
  551. '''
  552. loop = self.interpret(ops, [4, 7, 9, 9 ,9, 9, 9, 9, 9, 9])
  553. assert self.getints(10) == [5, 7, 9, 9, 9, 9, 9, 9, 9, 9]
  554. clt = loop._jitcelltoken.compiled_loop_token
  555. assert clt.param_depth == self.expected_param_depth(1)
  556. def test_two_calls(self):
  557. ops = '''
  558. [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9]
  559. i10 = call(ConstClass(f1ptr), i0, descr=f1_calldescr)
  560. i11 = call(ConstClass(f2ptr), i10, i1, descr=f2_calldescr)
  561. finish(i11, i1, i2, i3, i4, i5, i6, i7, i8, i9)
  562. '''
  563. loop = self.interpret(ops, [4, 7, 9, 9 ,9, 9, 9, 9, 9, 9])
  564. assert self.getints(10) == [5*7, 7, 9, 9, 9, 9, 9, 9, 9, 9]
  565. clt = loop._jitcelltoken.compiled_loop_token
  566. assert clt.param_depth == self.expected_param_depth(2)
  567. def test_call_many_arguments(self):
  568. # NB: The first and last arguments in the call are constants. This
  569. # is primarily for x86-64, to ensure that loading a constant to an
  570. # argument register or to the stack works correctly
  571. ops = '''
  572. [i0, i1, i2, i3, i4, i5, i6, i7]
  573. i8 = call(ConstClass(f10ptr), 1, i0, i1, i2, i3, i4, i5, i6, i7, 10, descr=f10_calldescr)
  574. finish(i8)
  575. '''
  576. loop = self.interpret(ops, [2, 3, 4, 5, 6, 7, 8, 9])
  577. assert self.getint(0) == 55
  578. clt = loop._jitcelltoken.compiled_loop_token
  579. assert clt.param_depth == self.expected_param_depth(10)
  580. def test_bridge_calls_1(self):
  581. ops = '''
  582. [i0, i1]
  583. i2 = call(ConstClass(f1ptr), i0, descr=f1_calldescr)
  584. guard_value(i2, 0, descr=fdescr1) [i2, i1]
  585. finish(i1)
  586. '''
  587. loop = self.interpret(ops, [4, 7])
  588. assert self.getint(0) == 5
  589. ops = '''
  590. [i2, i1]
  591. i3 = call(ConstClass(f2ptr), i2, i1, descr=f2_calldescr)
  592. finish(i3, descr=fdescr2)
  593. '''
  594. bridge = self.attach_bridge(ops, loop, -2)
  595. assert loop.operations[-2].getdescr()._x86_bridge_param_depth == self.expected_param_depth(2)
  596. self.run(loop, 4, 7)
  597. assert self.getint(0) == 5*7
  598. def test_bridge_calls_2(self):
  599. ops = '''
  600. [i0, i1]
  601. i2 = call(ConstClass(f2ptr), i0, i1, descr=f2_calldescr)
  602. guard_value(i2, 0, descr=fdescr1) [i2]
  603. finish(i1)
  604. '''
  605. loop = self.interpret(ops, [4, 7])
  606. assert self.getint(0) == 4*7
  607. ops = '''
  608. [i2]
  609. i3 = call(ConstClass(f1ptr), i2, descr=f1_calldescr)
  610. finish(i3, descr=fdescr2)
  611. '''
  612. bridge = self.attach_bridge(ops, loop, -2)
  613. assert loop.operations[-2].getdescr()._x86_bridge_param_depth == self.expected_param_depth(2)
  614. self.run(loop, 4, 7)
  615. assert self.getint(0) == 29