Author: Carl Friedrich Bolz-Tereick <[email protected]>
Branch: regalloc-playground
Changeset: r92218:0c3b2571af1c
Date: 2017-08-23 08:41 +0200
http://bitbucket.org/pypy/pypy/changeset/0c3b2571af1c/

Log:    implement chained coalescing. fix a bug in free_reg_whole_lifetime

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
@@ -843,7 +843,7 @@
         self.share_with = None
 
         # the other lifetime will have this variable set to self.definition_pos
-        self.definition_pos_shared = UNDEF_POS
+        self._definition_pos_shared = UNDEF_POS
 
     def is_last_real_use_before(self, position):
         if self.real_usages is None:
@@ -864,6 +864,12 @@
                 low = mid + 1
         return l[low]
 
+    def definition_pos_shared(self):
+        if self._definition_pos_shared != UNDEF_POS:
+            return self._definition_pos_shared
+        else:
+            return self.definition_pos
+
     def fixed_register(self, position, reg):
         """ registers a fixed register use for the variable at position in
         register reg. returns the position from where on the register should be
@@ -871,10 +877,7 @@
         assert self.definition_pos <= position <= self.last_usage
         if self.fixed_positions is None:
             self.fixed_positions = []
-            if self.definition_pos_shared != UNDEF_POS:
-                res = self.definition_pos_shared
-            else:
-                res = self.definition_pos
+            res = self.definition_pos_shared()
         else:
             assert position > self.fixed_positions[-1][0]
             res = self.fixed_positions[-1][0]
@@ -957,7 +960,7 @@
         if longevityvar0.last_usage != longevityvar1.definition_pos:
             return # not supported for now
         longevityvar0.share_with = longevityvar1
-        longevityvar1.definition_pos_shared = longevityvar0.definition_pos
+        longevityvar1._definition_pos_shared = 
longevityvar0.definition_pos_shared()
 
     def longest_free_reg(self, position, free_regs):
         """ for every register in free_regs, compute how far into the future
@@ -993,7 +996,10 @@
             if fixed_reg_pos is None:
                 unfixed_reg = reg
                 continue
-            use_after = fixed_reg_pos.free_until_pos(longevityvar.last_usage)
+            use_after = fixed_reg_pos.free_until_pos(position)
+            if use_after < longevityvar.last_usage:
+                # can't fit
+                continue
             assert use_after >= longevityvar.last_usage
             if use_after < min_fixed_use_after:
                 best_reg = reg
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
@@ -297,6 +297,17 @@
     loc = longevity.try_pick_free_reg(0, b4, [r1, r2, r3])
     assert loc is r3
 
+def test_try_pick_free_reg_bug():
+    b0, b1, b2, b3, b4 = newboxes(0, 0, 0, 0, 0)
+    l0 = Lifetime(10, 30)
+    l1 = Lifetime(0, 15)
+    longevity = LifetimeManager({b0: l0, b1: l1})
+    longevity.fixed_register(20, r0, b0)
+
+    # does not fit into r0, use r1
+    loc = longevity.try_pick_free_reg(0, b1, [r0, r1])
+    assert loc == r1
+
 def test_simple_coalescing():
     b0, b1, b2, b3, b4 = newboxes(0, 0, 0, 0, 0)
     l0 = Lifetime(0, 4)
@@ -330,6 +341,42 @@
     # r1 is picked, because b4 fits before b0
     assert loc is r1
 
+
+def test_chained_coalescing():
+    #              5 + b4
+    #                |
+    #  10  + b0      |
+    #      |         |
+    #      |      15 +
+    #      |
+    #      +
+    #  20
+    #      + b1
+    #      |
+    #      |
+    #      |
+    #      +
+    #  30
+    #      + b2
+    #      |
+    #  r1  *
+    #      |
+    #      +
+    #  40
+    b0, b1, b2, b3, b4 = newboxes(0, 0, 0, 0, 0)
+    l0 = Lifetime(10, 20)
+    l1 = Lifetime(20, 30)
+    l2 = Lifetime(30, 40)
+    l4 = Lifetime(5, 15)
+    longevity = LifetimeManager({b0: l0, b1: l1, b2: l2, b4: l4})
+    longevity.try_use_same_register(b0, b1)
+    longevity.try_use_same_register(b1, b2)
+    longevity.fixed_register(35, r1, b2)
+
+    loc = longevity.try_pick_free_reg(5, b4, [r0, r1])
+    assert loc is r0
+
+
 class TestRegalloc(object):
     def test_freeing_vars(self):
         b0, b1, b2 = newboxes(0, 0, 0)
@@ -356,7 +403,7 @@
         rm._check_invariants()
         assert len(rm.free_regs) == 4
         assert len(rm.reg_bindings) == 0
-        
+
     def test_register_exhaustion(self):
         boxes, longevity = boxes_and_longevity(5)
         rm = RegisterManager(longevity)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to