Author: David Schneider <david.schnei...@picle.org>
Branch: arm-backed-float
Changeset: r44645:d3279ad17fe6
Date: 2011-06-01 17:46 +0200
http://bitbucket.org/pypy/pypy/changeset/d3279ad17fe6/

Log:    (arigo, bivab) add a resoperation for testing called force_spill,
        that forces a variable to be spilled. It is used to the generate
        different call patterns with variables that are currently spilled as
        arguments

diff --git a/pypy/jit/backend/llsupport/regalloc.py 
b/pypy/jit/backend/llsupport/regalloc.py
--- a/pypy/jit/backend/llsupport/regalloc.py
+++ b/pypy/jit/backend/llsupport/regalloc.py
@@ -226,6 +226,18 @@
             else:
                 raise ValueError
 
+    def force_spill_var(self, var):
+        self._sync_var(var)
+        try:
+            loc = self.reg_bindings[var]
+            del self.reg_bindings[var]
+            self.free_regs.append(loc)
+        except KeyError:
+            if not we_are_translated():
+                import pdb; pdb.set_trace()
+            else:
+                raise ValueError
+
     def loc(self, box):
         """ Return the location of 'box'.
         """
diff --git a/pypy/jit/backend/test/calling_convention_test.py 
b/pypy/jit/backend/test/calling_convention_test.py
--- a/pypy/jit/backend/test/calling_convention_test.py
+++ b/pypy/jit/backend/test/calling_convention_test.py
@@ -1,4 +1,3 @@
-import py, sys, random, os, struct, operator, itertools
 from pypy.jit.metainterp.history import (AbstractFailDescr,
                                          AbstractDescr,
                                          BasicFailDescr,
@@ -24,6 +23,7 @@
 
 def constfloat(x):
     return ConstFloat(longlong.getfloatstorage(x))
+
 class FakeStats(object):
     pass
 class TestCallingConv(Runner):
@@ -35,11 +35,127 @@
         self.cpu = getcpuclass()(rtyper=None, stats=FakeStats())
         self.cpu.setup_once()
 
+    def _prepare_args(self, args, floats, ints):
+        local_floats = list(floats)
+        local_ints = list(ints)
+        expected_result = 0.0
+        for i in range(len(args)):
+            x = args[i]
+            if x[0] == 'f':
+                x = local_floats.pop()
+                t = longlong.getfloatstorage(x)
+                self.cpu.set_future_value_float(i, t)
+            else:
+                x = local_ints.pop()
+                self.cpu.set_future_value_int(i, x)
+            expected_result += x
+        return expected_result
+
     @classmethod
     def get_funcbox(cls, cpu, func_ptr):
         addr = llmemory.cast_ptr_to_adr(func_ptr)
         return ConstInt(heaptracker.adr2int(addr))
 
+    def test_call_aligned_with_spilled_values(self):
+            from pypy.rlib.libffi import types
+            cpu = self.cpu
+            if not cpu.supports_floats:
+                py.test.skip('requires floats')
+
+
+            def func(*args):
+                return float(sum(args))
+
+            F = lltype.Float
+            I = lltype.Signed
+            floats = [0.7, 5.8, 0.1, 0.3, 0.9, -2.34, -3.45, -4.56]
+            ints = [7, 11, 23, 13, -42, 1111, 95, 1]
+            for case in range(256):
+                local_floats = list(floats)
+                local_ints = list(ints)
+                args = []
+                spills = []
+                funcargs = []
+                float_count = 0
+                int_count = 0
+                for i in range(8):
+                    if case & (1<<i):
+                        args.append('f%d' % float_count)
+                        spills.append('force_spill(f%d)' % float_count)
+                        float_count += 1
+                        funcargs.append(F)
+                    else:
+                        args.append('i%d' % int_count)
+                        spills.append('force_spill(i%d)' % int_count)
+                        int_count += 1
+                        funcargs.append(I)
+
+                arguments = ', '.join(args)
+                spill_ops = '\n'.join(spills)
+
+                FUNC = self.FuncType(funcargs, F)
+                FPTR = self.Ptr(FUNC)
+                func_ptr = llhelper(FPTR, func)
+                calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
+                funcbox = self.get_funcbox(cpu, func_ptr)
+
+                ops = '[%s]\n' % arguments
+                ops += '%s\n' % spill_ops
+                ops += 'f99 = call(ConstClass(func_ptr), %s, 
descr=calldescr)\n' % arguments
+                ops += 'finish(f99, %s)\n' % arguments
+
+                loop = parse(ops, namespace=locals())
+                looptoken = LoopToken()
+                done_number = 
self.cpu.get_fail_descr_number(loop.operations[-1].getdescr())
+                self.cpu.compile_loop(loop.inputargs, loop.operations, 
looptoken)
+                expected_result = self._prepare_args(args, floats, ints)
+
+                res = self.cpu.execute_token(looptoken)
+                x = longlong.getrealfloat(cpu.get_latest_value_float(0))
+                assert abs(x - expected_result) < 0.0001
+
+    def test_call_aligned_with_imm_values(self):
+            from pypy.rlib.libffi import types
+            cpu = self.cpu
+            if not cpu.supports_floats:
+                py.test.skip('requires floats')
+
+
+            def func(*args):
+                return float(sum(args))
+
+            F = lltype.Float
+            I = lltype.Signed
+            floats = [0.7, 5.8, 0.1, 0.3, 0.9, -2.34, -3.45, -4.56]
+            ints = [7, 11, 23, 13, -42, 1111, 95, 1]
+            for case in range(256):
+                result = 0.0
+                args = []
+                argslist = []
+                local_floats = list(floats)
+                local_ints = list(ints)
+                for i in range(8):
+                    if case & (1<<i):
+                        args.append(F)
+                        arg = local_floats.pop()
+                        result += arg
+                        argslist.append(constfloat(arg))
+                    else:
+                        args.append(I)
+                        arg = local_ints.pop()
+                        result += arg
+                        argslist.append(ConstInt(arg))
+                FUNC = self.FuncType(args, F)
+                FPTR = self.Ptr(FUNC)
+                func_ptr = llhelper(FPTR, func)
+                calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
+                funcbox = self.get_funcbox(cpu, func_ptr)
+
+                res = self.execute_operation(rop.CALL,
+                                             [funcbox] + argslist,
+                                             'float', descr=calldescr)
+                assert abs(res.getfloat() - result) < 0.0001
+
     def test_call_aligned_with_args_on_the_stack(self):
             from pypy.rlib.libffi import types
             cpu = self.cpu
@@ -48,79 +164,46 @@
 
 
             def func(*args):
-                return sum(args)
+                return float(sum(args))
 
             F = lltype.Float
             I = lltype.Signed
-            base_args = [F, F]
-            floats = [0.7, 5.8, 0.1, 0.3, 0.9]
-            ints = [7, 11, 23]
-            result = sum(floats + ints)
-            for p in itertools.permutations([I, I, I, F, F, F]):
-                args = base_args + list(p)
+            floats = [0.7, 5.8, 0.1, 0.3, 0.9, -2.34, -3.45, -4.56]
+            ints = [7, 11, 23, 13, -42, 1111, 95, 1]
+            for case in range(256):
+                result = 0.0
+                args = []
+                argslist = []
                 local_floats = list(floats)
                 local_ints = list(ints)
+                for i in range(8):
+                    if case & (1<<i):
+                        args.append(F)
+                        arg = local_floats.pop()
+                        result += arg
+                        argslist.append(boxfloat(arg))
+                    else:
+                        args.append(I)
+                        arg = local_ints.pop()
+                        result += arg
+                        argslist.append(BoxInt(arg))
                 FUNC = self.FuncType(args, F)
                 FPTR = self.Ptr(FUNC)
                 func_ptr = llhelper(FPTR, func)
                 calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
                 funcbox = self.get_funcbox(cpu, func_ptr)
-                argslist = []
-                for x in args:
-                    if x is F:
-                        argslist.append(boxfloat(local_floats.pop()))
-                    else:
-                        argslist.append(BoxInt(local_ints.pop()))
 
                 res = self.execute_operation(rop.CALL,
                                              [funcbox] + argslist,
                                              'float', descr=calldescr)
                 assert abs(res.getfloat() - result) < 0.0001
 
-    def test_call_alignment_register_args(self):
-            from pypy.rlib.libffi import types
-            cpu = self.cpu
-            if not cpu.supports_floats:
-                py.test.skip('requires floats')
-
-
-            def func(*args):
-                return sum(args)
-
-            F = lltype.Float
-            I = lltype.Signed
-            floats = [0.7, 5.8]
-            ints = [7, 11]
-            result = sum(floats + ints)
-            for args in itertools.permutations([I, I, F, F]):
-                local_floats = list(floats)
-                local_ints = list(ints)
-                FUNC = self.FuncType(args, F)
-                FPTR = self.Ptr(FUNC)
-                func_ptr = llhelper(FPTR, func)
-                calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
-                funcbox = self.get_funcbox(cpu, func_ptr)
-                argslist = []
-                for x in args:
-                    if x is F:
-                        argslist.append(boxfloat(local_floats.pop()))
-                    else:
-                        argslist.append(BoxInt(local_ints.pop()))
-
-                res = self.execute_operation(rop.CALL,
-                                             [funcbox] + argslist,
-                                             'float', descr=calldescr)
-                assert abs(res.getfloat() - result) < 0.0001
-
-
     def test_call_alignment_call_assembler(self):
         from pypy.rlib.libffi import types
         cpu = self.cpu
         if not cpu.supports_floats:
             py.test.skip('requires floats')
 
-        fdescr1 = BasicFailDescr(1)
-        fdescr2 = BasicFailDescr(2)
         fdescr3 = BasicFailDescr(3)
         fdescr4 = BasicFailDescr(4)
 
@@ -136,35 +219,34 @@
             assembler_helper_adr = llmemory.cast_ptr_to_adr(
                 _assembler_helper_ptr)
 
-        arglist = ['f0', 'f1', 'f2', 'i0', 'f3']
-        floats = [0.7, 5.8, 0.1, 0.3]
-        ints = [7, 11, 23, 42]
-        def _prepare_args(args):
-            local_floats = list(floats)
-            local_ints = list(ints)
-            for i in range(len(args)):
-                x = args[i]
-                if x[0] == 'f':
-                    t = longlong.getfloatstorage(local_floats.pop())
-                    cpu.set_future_value_float(i, t)
+        floats = [0.7, 5.8, 0.1, 0.3, 0.9, -2.34, -3.45, -4.56]
+        ints = [7, 11, 23, 42, -42, 1111, 95, 1]
+
+        for case in range(256):
+            float_count = 0
+            int_count = 0
+            args = []
+            called_ops = ''
+            total_index = -1
+            for i in range(8):
+                if case & (1<<i):
+                    args.append('f%d' % float_count)
                 else:
-                    cpu.set_future_value_int(i, (local_ints.pop()))
-
-        for args in itertools.permutations(arglist):
-            args += ('i1', 'i2', 'i3')
+                    args.append('i%d' % int_count)
+                    called_ops += 'f%d = cast_int_to_float(i%d)\n' % (
+                        float_count, int_count)
+                    int_count += 1
+                if total_index == -1:
+                    total_index = float_count
+                    float_count += 1
+                else:
+                    called_ops += 'f%d = float_add(f%d, f%d)\n' % (
+                        float_count + 1, total_index, float_count)
+                    total_index = float_count + 1
+                    float_count += 2
             arguments = ', '.join(args)
-            called_ops = '''
-            [%s]
-            i4 = int_add(i0, i1)
-            i5 = int_add(i4, i2)
-            i6 = int_add(i5, i3)
-            guard_value(i6, 83, descr=fdescr1) [i4, i5, i6]
-            f4 = float_add(f0, f1)
-            f5 = float_add(f4, f2)
-            f6 = float_add(f5, f3)
-            i7 = float_lt(f6, 6.99)
-            guard_true(i7, descr=fdescr2) [f4, f5, f6]
-            finish(i6, f6, descr=fdescr3)''' % arguments
+            called_ops = '[%s]\n' % arguments + called_ops
+            called_ops += 'finish(f%d, descr=fdescr3)\n' % total_index
             # compile called loop
             called_loop = parse(called_ops, namespace=locals())
             called_looptoken = LoopToken()
@@ -172,15 +254,14 @@
             done_number = 
self.cpu.get_fail_descr_number(called_loop.operations[-1].getdescr())
             self.cpu.compile_loop(called_loop.inputargs, 
called_loop.operations, called_looptoken)
 
-            _prepare_args(args)
+            expected_result = self._prepare_args(args, floats, ints)
             res = cpu.execute_token(called_looptoken)
             assert res.identifier == 3
-            assert cpu.get_latest_value_int(0) == 83
-            t = longlong.getrealfloat(cpu.get_latest_value_float(1))
-            assert abs(t - 6.9) < 0.0001
+            t = longlong.getrealfloat(cpu.get_latest_value_float(0))
+            assert abs(t - expected_result) < 0.0001
 
             ARGS = []
-            RES = lltype.Signed
+            RES = lltype.Float
             for x in args:
                 if x[0] == 'f':
                     ARGS.append(lltype.Float)
@@ -190,22 +271,23 @@
                 lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES)
             ops = '''
             [%s]
-            i10 = call_assembler(%s, descr=called_looptoken)
+            f99 = call_assembler(%s, descr=called_looptoken)
             guard_not_forced()[]
-            finish(i10, descr=fdescr4)
+            finish(f99, descr=fdescr4)
             ''' % (arguments, arguments)
             loop = parse(ops, namespace=locals())
             # we want to take the fast path
-            self.cpu.done_with_this_frame_int_v = done_number
+            self.cpu.done_with_this_frame_float_v = done_number
             try:
                 othertoken = LoopToken()
                 self.cpu.compile_loop(loop.inputargs, loop.operations, 
othertoken)
 
                 # prepare call to called_loop
-                _prepare_args(args)
+                self._prepare_args(args, floats, ints)
                 res = cpu.execute_token(othertoken)
-                x = cpu.get_latest_value_int(0)
+                x = longlong.getrealfloat(cpu.get_latest_value_float(0))
                 assert res.identifier == 4
-                assert x == 83
+                assert abs(x - expected_result) < 0.0001
             finally:
-                del self.cpu.done_with_this_frame_int_v
+                del self.cpu.done_with_this_frame_float_v
+
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -266,6 +266,12 @@
             return self.rm.force_allocate_reg(var, forbidden_vars,
                                               selected_reg, need_lower_byte)
 
+    def force_spill_var(self, var):
+        if var.type == FLOAT:
+            return self.xrm.force_spill_var(var)
+        else:
+            return self.rm.force_spill_var(var)
+
     def load_xmm_aligned_16_bytes(self, var, forbidden_vars=[]):
         # Load 'var' in a register; but if it is a constant, we can return
         # a 16-bytes-aligned ConstFloatLoc.
@@ -400,6 +406,8 @@
             if self.can_merge_with_next_guard(op, i, operations):
                 oplist_with_guard[op.getopnum()](self, op, operations[i + 1])
                 i += 1
+            elif not we_are_translated() and op.getopnum() == -124: 
+                self._consider_force_spill(op)
             else:
                 oplist[op.getopnum()](self, op)
             if op.result is not None:
@@ -1228,6 +1236,10 @@
     def consider_jit_debug(self, op):
         pass
 
+    def _consider_force_spill(self, op):
+        # This operation is used only for testing
+        self.force_spill_var(op.getarg(0))
+
     def get_mark_gc_roots(self, gcrootmap, use_copy_area=False):
         shape = gcrootmap.get_basic_shape(IS_X86_64)
         for v, val in self.fm.frame_bindings.items():
diff --git a/pypy/jit/tool/oparser.py b/pypy/jit/tool/oparser.py
--- a/pypy/jit/tool/oparser.py
+++ b/pypy/jit/tool/oparser.py
@@ -6,7 +6,9 @@
 from pypy.jit.metainterp.history import TreeLoop, BoxInt, ConstInt,\
      ConstObj, ConstPtr, Box, BasicFailDescr, BoxFloat, ConstFloat,\
      LoopToken, get_const_ptr_for_string, get_const_ptr_for_unicode
-from pypy.jit.metainterp.resoperation import rop, ResOperation, 
ResOpWithDescr, N_aryOp
+from pypy.jit.metainterp.resoperation import rop, ResOperation, \
+                                            ResOpWithDescr, N_aryOp, \
+                                            UnaryOp, PlainResOp
 from pypy.jit.metainterp.typesystem import llhelper
 from pypy.jit.codewriter.heaptracker import adr2int
 from pypy.jit.codewriter import longlong
@@ -35,6 +37,23 @@
     def clone(self):
         return ESCAPE_OP(self.OPNUM, self.getarglist()[:], self.result, 
self.getdescr())
 
+class FORCE_SPILL(UnaryOp, PlainResOp):
+
+    OPNUM = -124
+
+    def __init__(self, opnum, args, result=None, descr=None):
+        assert result is None
+        assert descr is None
+        assert opnum == self.OPNUM
+        self.result = result
+        self.initarglist(args)
+
+    def getopnum(self):
+        return self.OPNUM
+
+    def clone(self):
+        return FORCE_SPILL(self.OPNUM, self.getarglist()[:])
+
 class ExtendedTreeLoop(TreeLoop):
 
     def getboxes(self):
@@ -220,6 +239,8 @@
         except AttributeError:
             if opname == 'escape':
                 opnum = ESCAPE_OP.OPNUM
+            elif opname == 'force_spill':
+                opnum = FORCE_SPILL.OPNUM
             else:
                 raise ParseError("unknown op: %s" % opname)
         endnum = line.rfind(')')
@@ -261,6 +282,8 @@
     def create_op(self, opnum, args, result, descr):
         if opnum == ESCAPE_OP.OPNUM:
             return ESCAPE_OP(opnum, args, result, descr)
+        if opnum == FORCE_SPILL.OPNUM:
+            return FORCE_SPILL(opnum, args, result, descr)
         else:
             return ResOperation(opnum, args, result, descr)
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to