[pypy-svn] r34340 - in pypy/dist/pypy/jit/codegen/ppc: . test

mwh at codespeak.net mwh at codespeak.net
Tue Nov 7 19:17:10 CET 2006


Author: mwh
Date: Tue Nov  7 19:17:09 2006
New Revision: 34340

Modified:
   pypy/dist/pypy/jit/codegen/ppc/instruction.py
   pypy/dist/pypy/jit/codegen/ppc/regalloc.py
   pypy/dist/pypy/jit/codegen/ppc/rgenop.py
   pypy/dist/pypy/jit/codegen/ppc/test/test_rgenop.py
Log:
add a test that uses all the int_* comparison functions.
implement all of them plus a little support code
also support for moving such results from the condition register to a general
purpose register.


Modified: pypy/dist/pypy/jit/codegen/ppc/instruction.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/instruction.py	(original)
+++ pypy/dist/pypy/jit/codegen/ppc/instruction.py	Tue Nov  7 19:17:09 2006
@@ -52,6 +52,9 @@
     regclass = CR_FIELD
     def __init__(self, number):
         self.number = number
+    def move_to_gpr(self, allocator, gpr):
+        bit, negated = allocator.crfinfo[self.number]
+        return _CRF2GPR(gpr, self.number*4 + bit, negated)
 
 crfs = map(CRF, range(8))
 
@@ -213,7 +216,15 @@
             BO = 4  # jump if relavent bit is NOT set in the CR
         asm.bcctr(BO, self.crf.number*4 + self.bit)
 
-class Unspill(Insn):
+class AllocTimeInsn(Insn):
+    def __init__(self):
+        Insn.__init__(self)
+        self.reg_args = []
+        self.reg_arg_regclasses = []
+        self.result_regclass =  NO_REGISTER
+        self.result = None
+
+class Unspill(AllocTimeInsn):
     """ 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. """
@@ -223,14 +234,14 @@
         reg --- the reg we spilled it from (an integer)
         offset --- the offset on the stack we spilled it to (an integer)
         """
-        Insn.__init__(self)
+        AllocTimeInsn.__init__(self)
         self.var = var
         self.reg = reg
         self.stack = stack
     def emit(self, asm):
         asm.lwz(self.reg.number, rFP, self.stack.offset)
 
-class Spill(Insn):
+class Spill(AllocTimeInsn):
     """ 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."""
@@ -240,13 +251,25 @@
         reg --- the reg we are spilling it from (an integer)
         offset --- the offset on the stack we are spilling it to (an integer)
         """
-        Insn.__init__(self)
+        AllocTimeInsn.__init__(self)
         self.var = var
         self.reg = reg
         self.stack = stack
     def emit(self, asm):
         asm.stw(self.reg.number, rFP, self.stack.offset)
 
+class _CRF2GPR(AllocTimeInsn):
+    def __init__(self, targetreg, bit, negated):
+        AllocTimeInsn.__init__(self)
+        self.targetreg = targetreg
+        self.bit = bit
+        self.negated = negated
+    def emit(self, asm):
+        asm.mfcr(self.targetreg)
+        asm.extrwi(self.targetreg, self.targetreg, 1, self.bit)
+        if self.negated:
+            asm.xori(self.targetreg, self.targetreg, 1)
+
 class Return(Insn):
     """ Ensures the return value is in r3 """
     def __init__(self, var):

Modified: pypy/dist/pypy/jit/codegen/ppc/regalloc.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/regalloc.py	(original)
+++ pypy/dist/pypy/jit/codegen/ppc/regalloc.py	Tue Nov  7 19:17:09 2006
@@ -110,10 +110,20 @@
                 arg = insn.reg_args[i]
                 argcls = insn.reg_arg_regclasses[i]
                 #print "Allocating register for %r..." % (arg,)
+                argloc = self.var2loc[arg]
 
-                if not self.var2loc[arg].is_register:
+                if not argloc.is_register:
                     # It has no register now because it has been spilled
                     self._allocate_reg(argcls, arg)
+                elif argloc.regclass != argcls:
+                    if argcls == GP_REGISTER:
+                        del self.var2loc[arg]
+                        del self.loc2var[argloc]
+                        newloc = self._allocate_reg(GP_REGISTER, arg)
+                        self.insns.append(
+                            argloc.move_to_gpr(self, newloc.number))
+                    else:
+                        assert 0
                 else:
                     #print "it was in ", self.var2loc[arg]
                     pass

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	Tue Nov  7 19:17:09 2006
@@ -395,21 +395,59 @@
         return gv_result
 
     def _compare(self, op, gv_x, gv_y):
-        assert op == 'gt'
+        cmp2info = {
+            #      bit-in-crf  negated
+            'gt': (    1,         0   ),
+            'lt': (    0,         0   ),
+            'le': (    1,         1   ),
+            'ge': (    0,         1   ),
+            'eq': (    2,         0   ),
+            'ne': (    2,         1   ),
+            }
+        cmp2info_flipped = {
+            #      bit-in-crf  negated
+            'gt': (    1,         1   ),
+            'lt': (    0,         1   ),
+            'le': (    1,         0   ),
+            'ge': (    0,         0   ),
+            'eq': (    2,         0   ),
+            'ne': (    2,         1   ),
+            }
         result = self.newvar()
         if isinstance(gv_y, IntConst) and abs(gv_y.value) < 2*16:
             gv_x = gv_x.load(self)
