[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