[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