[pypy-svn] r78671 - in pypy/branch/arm-backend/pypy/jit/backend/arm: . helper test

david at codespeak.net david at codespeak.net
Wed Nov 3 15:10:39 CET 2010


Author: david
Date: Wed Nov  3 15:10:37 2010
New Revision: 78671

Modified:
   pypy/branch/arm-backend/pypy/jit/backend/arm/assembler.py
   pypy/branch/arm-backend/pypy/jit/backend/arm/helper/assembler.py
   pypy/branch/arm-backend/pypy/jit/backend/arm/locations.py
   pypy/branch/arm-backend/pypy/jit/backend/arm/opassembler.py
   pypy/branch/arm-backend/pypy/jit/backend/arm/regalloc.py
   pypy/branch/arm-backend/pypy/jit/backend/arm/registers.py
   pypy/branch/arm-backend/pypy/jit/backend/arm/test/test_assembler.py
Log:
Implement register spilling on the stack. 
Introduce a frame pointer to manage the stack frame
For now with a fixed frame size of 10 words for spilling



Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/assembler.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/assembler.py	(original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/assembler.py	Wed Nov  3 15:10:37 2010
@@ -57,16 +57,21 @@
         while(True):
             i += 1
             fail_index += 1
-            r = enc[i]
-            if r == '\xFE':
+            res = enc[i]
+            if res == '\xFE':
                 continue
-            if r == '\xFF':
+            if res == '\xFF':
                 break
-            if r == '\xFD':
+            if res == '\xFD':
                 # imm value
                 value = self.decode32(enc, i+1)
                 i += 4
-            else:
+            elif res == '\xFC': # stack location
+                stack_loc = self.decode32(enc, i+1)
+                #XXX ffuu use propper calculation here
+                value = self.decode32(stack, len(r.all_regs)*WORD+40-stack_loc*WORD)
+                i += 4
+            else: # an int for now
                 reg = ord(enc[i])
                 value = self.decode32(stack, reg*WORD)
 
@@ -96,20 +101,24 @@
         self.setup_failure_recovery()
         functype = lltype.Ptr(lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
         decode_registers_addr = llhelper(functype, self.failure_recovery_func)
-        self.mc.PUSH(range(12))     # registers r0 .. r11
+        self.mc.PUSH([reg.value for reg in r.all_regs])     # registers r0 .. r10
         self.mc.MOV_rr(r.r0.value, r.lr.value)  # move mem block address, to r0 to pass as
                                     # parameter to next procedure call
         self.mc.MOV_rr(r.r1.value, r.sp.value)  # pass the current stack pointer as second param
 
         self.mc.BL(rffi.cast(lltype.Signed, decode_registers_addr))
         self.mc.MOV_rr(r.ip.value, r.r0.value)
-        self.mc.LDM(r.sp.value, range(12), w=1) # XXX Replace with POP instr. someday
-
+        self.mc.LDM(r.sp.value, [reg.value for reg in r.all_regs], w=1) # XXX Replace with POP instr. someday
         self.mc.MOV_rr(r.r0.value, r.ip.value)
-
         self.gen_func_epilog()
 
     def _gen_path_to_exit_path(self, op, args, regalloc, fcond=c.AL):
+        """
+        \xFC = stack location
+        \xFD = imm location
+        \xFE = Empty arg
+        """
+
         box = Box()
         reg = regalloc.force_allocate_reg(box)
         # XXX free this memory
@@ -118,13 +127,18 @@
         j = 0
         while(i < len(args)):
             if args[i]:
-                if not isinstance(args[i], ConstInt):
-                    curreg = regalloc.make_sure_var_in_reg(args[i])
-                    mem[j] = chr(curreg.value)
+                loc = regalloc.loc(args[i])
+                if loc.is_reg():
+                    mem[j] = chr(loc.value)
                     j += 1
-                else:
+                elif loc.is_imm():
                     mem[j] = '\xFD'
-                    self.encode32(mem, j+1, args[i].getint())
+                    self.encode32(mem, j+1, loc.getint())
+                    j += 5
+                else:
+                    #print 'Encoding a stack location'
+                    mem[j] = '\xFC'
+                    self.encode32(mem, j+1, loc.position)
                     j += 5
             else:
                 mem[j] = '\xFE'
@@ -152,11 +166,14 @@
         while(self.mc.curraddr() % FUNC_ALIGN != 0):
             self.mc.writechar(chr(0))
 
+    epilog_size = 2*WORD
     def gen_func_epilog(self,cond=c.AL):
+        self.mc.MOV_rr(r.sp.value, r.fp.value)
         self.mc.LDM(r.sp.value, [reg.value for reg in r.callee_restored_registers], cond=cond, w=1)
 
     def gen_func_prolog(self):
         self.mc.PUSH([reg.value for reg in r.callee_saved_registers])
+        self.mc.MOV_rr(r.fp.value, r.sp.value)
 
     def gen_bootstrap_code(self, inputargs, regalloc, looptoken):
         regs = []
@@ -175,6 +192,10 @@
         self.align()
         loop_start=self.mc.curraddr()
         self.gen_func_prolog()
+        # XXX
+        #Patch the sp with a correct value
+        self.mc.SUB_ri(r.sp.value, r.sp.value, 10*WORD)
+        # END
         self.gen_bootstrap_code(inputargs, regalloc, looptoken)
         loop_head=self.mc.curraddr()
         looptoken._arm_bootstrap_code = loop_start
@@ -185,7 +206,7 @@
             # XXX consider merging ops with next one if it is an adecuate guard
             opnum = op.getopnum()
             fcond = self.operations[opnum](self, op, regalloc, fcond)
-        self.gen_func_epilog()
+        #self.gen_func_epilog()
         if self._debug_asm:
             self._dump_trace('loop.asm')
         print 'Done assembling'
@@ -213,9 +234,13 @@
     def _dump_trace(self, name):
         self.mc._dump_trace(name)
 
-    def _check_imm_arg(self, arg, size=0xFF):
+    def _check_imm_arg(self, arg, size=0xFF, allow_zero=True):
+        if allow_zero:
+            lower_bound = arg.getint() >= 0
+        else:
+            lower_bound = arg.getint() > 0
         #XXX check ranges for different operations
-        return isinstance(arg, ConstInt) and arg.getint() <= size and arg.getint() > 0
+        return isinstance(arg, ConstInt) and arg.getint() <= size and lower_bound
 
     def patch_trace(self, faildescr, bridge_addr):
         # XXX make sure there is enough space at patch target
@@ -228,8 +253,13 @@
         if prev_loc.is_imm():
             # XXX check size of imm for current instr
             self.mc.gen_load_int(loc.value, prev_loc.getint())
+        elif loc.is_stack():
+            self.mc.STR_ri(prev_loc.value, r.fp.value, loc.position*-WORD)
+        elif prev_loc.is_stack():
+            self.mc.LDR_ri(loc.value, r.fp.value, prev_loc.position*-WORD)
         else:
             self.mc.MOV_rr(loc.value, prev_loc.value)
+    mov_loc_loc = regalloc_mov
 
 def make_operation_list():
     def notimplemented(self, op, regalloc, fcond):

Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/helper/assembler.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/helper/assembler.py	(original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/helper/assembler.py	Wed Nov  3 15:10:37 2010
@@ -13,27 +13,29 @@
         return fcond
     return f
 
-def gen_emit_op_ri(opname, imm_size=0xFF, commutative=True):
+def gen_emit_op_ri(opname, imm_size=0xFF, commutative=True, allow_zero=True):
     def f(self, op, regalloc, fcond):
         ri_op = getattr(self.mc, '%s_ri' % opname)
         rr_op = getattr(self.mc, '%s_rr' % opname)
 
         arg0 = op.getarg(0)
         arg1 = op.getarg(1)
-        imm_a0 = self._check_imm_arg(arg0, imm_size)
-        imm_a1 = self._check_imm_arg(arg1, imm_size)
-        res = regalloc.force_allocate_reg(op.result)
+        imm_a0 = self._check_imm_arg(arg0, imm_size, allow_zero=allow_zero)
+        imm_a1 = self._check_imm_arg(arg1, imm_size, allow_zero=allow_zero)
         if commutative and imm_a0:
             l0 = regalloc.make_sure_var_in_reg(arg0, imm_fine=imm_a0)
             l1 = regalloc.make_sure_var_in_reg(arg1)
+            res = regalloc.force_allocate_reg(op.result)
             ri_op(res.value, l1.value, imm=l0.getint(), cond=fcond)
         elif imm_a1:
             l0 = regalloc.make_sure_var_in_reg(arg0, imm_fine=False)
             l1 = regalloc.make_sure_var_in_reg(arg1, imm_fine=True)
+            res = regalloc.force_allocate_reg(op.result)
             ri_op(res.value, l0.value, imm=l1.getint(), cond=fcond)
         else:
             l0 = regalloc.make_sure_var_in_reg(arg0, imm_fine=False)
             l1 = regalloc.make_sure_var_in_reg(arg1, imm_fine=False)
+            res = regalloc.force_allocate_reg(op.result)
             rr_op(res.value, l0.value, l1.value)
         regalloc.possibly_free_vars_for_op(op)
         return fcond
@@ -61,17 +63,18 @@
         else:
             arg0 = op.getarg(1)
             arg1 = op.getarg(0)
-        res = regalloc.force_allocate_reg(op.result)
         # XXX consider swapping argumentes if arg0 is const
         imm_a0 = self._check_imm_arg(arg0)
         imm_a1 = self._check_imm_arg(arg1)
         if imm_a1 and not imm_a0:
             l0 = regalloc.make_sure_var_in_reg(arg0, imm_fine=False)
-            l1 = regalloc.make_sure_var_in_reg(arg1)
+            l1 = regalloc.make_sure_var_in_reg(arg1, [l0])
+            res = regalloc.force_allocate_reg(op.result)
             self.mc.CMP_ri(l0.value, imm=l1.getint(), cond=fcond)
         else:
             l0 = regalloc.make_sure_var_in_reg(arg0, imm_fine=False)
-            l1 = regalloc.make_sure_var_in_reg(arg1, imm_fine=False)
+            l1 = regalloc.make_sure_var_in_reg(arg1, [l0], imm_fine=False)
+            res = regalloc.force_allocate_reg(op.result)
             self.mc.CMP_rr(l0.value, l1.value)
 
         inv = c.get_opposite_of(condition)

Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/locations.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/locations.py	(original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/locations.py	Wed Nov  3 15:10:37 2010
@@ -1,8 +1,16 @@
+from pypy.jit.metainterp.history import INT
+from pypy.jit.backend.arm.arch import WORD
 class AssemblerLocation(object):
     pass
     def is_imm(self):
         return False
 
+    def is_stack(self):
+        return False
+
+    def is_reg(self):
+        return False
+
 class RegisterLocation(AssemblerLocation):
 
     def __init__(self, value):
@@ -11,6 +19,9 @@
     def __repr__(self):
         return 'r%d' % self.value
 
+    def is_reg(self):
+        return True
+
 class ImmLocation(AssemblerLocation):
     _immutable_ = True
     def __init__(self, value):
@@ -20,7 +31,32 @@
         return self.value
 
     def __repr__(self):
-        return "ImmedLoc(%d)" % (self.value)
+        return "imm(%d)" % (self.value)
 
     def is_imm(self):
         return True
+
+class StackLocation(AssemblerLocation):
+    _immutable_ = True
+    def __init__(self, position, num_words=1, type=INT):
+        self.position = position
+        self.width = num_words * WORD
+        # One of INT, REF, FLOAT
+        assert num_words == 1
+        assert type == INT
+        #self.type = type
+
+    def frame_size(self):
+        return self.width // WORD
+
+    def __repr__(self):
+        return 'SP+%d' % (self.position,)
+
+    def location_code(self):
+        return 'b'
+
+    def assembler(self):
+        return repr(self)
+
+    def is_stack(self):
+        return True

Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/opassembler.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/opassembler.py	(original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/opassembler.py	Wed Nov  3 15:10:37 2010
@@ -21,19 +21,17 @@
 
     def emit_op_int_add(self, op, regalloc, fcond):
         # assuming only one argument is constant
-        res = regalloc.force_allocate_reg(op.result)
         a0 = op.getarg(0)
         a1 = op.getarg(1)
         imm_a0 = isinstance(a0, ConstInt) and (a0.getint() <= 0xFF or -1 * a0.getint() <= 0xFF)
         imm_a1 = isinstance(a1, ConstInt) and (a1.getint() <= 0xFF or -1 * a1.getint() <= 0xFF)
-        l0 = regalloc.make_sure_var_in_reg(a0, imm_fine=imm_a0)
-        l1 = regalloc.make_sure_var_in_reg(a1, imm_fine=imm_a1)
         if imm_a0:
             imm_a0, imm_a1 = imm_a1, imm_a0
             a0, a1 = a1, a0
         if imm_a1:
             l0 = regalloc.make_sure_var_in_reg(a0, imm_fine=False)
             l1 = regalloc.make_sure_var_in_reg(a1, imm_fine=True)
+            res = regalloc.force_allocate_reg(op.result)
             if l1.getint() < 0:
                 self.mc.SUB_ri(res.value, l0.value, -1 * l1.getint())
             else:
@@ -41,6 +39,7 @@
         else:
             l0 = regalloc.make_sure_var_in_reg(a0, imm_fine=False)
             l1 = regalloc.make_sure_var_in_reg(a1, imm_fine=False)
+            res = regalloc.force_allocate_reg(op.result)
             self.mc.ADD_rr(res.value, l0.value, l1.value)
 
         regalloc.possibly_free_vars_for_op(op)
@@ -48,13 +47,13 @@
 
     def emit_op_int_sub(self, op, regalloc, fcond):
         # assuming only one argument is constant
-        res = regalloc.force_allocate_reg(op.result)
         a0 = op.getarg(0)
         a1 = op.getarg(1)
         imm_a0 = isinstance(a0, ConstInt) and (a0.getint() <= 0xFF or -1 * a0.getint() <= 0xFF)
         imm_a1 = isinstance(a1, ConstInt) and (a1.getint() <= 0xFF or -1 * a1.getint() <= 0xFF)
         l0 = regalloc.make_sure_var_in_reg(a0, imm_fine=imm_a0)
         l1 = regalloc.make_sure_var_in_reg(a1, imm_fine=imm_a1)
+        res = regalloc.force_allocate_reg(op.result)
         if imm_a0:
             value = l0.getint()
             if value < 0:
@@ -65,7 +64,7 @@
                 # reverse substract ftw
                 self.mc.RSB_ri(res.value, l1.value, value)
         elif imm_a1:
-            value = a1.getint()
+            value = l1.getint()
             if value < 0:
                 self.mc.ADD_ri(res.value, l0.value, -1 * value)
             else:
@@ -77,9 +76,9 @@
         return fcond
 
     def emit_op_int_mul(self, op, regalloc, fcond):
-        res = regalloc.force_allocate_reg(op.result)
         reg1 = regalloc.make_sure_var_in_reg(op.getarg(0), imm_fine=False)
         reg2 = regalloc.make_sure_var_in_reg(op.getarg(1), imm_fine=False)
+        res = regalloc.force_allocate_reg(op.result)
         self.mc.MUL(res.value, reg1.value, reg2.value)
         regalloc.possibly_free_vars_for_op(op)
         return fcond
@@ -91,7 +90,7 @@
     emit_op_int_and = gen_emit_op_ri('AND')
     emit_op_int_or = gen_emit_op_ri('ORR')
     emit_op_int_xor = gen_emit_op_ri('EOR')
-    emit_op_int_lshift = gen_emit_op_ri('LSL', imm_size=0x1F, commutative=False)
+    emit_op_int_lshift = gen_emit_op_ri('LSL', imm_size=0x1F, allow_zero=False, commutative=False)
     emit_op_int_rshift = gen_emit_op_ri('ASR', imm_size=0x1F, commutative=False)
     emit_op_uint_rshift = gen_emit_op_ri('LSR', imm_size=0x1F, commutative=False)
 
@@ -143,6 +142,7 @@
         descr._failure_recovery_code = memaddr
         descr._arm_guard_cond = fcond
         descr._arm_guard_size = self.mc.curraddr() - descr._arm_guard_code
+        regalloc.possibly_free_vars_for_op(op)
 
     def emit_op_guard_true(self, op, regalloc, fcond):
         assert fcond == c.LE
@@ -162,10 +162,11 @@
     def emit_op_jump(self, op, regalloc, fcond):
         registers = op.getdescr()._arm_arglocs
         for i in range(op.numargs()):
-            #XXX we are assuming that every value is in a register for now
-            reg = regalloc.make_sure_var_in_reg(op.getarg(i), imm_fine=False)
-            inpreg = registers[i]
-            self.mc.MOV_rr(inpreg.value, reg.value)
+            # avoid moving stuff twice
+            loc = registers[i]
+            prev_loc = regalloc.loc(op.getarg(i))
+            self.mov_loc_loc(prev_loc, loc)
+
         loop_code = op.getdescr()._arm_loop_code
         self.mc.B(loop_code, fcond)
         return fcond

Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/regalloc.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/regalloc.py	(original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/regalloc.py	Wed Nov  3 15:10:37 2010
@@ -15,6 +15,7 @@
     def update_bindings(self, enc, inputargs):
         j = 0
         for i in range(len(inputargs)):
+            # XXX decode imm and and stack locs
             while enc[j] == '\xFE':
                 j += 1
             self.force_allocate_reg(inputargs[i], selected_reg=r.all_regs[ord(enc[j])])
@@ -24,6 +25,11 @@
         return locations.ImmLocation(c.value)
 
 class ARMFrameManager(FrameManager):
+    def __init__(self):
+        FrameManager.__init__(self)
+        self.frame_depth = 1
+
     @staticmethod
     def frame_pos(loc, type):
-        pass
+        # XXX for now we only have one word stack locs
+        return locations.StackLocation(loc)

Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/registers.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/registers.py	(original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/registers.py	Wed Nov  3 15:10:37 2010
@@ -10,7 +10,7 @@
 lr = r14
 pc = r15
 
-all_regs = registers[:12]
+all_regs = registers[:11]
 
 callee_resp = [r4, r5, r6, r7, r8, r9, r10, r11]
 callee_saved_registers = callee_resp+[lr]

Modified: pypy/branch/arm-backend/pypy/jit/backend/arm/test/test_assembler.py
==============================================================================
--- pypy/branch/arm-backend/pypy/jit/backend/arm/test/test_assembler.py	(original)
+++ pypy/branch/arm-backend/pypy/jit/backend/arm/test/test_assembler.py	Wed Nov  3 15:10:37 2010
@@ -113,7 +113,8 @@
         loop_head = self.a.mc.curraddr()
         self.a.mc.ADD_ri(r.r1.value, r.r1.value, 1)
         self.a.mc.CMP_ri(r.r1.value, 9)
-        self.a.mc.LDR_ri(r.pc.value, r.pc.value, imm=4, cond=c.NE)
+        self.a.mc.LDR_ri(r.pc.value, r.pc.value,
+        imm=self.a.epilog_size, cond=c.NE) # we want to read after the last instr. of gen_func_prolog
         self.a.mc.MOV_rr(r.r0.value, r.r1.value)
         self.a.gen_func_epilog()
         self.a.mc.write32(loop_head)



More information about the Pypy-commit mailing list