Author: Richard Plangger <planri...@gmail.com> Branch: s390x-backend Changeset: r80732:173b585af649 Date: 2015-11-17 20:00 +0100 http://bitbucket.org/pypy/pypy/changeset/173b585af649/
Log: ironed out the bug in mul overflow, test runner is now passing two ovf tests! diff --git a/rpython/jit/backend/zarch/assembler.py b/rpython/jit/backend/zarch/assembler.py --- a/rpython/jit/backend/zarch/assembler.py +++ b/rpython/jit/backend/zarch/assembler.py @@ -643,17 +643,21 @@ gcmap = self._finish_gcmap else: gcmap = lltype.nullptr(jitframe.GCMAP) - #self.pool.load_gcmap(self.mc, r.r2, gcmap) + self.load_gcmap(self.mc, r.r2, gcmap) - assert fail_descr_loc.getint() <= 2**12-1 - self.mc.LGHI(r.r5, fail_descr_loc) - self.mc.STG(r.r5, l.addr(ofs, r.SPP)) - self.mc.XGR(r.r2, r.r2) # TODO + assert fail_descr_loc.getint() <= 2**32-1 + self.mc.LGFI(r.r3, fail_descr_loc) + self.mc.STG(r.r3, l.addr(ofs, r.SPP)) self.mc.STG(r.r2, l.addr(ofs2, r.SPP)) # exit function self._call_footer() + def load_gcmap(self, mc, reg, gcmap): + # load the current gcmap into register 'reg' + ptr = rffi.cast(lltype.Signed, gcmap) + mc.load_imm(reg, ptr) + def notimplemented_op(asm, op, arglocs, regalloc): print "[ZARCH/asm] %s not implemented" % op.getopname() raise NotImplementedError(op) diff --git a/rpython/jit/backend/zarch/codebuilder.py b/rpython/jit/backend/zarch/codebuilder.py --- a/rpython/jit/backend/zarch/codebuilder.py +++ b/rpython/jit/backend/zarch/codebuilder.py @@ -146,6 +146,14 @@ self.CGR(a, b) + def load_imm(self, dest_reg, word): + if word <= 32767 and word >= -32768: + self.LGHI(dest_reg, l.imm(word)) + elif word <= 2**31-1 and word >= -2**31: + self.LGFI(dest_reg, l.imm(word)) + else: + xxx + _classes = (AbstractZARCHBuilder,) # Used to build the MachineCodeBlockWrapper 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 @@ -71,8 +71,6 @@ def gen_emit_shift(func): def f(self, op, arglocs, regalloc): l0, l1 = arglocs - if not l1.is_imm() or l1.is_in_pool(): - assert 0, "shift imm must NOT reside in pool!" getattr(self.mc, func)(l0, l0, l1) return f @@ -111,7 +109,7 @@ assert lr.is_even() assert lq.is_odd() if l1.is_in_pool(): - self.mc.DSG(lr, l1) + getattr(self.mc,pool_func)(lr, l1) else: - self.mc.DSGR(lr, l1) + getattr(self.mc,rr_func)(lr, l1) return emit diff --git a/rpython/jit/backend/zarch/helper/regalloc.py b/rpython/jit/backend/zarch/helper/regalloc.py --- a/rpython/jit/backend/zarch/helper/regalloc.py +++ b/rpython/jit/backend/zarch/helper/regalloc.py @@ -100,7 +100,6 @@ a0 = op.getarg(0) a1 = op.getarg(1) assert isinstance(a1, ConstInt) - l1 = self.ensure_reg(a1) assert check_imm20(a1) l0 = self.ensure_reg(a0) # note that the shift value is stored diff --git a/rpython/jit/backend/zarch/instruction_builder.py b/rpython/jit/backend/zarch/instruction_builder.py --- a/rpython/jit/backend/zarch/instruction_builder.py +++ b/rpython/jit/backend/zarch/instruction_builder.py @@ -338,6 +338,21 @@ build_rie_g = build_rie_a +def build_rie_b(mnemonic, (opcode1,opcode2)): + br = is_branch_relative(mnemonic) + @builder.arguments('r,r,r/m,i16') + def encode_rie_b(self, reg1, reg2, mask, imm16): + self.writechar(opcode1) + byte = (reg1 & BIT_MASK_4) << 4 | (reg2 & BIT_MASK_4) + self.writechar(chr(byte)) + if br: + imm16 = imm16 >> 1 + self.write_i16(imm16 & BIT_MASK_16) + byte = (mask & BIT_MASK_4) << 4 + self.writechar(chr(byte)) + self.writechar(opcode2) + return encode_rie_b + def build_rie_c(mnemonic, (opcode1,opcode2), argtypes='r,i8,r/m,i16'): br = is_branch_relative(mnemonic) @builder.arguments(argtypes) @@ -395,6 +410,19 @@ self.writechar(opcode2) return encode_rxe +def build_ris(mnemonic, (opcode1,opcode2), argtypes='r,i8,r/m,bd'): + br = is_branch_relative(mnemonic) + @builder.arguments(argtypes) + def encode_rie_c(self, reg1, imm8, mask, basedisp): + self.writechar(opcode1) + byte = (reg1 & BIT_MASK_4) << 4 | (mask & BIT_MASK_4) + self.writechar(chr(byte)) + # + encode_base_displace(self, basedisp) + self.writechar(chr(imm8 & 0xff)) + self.writechar(opcode2) + return encode_rie_c + def build_unpack_func(mnemonic, func): def function(self, *args): newargs = [None] * len(func._arguments_) diff --git a/rpython/jit/backend/zarch/instructions.py b/rpython/jit/backend/zarch/instructions.py --- a/rpython/jit/backend/zarch/instructions.py +++ b/rpython/jit/backend/zarch/instructions.py @@ -43,8 +43,6 @@ 'LNGR': ('rre', ['\xB9','\x01']), 'LCGR': ('rre', ['\xB9','\x03']), - - # div 'AY': ('rxy', ['\xE3','\x5A']), @@ -63,6 +61,9 @@ 'CGFI': ('ril', ['\xC2','\x0C']), 'CGIJ': ('rie_c', ['\xEC','\x7C']), 'CLGIJ': ('rie_c', ['\xEC','\x7D'], 'r,u8,r/m,i16'), + 'CGIB': ('ris', ['\xEC','\xFC']), + 'CGRJ': ('rie_b', ['\xEC','\x64']), + 'CLGRJ': ('rie_b', ['\xEC','\x65']), } logic_mnemonic_codes = { diff --git a/rpython/jit/backend/zarch/locations.py b/rpython/jit/backend/zarch/locations.py --- a/rpython/jit/backend/zarch/locations.py +++ b/rpython/jit/backend/zarch/locations.py @@ -204,10 +204,10 @@ return True def is_imm(self): - return True + return False def is_imm_float(self): - return self.isfloat + return False def is_float(self): return self.isfloat 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 @@ -25,13 +25,22 @@ l1 = r.SCRATCH mc = self.mc + bc_one_decision = mc.CLGRJ_byte_count +\ + mc.CLGIJ_byte_count + \ + mc.LCGR_byte_count + \ + mc.BRC_byte_count + \ + mc.SPM_byte_count bc_one_signed = mc.LPGR_byte_count * 2 + \ mc.MLGR_byte_count + \ - mc.XG_byte_count + \ - mc.CLGIJ_byte_count * 2 + \ - mc.BRC_byte_count - bc_none_signed = mc.MLGR_byte_count + mc.CGIJ_byte_count * 2 + mc.BRC_byte_count + mc.LPGR_byte_count * 2 - bc_set_overflow = mc.IPM_byte_count + mc.OIHL_byte_count + mc.SPM_byte_count + mc.LG_byte_count + \ + bc_one_decision + bc_none_signed = mc.LPGR_byte_count * 2 + \ + mc.MLGR_byte_count + \ + mc.LG_byte_count + \ + mc.CLGRJ_byte_count + \ + mc.CLGIJ_byte_count + \ + mc.BRC_byte_count + bc_set_overflow = mc.OIHL_byte_count + mc.SPM_byte_count # check left neg mc.CGIJ(lq, l.imm(0), c.LT, l.imm(mc.CGIJ_byte_count*2)) @@ -41,22 +50,27 @@ mc.LPGR(lq, lq) mc.LPGR(l1, l1) mc.MLGR(lr, l1) - off = mc.CLGIJ_byte_count * 2 + mc.XG_byte_count + mc.BRC_byte_count + bc_none_signed - mc.CLGIJ(lr, l.imm(0), c.GT, l.imm(off)) # jump to overflow - mc.CGIJ(lq, l.imm(0), c.LT, l.imm(off - mc.CGIJ_byte_count)) # jump to over overflow - mc.XG(lq, l.pool(self.pool.constant_64_sign_bit)) # only one is negative, set the sign bit! + mc.LG(r.SCRATCH, l.pool(self.pool.constant_max_64_positive)) + # is the value greater than 2**63 ? then an overflow occured + mc.CLGRJ(lq, r.SCRATCH, c.GT, l.imm(bc_one_decision + bc_none_signed)) # jump to over overflow + mc.CLGIJ(lr, l.imm(0), c.GT, l.imm(bc_one_decision - mc.CLGRJ_byte_count + bc_none_signed)) # jump to overflow + mc.LCGR(lq, lq) + mc.SPM(r.SCRATCH) # 0x80 ... 00 clears the condition code and program mask mc.BRC(c.ANY, l.imm(mc.BRC_byte_count + bc_set_overflow + bc_none_signed)) # no overflow happened # both are positive mc.LPGR(lq, lq) mc.LPGR(l1, l1) mc.MLGR(lr, l1) - mc.CGIJ(lq, l.imm(0), c.LT, l.imm(mc.CGIJ_byte_count * 2 + mc.BRC_byte_count)) # jump to over overflow - mc.CLGIJ(lr, l.imm(0), c.GT, l.imm(mc.CGIJ_byte_count + mc.BRC_byte_count)) # jump to overflow + off = mc.CLGRJ_byte_count + mc.CLGIJ_byte_count + \ + mc.BRC_byte_count + mc.LG(r.SCRATCH, l.pool(self.pool.constant_64_ones)) + mc.CLGRJ(lq, r.SCRATCH, c.GT, l.imm(off)) # jump to over overflow + mc.CLGIJ(lr, l.imm(0), c.GT, l.imm(off - mc.CLGRJ_byte_count)) # jump to overflow mc.BRC(c.ANY, l.imm(mc.BRC_byte_count + bc_set_overflow)) # no overflow happened # set overflow! - mc.IPM(r.SCRATCH) + #mc.IPM(r.SCRATCH) # set bit 34 & 35 -> indicates overflow mc.OILH(r.SCRATCH, l.imm(0x3000)) # sets OF mc.SPM(r.SCRATCH) @@ -67,7 +81,27 @@ 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') + #emit_int_mod = gen_emit_pool_or_rr_evenodd('DSG','DSGR') + 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) + # python behavior? + #off = self.mc.CGIJ_byte_count+self.mc.AG_byte_count + #self.mc.CGIJ(lr, l.imm(0), c.GE, l.imm(off)) + #self.mc.AG(lr, l1) + else: + self.mc.DSGR(lr, l1) + # python behavior? + #off = self.mc.CGIJ_byte_count+self.mc.AGR_byte_count + #self.mc.CGIJ(lr, l.imm(0), c.GE, l.imm(off)) + #self.mc.AGR(lr, l1) def emit_int_invert(self, op, arglocs, regalloc): l0 = arglocs[0] diff --git a/rpython/jit/backend/zarch/pool.py b/rpython/jit/backend/zarch/pool.py --- a/rpython/jit/backend/zarch/pool.py +++ b/rpython/jit/backend/zarch/pool.py @@ -18,8 +18,10 @@ self.constant_64_zeros = -1 self.constant_64_ones = -1 self.constant_64_sign_bit = -1 + self.constant_max_64_positive = -1 def ensure_can_hold_constants(self, asm, op): + opnum = op.getopnum() if op.is_guard(): # 1x gcmap pointer # 1x target address @@ -41,6 +43,10 @@ self.constant_64_ones = 1 # we need constant ones!!! elif op.getopnum() == rop.INT_MUL_OVF: self.constant_64_sign_bit = 1 + self.constant_max_64_positive = 1 + elif opnum == rop.INT_RSHIFT or opnum == rop.INT_LSHIFT or \ + opnum == rop.UINT_RSHIFT: + return for arg in op.getarglist(): if arg.is_constant(): self.offset_map[arg] = self.size @@ -58,6 +64,10 @@ self.label_offset = 0 self.size = 0 self.offset_map.clear() + self.constant_64_zeros = -1 + self.constant_64_ones = -1 + self.constant_64_sign_bit = -1 + self.constant_max_64_positive -1 def pre_assemble(self, asm, operations, bridge=False): self.reset() @@ -84,20 +94,24 @@ assert self.size % 2 == 0 #if self.size % 2 == 1: # self.size += 1 - asm.mc.write('\xFF' * self.size) + asm.mc.write('\x00' * self.size) written = 0 - if self.constant_64_ones: + if self.constant_64_ones != -1: asm.mc.write('\xFF' * 8) self.constant_64_ones = self.size written += 8 - if self.constant_64_zeros: + if self.constant_64_zeros != -1: asm.mc.write('\x00' * 8) self.constant_64_zeros = self.size written += 8 - if self.constant_64_sign_bit: - asm.mc.write('\x80' + '\x00' * 7) + if self.constant_64_sign_bit != -1: + asm.mc.write('\x80' + ('\x00' * 7)) self.constant_64_sign_bit = self.size written += 8 + if self.constant_max_64_positive != -1: + asm.mc.write('\x7F' + ('\xFF' * 7)) + self.constant_max_64_positive = self.size + written += 8 self.size += written print "pool with %d quad words" % (self.size // 8) diff --git a/rpython/jit/backend/zarch/registers.py b/rpython/jit/backend/zarch/registers.py --- a/rpython/jit/backend/zarch/registers.py +++ b/rpython/jit/backend/zarch/registers.py @@ -7,7 +7,7 @@ [r0,r1,r2,r3,r4,r5,r6,r7,r8, r9,r10,r11,r12,r13,r14,r15] = registers -MANAGED_REGS = [r0,r1,r4,r5,r6,r7,r8,r9,r10,r12] +MANAGED_REGS = [r0,r1,r4,r5,r6,r7,r8,r9,r10,r12] # keep this list sorted (asc)! VOLATILES = [r6,r7,r8,r9,r10,r12] SP = r15 RETURN = r14 diff --git a/rpython/jit/backend/zarch/test/test_int.py b/rpython/jit/backend/zarch/test/test_int.py new file mode 100644 --- /dev/null +++ b/rpython/jit/backend/zarch/test/test_int.py @@ -0,0 +1,192 @@ +from rpython.jit.backend.test.runner_test import LLtypeBackendTest +from rpython.jit.backend.zarch.runner import CPU_S390_64 +from rpython.jit.tool.oparser import parse +from rpython.jit.metainterp.history import (AbstractFailDescr, + AbstractDescr, + BasicFailDescr, BasicFinalDescr, + JitCellToken, TargetToken, + ConstInt, ConstPtr, + Const, ConstFloat) +from rpython.jit.metainterp.resoperation import InputArgInt, InputArgFloat +from rpython.rtyper.lltypesystem import lltype +from rpython.jit.metainterp.resoperation import ResOperation, rop +import py + +class FakeStats(object): + pass + +class TestIntResOpZARCH(object): + cpu = CPU_S390_64(rtyper=None, stats=FakeStats()) + cpu.setup_once() + + @py.test.mark.parametrize('value,opcode,result', + [ (30,'i1 = int_mul(i0, 2)',60), + (30,'i1 = int_floordiv(i0, 2)',15), + (2**31,'i1 = int_floordiv(i0, 15)',2**31//15), + (0,'i1 = int_floordiv(i0, 1)', 0), + (1,'i1 = int_floordiv(i0, 1)', 1), + (0,'i1 = uint_floordiv(i0, 1)', 0), + (1,'i1 = uint_floordiv(i0, 1)', 1), + (30,'i1 = int_mod(i0, 2)', 0), + (1,'i1 = int_mod(i0, 2)', 1), + (1,'i1 = int_lshift(i0, 4)', 16), + (1,'i1 = int_lshift(i0, 0)', 1), + (4,'i1 = int_rshift(i0, 0)', 4), + (4,'i1 = int_rshift(i0, 1)', 2), + (-1,'i1 = int_rshift(i0, 0)', -1), + (-1,'i1 = int_lshift(i0, 1)', -2), + (-2**35,'i1 = int_lshift(i0, 1)', (-2**35)*2), + (2**64-1,'i1 = uint_rshift(i0, 2)', (2**64-1)//4), + (-1,'i1 = int_neg(i0)', -1), + (1,'i1 = int_neg(i0)', -1), + (2**63-1,'i1 = int_neg(i0)', -(2**63-1)), + (1,'i1 = int_invert(i0)', ~1), + (15,'i1 = int_invert(i0)', ~15), + (-1,'i1 = int_invert(i0)', ~(-1)), + (0,'i1 = int_is_zero(i0)', 1), + (50,'i1 = int_is_zero(i0)', 0), + (-1,'i1 = int_is_true(i0)', 1), + (0,'i1 = int_is_true(i0)', 0), + ]) + def test_int_arithmetic_and_logic(self, value, opcode, result): + loop = parse(""" + [i0] + {opcode} + finish(i1, descr=faildescr) + """.format(opcode=opcode),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 + + @py.test.mark.parametrize('value,opcode,result,guard', + [ (2**63-1,'i1 = int_add_ovf(i0, 1)',1,'guard_no_overflow'), + (2**63-2,'i1 = int_add_ovf(i0, 1)',0,'guard_no_overflow'), + (2**63-2,'i1 = int_add_ovf(i0, 1)',1,'guard_overflow'), + (2**63-1,'i1 = int_add_ovf(i0, 1)',0,'guard_overflow'), + + (-2**63, 'i1 = int_sub_ovf(i0, 1)',1,'guard_no_overflow'), + (-2**63+1,'i1 = int_sub_ovf(i0, 1)',0,'guard_no_overflow'), + (-2**63+1,'i1 = int_sub_ovf(i0, 1)',1,'guard_overflow'), + (-2**63, 'i1 = int_sub_ovf(i0, 1)',0,'guard_overflow'), + + (-2**63, 'i1 = int_mul_ovf(i0, 2)',1,'guard_no_overflow'), + (-2**63, 'i1 = int_mul_ovf(i0, -2)',1,'guard_no_overflow'), + (-2**15, 'i1 = int_mul_ovf(i0, 2)',0,'guard_no_overflow'), + (-2**63, 'i1 = int_mul_ovf(i0, 0)',0,'guard_no_overflow'), + (-2**63, 'i1 = int_mul_ovf(i0, 2)',0,'guard_overflow'), + (-2**63, 'i1 = int_mul_ovf(i0, -2)',0,'guard_overflow'), + (-2**63, 'i1 = int_mul_ovf(i0, 0)',1,'guard_overflow'), + # positive! + (2**63-1, 'i1 = int_mul_ovf(i0, 33)',1,'guard_no_overflow'), + (2**63-1, 'i1 = int_mul_ovf(i0, -2)',1,'guard_no_overflow'), + (2**15, 'i1 = int_mul_ovf(i0, 2)',0,'guard_no_overflow'), + (2**63-1, 'i1 = int_mul_ovf(i0, 0)',0,'guard_no_overflow'), + (2**63-1, 'i1 = int_mul_ovf(i0, 99)',0,'guard_overflow'), + (2**63-1, 'i1 = int_mul_ovf(i0, 3323881828381)',0,'guard_overflow'), + (2**63-1, 'i1 = int_mul_ovf(i0, 0)',1,'guard_overflow'), + ]) + def test_int_arithmetic_overflow(self, value, opcode, result, guard): + # result == 1 means branch has been taken of the guard + code = """ + [i0] + {opcode} + {guard}() [i0] + i2 = int_xor(i1,i1) + finish(i2, 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) + if result == 1: + assert res == value + else: + assert res == 0 + + def test_double_evenodd_pair(self): + code = """ + [i0] + i1 = int_floordiv(i0, 2) + i2 = int_floordiv(i0, 3) + i3 = int_floordiv(i0, 4) + i4 = int_floordiv(i0, 5) + i5 = int_floordiv(i0, 6) + i6 = int_floordiv(i0, 7) + i7 = int_floordiv(i0, 8) + i8 = int_le(i1, 0) + guard_true(i8) [i1,i2,i3,i4,i5,i6,i7] + finish(i0, descr=faildescr) + """ + # the guard forces 3 spills because after 4 divisions + # all even slots of the managed registers are full + loop = parse(code, namespace={'faildescr': BasicFinalDescr(1)}) + looptoken = JitCellToken() + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) + deadframe = self.cpu.execute_token(looptoken, 100) + fail = self.cpu.get_latest_descr(deadframe) + for i in range(2,9): + assert self.cpu.get_int_value(deadframe, i-2) == 100//i + + + + @py.test.mark.parametrize('value', [2,3,15,2**16]) + def test_evenodd_pair_extensive(self, value): + instrs = [] + failargs = [] + values = [] + j = 0 + mapping = (('int_floordiv',lambda x,y: x // y), + ('int_mod', lambda x,y: x % y), + ('int_mul_ovf', lambda x,y: x * y)) + for i in range(20): + name, func = mapping[j] + instrs.append("i{d} = {i}(i0, {d})".format(d=i+1, i=name)) + values.append((name, func(value, i+1))) + failargs.append("i" + str(i+1)) + j += 1 + if j >= len(mapping): + j = 0 + code = """ + [i0] + {instrs} + i99 = int_add(i0, 1) + i100 = int_eq(i0,i99) + guard_true(i100) [{failargs}] # will always fail!! + finish(i0, descr=faildescr) + """.format(instrs=('\n' +' '*8).join(instrs), failargs=','.join(failargs)) + # the guard forces 3 spills because after 4 divisions + # all even slots of the managed registers are full + 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) + for i,(name, v) in enumerate(values): + assert self.cpu.get_int_value(deadframe, i) == v + + @py.test.mark.parametrize('v1,v2', [ + (-32,3), (-32,4), (-32,1), (-32,199), + (16236612,3), (-1201203,4), (-123101010023,1231), (-0,199), + ]) + def test_int_mul_no_overflow(self, v1, v2): + try: + result = v1*v2 + except OverflowError: + py.test.skip("this test is not made to check the overflow!") + code = """ + [i0] + i1 = int_mul_ovf(i0,{v}) + finish(i1, descr=faildescr) + """.format(v=v2) + loop = parse(code, namespace={"faildescr": BasicFinalDescr(1)}) + looptoken = JitCellToken() + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) + deadframe = self.cpu.execute_token(looptoken, v1) + fail = self.cpu.get_latest_descr(deadframe) + assert self.cpu.get_int_value(deadframe, 0) == result 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 @@ -23,176 +23,3 @@ cpu = CPU_S390_64(rtyper=None, stats=FakeStats()) cpu.setup_once() return cpu - - @py.test.mark.parametrize('value,opcode,result', - [ (30,'i1 = int_mul(i0, 2)',60), - (30,'i1 = int_floordiv(i0, 2)',15), - (2**31,'i1 = int_floordiv(i0, 15)',2**31//15), - (0,'i1 = int_floordiv(i0, 1)', 0), - (1,'i1 = int_floordiv(i0, 1)', 1), - (0,'i1 = uint_floordiv(i0, 1)', 0), - (1,'i1 = uint_floordiv(i0, 1)', 1), - (30,'i1 = int_mod(i0, 2)', 0), - (1,'i1 = int_mod(i0, 2)', 1), - (1,'i1 = int_lshift(i0, 4)', 16), - (1,'i1 = int_lshift(i0, 0)', 1), - (4,'i1 = int_rshift(i0, 0)', 4), - (4,'i1 = int_rshift(i0, 1)', 2), - (-1,'i1 = int_rshift(i0, 0)', -1), - (-1,'i1 = int_lshift(i0, 1)', -2), - (-2**35,'i1 = int_lshift(i0, 1)', (-2**35)*2), - (2**64-1,'i1 = uint_rshift(i0, 2)', (2**64-1)//4), - (-1,'i1 = int_neg(i0)', -1), - (1,'i1 = int_neg(i0)', -1), - (2**63-1,'i1 = int_neg(i0)', -(2**63-1)), - (1,'i1 = int_invert(i0)', ~1), - (15,'i1 = int_invert(i0)', ~15), - (-1,'i1 = int_invert(i0)', ~(-1)), - (0,'i1 = int_is_zero(i0)', 1), - (50,'i1 = int_is_zero(i0)', 0), - (-1,'i1 = int_is_true(i0)', 1), - (0,'i1 = int_is_true(i0)', 0), - ]) - def test_int_arithmetic_and_logic(self, value, opcode, result): - loop = parse(""" - [i0] - {opcode} - finish(i1, descr=faildescr) - """.format(opcode=opcode),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 - - @py.test.mark.parametrize('value,opcode,result,guard', - [ (2**63-1,'i1 = int_add_ovf(i0, 1)',1,'guard_no_overflow'), - (2**63-2,'i1 = int_add_ovf(i0, 1)',0,'guard_no_overflow'), - (2**63-2,'i1 = int_add_ovf(i0, 1)',1,'guard_overflow'), - (2**63-1,'i1 = int_add_ovf(i0, 1)',0,'guard_overflow'), - - (-2**63, 'i1 = int_sub_ovf(i0, 1)',1,'guard_no_overflow'), - (-2**63+1,'i1 = int_sub_ovf(i0, 1)',0,'guard_no_overflow'), - (-2**63+1,'i1 = int_sub_ovf(i0, 1)',1,'guard_overflow'), - (-2**63, 'i1 = int_sub_ovf(i0, 1)',0,'guard_overflow'), - - (-2**63, 'i1 = int_mul_ovf(i0, 2)',1,'guard_no_overflow'), - (-2**63, 'i1 = int_mul_ovf(i0, -2)',1,'guard_no_overflow'), - (-2**15, 'i1 = int_mul_ovf(i0, 2)',0,'guard_no_overflow'), - (-2**63, 'i1 = int_mul_ovf(i0, 0)',0,'guard_no_overflow'), - (-2**63, 'i1 = int_mul_ovf(i0, 2)',0,'guard_overflow'), - (-2**63, 'i1 = int_mul_ovf(i0, -2)',0,'guard_overflow'), - (-2**63, 'i1 = int_mul_ovf(i0, 0)',1,'guard_overflow'), - # positive! - (2**63-1, 'i1 = int_mul_ovf(i0, 33)',1,'guard_no_overflow'), - (2**63-1, 'i1 = int_mul_ovf(i0, -2)',1,'guard_no_overflow'), - (2**15, 'i1 = int_mul_ovf(i0, 2)',0,'guard_no_overflow'), - (2**63-1, 'i1 = int_mul_ovf(i0, 0)',0,'guard_no_overflow'), - (2**63-1, 'i1 = int_mul_ovf(i0, 99)',0,'guard_overflow'), - (2**63-1, 'i1 = int_mul_ovf(i0, 3323881828381)',0,'guard_overflow'), - (2**63-1, 'i1 = int_mul_ovf(i0, 0)',1,'guard_overflow'), - ]) - def test_int_arithmetic_overflow(self, value, opcode, result, guard): - # result == 1 means branch has been taken of the guard - code = """ - [i0] - {opcode} - {guard}() [i0] - i2 = int_xor(i1,i1) - finish(i2, 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) - if result == 1: - assert res == value - else: - assert res == 0 - - def test_double_evenodd_pair(self): - code = """ - [i0] - i1 = int_floordiv(i0, 2) - i2 = int_floordiv(i0, 3) - i3 = int_floordiv(i0, 4) - i4 = int_floordiv(i0, 5) - i5 = int_floordiv(i0, 6) - i6 = int_floordiv(i0, 7) - i7 = int_floordiv(i0, 8) - i8 = int_le(i1, 0) - guard_true(i8) [i1,i2,i3,i4,i5,i6,i7] - finish(i0, descr=faildescr) - """ - # the guard forces 3 spills because after 4 divisions - # all even slots of the managed registers are full - loop = parse(code, namespace={'faildescr': BasicFinalDescr(1)}) - looptoken = JitCellToken() - self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) - deadframe = self.cpu.execute_token(looptoken, 100) - fail = self.cpu.get_latest_descr(deadframe) - for i in range(2,9): - assert self.cpu.get_int_value(deadframe, i-2) == 100//i - - - - @py.test.mark.parametrize('value', [2,3,15,2**16,-2**5]) - def test_double_evenodd_pair_extensive(self, value): - instrs = [] - failargs = [] - values = [] - j = 0 - mapping = (('int_floordiv',lambda x,y: x // y), - ('int_mod', lambda x,y: x % y), - ('int_mul_ovf', lambda x,y: x * y)) - for i in range(20): - name, func = mapping[j] - instrs.append("i{d} = {i}(i0, {d})".format(d=i+1, i=name)) - values.append((name, func(value, i+1))) - failargs.append("i" + str(i+1)) - j += 1 - if j >= len(mapping): - j = 0 - code = """ - [i0] - {instrs} - i99 = int_add(i0, 1) - i100 = int_eq(i0,i99) - guard_true(i100) [{failargs}] # will always fail!! - finish(i0, descr=faildescr) - """.format(instrs=('\n' +' '*8).join(instrs), failargs=','.join(failargs)) - # the guard forces 3 spills because after 4 divisions - # all even slots of the managed registers are full - 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) - for i,(name, v) in enumerate(values): - assert self.cpu.get_int_value(deadframe, i) == v - - @py.test.mark.parametrize('v1,v2', [ - (-32,3), - ]) - def test_int_mul_no_overflow(self, v1, v2): - try: - result = v1*v2 - except OverflowError: - py.test.skip("this test is not made to check the overflow!") - code = """ - [i0] - i1 = int_mul_ovf(i0,{v}) - finish(i1, descr=faildescr) - """.format(v=v2) - loop = parse(code, namespace={"faildescr": BasicFinalDescr(1)}) - looptoken = JitCellToken() - self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) - import pdb; pdb.set_trace() - deadframe = self.cpu.execute_token(looptoken, v1) - fail = self.cpu.get_latest_descr(deadframe) - assert self.cpu.get_int_value(deadframe, 0) == result - _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit