[pypy-commit] pypy arm64: overflow ops (except mul_ovf)

fijal pypy.commits at gmail.com
Sun Apr 14 10:39:39 EDT 2019


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: arm64
Changeset: r96490:ba9733af746e
Date: 2019-04-14 13:30 +0000
http://bitbucket.org/pypy/pypy/changeset/ba9733af746e/

Log:	overflow ops (except mul_ovf)

diff --git a/rpython/jit/backend/aarch64/TODO b/rpython/jit/backend/aarch64/TODO
--- a/rpython/jit/backend/aarch64/TODO
+++ b/rpython/jit/backend/aarch64/TODO
@@ -1,2 +1,3 @@
 * int_add - IMM
 * int_cmp - IMM
+* *_ovf - merging operations
\ No newline at end of file
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
@@ -606,7 +606,11 @@
                 regalloc.possibly_free_vars_for_op(op)
             elif not we_are_translated() and op.getopnum() == rop.FORCE_SPILL:
                 regalloc.prepare_force_spill(op)
-            elif i < len(operations) - 1 and regalloc.next_op_can_accept_cc(operations, i):
+            elif i < len(operations) - 1 and (regalloc.next_op_can_accept_cc(operations, i) or
+                                              operations[i].is_ovf()):
+                if operations[i].is_ovf():
+                    assert operations[i + 1].getopnum() in [rop.GUARD_OVERFLOW,
+                                                            rop.GUARD_NO_OVERFLOW]
                 guard_op = operations[i + 1]
                 guard_num = guard_op.getopnum()
                 arglocs, fcond = guard_operations[guard_num](regalloc, guard_op, op)
diff --git a/rpython/jit/backend/aarch64/codebuilder.py b/rpython/jit/backend/aarch64/codebuilder.py
--- a/rpython/jit/backend/aarch64/codebuilder.py
+++ b/rpython/jit/backend/aarch64/codebuilder.py
@@ -65,14 +65,14 @@
         assert 0 <= immed < 1 << 16
         self.write32((base << 21) | (immed << 5) | rd)
 
-    def ADD_ri(self, rd, rn, constant):
-        base = 0b1001000100
+    def ADD_ri(self, rd, rn, constant, s=0):
+        base = 0b1001000100 | (s << 7)
         assert 0 <= constant < 4096
         self.write32((base << 22) | (constant << 10) |
                      (rn << 5) | rd)
 
-    def SUB_ri(self, rd, rn, constant):
-        base = 0b1101000100
+    def SUB_ri(self, rd, rn, constant, s=0):
+        base = 0b1101000100 | (s << 7)
         assert 0 <= constant < 4096
         self.write32((base << 22) | (constant << 10) | (rn << 5) | rd)
 
@@ -106,12 +106,12 @@
         assert offset & 0x3 == 0
         self.write32((base << 24) | ((0x7ffff & (offset >> 2)) << 5) | rt)
 
-    def ADD_rr(self, rd, rn, rm):
-        base = 0b10001011000
+    def ADD_rr(self, rd, rn, rm, s=0):
+        base = 0b10001011000 | (s << 8)
         self.write32((base << 21) | (rm << 16) | (rn << 5) | (rd))
 
-    def SUB_rr(self, rd, rn, rm):
-        base = 0b11001011001
+    def SUB_rr(self, rd, rn, rm, s=0):
+        base = 0b11001011001 | (s << 8)
         self.write32((base << 21) | (rm << 16) | (0b11 << 13) | (rn << 5) | (rd))
 
     def SUB_rr_shifted(self, rd, rn, rm, shift=0):
@@ -151,6 +151,14 @@
         base = 0b10101010001
         self.write32((base << 21) | (rm << 16) | (0b11111 << 5)| rd)
 
+    def SMULL_rr(self, rd, rn, rm):
+        base = 0b10011011001
+        self.write32((base << 21) | (rm << 16) | (0b11111 << 10) | (rn << 5) | rd)
+
+    def SMULH_rr(self, rd, rn, rm):
+        base = 0b10011011010
+        self.write32((base << 21) | (rm << 16) | (0b11111 << 10) | (rn << 5) | rd)
+
     def CMP_rr(self, rn, rm):
         base = 0b11101011000
         self.write32((base << 21) | (rm << 16) | (rn << 5) | 0b11111)
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
@@ -18,45 +18,55 @@
     return emit_op
 
 class ResOpAssembler(BaseAssembler):
-    def emit_op_int_add(self, op, arglocs):
-        return self.int_add_impl(op, arglocs)
-
     def int_sub_impl(self, op, arglocs, flags=0):
         l0, l1, res = arglocs
         if flags:
-            xxx
             s = 1
         else:
             s = 0
         if l1.is_imm():
             value = l1.getint()
             assert value >= 0
-            self.mc.SUB_ri(res.value, l0.value, value)
+            self.mc.SUB_ri(res.value, l0.value, value, s)
         else:
-            self.mc.SUB_rr(res.value, l0.value, l1.value)
+            self.mc.SUB_rr(res.value, l0.value, l1.value, s)
 
     def emit_op_int_sub(self, op, arglocs):
         self.int_sub_impl(op, arglocs)
 
