[pypy-commit] pypy ppc-backend-2: Start for float support in PPC backend.

edelsohn noreply at buildbot.pypy.org
Mon Apr 23 19:55:40 CEST 2012


Author: edelsohn
Branch: ppc-backend-2
Changeset: r54689:00899aeb3dbb
Date: 2012-04-23 13:54 -0400
http://bitbucket.org/pypy/pypy/changeset/00899aeb3dbb/

Log:	Start for float support in PPC backend.

diff --git a/pypy/jit/backend/ppc/helper/assembler.py b/pypy/jit/backend/ppc/helper/assembler.py
--- a/pypy/jit/backend/ppc/helper/assembler.py
+++ b/pypy/jit/backend/ppc/helper/assembler.py
@@ -6,12 +6,15 @@
 import pypy.jit.backend.ppc.register as r
 from pypy.rpython.lltypesystem import rffi, lltype
 
-def gen_emit_cmp_op(condition, signed=True):
+def gen_emit_cmp_op(condition, signed=True, fp=False):
     def f(self, op, arglocs, regalloc):
         l0, l1, res = arglocs
         # do the comparison
-        self.mc.cmp_op(0, l0.value, l1.value,
-                       imm=l1.is_imm(), signed=signed)
+        if fp == True:
+            self.mc.fcmpu(0, l0.value, l1.value)
+        else:
+            self.mc.cmp_op(0, l0.value, l1.value,
+                           imm=l1.is_imm(), signed=signed)
         # After the comparison, place the result
         # in the first bit of the CR
         if condition == c.LT or condition == c.U_LT:
diff --git a/pypy/jit/backend/ppc/helper/regalloc.py b/pypy/jit/backend/ppc/helper/regalloc.py
--- a/pypy/jit/backend/ppc/helper/regalloc.py
+++ b/pypy/jit/backend/ppc/helper/regalloc.py
@@ -1,5 +1,4 @@
-from pypy.jit.metainterp.history import ConstInt
-from pypy.jit.metainterp.history import Box
+from pypy.jit.metainterp.history import ConstInt, Box, FLOAT
 
 IMM_SIZE = 2 ** 15 - 1
 
@@ -84,3 +83,41 @@
         self.possibly_free_var(op.result)
         return [reg1, reg2, res]
     return f
+
+def prepare_float_op(name=None, base=True, float_result=True, guard=False):
+    if guard:
+        def f(self, op, guard_op):
+            locs = []
+            loc1 = self._ensure_value_is_boxed(op.getarg(0))
+            locs.append(loc1)
+            if base:
+                loc2 = self._ensure_value_is_boxed(op.getarg(1))
+                locs.append(loc2)
+            self.possibly_free_vars_for_op(op)
+            self.free_temp_vars()
+            if guard_op is None:
+                res = self.force_allocate_reg(op.result)
+                assert float_result == (op.result.type == FLOAT)
+                locs.append(res)
+                return locs
+            else:
+                args = self._prepare_guard(guard_op, locs)
+                return args
+    else:
+        def f(self, op):
+            locs = []
+            loc1 = self._ensure_value_is_boxed(op.getarg(0))
+            locs.append(loc1)
+            if base:
+                loc2 = self._ensure_value_is_boxed(op.getarg(1))
+                locs.append(loc2)
+            self.possibly_free_vars_for_op(op)
+            self.free_temp_vars()
+            res = self.force_allocate_reg(op.result)
+            assert float_result == (op.result.type == FLOAT)
+            locs.append(res)
+            return locs
+    if name:
+        f.__name__ = name
+    return f
+
diff --git a/pypy/jit/backend/ppc/locations.py b/pypy/jit/backend/ppc/locations.py
--- a/pypy/jit/backend/ppc/locations.py
+++ b/pypy/jit/backend/ppc/locations.py
@@ -4,8 +4,10 @@
 # XXX import from arch.py, currently we have a circular import
 if sys.maxint == (2**31 - 1):
     WORD = 4
+    FWORD = 8
 else:
     WORD = 8
+    FWORD = 8
 DWORD = 2 * WORD
 
 class AssemblerLocation(object):
@@ -49,7 +51,7 @@
 class FPRegisterLocation(RegisterLocation):
     _immutable_ = True
     type = FLOAT 
