[pypy-commit] pypy regalloc-playground: chose the fixed register if it is available

cfbolz pypy.commits at gmail.com
Tue Aug 22 15:21:33 EDT 2017


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: regalloc-playground
Changeset: r92211:bb3d99077725
Date: 2017-08-22 21:07 +0200
http://bitbucket.org/pypy/pypy/changeset/bb3d99077725/

Log:	chose the fixed register if it is available

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
@@ -381,24 +381,27 @@
             loc = self.reg_bindings.get(v, None)
             if loc is not None and loc not in self.no_lower_byte_regs:
                 return loc
-            for i in range(len(self.free_regs) - 1, -1, -1):
-                reg = self.free_regs[i]
-                if reg not in self.no_lower_byte_regs:
-                    if loc is not None:
-                        self.free_regs[i] = loc
-                    else:
-                        del self.free_regs[i]
-                    self.reg_bindings[v] = reg
-                    return reg
-            return None
+            free_regs = [reg for reg in self.free_regs
+                         if reg not in self.no_lower_byte_regs]
+            newloc = self.longevity.try_pick_free_reg(
+                self.position, v, free_regs)
+            if newloc is None:
+                return None
+            self.free_regs.remove(newloc)
+            if loc is not None:
+                self.free_regs.append(loc)
+            self.reg_bindings[v] = newloc
+            return newloc
         try:
             return self.reg_bindings[v]
         except KeyError:
-            # YYY here we should chose the free variable a bit more carefully
-            if self.free_regs:
-                loc = self.free_regs.pop()
-                self.reg_bindings[v] = loc
-                return loc
+            loc = self.longevity.try_pick_free_reg(
+                self.position, v, self.free_regs)
+            if loc is None:
+                return None
+            self.reg_bindings[v] = loc
+            self.free_regs.remove(loc)
+            return loc
 
     def _spill_var(self, v, forbidden_vars, selected_reg,
                    need_lower_byte=False):
@@ -421,6 +424,8 @@
         # if that doesn't exist, spill the variable that has a real_usage that
         # is the furthest away from the current position
 
+        # YYY check for fixed variable usages
+
         cur_max_use_distance = -1
         position = self.position
         candidate = None
@@ -579,9 +584,9 @@
         if v not in self.reg_bindings:
             # v not in a register. allocate one for result_v and move v there
             prev_loc = self.frame_manager.loc(v)
-            loc = self.force_allocate_reg(v, forbidden_vars)
+            loc = self.force_allocate_reg(result_v, forbidden_vars)
             self.assembler.regalloc_mov(prev_loc, loc)
-        assert v in self.reg_bindings
+            return loc
         if self.longevity[v].last_usage > self.position:
             # we need to find a new place for variable v and
             # store result in the same place
@@ -865,6 +870,14 @@
         self.fixed_positions.append((position, reg))
         return res
 
+    def find_fixed_register(self, opindex):
+        # XXX could use binary search
+        if self.fixed_positions is None:
+            return None
+        for (index, reg) in self.fixed_positions:
+            if opindex <= index:
+                return reg
+
     def _check_invariants(self):
         assert self.definition_pos <= self.last_usage
         if self.real_usages is not None:
@@ -928,9 +941,11 @@
         fixed registers. Find the register that is free the longest. Return a
         tuple (reg, free_until_pos). """
         free_until_pos = {}
-        max_free_pos = -1
+        max_free_pos = position
         best_reg = None
-        for reg in free_regs:
+        # reverse for compatibility with old code
+        for i in range(len(free_regs) - 1, -1, -1):
+            reg = free_regs[i]
             fixed_reg_pos = self.fixed_register_use.get(reg, None)
             if fixed_reg_pos is None:
                 return reg, sys.maxint
@@ -941,6 +956,26 @@
                     max_free_pos = free_until_pos
         return best_reg, max_free_pos
 
+    def try_pick_free_reg(self, position, v, free_regs):
+        if not free_regs:
+            return None
+        longevityvar = self[v]
+        reg = longevityvar.find_fixed_register(position)
+        if reg is not None and reg in free_regs:
+            return reg
+        return free_regs[-1]
+        # more advanced stuff below, needs tests
+
+
+
+        loc, free_until = self.longevity.longest_free_reg(
+                self.position, free_regs)
+        if loc is None:
+            return None
+        # YYY could check whether it's best to spill v here, but hard
+        # to do in the current system
+        return loc
+
     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
@@ -56,6 +56,12 @@
 
 class RegisterManager(BaseRegMan):
     all_regs = regs
+
+    def __init__(self, longevity, frame_manager=None, assembler=None):
+        if isinstance(longevity, dict):
+            longevity = LifetimeManager(longevity)
+        BaseRegMan.__init__(self, longevity, frame_manager, assembler)
+
     def convert_to_imm(self, v):
         return v
 
@@ -840,6 +846,7 @@
         # note: we need to make a copy of inputargs because possibly_free_vars
         # is also used on op args, which is a non-resizable list
         self.possibly_free_vars(list(inputargs))
+        self._add_fixed_registers()
         return operations
 
     def _prepare(self, inputargs, operations, allgcrefs):
@@ -916,6 +923,16 @@
                     emit((opname, locs))
         return self.assembler.emitted
 
+    def _add_fixed_registers(self):
+        for i, op in enumerate(self.operations):
+            if rop.is_call(op.getopnum()):
+                # calling convention!
+                arglist = op.getarglist()[1:]
+                for arg, reg in zip(arglist + [None] * (3 - len(arglist)), [r1, r2, r3]):
+                    self.longevity.fixed_register(i, reg, arg)
+                self.longevity.fixed_register(i, r0, op)
+
+
 CPU = getcpuclass()
 class TestFullRegallocFakeCPU(object):
     # XXX copy-paste from test_regalloc_integration
@@ -1006,9 +1023,8 @@
         emitted = self.allocate(ops)
         fp0 = FakeFramePos(0, INT)
         assert emitted == [
-            ("move", r0, fp0),
-            ("int_mul", r0, [2]),
-            ("move", r1, r0),
+            ("move", r1, fp0),
+            ("int_mul", r1, [2]),
             ("call_i", r0, [r1]),
             ("guard_false", r0, []),
         ]


More information about the pypy-commit mailing list