-    emit_op_nursery_ptr_increment = emit_op_int_add
-
     def int_add_impl(self, op, arglocs, ovfcheck=False):
         l0, l1, res = arglocs
         assert not l0.is_imm()
         if ovfcheck:
-            XXX
             s = 1
         else:
             s = 0
         if l1.is_imm():
-            self.mc.ADD_ri(res.value, l0.value, l1.value)
+            self.mc.ADD_ri(res.value, l0.value, l1.value, s)
         else:
-            self.mc.ADD_rr(res.value, l0.value, l1.value)
+            self.mc.ADD_rr(res.value, l0.value, l1.value, s)
+
+    def emit_op_int_add(self, op, arglocs):
+        self.int_add_impl(op, arglocs)
+    emit_op_nursery_ptr_increment = emit_op_int_add
+
+    def emit_comp_op_int_add_ovf(self, op, arglocs):
+        self.int_add_impl(op, arglocs, True)
+
+    def emit_comp_op_int_sub_ovf(self, op, arglocs):
+        self.int_sub_impl(op, arglocs, True)
 
     def emit_op_int_mul(self, op, arglocs):
         reg1, reg2, res = arglocs
         self.mc.MUL_rr(res.value, reg1.value, reg2.value)
 
+    def emit_comp_op_int_mul_ovf(self, op, arglocs):
+        reg1, reg2, res = arglocs
+        self.mc.MUL_rr(res.value, reg1.value, reg2.value)
+        xxx # what to do here?
+        self.mc.SMULH_rr(res.value, reg1.value, reg2.value)
+        self.mc.CMP_ri(r.ip0.value, 0)
+
     def emit_op_int_and(self, op, arglocs):
         l0, l1, res = arglocs
         self.mc.AND_rr(res.value, l0.value, l1.value)
@@ -175,9 +185,11 @@
 
     def emit_guard_op_guard_true(self, guard_op, fcond, arglocs):
         self._emit_guard(guard_op, fcond, arglocs)
+    emit_guard_op_guard_no_overflow = emit_guard_op_guard_true
 
     def emit_guard_op_guard_false(self, guard_op, fcond, arglocs):
         self._emit_guard(guard_op, c.get_opposite_of(fcond), arglocs)
+    emit_guard_op_guard_overflow = emit_guard_op_guard_false
 
     def load_condition_into_cc(self, loc):
         if not loc.is_core_reg():
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
@@ -1,6 +1,7 @@
 
 from rpython.jit.backend.aarch64 import registers as r
 from rpython.jit.backend.aarch64 import locations
+from rpython.jit.backend.arm import conditions as c
 from rpython.jit.backend.aarch64.arch import WORD, JITFRAME_FIXED_SIZE
 
 from rpython.jit.metainterp.history import (Const, ConstInt, ConstFloat,
@@ -298,7 +299,7 @@
         self.free_temp_vars()
         return [base_loc, value_loc]
 
-    def prepare_int_ri(self, op):
+    def prepare_int_ri(self, op, res_in_cc):
         boxes = op.getarglist()
         a0, a1 = boxes
         imm_a0 = check_imm_box(a0)
@@ -314,9 +315,12 @@
             l1 = self.make_sure_var_in_reg(a1, boxes)
         self.possibly_free_vars_for_op(op)
         res = self.force_allocate_reg(op)
+        # note that we always allocate res, even if res_in_cc is True,
+        # that only means overflow is in CC
         return [l0, l1, res]
 
-    prepare_op_int_add = prepare_int_ri
+    def prepare_op_int_add(self, op):
+        return self.prepare_int_ri(op, False)
 
     def prepare_op_int_sub(self, op):
         boxes = op.getarglist()
@@ -332,6 +336,10 @@
         res = self.force_allocate_reg(op)
         return [l0, l1, res]
 
+    def prepare_comp_op_int_sub_ovf(self, op, res_in_cc):
+        # ignore res_in_cc
+        return self.prepare_op_int_sub(op)
+
     def prepare_op_int_mul(self, op):
         boxes = op.getarglist()
         a0, a1 = boxes
@@ -345,6 +353,9 @@
         self.possibly_free_var(op)
         return [reg1, reg2, res]
 
+    def prepare_comp_op_int_mul_ovf(self, op, res_in_cc):
+        return self.prepare_op_int_mul(op)
+
     # some of those have forms of imm that they accept, but they're rather
     # obscure. Can be future optimization
     prepare_op_int_and = prepare_op_int_mul
@@ -470,10 +481,19 @@
     prepare_guard_op_guard_true = guard_impl
     prepare_guard_op_guard_false = guard_impl
 
+    def prepare_guard_op_guard_overflow(self, guard_op, prev_op):
+        self.assembler.dispatch_comparison(prev_op)
+        # result in CC
+        if prev_op.opnum == rop.INT_MUL_OVF:
+            return self._guard_impl(guard_op), c.GT
+        return self._guard_impl(guard_op), c.VC
+    prepare_guard_op_guard_no_overflow = prepare_guard_op_guard_overflow
+
     prepare_op_guard_true = _guard_impl
     prepare_op_guard_false = _guard_impl
 
     prepare_op_nursery_ptr_increment = prepare_op_int_add
+    prepare_comp_op_int_add_ovf = prepare_int_ri
 
     def prepare_op_jump(self, op):
         assert self.jump_target_descr is None


More information about the pypy-commit mailing list