Author: Richard Plangger <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit