[pypy-commit] pypy s390x-backend: added test for an overflow operations, added regalloc for guards (overflow, exception). they are not yet fully functional
plan_rich
noreply at buildbot.pypy.org
Fri Nov 13 06:52:12 EST 2015
Author: Richard Plangger <planrichi at gmail.com>
Branch: s390x-backend
Changeset: r80661:d49e13685df3
Date: 2015-11-13 12:52 +0100
http://bitbucket.org/pypy/pypy/changeset/d49e13685df3/
Log: added test for an overflow operations, added regalloc for guards
(overflow, exception). they are not yet fully functional
diff --git a/rpython/jit/backend/zarch/conditions.py b/rpython/jit/backend/zarch/conditions.py
--- a/rpython/jit/backend/zarch/conditions.py
+++ b/rpython/jit/backend/zarch/conditions.py
@@ -5,10 +5,11 @@
EQ = loc.imm(0x8)
LT = loc.imm(0x4)
GT = loc.imm(0x2)
-OF = loc.imm(0x1)
+OF = loc.imm(0x1) # overflow
LE = loc.imm(EQ.value | LT.value)
GE = loc.imm(EQ.value | GT.value)
NE = loc.imm(LT.value | GT.value)
+NO = loc.imm(0xe) # NO overflow
ANY = loc.imm(0xf)
cond_none = loc.imm(0x0)
diff --git a/rpython/jit/backend/zarch/helper/assembler.py b/rpython/jit/backend/zarch/helper/assembler.py
--- a/rpython/jit/backend/zarch/helper/assembler.py
+++ b/rpython/jit/backend/zarch/helper/assembler.py
@@ -76,7 +76,7 @@
getattr(self.mc, func)(l0, l0, l1)
return f
-def gen_emit_rr_or_rpool(rr_func, rp_func):
+def gen_emit_rr_or_rpool(rr_func, rp_func, overflow=False):
""" the parameters can either be both in registers or
the first is in the register, second in literal pool.
"""
@@ -88,4 +88,34 @@
getattr(self.mc, rp_func)(l0, l1)
else:
getattr(self.mc, rr_func)(l0, l1)
+ if overflow:
+ self.guard_success_cc = c.OF
return f
+
+def gen_emit_imm_pool_rr(imm_func, pool_func, rr_func, overflow=False):
+ def emit(self, op, arglocs, regalloc):
+ l0, l1 = arglocs
+ if l1.is_in_pool():
+ getattr(self.mc, pool_func)(l0, l1)
+ elif l1.is_imm():
+ getattr(self.mc, imm_func)(l0, l1)
+ else:
+ getattr(self.mc, rr_func)(l0, l1)
+ if overflow:
+ self.guard_success_cc = c.OF
+ return emit
+
+def gen_emit_pool_or_rr_evenodd(pool_func, rr_func):
+ def emit(self, op, arglocs, regalloc):
+ lr, lq, l1 = arglocs # lr == remainer, lq == quotient
+ # when entering the function lr contains the dividend
+ # after this operation either lr or lq is used further
+ assert l1.is_in_pool() or not l1.is_imm() , "imm divider not supported"
+ # remainer is always a even register r0, r2, ... , r14
+ assert lr.is_even()
+ assert lq.is_odd()
+ if l1.is_in_pool():
+ self.mc.DSG(lr, l1)
+ else:
+ self.mc.DSGR(lr, l1)
+ return emit
diff --git a/rpython/jit/backend/zarch/opassembler.py b/rpython/jit/backend/zarch/opassembler.py
--- a/rpython/jit/backend/zarch/opassembler.py
+++ b/rpython/jit/backend/zarch/opassembler.py
@@ -1,5 +1,6 @@
from rpython.jit.backend.zarch.helper.assembler import (gen_emit_cmp_op,
- gen_emit_rr_or_rpool, gen_emit_shift)
+ gen_emit_rr_or_rpool, gen_emit_shift, gen_emit_pool_or_rr_evenodd,
+ gen_emit_imm_pool_rr)
from rpython.jit.backend.zarch.codebuilder import ZARCHGuardToken
import rpython.jit.backend.zarch.conditions as c
import rpython.jit.backend.zarch.registers as r
@@ -9,70 +10,17 @@
class IntOpAssembler(object):
_mixin_ = True
- def emit_int_add(self, op, arglocs, regalloc):
- l0, l1 = arglocs
- if l1.is_imm():
- self.mc.AGFI(l0, l1)
- elif l1.is_in_pool():
- self.mc.AG(l0, l1)
- else:
- self.mc.AGR(l0, l1)
+ emit_int_add = gen_emit_imm_pool_rr('AGFI','AG','AGR')
+ emit_int_add_ovf = gen_emit_imm_pool_rr('AGFI','AG','AGR', overflow=True)
+ emit_int_sub = gen_emit_rr_or_rpool('SGR', 'SG')
+ emit_int_sub_ovf = gen_emit_rr_or_rpool('SGR', 'SG', overflow=True)
+ emit_int_mul = gen_emit_imm_pool_rr('MSGFI', 'MSG', 'MSGR')
- def emit_int_mul(self, op, arglocs, regalloc):
- l0, l1 = arglocs
- if l1.is_imm():
- self.mc.MSGFI(l0, l1)
- elif l1.is_in_pool():
- self.mc.MSG(l0, l1)
- else:
- self.mc.MSGR(l0, l1)
-
- def emit_int_floordiv(self, op, arglocs, regalloc):
- lr, lq, l1 = arglocs # lr == remainer, lq == quotient
- # when entering the function lr contains the dividend
- # after this operation either lr or lq is used further
- assert l1.is_in_pool() or not l1.is_imm() , "imm divider not supported"
- # remainer is always a even register r0, r2, ... , r14
- assert lr.is_even()
- assert lq.is_odd()
- if l1.is_in_pool():
- self.mc.DSG(lr, l1)
- else:
- self.mc.DSGR(lr, l1)
-
- def emit_uint_floordiv(self, op, arglocs, regalloc):
- lr, lq, l1 = arglocs # lr == remainer, lq == quotient
- # when entering the function lr contains the dividend
- # after this operation either lr or lq is used further
- assert l1.is_in_pool() or not l1.is_imm() , "imm divider not supported"
- # remainer is always a even register r0, r2, ... , r14
- assert lr.is_even()
- assert lq.is_odd()
- self.mc.XGR(lr, lr)
- if l1.is_in_pool():
- self.mc.DLG(lr, l1)
- else:
- self.mc.DLGR(lr, l1)
-
- def emit_int_mod(self, op, arglocs, regalloc):
- lr, lq, l1 = arglocs # lr == remainer, lq == quotient
- # when entering the function lr contains the dividend
- # after this operation either lr or lq is used further
- assert l1.is_in_pool() or not l1.is_imm() , "imm divider not supported"
- # remainer is always a even register r0, r2, ... , r14
- assert lr.is_even()
- assert lq.is_odd()
- if l1.is_in_pool():
- self.mc.DSG(lr, l1)
- else:
- self.mc.DSGR(lr, l1)
-
- def emit_int_sub(self, op, arglocs, regalloc):
- l0, l1 = arglocs
- if l1.is_in_pool():
- self.mc.SG(l0, l1)
- else:
- self.mc.SGR(l0, l1)
+ emit_int_floordiv = gen_emit_pool_or_rr_evenodd('DSG','DSGR')
+ emit_uint_floordiv = gen_emit_pool_or_rr_evenodd('DLG','DLGR')
+ # NOTE division sets one register with the modulo value, thus
+ # the regalloc ensures the right register survives.
+ emit_int_mod = gen_emit_pool_or_rr_evenodd('DSG','DSGR')
def emit_int_invert(self, op, arglocs, regalloc):
l0 = arglocs[0]
@@ -93,7 +41,6 @@
self.mc.CGHI(l0, l.imm(0))
self.flush_cc(c.NE, l0)
-
emit_int_and = gen_emit_rr_or_rpool("NGR", "NG")
emit_int_or = gen_emit_rr_or_rpool("OGR", "OG")
emit_int_xor = gen_emit_rr_or_rpool("XGR", "XG")
@@ -174,11 +121,11 @@
self._emit_guard(op, arglocs)
def emit_guard_overflow(self, op, arglocs, regalloc):
- self.guard_success_cc = c.SO
+ self.guard_success_cc = c.NO
self._emit_guard(op, arglocs)
def emit_guard_no_overflow(self, op, arglocs, regalloc):
- self.guard_success_cc = c.NS
+ self.guard_success_cc = c.OF
self._emit_guard(op, arglocs)
def emit_guard_value(self, op, arglocs, regalloc):
diff --git a/rpython/jit/backend/zarch/regalloc.py b/rpython/jit/backend/zarch/regalloc.py
--- a/rpython/jit/backend/zarch/regalloc.py
+++ b/rpython/jit/backend/zarch/regalloc.py
@@ -534,7 +534,9 @@
pass # XXX
prepare_int_add = helper.prepare_int_add
+ prepare_int_add_ovf = helper.prepare_int_add
prepare_int_sub = helper.prepare_int_sub
+ prepare_int_sub_ovf = helper.prepare_int_sub
prepare_int_mul = helper.prepare_int_mul
prepare_int_floordiv = helper.prepare_int_div
prepare_uint_floordiv = helper.prepare_int_div
@@ -561,6 +563,7 @@
prepare_int_invert = helper.prepare_unary_op
prepare_int_force_ge_zero = helper.prepare_unary_op
+
prepare_float_add = helper.prepare_binary_op
prepare_float_sub = helper.prepare_binary_op
prepare_float_mul = helper.prepare_binary_op
@@ -598,6 +601,15 @@
prepare_guard_false = _prepare_guard_cc
prepare_guard_nonnull = _prepare_guard_cc
prepare_guard_isnull = _prepare_guard_cc
+ prepare_guard_overflow = _prepare_guard_cc
+
+ def prepare_guard_no_exception(self, op):
+ arglocs = self._prepare_guard(op)
+ return arglocs
+
+ prepare_guard_no_overflow = prepare_guard_no_exception
+ prepare_guard_overflow = prepare_guard_no_exception
+ prepare_guard_not_forced = prepare_guard_no_exception
def prepare_label(self, op):
descr = op.getdescr()
diff --git a/rpython/jit/backend/zarch/test/test_runner.py b/rpython/jit/backend/zarch/test/test_runner.py
--- a/rpython/jit/backend/zarch/test/test_runner.py
+++ b/rpython/jit/backend/zarch/test/test_runner.py
@@ -66,3 +66,32 @@
res = self.cpu.get_int_value(deadframe, 0)
assert res == result
assert fail.identifier == 1
+
+ @py.test.mark.parametrize('value,opcode,result,guard',
+ [ (-2**63, 'i1 = int_add_ovf(i0, 1)', -2**63, 'guard_no_overflow'),
+ (-2**63+1,'i1 = int_add_ovf(i0, 1)', -2**63, 'guard_no_overflow'),
+ (-2**63+1,'i1 = int_add_ovf(i0, 1)', -2**63+1, 'guard_overflow'),
+ ])
+ def test_int_arithmetic_overflow(self, value, opcode, result, guard):
+ code = """
+ [i0]
+ {opcode}
+ {guard}() [i0]
+ finish(i1, descr=faildescr)
+ """.format(opcode=opcode,guard=guard)
+ loop = parse(code, namespace={"faildescr": BasicFinalDescr(1)})
+ looptoken = JitCellToken()
+ self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
+ deadframe = self.cpu.execute_token(looptoken, value)
+ fail = self.cpu.get_latest_descr(deadframe)
+ res = self.cpu.get_int_value(deadframe, 0)
+ assert res == result
+ #assert fail.identifier == 1
+
+ def test_double_evenodd_pair(self):
+ # TODO
+ pass
+
+ def test_double_evenodd_pair_spill(self):
+ # TODO
+ pass
More information about the pypy-commit
mailing list