-            self.insns.append(insn.CMPWI((1, 0), result, [gv_x, gv_y]))
+            self.insns.append(
+                insn.CMPWI(cmp2info[op], result,
+                           [gv_x, gv_y]))
         elif isinstance(gv_x, IntConst) and abs(gv_x.value) < 2*16:
             gv_y = gv_y.load(self)
-            self.insns.append(insn.CMPWI((1, 1), result, [gv_y, gv_x]))
+            self.insns.append(
+                insn.CMPWI(cmp2info_flipped[op], result,
+                           [gv_y, gv_x]))
         else:
-            self.insns.append(insn.CMPW((1, 0), result, [gv_x.load(self), gv_y.load(self)]))
+            self.insns.append(
+                insn.CMPW(cmp2info[op], result,
+                          [gv_x.load(self), gv_y.load(self)]))
         return result
 
     def op_int_gt(self, gv_x, gv_y):
         return self._compare('gt', gv_x, gv_y)
 
+    def op_int_lt(self, gv_x, gv_y):
+        return self._compare('lt', gv_x, gv_y)
+
+    def op_int_ge(self, gv_x, gv_y):
+        return self._compare('ge', gv_x, gv_y)
+
+    def op_int_le(self, gv_x, gv_y):
+        return self._compare('le', gv_x, gv_y)
+
+    def op_int_eq(self, gv_x, gv_y):
+        return self._compare('eq', gv_x, gv_y)
+
+    def op_int_ne(self, gv_x, gv_y):
+        return self._compare('ne', gv_x, gv_y)
+
     def _jump(self, gv_condition, if_true):
         targetbuilder = self._fork()
 

Modified: pypy/dist/pypy/jit/codegen/ppc/test/test_rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/ppc/test/test_rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/ppc/test/test_rgenop.py	Tue Nov  7 19:17:09 2006
@@ -1,6 +1,8 @@
 import py
 from pypy.jit.codegen.ppc.rgenop import RPPCGenOp
-from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTests
+from pypy.rpython.lltypesystem import lltype
+from pypy.jit.codegen.test.rgenop_tests import AbstractRGenOpTests, FUNC2
+from ctypes import cast, c_int, c_void_p, CFUNCTYPE
 
 class FewRegisters(RPPCGenOp):
     MINUSERREG = 29
@@ -8,7 +10,50 @@
 class TestRPPCGenop(AbstractRGenOpTests):
     RGenOp = RPPCGenOp
 
-class TestRPPCGenopNoRegs(AbstractRGenOpTests):
+    def test_multiple_cmps(self):
+        # return x>y + 10*x<y + 100*x<=y + 1000*x>=y + 10000*x==y + 100000*x!=y
+        rgenop = self.RGenOp()
+        signed_kind = rgenop.kindToken(lltype.Signed)
+        sigtoken = rgenop.sigToken(FUNC2)
+        builder, entrypoint, [gv_x, gv_y] = rgenop.newgraph(sigtoken)
+
+        args_gv = [gv_x, gv_y]
+        builder.enter_next_block([signed_kind, signed_kind], args_gv)
+        [gv_x, gv_y] = args_gv
+        
+        gv_gt = builder.genop2("int_gt", gv_x, gv_y)
+        gv_lt = builder.genop2("int_lt", gv_x, gv_y)
+        gv_ge = builder.genop2("int_ge", gv_x, gv_y)
+        gv_le = builder.genop2("int_le", gv_x, gv_y)
+        gv_eq = builder.genop2("int_eq", gv_x, gv_y)
+        gv_ne = builder.genop2("int_ne", gv_x, gv_y)
+
+        gv_gt2 = gv_gt
+        gv_lt2 = builder.genop2("int_mul", rgenop.genconst(10), gv_lt)
+        gv_ge2 = builder.genop2("int_mul", rgenop.genconst(100), gv_ge)
+        gv_le2 = builder.genop2("int_mul", rgenop.genconst(1000), gv_le)
+        gv_eq2 = builder.genop2("int_mul", rgenop.genconst(10000), gv_eq)
+        gv_ne2 = builder.genop2("int_mul", rgenop.genconst(100000), gv_ne)
+
+        gv_r0 = gv_gt
+        gv_r1 = builder.genop2("int_add", gv_r0, gv_lt2)
+        gv_r2 = builder.genop2("int_add", gv_r1, gv_ge2)
+        gv_r3 = builder.genop2("int_add", gv_r2, gv_le2)
+        gv_r4 = builder.genop2("int_add", gv_r3, gv_eq2)
+        gv_r5 = builder.genop2("int_add", gv_r4, gv_ne2)
+
+        builder.finish_and_return(sigtoken, gv_r5)
+        gv_callable = rgenop.gencallableconst(sigtoken, "multicmp", entrypoint)
+        fnptr = cast(c_void_p(gv_callable.value), CFUNCTYPE(c_int, c_int))
+        res = fnptr(1, 2)
+        assert res == 101010
+        res = fnptr(1, 1)
+        assert res ==  11100
+        res = fnptr(2, 1)
+        assert res == 100101
+
+
+class TestRPPCGenopNoRegs(TestRPPCGenop):
     RGenOp = FewRegisters
 
     def compile(self, runner, argtypes):



More information about the Pypy-commit mailing list