-    width = DWORD
+    width = FWORD
 
     def __repr__(self):
         return 'fp%d' % self.value
@@ -83,6 +85,28 @@
     def as_key(self):
         return self.value + 40
 
+class ConstFloatLoc(AssemblerLocation):
+    """This class represents an imm float value which is stored in memory at
+    the address stored in the field value"""
+    _immutable_ = True
+    width = FWORD
+    type = FLOAT
+
+    def __init__(self, value):
+        self.value = value
+
+    def getint(self):
+        return self.value
+
+    def __repr__(self):
+        return "imm_float(stored at %d)" % (self.value)
+
+    def is_imm_float(self):
+        return True
+
+    def as_key(self):
+        return self.value
+
 class StackLocation(AssemblerLocation):
     _immutable_ = True
 
diff --git a/pypy/jit/backend/ppc/opassembler.py b/pypy/jit/backend/ppc/opassembler.py
--- a/pypy/jit/backend/ppc/opassembler.py
+++ b/pypy/jit/backend/ppc/opassembler.py
@@ -174,6 +174,53 @@
         l0, res = arglocs
         self.mc.not_(res.value, l0.value)
 
+class FloatOpAssembler(object):
+    _mixin_ = True
+
+    def emit_float_add(self, op, argsloc, regalloc):
+        l0, l1, res = arglocs
+        self.mc.fadd(res.value, l0.value, l1.value)
+
+    def emit_float_sub(self, op, argsloc, regalloc):
+        l0, l1, res = arglocs
+        self.mc.fsub(res.value, l0.value, l1.value)
+
+    def emit_float_mul(self, op, argsloc, regalloc):
+        l0, l1, res = arglocs
+        self.mc.fmul(res.value, l0.value, l1.value)
+
+    def emit_float_truediv(self, op, argsloc, regalloc):
+        l0, l1, res = arglocs
+        self.mc.fdiv(res.value, l0.value, l1.value)
+
+    def emit_float_neg(self, op, argsloc, regalloc):
+        l0, res = arglocs
+        self.mc.fneg(res.value, l0.value)
+
+    def emit_float_abs(self, op, argsloc, regalloc):
+        l0, res = arglocs
+        self.mc.fabs(res.value, l0.value)
+
+    def emit_float_sqrt(self, op, argsloc, regalloc):
+        l0, res = arglocs
+        self.mc.fsqrt(res.value, l0.value)
+
+    emit_float_le = gen_emit_cmp_op(c.LE, fp=True)
+    emit_float_lt = gen_emit_cmp_op(c.LT, fp=True)
+    emit_float_gt = gen_emit_cmp_op(c.GT, fp=True)
+    emit_float_ge = gen_emit_cmp_op(c.GE, fp=True)
+    emit_float_eq = gen_emit_cmp_op(c.EQ, fp=True)
+    emit_float_ne = gen_emit_cmp_op(c.NE, fp=True)
+
+    def emit_op_cast_float_to_int(self, op, arglocs, regalloc):
+        l0, temp_loc, res = arglocs
+        self.mc.fctidz(temp_loc.value, l0.value)
+        self.mc.mfprgpr(res.value, temp_loc.value)
+
+    def emit_op_cast_int_to_float(self, op, arglocs, regalloc):
+        l0, temp_loc, res = arglocs
+        self.mc.mgprfpr(temp_loc.value, l0.value)
+        self.mc.fcfid(res.value, temp_loc.value)
 
 class GuardOpAssembler(object):
 
@@ -1254,7 +1301,7 @@
                   MiscOpAssembler, FieldOpAssembler,
                   ArrayOpAssembler, StrOpAssembler,
                   UnicodeOpAssembler, ForceOpAssembler,
-                  AllocOpAssembler):
+                  AllocOpAssembler, FloatOpAssembler):
 
     def nop(self):
         self.mc.ori(0, 0, 0)
diff --git a/pypy/jit/backend/ppc/regalloc.py b/pypy/jit/backend/ppc/regalloc.py
--- a/pypy/jit/backend/ppc/regalloc.py
+++ b/pypy/jit/backend/ppc/regalloc.py
@@ -8,7 +8,8 @@
                                                   prepare_unary_int_op,
                                                   prepare_binary_int_op,
                                                   prepare_binary_int_op_with_imm,
-                                                  prepare_unary_cmp)
+                                                  prepare_unary_cmp,
+                                                  prepare_float_op)
 from pypy.jit.metainterp.history import (Const, ConstInt, ConstPtr,
                                          Box, BoxPtr,
                                          INT, REF, FLOAT)
@@ -41,6 +42,57 @@
     def __repr__(self):
         return "<TempPtr at %s>" % (id(self),)
 
+class TempFloat(TempBox):
+    type = FLOAT
+
+    def __repr__(self):
+        return "<TempFloat at %s>" % (id(self),)
+
+
+class FPRegisterManager(RegisterManager):
+    all_regs              = r.ALL_FLOAT_REGS
+    box_types             = [FLOAT]
+    save_around_call_regs = r.VOLATILES_FLOAT
+
+    def convert_to_imm(self, c):
+        adr = self.assembler.datablockwrapper.malloc_aligned(8, 8)
+        x = c.getfloatstorage()
+        rffi.cast(rffi.CArrayPtr(long.FLOATSTORAGE), adr)[0] = x
+        return locations.ConstFloatLoc(adr)
+
+    def __init__(self, longevity, frame_manager=None, assembler=None):
+        RegisterManager.__init__(self, longevity, frame_manager, assembler)
+
+    def after_call(self, v):
+        """ Adjust registers according to the result of the call,
+        which is in variable v.
+        """
+        self._check_type(v)
+        r = self.force_allocate_reg(v)
+        return r
+
+    def ensure_value_is_boxed(self, thing, forbidden_vars=[]):
+        loc = None
+        if isinstance(thing, Const):
+            assert isinstance(thing, ConstFloat)
+            loc = self.get_scratch_reg(FLOAT, self.temp_boxes + forbidden_vars)
+            immvalue = self.convert_to_imm(thing)
+            self.assembler.load(loc, immvalue)
+        else:
+            loc = self.make_sure_var_in_reg(thing,
+                            forbidden_vars=self.temp_boxes + forbidden_vars)
+        return loc
+
+    def get_scratch_reg(self, type=FLOAT, forbidden_vars=[],
+                                                        selected_reg=None):
+        assert type == FLOAT  # for now
+        box = TempFloat()
+        self.temp_boxes.append(box)
+        reg = self.force_allocate_reg(box, forbidden_vars=forbidden_vars,
+                                                    selected_reg=selected_reg)
+        return reg
+
+
 class PPCRegisterManager(RegisterManager):
     all_regs              = r.MANAGED_REGS
     box_types             = None       # or a list of acceptable types
@@ -131,21 +183,15 @@
     @staticmethod
     def frame_pos(loc, type):
         num_words = PPCFrameManager.frame_size(type)
-        if type == FLOAT:
-            assert 0, "not implemented yet"
         return locations.StackLocation(loc, num_words=num_words, type=type)
 
     @staticmethod
     def frame_size(type):
-        if type == FLOAT:
-            assert 0, "TODO"
         return 1
 
     @staticmethod
     def get_loc_index(loc):
         assert loc.is_stack()
-        if loc.type == FLOAT:
-            assert 0, "not implemented yet"
         return loc.position
 
 class Regalloc(object):
@@ -164,6 +210,7 @@
         self.last_real_usage = last_real_usage
         fm = self.frame_manager
         asm = self.assembler
+        self.fprm = FPRegisterManager(longevity, fm, asm)
         self.rm = PPCRegisterManager(longevity, fm, asm)
 
     def prepare_loop(self, inputargs, operations):
@@ -182,12 +229,11 @@
         cur_frame_pos = -self.assembler.OFFSET_STACK_ARGS // WORD + 1
         for box in inputargs:
             assert isinstance(box, Box)
-            # handle inputargs in argument registers
-            if box.type == FLOAT and arg_index % 2 != 0:
-                assert 0, "not implemented yet"
             if arg_index < n_register_args:
                 if box.type == FLOAT:
-                    assert 0, "not implemented yet"
+                    loc = r.PARAM_FPREGS[arg_index]
+                    self.try_allocate_reg(box, selected_reg=loc)
+                    arg_index += 1
                 else:
                     loc = r.PARAM_REGS[arg_index]
                     self.try_allocate_reg(box, selected_reg=loc)
@@ -195,7 +241,13 @@
             else:
                 # treat stack args as stack locations with a negative offset
                 if box.type == FLOAT:
-                    assert 0, "not implemented yet"
+                    if IS_PPC_32:
+                        cur_frame_pos -= 2
+                    else:
+                        cur_frame_pos -= 1
+                    if count % 2 != 0: # Stack argument alignment
+                        cur_frame_pos -= 1
+                        count = 0
                 else:
                     cur_frame_pos -= 1
                     count += 1
@@ -255,21 +307,24 @@
 
     def _check_invariants(self):
         self.rm._check_invariants()
+        self.fprm._check_invariants()
 
     def loc(self, var):
         if var.type == FLOAT:
-            assert 0, "not implemented yet"
-        return self.rm.loc(var)
+            return self.fprm.loc(var)
+        else:
+            return self.rm.loc(var)
 
     def position(self):
         return self.rm.position
 
     def next_instruction(self):
         self.rm.next_instruction()
+        self.fprm.next_instruction()
 
     def force_spill_var(self, var):
         if var.type == FLOAT:
-            assert 0, "not implemented yet"
+            self.fprm.force_spill_var(var)
         else:
             self.rm.force_spill_var(var)
 
@@ -278,30 +333,32 @@
 
     def after_call(self, v):
         if v.type == FLOAT:
-            assert 0, "not implemented yet"
+            return self.fprm.after_call(v)
         else:
             return self.rm.after_call(v)
 
     def call_result_location(self, v):
         if v.type == FLOAT:
-            assert 0, "not implemented yet"
+            return self.fprm.call_result_location(v)
         else:
             return self.rm.call_result_location(v)
 
     def _ensure_value_is_boxed(self, thing, forbidden_vars=[]):
         if thing.type == FLOAT:
-            assert 0, "not implemented yet"
+            return self.fprm.ensure_value_is_boxed(thing, forbidden_vars)
         else:
             return self.rm.ensure_value_is_boxed(thing, forbidden_vars)
 
     def get_scratch_reg(self, type, forbidden_vars=[], selected_reg=None):
         if type == FLOAT:
-            assert 0, "not implemented yet"
+            return self.fprm.get_scratch_reg(type, forbidden_vars,
+                                                                selected_reg)
         else:
             return self.rm.get_scratch_reg(type, forbidden_vars, selected_reg)
 
     def free_temp_vars(self):
         self.rm.free_temp_vars()
+        self.fprm.free_temp_vars()
 
     def make_sure_var_in_reg(self, var, forbidden_vars=[],
                              selected_reg=None, need_lower_byte=False):
@@ -315,11 +372,12 @@
         if isinstance(value, ConstInt):
             return self.rm.convert_to_imm(value)
         else:
-            assert 0, "not implemented yet"
+            assert isinstance(value, ConstFloat)
+            return self.fprm.convert_to_imm(value)
 
     def _sync_var(self, v):
         if v.type == FLOAT:
-            assert 0, "not implemented yet"
+            self.fprm._sync_var(v)
         else:
             self.rm._sync_var(v)
 
@@ -373,6 +431,65 @@
     prepare_int_is_true = prepare_unary_cmp()
     prepare_int_is_zero = prepare_unary_cmp()
 
+    prepare_float_add = prepare_float_op(name='prepare_float_add')
+    prepare_float_sub = prepare_float_op(name='prepare_float_sub')
+    prepare_float_mul = prepare_float_op(name='prepare_float_mul')
+    prepare_float_truediv = prepare_float_op(name='prepare_float_truediv')
+
+    prepare_float_lt = prepare_float_op(float_result=False,
+                                        name='prepare_op_float_lt')
+    prepare_float_le = prepare_float_op(float_result=False,
+                                        name='prepare_op_float_le')
+    prepare_float_eq = prepare_float_op(float_result=False,
+                                        name='prepare_op_float_eq')
+    prepare_float_ne = prepare_float_op(float_result=False,
+                                        name='prepare_op_float_ne')
+    prepare_float_gt = prepare_float_op(float_result=False,
+                                        name='prepare_op_float_gt')
+    prepare_float_ge = prepare_float_op(float_result=False,
+                                        name='prepare_op_float_ge')
+    prepare_float_neg = prepare_float_op(base=False,
+                                         name='prepare_op_float_neg')
+    prepare_float_abs = prepare_float_op(base=False,
+                                         name='prepare_op_float_abs')
+
+    prepare_guard_float_lt = prepare_float_op(guard=True,
+                            float_result=False, name='prepare_guard_float_lt')
+    prepare_guard_float_le = prepare_float_op(guard=True,
+                            float_result=False, name='prepare_guard_float_le')
+    prepare_guard_float_eq = prepare_float_op(guard=True,
+                            float_result=False, name='prepare_guard_float_eq')
+    prepare_guard_float_ne = prepare_float_op(guard=True,
+                            float_result=False, name='prepare_guard_float_ne')
+    prepare_guard_float_gt = prepare_float_op(guard=True,
+                            float_result=False, name='prepare_guard_float_gt')
+    prepare_guard_float_ge = prepare_float_op(guard=True,
+                            float_result=False, name='prepare_guard_float_ge')
+
+    def prepare_math_sqrt(self, op):
+        loc = self._ensure_value_is_boxed(op.getarg(1))
+        self.possibly_free_vars_for_op(op)
+        self.free_temp_vars()
+        res = self.fprm.force_allocate_reg(op.result)
+        self.possibly_free_var(op.result)
+        return [loc, res]
+
+    def prepare_cast_float_to_int(self, op):
+        loc1 = self._ensure_value_is_boxed(op.getarg(0))
+        temp_loc = self.get_scratch_reg(FLOAT)
+        self.possibly_free_vars_for_op(op)
+        self.free_temp_vars()
+        res = self.rm.force_allocate_reg(op.result)
+        return [loc1, temp_loc, res]
+
+    def prepare_cast_int_to_float(self, op):
+        loc1 = self._ensure_value_is_boxed(op.getarg(0))
+        temp_loc = self.get_scratch_reg(FLOAT)
+        self.possibly_free_vars_for_op(op)
+        self.free_temp_vars()
+        res = self.fprm.force_allocate_reg(op.result)
+        return [loc1, temp_loc, res]
+
     def prepare_finish(self, op):
         args = [None] * (op.numargs() + 1)
         for i in range(op.numargs()):
@@ -776,6 +893,7 @@
         for i in range(op.numargs()):
             args.append(self.loc(op.getarg(i)))
         # spill variables that need to be saved around calls
+        self.fprm.before_call(save_all_regs=save_all_regs)
         if not save_all_regs:
             gcrootmap = self.assembler.cpu.gc_ll_descr.gcrootmap
             if gcrootmap and gcrootmap.is_shadow_stack:
diff --git a/pypy/jit/backend/ppc/register.py b/pypy/jit/backend/ppc/register.py
--- a/pypy/jit/backend/ppc/register.py
+++ b/pypy/jit/backend/ppc/register.py
@@ -19,7 +19,7 @@
 
 NONVOLATILES_FLOAT  = [f14, f15, f16, f17, f18, f19, f20, f21, f22, f23,
                     f24, f25, f26, f27, f28, f29, f30, f31]
-
+VOLATILES_FLOAT  = [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13]
 
 SCRATCH = r0
 SP      = r1
@@ -33,6 +33,7 @@
                 r27, r28, r29, r30]
 
 PARAM_REGS = [r3, r4, r5, r6, r7, r8, r9, r10]
+PARAM_FPREGS = [f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13]
 
 def get_managed_reg_index(reg):
     if reg > r13.value:
diff --git a/pypy/jit/backend/ppc/runner.py b/pypy/jit/backend/ppc/runner.py
--- a/pypy/jit/backend/ppc/runner.py
+++ b/pypy/jit/backend/ppc/runner.py
@@ -27,7 +27,7 @@
                                translate_support_code, gcdescr)
 
         # floats are not supported yet
-        self.supports_floats = False
+        self.supports_floats = True
 
     def setup(self):
         self.asm = AssemblerPPC(self)


More information about the pypy-commit mailing list