Author: Richard Plangger <[email protected]>
Branch: regalloc
Changeset: r78168:0dcfffa6613e
Date: 2015-06-18 11:00 +0200
http://bitbucket.org/pypy/pypy/changeset/0dcfffa6613e/

Log:    exchanged the heuristic for the register allocator. it now takes the
        live range whose next use is furthest in the future added 2 tests to
        check this

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
@@ -1,6 +1,7 @@
 import os
 from rpython.jit.metainterp.history import Const, Box, REF, JitCellToken
 from rpython.rlib.objectmodel import we_are_translated, specialize
+from rpython.rlib.rbisect import bisect_left
 from rpython.jit.metainterp.resoperation import rop
 from rpython.rtyper.lltypesystem import lltype
 from rpython.rtyper.lltypesystem.lloperation import llop
@@ -409,9 +410,12 @@
 
     def _pick_variable_to_spill(self, v, forbidden_vars, selected_reg=None,
                                 need_lower_byte=False):
-        """ Slightly less silly algorithm.
+        """ Heuristic: take the variable which has it's next use
+            the furthest in the future.
+            The original heuristic proposed by Poletto & Sarkar takes
+            the live range that ends the last.
         """
-        cur_max_age = -1
+        furthest_pos = -1
         candidate = None
         for next in self.reg_bindings:
             reg = self.reg_bindings[next]
@@ -424,9 +428,9 @@
                     continue
             if need_lower_byte and reg in self.no_lower_byte_regs:
                 continue
-            max_age = self.longevity[next][1]
-            if cur_max_age < max_age:
-                cur_max_age = max_age
+            pos = next_var_usage(self.longevity[next], self.position)
+            if furthest_pos < pos:
+                furthest_pos = pos
                 candidate = next
         if candidate is None:
             raise NoVariableToSpill
@@ -673,6 +677,19 @@
         else:
             return [self.loc(op.getarg(0))]
 
+def next_var_usage(longevity, pos):
+    start, end, uses = longevity
+    if pos > end:
+        # there is no next usage, has already been passed
+        return -1
+    if pos < start:
+        return start
+    if uses is None:
+        # a live range with just a definition and one use
+        return end
+    i = bisect_left(uses, pos, len(uses))
+    return uses[i]
+
 def compute_vars_longevity(inputargs, operations):
     # compute a dictionary that maps variables to index in
     # operations that is a "last-time-seen"
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
@@ -3,7 +3,7 @@
     INT, FLOAT, BoxPtr)
 from rpython.jit.metainterp.resoperation import rop, ResOperation
 from rpython.jit.backend.llsupport.regalloc import (FrameManager,
-        LinkedList, compute_vars_longevity)
+        LinkedList, compute_vars_longevity, next_var_usage)
 from rpython.jit.backend.llsupport.regalloc import RegisterManager as 
BaseRegMan
 
 def newboxes(*values):
@@ -32,6 +32,13 @@
 
 class RegisterManager(BaseRegMan):
     all_regs = regs
+
+    def __init__(self, longevity, frame_manager=None, assembler=None):
+        for k,v in longevity.items():
+            if len(v) == 2:
+                longevity[k] = (v[0], v[1], None)
+        BaseRegMan.__init__(self, longevity, frame_manager, assembler)
+
     def convert_to_imm(self, v):
         return v
 
@@ -598,3 +605,40 @@
         assert longevity[d] == (4,5, None)
         assert longevity[e] == (0,2, None)
         assert longevity[f] == (2,5, None)
+
+
+    def test_next_var_usage(self):
+        assert next_var_usage( (0,9,None), 10 ) == -1
+        assert next_var_usage( (4,9,None), 2 ) == 4
+        assert next_var_usage( (0,9,None), -1 ) == 0
+        assert next_var_usage( (0,5,[0,1,2,3,4,5]), 3 ) == 3
+        assert next_var_usage( (1,10,[1,5,8,10]), 4 ) == 5
+        assert next_var_usage( (1,10,[1,5,8,10]), 1 ) == 1
+        assert next_var_usage( (1,10,[1,5,8,10]), 2 ) == 5
+        assert next_var_usage( (1,10,[1,5,8,10]), 9 ) == 10
+
+    def test_pick_to_spill(self):
+        b = [BoxInt() for i in range(0,10)]
+        longevity = {
+            b[0] : (1, 10, [1,2,8,10]),
+            b[1] : (3,  4, None),
+            b[2] : (0,  7, None),
+        }
+        rm = RegisterManager(longevity)
+
+        rm.reg_bindings[b[2]] = None
+        rm.position = 0
+        assert rm._pick_variable_to_spill(None, []) is b[2]
+
+        rm.reg_bindings[b[0]] = None
+        rm.position = 1
+        assert rm._pick_variable_to_spill(None, []) in (b[2],)
+
+        rm.reg_bindings[b[1]] = None
+        rm.position = 3
+        assert rm._pick_variable_to_spill(None, []) in (b[0],)
+
+        del rm.reg_bindings[b[1]]
+        rm.position = 5
+        assert rm._pick_variable_to_spill(None, []) in (b[0],)
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to