[pypy-commit] pypy s390x-backend: finished implementation to allocate a register pair (even/odd), added test case to ensure the spilling is done correctly

plan_rich noreply at buildbot.pypy.org
Tue Nov 17 08:37:09 EST 2015


Author: Richard Plangger <planrichi at gmail.com>
Branch: s390x-backend
Changeset: r80730:0b2023218277
Date: 2015-11-17 14:37 +0100
http://bitbucket.org/pypy/pypy/changeset/0b2023218277/

Log:	finished implementation to allocate a register pair (even/odd),
	added test case to ensure the spilling is done correctly

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
@@ -193,7 +193,7 @@
                 # a candidate?
                 odd = even
                 even = REGS[even.value-1]
-                if even in r.MANAGED_REGS:
+                if even in r.MANAGED_REGS and even not in self.free_regs:
                     # yes even might be a candidate
                     candidates.append(even)
             i -= 1
@@ -209,11 +209,17 @@
                     continue
                 reg = self.reg_bindings[next]
                 if reg in candidates:
-                    pass
-                max_age = self.longevity[next][1]
-                if cur_max_age < max_age:
-                    cur_max_age = max_age
-                    candidate = next
+                    reg2 = None
+                    if reg.is_even():
+                        reg2 = REGS[reg.value+1]
+                    else:
+                        reg2 = REGS[reg.value-1]
+                    if reg2 not in r.MANAGED_REGS:
+                        continue
+                    max_age = self.longevity[next][1]
+                    if cur_max_age < max_age:
+                        cur_max_age = max_age
+                        candidate = next
             if candidate is not None:
                 # well, we got away with a single spill :)
                 reg = self.reg_bindings[candidate]
@@ -221,12 +227,16 @@
                 if reg.is_even():
                     self.reg_bindings[var] = reg
                     rmfree = REGS[reg.value+1]
+                    rmidx = self.free_regs.index(reg)
+                    del self.free_regs[rmidx]
                     self.reg_bindings[var2] = rmfree
                     rmidx = self.free_regs.index(rmfree)
                     del self.free_regs[rmidx]
                     return reg, rmfree
                 else:
                     self.reg_bindings[var2] = reg
+                    rmidx = self.free_regs.index(reg)
+                    del self.free_regs[rmidx]
                     rmfree = REGS[reg.value-1]
                     self.reg_bindings[var] = rmfree
                     rmidx = self.free_regs.index(rmfree)
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
@@ -138,6 +138,61 @@
         for i in range(2,9):
             assert self.cpu.get_int_value(deadframe, i-2) == 100//i
 
-    def test_double_evenodd_pair_spill(self):
-        # TODO
-        pass
+
+
+    @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
+


More information about the pypy-commit mailing list