[pypy-svn] r34117 - pypy/dist/pypy/jit/codegen/ppc

niko at codespeak.net niko at codespeak.net
Fri Nov 3 16:26:51 CET 2006


Author: niko
Date: Fri Nov  3 16:26:51 2006
New Revision: 34117

Modified:
   pypy/dist/pypy/jit/codegen/ppc/rgenop.py
Log:
(mwh, niko)
add a preliminary version of a greedy register allocator



Modified: pypy/dist/pypy/jit/codegen/ppc/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/ppc/rgenop.py	Fri Nov  3 16:26:51 2006
@@ -44,25 +44,71 @@
 class RegisterAllocation:
     def __init__(self, initial_mapping):
         self.insns = []
+        self.freeregs = gprs[3:]
         self.reg2var = {}
         self.var2reg = {}
+        self.var2spill = {}
         for var, reg in initial_mapping.iteritems():
             self.reg2var[reg] = var
             self.var2reg[var] = reg
         self.crfinfo = [(0, 0)] * 8
+        self._spill_index = 0
+
+    def _spill(self):
+        self._spill_index += 4
+        return self._spill_index
+
+    def _allocate_reg(self, newarg, lru):
+
+        # check if there is a register available
+        if self.freeregs:
+            reg = self.freeregs.pop()
+            self.reg2var[reg] = newarg
+            self.var2reg[newarg] = reg
+            return reg
+
+        # if not, find something to spill
+        argtospill = lru.pop(0)
+        assert argtospill in self.var2reg
+        spill = self._spill()
+        reg = self.var2reg[argtospill] # move argtospill to spill slot
+        self.var2spill[argtospill] = spill
+        del self.var2reg[argtospill]
+        self.reg2var[reg] = newarg     # assign reg to newarg
+        self.var2reg[newarg] = reg
+        self.insns.append(Spill(argtospill, reg, spill))
+        return reg
+        
     def allocate_for_insns(self, insns):
+        # Walk through instructions in forward order
+        lru = []
         for insn in insns:
+
+            # put things into the lru
+            for arg in insn.reg_args:
+                if arg in lru:
+                    del lru[lru.index(arg)]
+                lru.append(arg)
+
+            # We need to allocate a register for each used
+            # argument that is not already in one
             for i in range(len(insn.reg_args)):
                 arg = insn.reg_args[i]
                 argcls = insn.reg_arg_regclasses[i]
-                assert arg in self.var2reg
+
+                if arg not in self.var2reg:
+                    # It has no register now because it has been spilled
+                    assert argcls is GP_REGISTER, "uh-oh"
+                    reg = self._allocate_reg(arg, lru)
+                    self.insns.append(
+                        Unspill(arg, reg, self.var2spill[arg]))
+                    del self.var2spill[arg]
+
+            # Need to allocate a register for the destination
+            assert not insn.result or insn.result not in self.var2reg
             cand = None
             if insn.result_regclass is GP_REGISTER:
-                for cand in gprs[3:]:
-                    if cand not in self.reg2var:
-                        break
-                if not cand:
-                    assert 0
+                cand = self._allocate_reg(insn.result, lru)
             elif insn.result_regclass is CR_FIELD:
                 assert crfs[0] not in self.reg2var
                 cand = crfs[0]
@@ -238,6 +284,38 @@
             BO = 4  # jump if relavent bit is NOT set in the CR
         asm.bcctr(BO, self.bit)
 
+class Unspill(Insn):
+    """ A special instruction inserted by our register "allocator."  It
+    indicates that we need to load a value from the stack into a register
+    because we spilled a particular value. """
+    def __init__(self, var, reg, offset):
+        """
+        var --- the var we spilled (a Var)
+        reg --- the reg we spilled it from (an integer)
+        offset --- the offset on the stack we spilled it to (an integer)
+        """
+        self.var = var
+        self.reg = reg
+        self.offset = offset
+    def emit(self, asm):
+        asm.lwz(self.reg.number, rSP, self.offset)
+
+class Spill(Insn):
+    """ A special instruction inserted by our register "allocator."
+    It indicates that we need to store a value from the register into
+    the stack because we spilled a particular value."""
+    def __init__(self, var, reg, offset):
+        """
+        var --- the var we are spilling (a Var)
+        reg --- the reg we are spilling it from (an integer)
+        offset --- the offset on the stack we are spilling it to (an integer)
+        """
+        self.var = var
+        self.reg = reg
+        self.offset = offset
+    def emit(self, asm):
+        asm.stw(self.reg.number, rSP, self.offset)
+
 from pypy.jit.codegen.ppc import codebuf_posix as memhandler
 from ctypes import POINTER, cast, c_char, c_void_p, CFUNCTYPE, c_int
 
@@ -455,7 +533,7 @@
         return (gv_result, gv_x.load(self))
 
     def op_int_add(self, gv_x, gv_y):
-        if isinstance(gv_y, IntConst) and abs(gv_y.value) < 2*16:
+        if isinstance(gv_y, IntConst) and abs(gv_y.value) < 2**16:
             gv_result = self.newvar()
             self.insns.append(
                 Insn_GPR__GPR_IMM(RPPCAssembler.addi,


More information about the pypy-svn mailing list