Author: Richard Plangger <[email protected]>
Branch: s390x-backend
Changeset: r80729:5df254e363c4
Date: 2015-11-17 11:41 +0100
http://bitbucket.org/pypy/pypy/changeset/5df254e363c4/

Log:    added test to stress register pair allocation (even odd) as it is
        needed for division, some invariant is failing still

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
@@ -62,6 +62,7 @@
     l1 = self.ensure_reg(a1)
     self.rm.force_result_in_reg(op, a0)
     self.free_op_vars()
+    self.rm._check_invariants()
     return [lr, lq, l1]
 
 def prepare_int_mod(self, op):
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
@@ -56,13 +56,12 @@
         mc.BRC(c.ANY, l.imm(mc.BRC_byte_count + bc_set_overflow)) # no 
overflow happened
 
         # set overflow!
-        mc.XGR(r.SCRATCH, 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)
 
         # no overflow happended
-        # import pdb; pdb.set_trace()
 
     emit_int_floordiv = gen_emit_pool_or_rr_evenodd('DSG','DSGR')
     emit_uint_floordiv = gen_emit_pool_or_rr_evenodd('DLG','DLGR')
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
@@ -1,6 +1,6 @@
 from rpython.jit.backend.llsupport.regalloc import (RegisterManager, 
FrameManager,
                                                     TempVar, 
compute_vars_longevity,
-                                                    BaseRegalloc)
+                                                    BaseRegalloc, 
NoVariableToSpill)
 from rpython.jit.backend.llsupport.jump import remap_frame_layout_mixed
 from rpython.jit.backend.zarch.arch import WORD
 from rpython.jit.codewriter import longlong
@@ -170,32 +170,88 @@
         even, odd = None, None
         REGS = r.registers
         i = len(self.free_regs)-1
+        candidates = []
         while i >= 0:
             even = self.free_regs[i]
             if even.is_even():
+                # found an even registers that is actually free
                 odd = REGS[even.value+1]
-                print even, "is even", odd
                 if odd not in self.free_regs:
-                    print odd, "is NOT free"
+                    # sadly odd is not free, but for spilling
+                    # we found a candidate
+                    candidates.append(odd)
+                    i -= 1
                     continue
-                print odd, "is free"
                 self.reg_bindings[var] = even
                 self.reg_bindings[var2] = odd
                 del self.free_regs[i]
                 i = self.free_regs.index(odd)
                 del self.free_regs[i]
                 return even, odd
+            else:
+                # an odd free register, maybe the even one is
+                # a candidate?
+                odd = even
+                even = REGS[even.value-1]
+                if even in r.MANAGED_REGS:
+                    # yes even might be a candidate
+                    candidates.append(even)
             i -= 1
 
-        import pdb; pdb.set_trace()
-        xxx
-        loc = self._spill_var(v, forbidden_vars, selected_reg,
-                              need_lower_byte=need_lower_byte)
-        prev_loc = self.reg_bindings.get(v, None)
-        if prev_loc is not None:
-            self.free_regs.append(prev_loc)
-        self.reg_bindings[v] = loc
-        return loc
+        if len(candidates) != 0:
+            cur_max_age = -1
+            candidate = None
+            # pseudo step to find best spilling candidate
+            # similar to _pick_variable_to_spill, but tailored
+            # to take the even/odd register allocation in consideration
+            for next in self.reg_bindings:
+                if next in forbidden_vars:
+                    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
+            if candidate is not None:
+                # well, we got away with a single spill :)
+                reg = self.reg_bindings[candidate]
+                self.force_spill_var(candidate)
+                if reg.is_even():
+                    self.reg_bindings[var] = reg
+                    rmfree = REGS[reg.value+1]
+                    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
+                    rmfree = REGS[reg.value-1]
+                    self.reg_bindings[var] = rmfree
+                    rmidx = self.free_regs.index(rmfree)
+                    del self.free_regs[rmidx]
+                    return rmfree, reg
+
+        # there is no candidate pair that only would
+        # require one spill, thus we need to spill two!
+        # always take the first
+        for i, reg in enumerate(r.MANAGED_REGS):
+            if i+1 < len(r.MANAGED_REGS):
+                reg2 = r.MANAGED_REGS[i+1]
+                try:
+                    even = self._spill_var(var, forbidden_vars, reg)
+                    odd = self._spill_var(var2, forbidden_vars, reg2)
+                except NoVariableToSpill:
+                    # woops, this is in efficient
+                    continue
+                self.reg_bindings[var] = even
+                self.reg_bindings[var2] = odd
+                break
+        else:
+            # no break! this is bad. really bad
+            raise NoVariableToSpill()
+        return even, odd
 
 
     def force_result_in_even_reg(self, result_v, loc, forbidden_vars=[]):
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
@@ -106,7 +106,6 @@
         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, value)
         fail = self.cpu.get_latest_descr(deadframe)
         res = self.cpu.get_int_value(deadframe, 0)
@@ -116,8 +115,28 @@
             assert res == 0
 
     def test_double_evenodd_pair(self):
-        # TODO
-        pass
+        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
 
     def test_double_evenodd_pair_spill(self):
         # TODO
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to