Author: Armin Rigo <[email protected]>
Branch: conditional_call_value_4
Changeset: r88584:208a94fe7827
Date: 2016-11-23 17:46 +0100
http://bitbucket.org/pypy/pypy/changeset/208a94fe7827/
Log: add 'cond_call_value' in the ARM backend
diff --git a/rpython/jit/backend/arm/assembler.py
b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -268,12 +268,15 @@
"""
mc = InstrBuilder(self.cpu.cpuinfo.arch_version)
#
- self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats,
callee_only)
+ # We don't save/restore r4; instead the return value (if any)
+ # will be stored there.
+ self._push_all_regs_to_jitframe(mc, [r.r4], self.cpu.supports_floats,
callee_only)
## args are in their respective positions
mc.PUSH([r.ip.value, r.lr.value])
mc.BLX(r.r4.value)
+ mc.MOV_rr(r.r4.value, r.r0.value)
self._reload_frame_if_necessary(mc)
- self._pop_all_regs_from_jitframe(mc, [], supports_floats,
+ self._pop_all_regs_from_jitframe(mc, [r.r4], supports_floats,
callee_only)
# return
mc.POP([r.ip.value, r.pc.value])
diff --git a/rpython/jit/backend/arm/opassembler.py
b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -357,7 +357,13 @@
return fcond
def emit_op_cond_call(self, op, arglocs, regalloc, fcond):
- [call_loc] = arglocs
+ call_loc = arglocs[0]
+ if len(arglocs) == 2:
+ res_loc = arglocs[1] # cond_call_value
+ else:
+ res_loc = None # cond_call
+ # useless to list res_loc in the gcmap, because if the call is
+ # done it means res_loc was initially NULL
gcmap = regalloc.get_gcmap([call_loc])
assert call_loc is r.r4
@@ -378,8 +384,13 @@
floats = True
cond_call_adr = self.cond_call_slowpath[floats * 2 + callee_only]
self.mc.BL(cond_call_adr)
+ # if this is a COND_CALL_VALUE, we need to move the result in place
+ # from its current location (which is, unusually, in r4: see
+ # cond_call_slowpath)
+ if res_loc is not None and res_loc is not r.r4:
+ self.mc.MOV_rr(res_loc.value, r.r4.value)
+ #
self.pop_gcmap(self.mc)
- # never any result value
cond = c.get_opposite_of(self.guard_success_cc)
self.guard_success_cc = c.cond_none
pmc = OverwritingBuilder(self.mc, jmp_adr, WORD)
@@ -389,6 +400,9 @@
self.previous_cond_call_jcond = jmp_adr, cond
return fcond
+ emit_op_cond_call_value_i = emit_op_cond_call
+ emit_op_cond_call_value_r = emit_op_cond_call
+
def emit_op_jump(self, op, arglocs, regalloc, fcond):
target_token = op.getdescr()
assert isinstance(target_token, TargetToken)
diff --git a/rpython/jit/backend/arm/regalloc.py
b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -1004,7 +1004,6 @@
def prepare_op_cond_call(self, op, fcond):
# XXX don't force the arguments to be loaded in specific
# locations before knowing if we can take the fast path
- # XXX add cond_call_value support
assert 2 <= op.numargs() <= 4 + 2
tmpreg = self.get_scratch_reg(INT, selected_reg=r.r4)
v = op.getarg(1)
@@ -1017,8 +1016,33 @@
arg = op.getarg(i)
self.make_sure_var_in_reg(arg, args_so_far, selected_reg=reg)
args_so_far.append(arg)
- self.load_condition_into_cc(op.getarg(0))
- return [tmpreg]
+
+ if op.type == 'v':
+ # a plain COND_CALL. Calls the function when args[0] is
+ # true. Often used just after a comparison operation.
+ self.load_condition_into_cc(op.getarg(0))
+ return [tmpreg]
+ else:
+ # COND_CALL_VALUE_I/R. Calls the function when args[0]
+ # is equal to 0 or NULL. Returns the result from the
+ # function call if done, or args[0] if it was not 0/NULL.
+ # Implemented by forcing the result to live in the same
+ # register as args[0], and overwriting it if we really do
+ # the call.
+
+ # Load the register for the result. Possibly reuse 'args[0]'.
+ # But the old value of args[0], if it survives, is first
+ # spilled away. We can't overwrite any of op.args[2:] here.
+ args = op.getarglist()
+ resloc = self.rm.force_result_in_reg(op, args[0],
+ forbidden_vars=args[2:])
+ # Test the register for the result.
+ self.assembler.mc.CMP_ri(resloc.value, 0)
+ self.assembler.guard_success_cc = c.EQ
+ return [tmpreg, resloc]
+
+ prepare_op_cond_call_value_i = prepare_op_cond_call
+ prepare_op_cond_call_value_r = prepare_op_cond_call
def prepare_op_force_token(self, op, fcond):
# XXX for now we return a regular reg
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit