[pypy-commit] pypy arm64: start working on cond_call, we need float support for that

fijal pypy.commits at gmail.com
Tue Jun 18 07:01:00 EDT 2019


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: arm64
Changeset: r96818:98896de049b1
Date: 2019-06-18 10:56 +0000
http://bitbucket.org/pypy/pypy/changeset/98896de049b1/

Log:	start working on cond_call, we need float support for that

diff --git a/rpython/jit/backend/aarch64/assembler.py b/rpython/jit/backend/aarch64/assembler.py
--- a/rpython/jit/backend/aarch64/assembler.py
+++ b/rpython/jit/backend/aarch64/assembler.py
@@ -530,7 +530,26 @@
         self.propagate_exception_path = rawstart
 
     def _build_cond_call_slowpath(self, supports_floats, callee_only):
-        pass
+        """ This builds a general call slowpath, for whatever call happens to
+        come.
+        """
+        mc = InstrBuilder()
+        #
+        self._push_all_regs_to_jitframe(mc, [], self.cpu.supports_floats, callee_only)
+        ## args are in their respective positions
+        mc.SUB_ri(r.sp.value, r.sp.value, 2 * WORD)
+        mc.STR_ri(r.ip0.value, r.sp.value, WORD)
+        mc.STR_ri(r.lr.value, r.sp.value, 0)
+        mc.BL(r.ip1.value)
+        mc.MOV_rr(r.ip1.value, r.x0.value) # return comes back in ip1
+        self._reload_frame_if_necessary(mc)
+        self._pop_all_regs_from_jitframe(mc, [], supports_floats,
+                                         callee_only)
+        # return
+        mc.LDR_ri(r.ip0.value, r.sp.value, 0)
+        mc.ADD_ri(r.sp.value, r.sp.value, 2 * WORD)
+        mc.RET_r(r.ip0.value)
+        return mc.materialize(self.cpu, [])
 
     def _build_stack_check_slowpath(self):
         self.stack_check_slowpath = 0  #XXX
diff --git a/rpython/jit/backend/aarch64/opassembler.py b/rpython/jit/backend/aarch64/opassembler.py
--- a/rpython/jit/backend/aarch64/opassembler.py
+++ b/rpython/jit/backend/aarch64/opassembler.py
@@ -1,5 +1,6 @@
 
 from rpython.rlib.objectmodel import we_are_translated
+from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.jit.metainterp.history import (AbstractFailDescr, ConstInt,
                                             INT, FLOAT, REF)
 from rpython.jit.backend.aarch64 import registers as r
@@ -502,6 +503,49 @@
         self._write_barrier_fastpath(self.mc, op.getdescr(), arglocs,
                                      array=True)
 
+    def emit_op_cond_call(self, op, arglocs):
+        self.mc.gen_load_int(r.ip1.value, rffi.cast(lltype.Signed,
+            op.getarg(1).getint()))
+
+        #if len(arglocs) == 2:
+        #    res_loc = arglocs[1]     # cond_call_value
+        #else:
+        #    res_loc = None           # cond_call
+        # see x86.regalloc for why we skip res_loc in the gcmap
+        res_loc = None
+        gcmap = self._regalloc.get_gcmap([res_loc])
+
+        jmp_adr = self.mc.currpos()
+        self.mc.BRK()  # patched later: the conditional jump
+        #
+        self.push_gcmap(self.mc, gcmap)
+        #
+        callee_only = False
+        floats = False
+        if self._regalloc is not None:
+            for reg in self._regalloc.rm.reg_bindings.values():
+                if reg not in self._regalloc.rm.save_around_call_regs:
+                    break
+            else:
+                callee_only = True
+            if self._regalloc.vfprm.reg_bindings:
+                floats = True
+        cond_call_adr = self.cond_call_slowpath[floats * 2 + callee_only]
+        assert cond_call_adr
+        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:
+            self.mc.MOV_rr(res_loc.value, r.ip1.value)
+        #
+        self.pop_gcmap(self.mc)
+        pmc = OverwritingBuilder(self.mc, jmp_adr, WORD)
+        pmc.B_ofs_cond(self.mc.currpos(), c.EQ)
+        # might be overridden again to skip over the following
+        # guard_no_exception too
+        self.previous_cond_call_jcond = jmp_adr, c.EQ
+
     def _write_barrier_fastpath(self, mc, descr, arglocs, array=False, is_frame=False):
         # Write code equivalent to write_barrier() in the GC: it checks
         # a flag in the object at arglocs[0], and if set, it calls a
diff --git a/rpython/jit/backend/aarch64/regalloc.py b/rpython/jit/backend/aarch64/regalloc.py
--- a/rpython/jit/backend/aarch64/regalloc.py
+++ b/rpython/jit/backend/aarch64/regalloc.py
@@ -630,6 +630,42 @@
             self._compute_hint_frame_locations_from_descr(descr)
         return []
 
+    def prepare_op_cond_call(self, op):
+        assert 2 <= op.numargs() <= 4 + 2
+        v = op.getarg(1)
+        assert isinstance(v, Const)
+        args_so_far = []
+        for i in range(2, op.numargs()):
+            reg = r.argument_regs[i - 2]
+            arg = op.getarg(i)
+            self.make_sure_var_in_reg(arg, args_so_far, selected_reg=reg)
+            args_so_far.append(arg)
+
+        if op.type == 'v':
+            # a plain COND_CALL.  Calls the function when args[0] is
+            # true.  Often used just after a comparison operation.
+            return []
+        else:
+            XXX
+            # 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]
+
+
     def prepare_op_finish(self, op):
         # the frame is in fp, but we have to point where in the frame is
         # the potential argument to FINISH


More information about the pypy-commit mailing list