[pypy-commit] pypy default: tested & impl pair allocation. there was an edge case which caused the allocation to fail.
plan_rich
pypy.commits at gmail.com
Wed Apr 13 04:17:14 EDT 2016
Author: Richard Plangger <planrichi at gmail.com>
Branch:
Changeset: r83649:580534e4ba07
Date: 2016-04-13 10:11 +0200
http://bitbucket.org/pypy/pypy/changeset/580534e4ba07/
Log: tested & impl pair allocation. there was an edge case which caused
the allocation to fail.
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
@@ -178,6 +178,7 @@
bind_first: the even register will be bound to bindvar,
if bind_first == False: the odd register will
be bound
+ NOTE: Calling ensure_even_odd_pair twice in a prepare function is NOT supported!
"""
self._check_type(origvar)
prev_loc = self.loc(origvar, must_exist=must_exist)
@@ -227,9 +228,6 @@
i = len(self.free_regs)-1
while i >= 0:
even = self.free_regs[i]
- if even.value == 13:
- i -= 1
- continue
if even.is_even():
# found an even registers that is actually free
odd = r.odd_reg(even)
@@ -309,11 +307,50 @@
self.reg_bindings[odd_var] = odd
break
else:
- # no break! this is bad. really bad
- raise NoVariableToSpill()
+ # uff! in this case, we need to move a forbidden var to another register
+ assert len(forbidden_vars) <= 8 # otherwise it is NOT possible to complete
+ even, odd = r.r2, r.r3
+ even_var = reverse_mapping.get(even, None)
+ odd_var = reverse_mapping.get(odd, None)
+ if even_var:
+ if even_var in forbidden_vars:
+ self._relocate_forbidden_variable(even, even_var, reverse_mapping,
+ forbidden_vars, odd)
+ else:
+ self._sync_var(even_var)
+ if odd_var:
+ if odd_var in forbidden_vars:
+ self._relocate_forbidden_variable(odd, odd_var, reverse_mapping,
+ forbidden_vars, even)
+ else:
+ self._sync_var(odd_var)
+
+ self.free_regs = [fr for fr in self.free_regs \
+ if fr is not even and \
+ fr is not odd]
+ self.reg_bindings[even_var] = even
+ self.reg_bindings[odd_var] = odd
+ return even, odd
return even, odd
+ def _relocate_forbidden_variable(self, reg, var, reverse_mapping, forbidden_vars, forbidden_reg):
+ for candidate in r.MANAGED_REGS:
+ if candidate is reg or candidate is forbidden_reg:
+ continue
+ if candidate not in forbidden_vars:
+ var = reverse_mapping.get(candidate, None)
+ if var is not None:
+ self._sync_var(var)
+ self.assembler.regalloc_mov(reg, candidate)
+ self.reg_bindings[var] = candidate
+ reverse_mapping[reg] = var
+ self.free_regs.append(reg)
+ break
+ else:
+ raise NoVariableToSpill
+
+
class ZARCHFrameManager(FrameManager):
def __init__(self, base_ofs):
FrameManager.__init__(self)
diff --git a/rpython/jit/backend/zarch/test/test_regalloc.py b/rpython/jit/backend/zarch/test/test_regalloc.py
--- a/rpython/jit/backend/zarch/test/test_regalloc.py
+++ b/rpython/jit/backend/zarch/test/test_regalloc.py
@@ -44,6 +44,20 @@
assert self.rm.reg_bindings[a] == r.r2
assert self.rm.reg_bindings[b] == r.r3
+ def test_cannot_spill_too_many_forbidden_vars(self):
+ v = temp_vars(12)
+ a, b = v[10], v[11]
+ self.rm.frame_manager.bindings[a] = self.rm.frame_manager.loc(a)
+ self.rm.frame_manager.bindings[b] = self.rm.frame_manager.loc(b)
+ # all registers are allocated
+ self.rm.allocate((2,v[0]),(3,v[1]),(4,v[2]),(5,v[3]),
+ (6,v[4]),(7,v[5]),(8,v[6]),(9,v[7]),
+ (10,v[8]),(11,v[9]))
+ self.rm.temp_boxes = v[:-2]
+ with py.test.raises(AssertionError):
+ # assert len(forbidden_vars) <= 8
+ self.rm.ensure_even_odd_pair(a, b, bind_first=False)
+
def test_all_but_one_forbidden(self):
a,b,f1,f2,f3,f4,o = temp_vars(7)
self.rm.allocate((2,f1),(4,f2),(6,f3),(8,f4),(10,o))
@@ -51,12 +65,6 @@
assert self.rm.reg_bindings[a] == r.r10
assert self.rm.reg_bindings[b] == r.r11
- def test_cannot_spill(self):
- a,b,f1,f2,f3,f4,f5 = temp_vars(7)
- self.rm.allocate((2,f1),(4,f2),(6,f3),(8,f4),(10,f5))
- with py.test.raises(NoVariableToSpill):
- self.rm.force_allocate_reg_pair(a, b, [f1,f2,f3,f4,f5])
-
def test_all_but_one_forbidden_odd(self):
a,b,f1,f2,f3,f4,f5 = temp_vars(7)
self.rm.allocate((3,f1),(5,f2),(7,f3),(9,f4),(11,f5))
@@ -86,6 +94,25 @@
assert a not in self.rm.reg_bindings
assert self.rm.assembler.move_count == 2
+ def test_ensure_pair_fully_allocated_first_forbidden(self):
+ v = temp_vars(12)
+ a, b = v[10], v[11]
+ self.rm.frame_manager.bindings[a] = self.rm.frame_manager.loc(a)
+ self.rm.frame_manager.bindings[b] = self.rm.frame_manager.loc(b)
+ # all registers are allocated
+ self.rm.allocate((2,v[0]),(3,v[1]),(4,v[2]),(5,v[3]),
+ (6,v[4]),(7,v[5]),(8,v[6]),(9,v[7]),
+ (10,v[8]),(11,v[9]))
+ self.rm.temp_boxes = [v[0],v[2],v[4],v[6],v[8]]
+ e, o = self.rm.ensure_even_odd_pair(a, b, bind_first=False)
+ assert e == r.r2
+ assert o == r.r3
+
+ self.rm.temp_boxes = [v[0],v[1],v[2],v[4],v[6],v[8]]
+ e, o = self.rm.ensure_even_odd_pair(a, b, bind_first=False)
+ assert e == r.r2
+ assert o == r.r3
+
def run(inputargs, ops):
cpu = CPU(None, None)
cpu.setup_once()
More information about the pypy-commit
mailing list