Author: Armin Rigo <ar...@tunes.org> Branch: conditional_call_value_2 Changeset: r86996:87c41fa2e0f5 Date: 2016-09-11 12:23 +0200 http://bitbucket.org/pypy/pypy/changeset/87c41fa2e0f5/
Log: Add support for COND_CALL_X in the x86 backend diff --git a/rpython/jit/backend/llsupport/regalloc.py b/rpython/jit/backend/llsupport/regalloc.py --- a/rpython/jit/backend/llsupport/regalloc.py +++ b/rpython/jit/backend/llsupport/regalloc.py @@ -757,17 +757,17 @@ next_op = operations[i + 1] opnum = next_op.getopnum() if (opnum != rop.GUARD_TRUE and opnum != rop.GUARD_FALSE - and opnum != rop.COND_CALL): + and opnum != rop.COND_CALL_N): return False if next_op.getarg(0) is not op: return False if self.longevity[op][1] > i + 1: return False - if opnum != rop.COND_CALL: + if opnum != rop.COND_CALL_N: if op in operations[i + 1].getfailargs(): return False else: - if op in operations[i + 1].getarglist()[1:]: + if op in operations[i + 1].getarglist()[3:]: return False return True diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -392,7 +392,7 @@ opnum = next_op.getopnum() if not (opnum == rop.GUARD_TRUE or opnum == rop.GUARD_FALSE or - opnum == rop.COND_CALL): + opnum == rop.COND_CALL_N): return False if next_op.getarg(0) is not op: return False diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2215,51 +2215,6 @@ excvalue = self.cpu.grab_exc_value(deadframe) assert not excvalue - def test_cond_call_value(self): - def func_int(*args): - called.append(args) - return len(args) * 100 + 1000 - - for i in range(5): - called = [] - - FUNC = self.FuncType([lltype.Signed] * i, lltype.Signed) - func_ptr = llhelper(lltype.Ptr(FUNC), func_int) - calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, - EffectInfo.MOST_GENERAL) - - ops = ''' - [i0, i1, i2, i3, i4, i5, i6, f0, f1] - i15 = cond_call_i(i1, 20, ConstClass(func_ptr), %s) - guard_false(i0, descr=faildescr) [i1,i2,i3,i4,i5,i6,i15, f0,f1] - finish(i15) - ''' % ', '.join(['i%d' % (j + 2) for j in range(i)] + - ["descr=calldescr"]) - loop = parse(ops, namespace={'faildescr': BasicFailDescr(), - 'func_ptr': func_ptr, - 'calldescr': calldescr}) - looptoken = JitCellToken() - self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) - f1 = longlong.getfloatstorage(1.2) - f2 = longlong.getfloatstorage(3.4) - frame = self.cpu.execute_token(looptoken, 1, 50, 1, 2, 3, 4, 5, - f1, f2) - assert not called - assert [self.cpu.get_int_value(frame, j) for j in range(7)] == [ - 50, 1, 2, 3, 4, 5, 50] - assert longlong.getrealfloat( - self.cpu.get_float_value(frame, 7)) == 1.2 - assert longlong.getrealfloat( - self.cpu.get_float_value(frame, 8)) == 3.4 - # - frame = self.cpu.execute_token(looptoken, 1, 20, 1, 2, 3, 4, 5, - f1, f2) - assert called == [(1, 2, 3, 4)[:i]] - assert [self.cpu.get_int_value(frame, j) for j in range(7)] == [ - 20, 1, 2, 3, 4, 5, i * 100 + 1000] - assert longlong.getrealfloat(self.cpu.get_float_value(frame, 7)) == 1.2 - assert longlong.getrealfloat(self.cpu.get_float_value(frame, 8)) == 3.4 - def test_cond_call_gc_wb(self): def func_void(a): record.append(rffi.cast(lltype.Signed, a)) @@ -2422,7 +2377,7 @@ ops = ''' [i0, i1, i2, i3, i4, i5, i6, f0, f1] - cond_call(i1, ConstClass(func_ptr), %s) + cond_call_n(i1, 1, ConstClass(func_ptr), %s) guard_false(i0, descr=faildescr) [i1, i2, i3, i4, i5, i6, f0, f1] ''' % ', '.join(['i%d' % (j + 2) for j in range(i)] + ["descr=calldescr"]) loop = parse(ops, namespace={'faildescr': BasicFailDescr(), @@ -2434,7 +2389,7 @@ f2 = longlong.getfloatstorage(3.4) frame = self.cpu.execute_token(looptoken, 1, 0, 1, 2, 3, 4, 5, f1, f2) assert not called - for j in range(5): + for j in range(6): assert self.cpu.get_int_value(frame, j) == j assert longlong.getrealfloat(self.cpu.get_float_value(frame, 6)) == 1.2 assert longlong.getrealfloat(self.cpu.get_float_value(frame, 7)) == 3.4 @@ -2472,7 +2427,7 @@ ops = ''' [%s, %s, i3, i4] i2 = %s(%s) - cond_call(i2, ConstClass(func_ptr), i3, i4, descr=calldescr) + cond_call_n(i2, 1, ConstClass(func_ptr), i3, i4, descr=calldescr) guard_no_exception(descr=faildescr) [] finish() ''' % ("i0" if operation.startswith('int') else "f0", @@ -2492,6 +2447,51 @@ 67, 89) assert called == [(67, 89)] + def test_cond_call_value(self): + def func_int(*args): + called.append(args) + return len(args) * 100 + 1000 + + for i in range(5): + called = [] + + FUNC = self.FuncType([lltype.Signed] * i, lltype.Signed) + func_ptr = llhelper(lltype.Ptr(FUNC), func_int) + calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, + EffectInfo.MOST_GENERAL) + + ops = ''' + [i0, i1, i2, i3, i4, i5, i6, f0, f1] + i15 = cond_call_i(i1, 20, ConstClass(func_ptr), %s) + guard_false(i0, descr=faildescr) [i1,i2,i3,i4,i5,i6,i15, f0,f1] + finish(i15) + ''' % ', '.join(['i%d' % (j + 2) for j in range(i)] + + ["descr=calldescr"]) + loop = parse(ops, namespace={'faildescr': BasicFailDescr(), + 'func_ptr': func_ptr, + 'calldescr': calldescr}) + looptoken = JitCellToken() + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) + f1 = longlong.getfloatstorage(1.2) + f2 = longlong.getfloatstorage(3.4) + frame = self.cpu.execute_token(looptoken, 1, 50, 1, 2, 3, 4, 5, + f1, f2) + assert not called + assert [self.cpu.get_int_value(frame, j) for j in range(7)] == [ + 50, 1, 2, 3, 4, 5, 50] + assert longlong.getrealfloat( + self.cpu.get_float_value(frame, 7)) == 1.2 + assert longlong.getrealfloat( + self.cpu.get_float_value(frame, 8)) == 3.4 + # + frame = self.cpu.execute_token(looptoken, 1, 20, 1, 2, 3, 4, 5, + f1, f2) + assert called == [(1, 2, 3, 4)[:i]] + assert [self.cpu.get_int_value(frame, j) for j in range(7)] == [ + 20, 1, 2, 3, 4, 5, i * 100 + 1000] + assert longlong.getrealfloat(self.cpu.get_float_value(frame, 7)) == 1.2 + assert longlong.getrealfloat(self.cpu.get_float_value(frame, 8)) == 3.4 + def test_force_operations_returning_void(self): values = [] def maybe_force(token, flag): diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -174,8 +174,8 @@ # copy registers to the frame, with the exception of the # 'cond_call_register_arguments' and eax, because these have already # been saved by the caller. Note that this is not symmetrical: - # these 5 registers are saved by the caller but restored here at - # the end of this function. + # these 5 registers are saved by the caller but 4 of them are + # restored here at the end of this function. self._push_all_regs_to_frame(mc, cond_call_register_arguments + [eax], supports_floats, callee_only) # the caller already did push_gcmap(store=True) @@ -198,7 +198,7 @@ mc.ADD(esp, imm(WORD * 7)) self.set_extra_stack_depth(mc, 0) self.pop_gcmap(mc) # cancel the push_gcmap(store=True) in the caller - self._pop_all_regs_from_frame(mc, [], supports_floats, callee_only) + self._pop_all_regs_from_frame(mc, [eax], supports_floats, callee_only) mc.RET() return mc.materialize(self.cpu, []) @@ -1703,7 +1703,8 @@ self.implement_guard(guard_token) # If the previous operation was a COND_CALL, overwrite its conditional # jump to jump over this GUARD_NO_EXCEPTION as well, if we can - if self._find_nearby_operation(-1).getopnum() == rop.COND_CALL: + if self._find_nearby_operation(-1).getopnum() in ( + rop.COND_CALL_N, rop.COND_CALL_I, rop.COND_CALL_R): jmp_adr = self.previous_cond_call_jcond offset = self.mc.get_relative_pos() - jmp_adr if offset <= 127: @@ -2381,7 +2382,7 @@ def label(self): self._check_frame_depth_debug(self.mc) - def cond_call(self, op, gcmap, imm_func, arglocs): + def cond_call(self, op, gcmap, imm_func, arglocs, resloc=None): assert self.guard_success_cc >= 0 self.mc.J_il8(rx86.invert_condition(self.guard_success_cc), 0) # patched later @@ -2394,11 +2395,14 @@ # plus the register 'eax' base_ofs = self.cpu.get_baseofs_of_frame_field() should_be_saved = self._regalloc.rm.reg_bindings.values() + pop_eax = False for gpr in cond_call_register_arguments + [eax]: - if gpr not in should_be_saved: + if gpr not in should_be_saved or gpr is resloc: continue v = gpr_reg_mgr_cls.all_reg_indexes[gpr.value] self.mc.MOV_br(v * WORD + base_ofs, gpr.value) + if gpr is eax: + pop_eax = True # # load the 0-to-4 arguments into these registers from rpython.jit.backend.x86.jump import remap_frame_layout @@ -2422,8 +2426,15 @@ floats = True cond_call_adr = self.cond_call_slowpath[floats * 2 + callee_only] self.mc.CALL(imm(follow_jump(cond_call_adr))) + # if this is not a COND_CALL_N, we need to move the result in place + if resloc is not None and resloc is not eax: + self.mc.MOV(resloc, eax) # restoring the registers saved above, and doing pop_gcmap(), is left - # to the cond_call_slowpath helper. We never have any result value. + # to the cond_call_slowpath helper. We must only pop eax, if needed. + if pop_eax: + v = gpr_reg_mgr_cls.all_reg_indexes[eax.value] + self.mc.MOV_rb(eax.value, v * WORD + base_ofs) + # offset = self.mc.get_relative_pos() - jmp_adr assert 0 < offset <= 127 self.mc.overwrite(jmp_adr-1, chr(offset)) diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -928,7 +928,7 @@ consider_cond_call_gc_wb_array = consider_cond_call_gc_wb - def XXXconsider_cond_call(self, op): + def consider_cond_call_n(self, op): # A 32-bit-only, asmgcc-only issue: 'cond_call_register_arguments' # contains edi and esi, which are also in asmgcroot.py:ASM_FRAMEDATA. # We must make sure that edi and esi do not contain GC pointers. @@ -938,16 +938,27 @@ self.rm.force_spill_var(box) assert box not in self.rm.reg_bindings # - assert op.type == 'v' + #assert op.type == 'v' args = op.getarglist() - assert 2 <= len(args) <= 4 + 2 # maximum 4 arguments - v = args[1] - assert isinstance(v, Const) - imm_func = self.rm.convert_to_imm(v) - arglocs = [self.loc(args[i]) for i in range(2, len(args))] + assert 3 <= len(args) <= 4 + 3 # maximum 4 arguments + v_func = args[2] + assert isinstance(v_func, Const) + imm_func = self.rm.convert_to_imm(v_func) + arglocs = [self.loc(args[i]) for i in range(3, len(args))] gcmap = self.get_gcmap() - self.load_condition_into_cc(op.getarg(0)) - self.assembler.cond_call(op, gcmap, imm_func, arglocs) + if op.type == 'v': # COND_CALL_N + self.load_condition_into_cc(op.getarg(0)) + resloc = None + else: + condvalue_loc = self.loc(args[0]) + assert not isinstance(condvalue_loc, ImmedLoc) + self.assembler.mc.CMP(condvalue_loc, self.loc(args[1])) + self.assembler.guard_success_cc = rx86.Conditions['E'] + resloc = self.rm.force_result_in_reg(op, args[0]) + self.assembler.cond_call(op, gcmap, imm_func, arglocs, resloc) + + consider_cond_call_i = consider_cond_call_n + consider_cond_call_r = consider_cond_call_n def consider_call_malloc_nursery(self, op): size_box = op.getarg(0) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit