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

Reply via email to