Author: Carl Friedrich Bolz <[email protected]>
Branch: regalloc-playground
Changeset: r92213:e8eede93629e
Date: 2017-08-22 22:54 +0200
http://bitbucket.org/pypy/pypy/changeset/e8eede93629e/
Log: another heuristic: if there's a fixed register around and the
current to-be-allocated one fits before the next fixed use, use that
(and use the smallest lifetime hole)
diff --git a/rpython/jit/backend/llsupport/regalloc.py
b/rpython/jit/backend/llsupport/regalloc.py
--- a/rpython/jit/backend/llsupport/regalloc.py
+++ b/rpython/jit/backend/llsupport/regalloc.py
@@ -956,6 +956,30 @@
max_free_pos = free_until_pos
return best_reg, max_free_pos
+ def free_reg_whole_lifetime(self, position, v, free_regs):
+ """ try to find a register from free_regs for v at position that's
+ free for the whole lifetime of v. pick the one that is blocked first
+ *after* the lifetime of v. """
+ longevityvar = self[v]
+ min_fixed_use_after = sys.maxint
+ best_reg = None
+ unfixed_reg = None
+ for reg in free_regs:
+ fixed_reg_pos = self.fixed_register_use.get(reg, None)
+ if fixed_reg_pos is None:
+ unfixed_reg = reg
+ continue
+ use_after = fixed_reg_pos.free_until_pos(longevityvar.last_usage)
+ assert use_after >= longevityvar.last_usage
+ if use_after < min_fixed_use_after:
+ best_reg = reg
+ min_fixed_use_after = use_after
+ if best_reg is not None:
+ return best_reg
+
+ # no fitting fixed registers. pick a non-fixed one
+ return unfixed_reg
+
def try_pick_free_reg(self, position, v, free_regs):
if not free_regs:
return None
@@ -965,13 +989,19 @@
if reg is not None and reg in free_regs:
return reg
- # pick the register that's free the longest
+ # try to find a register that's free for the whole lifetime of v
+ # pick the one that is blocked first *after* the lifetime of v
+ loc = self.free_reg_whole_lifetime(position, v, free_regs)
+ if loc is not None:
+ return loc
+
+ # can't fit v completely, so pick the register that's free the longest
loc, free_until = self.longest_free_reg(position, free_regs)
- if loc is None:
- return None
+ if loc is not None:
+ return loc
# YYY could check whether it's best to spill v here, but hard
# to do in the current system
- return loc
+ return None
def __contains__(self, var):
return var in self.longevity
diff --git a/rpython/jit/backend/llsupport/test/test_regalloc.py
b/rpython/jit/backend/llsupport/test/test_regalloc.py
--- a/rpython/jit/backend/llsupport/test/test_regalloc.py
+++ b/rpython/jit/backend/llsupport/test/test_regalloc.py
@@ -52,6 +52,8 @@
return 'r%d' % self.n
r0, r1, r2, r3 = [FakeReg(i) for i in range(4)]
+r4, r5, r6, r7, r8, r9 = [FakeReg(i) for i in range(4, 10)]
+
regs = [r0, r1, r2, r3]
class RegisterManager(BaseRegMan):
@@ -270,6 +272,27 @@
assert longevity.longest_free_reg(0, [r0, r1, r2]) == (r1, 2)
+def test_try_pick_free_reg():
+ b0, b1, b2, b3, b4 = newboxes(0, 0, 0, 0, 0)
+ l0 = Lifetime(0, 4)
+ l1 = Lifetime(2, 20)
+ l2 = Lifetime(6, 20)
+ l3 = Lifetime(8, 20)
+ l4 = Lifetime(0, 10)
+ longevity = LifetimeManager({b0: l0, b1: l1, b2: l2, b3: l3, b4: l4})
+ longevity.fixed_register(3, r1, b1)
+ longevity.fixed_register(7, r2, b2)
+ longevity.fixed_register(9, r3, b3)
+
+ # a best fit
+ loc = longevity.try_pick_free_reg(0, b0, [r1, r2, r3, r4, r5])
+ assert loc is r2
+
+ # does not fit into any of the fixed regs, use a non-fixed one
+ loc = longevity.try_pick_free_reg(0, b4, [r5, r2, r3, r4, r1])
+ assert loc in [r4, r5]
+
+
class TestRegalloc(object):
def test_freeing_vars(self):
b0, b1, b2 = newboxes(0, 0, 0)
@@ -815,7 +838,6 @@
# _____________________________________________________
# tests that assign registers in a mocked way for a fake CPU
-r4, r5, r6, r7, r8, r9 = [FakeReg(i) for i in range(4, 10)]
class RegisterManager2(BaseRegMan):
all_regs = [r0, r1, r2, r3, r4, r5, r6, r7]
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit