Author: Richard Plangger <planri...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit