[pypy-svn] pypy jit-longlong: Merge "default".

arigo commits-noreply at bitbucket.org
Fri Jan 14 15:30:00 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: jit-longlong
Changeset: r40674:7d4ef364a765
Date: 2011-01-14 15:29 +0100
http://bitbucket.org/pypy/pypy/changeset/7d4ef364a765/

Log:	Merge "default".

diff --git a/pypy/rlib/test/test_rarithmetic.py b/pypy/rlib/test/test_rarithmetic.py
--- a/pypy/rlib/test/test_rarithmetic.py
+++ b/pypy/rlib/test/test_rarithmetic.py
@@ -406,3 +406,9 @@
     x = r_longlong(-1)
     y = r_ulonglong(x)
     assert long(y) == 2**r_ulonglong.BITS - 1
+
+def test_highest_bit():
+    py.test.raises(AssertionError, highest_bit, 0)
+    py.test.raises(AssertionError, highest_bit, 14)
+    for i in xrange(31):
+        assert highest_bit(2**i) == i

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
@@ -212,17 +212,15 @@
                 self.possibly_free_var(var)
 
     def make_sure_var_in_reg(self, var, forbidden_vars=[],
-                             selected_reg=None, imm_fine=True,
-                             need_lower_byte=False):
+                             selected_reg=None, need_lower_byte=False):
         if var.type == FLOAT:
-            # always pass imm_fine=False for now in this case
+            if isinstance(var, ConstFloat):
+                return FloatImmedLoc(var.getfloat())
             return self.xrm.make_sure_var_in_reg(var, forbidden_vars,
-                                                 selected_reg, False,
-                                                 need_lower_byte)
+                                                 selected_reg, need_lower_byte)
         else:
             return self.rm.make_sure_var_in_reg(var, forbidden_vars,
-                                                selected_reg, imm_fine,
-                                                need_lower_byte)
+                                                selected_reg, need_lower_byte)
 
     def force_allocate_reg(self, var, forbidden_vars=[], selected_reg=None,
                            need_lower_byte=False):
@@ -382,35 +380,42 @@
     def _compute_vars_longevity(self, inputargs, operations):
         # compute a dictionary that maps variables to index in
         # operations that is a "last-time-seen"
-        longevity = {}
-        start_live = {}
-        for inputarg in inputargs:
-            start_live[inputarg] = 0
-        for i in range(len(operations)):
+        produced = {}
+        last_used = {}
+        for i in range(len(operations)-1, -1, -1):
             op = operations[i]
-            if op.result is not None:
-                start_live[op.result] = i
+            if op.result:
+                if op.result not in last_used and op.has_no_side_effect():
+                    continue
+                assert op.result not in produced
+                produced[op.result] = i
             for j in range(op.numargs()):
                 arg = op.getarg(j)
-                if isinstance(arg, Box):
-                    if arg not in start_live:
-                        not_implemented("Bogus arg in operation %d at %d" %
-                                        (op.getopnum(), i))
-                    longevity[arg] = (start_live[arg], i)
+                if isinstance(arg, Box) and arg not in last_used:
+                    last_used[arg] = i
             if op.is_guard():
                 for arg in op.getfailargs():
                     if arg is None: # hole
                         continue
                     assert isinstance(arg, Box)
-                    if arg not in start_live:
-                        not_implemented("Bogus arg in guard %d at %d" %
-                                        (op.getopnum(), i))
-                    longevity[arg] = (start_live[arg], i)
+                    if arg not in last_used:
+                        last_used[arg] = i
+                        
+        longevity = {}
+        for arg in produced:
+            if arg in last_used:
+                assert isinstance(arg, Box)
+                assert produced[arg] < last_used[arg]
+                longevity[arg] = (produced[arg], last_used[arg])
+                del last_used[arg]
         for arg in inputargs:
-            if arg not in longevity:
+            assert isinstance(arg, Box)
+            if arg not in last_used:
                 longevity[arg] = (-1, -1)
-        for arg in longevity:
-            assert isinstance(arg, Box)
+            else:
+                longevity[arg] = (0, last_used[arg])
+                del last_used[arg]
+        assert len(last_used) == 0
         return longevity
 
     def loc(self, v):
@@ -590,11 +595,15 @@
     consider_float_truediv = _consider_float_op
 
     def _consider_float_cmp(self, op, guard_op):
-        args = op.getarglist()
-        loc0 = self.xrm.make_sure_var_in_reg(op.getarg(0), args,
-                                             imm_fine=False)
-        loc1 = self.xrm.loc(op.getarg(1))
-        arglocs = [loc0, loc1]
+        vx = op.getarg(0)
+        vy = op.getarg(1)
+        arglocs = [self.loc(vx), self.loc(vy)]
+        if not (isinstance(arglocs[0], RegLoc) or
+                isinstance(arglocs[1], RegLoc)):
+            if isinstance(vx, Const):
+                arglocs[1] = self.xrm.make_sure_var_in_reg(vy)
+            else:
+                arglocs[0] = self.xrm.make_sure_var_in_reg(vx)
         self.xrm.possibly_free_vars_for_op(op)
         if guard_op is None:
             res = self.rm.force_allocate_reg(op.result, need_lower_byte=True)
@@ -620,7 +629,7 @@
         self.xrm.possibly_free_var(op.getarg(0))
 
     def consider_cast_float_to_int(self, op):
-        loc0 = self.xrm.make_sure_var_in_reg(op.getarg(0), imm_fine=False)
+        loc0 = self.xrm.make_sure_var_in_reg(op.getarg(0))
         loc1 = self.rm.force_allocate_reg(op.result)
         self.Perform(op, [loc0], loc1)
         self.xrm.possibly_free_var(op.getarg(0))
@@ -818,8 +827,7 @@
         # ^^^ we force loc_newvalue in a reg (unless it's a Const),
         # because it will be needed anyway by the following setfield_gc.
         # It avoids loading it twice from the memory.
-        loc_base = self.rm.make_sure_var_in_reg(op.getarg(0), args,
-                                                imm_fine=False)
+        loc_base = self.rm.make_sure_var_in_reg(op.getarg(0), args)
         arglocs = [loc_base, loc_newvalue]
         # add eax, ecx and edx as extra "arguments" to ensure they are
         # saved and restored.  Fish in self.rm to know which of these

diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -196,6 +196,18 @@
         return r_class(0)
 most_neg_value_of._annspecialcase_ = 'specialize:memo'
 
+def highest_bit(n):
+    """
+    Calculates the highest set bit in n.  This function assumes that n is a
+    power of 2 (and thus only has a single set bit).
+    """
+    assert n and (n & (n - 1)) == 0
+    i = -1
+    while n:
+        i += 1
+        n >>= 1
+    return i
+
 
 class base_int(long):
     """ fake unsigned integer implementation """

diff --git a/pypy/rlib/rbigint.py b/pypy/rlib/rbigint.py
--- a/pypy/rlib/rbigint.py
+++ b/pypy/rlib/rbigint.py
@@ -295,7 +295,6 @@
         else:
             result = _x_sub(other, self)
         result.sign *= other.sign
-        result._normalize()
         return result
 
     def sub(self, other):
@@ -555,7 +554,8 @@
         while i > 1 and self.digits[i - 1] == 0:
             i -= 1
         assert i >= 1
-        self.digits = self.digits[:i]
+        if i != self._numdigits():
+            self.digits = self.digits[:i]
         if self._numdigits() == 1 and self.digits[0] == 0:
             self.sign = 0
 

diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py
--- a/pypy/jit/backend/x86/rx86.py
+++ b/pypy/jit/backend/x86/rx86.py
@@ -534,6 +534,7 @@
     CDQ = insn(rex_nw, '\x99')
 
     TEST8_mi = insn(rex_w, '\xF6', orbyte(0<<3), mem_reg_plus_const(1), immediate(2, 'b'))
+    TEST8_ji = insn(rex_w, '\xF6', orbyte(0<<3), '\x05', immediate(1), immediate(2, 'b'))
     TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0')
 
     # x87 instructions

diff --git a/pypy/rpython/rint.py b/pypy/rpython/rint.py
--- a/pypy/rpython/rint.py
+++ b/pypy/rpython/rint.py
@@ -242,7 +242,7 @@
             # return r + y*(((x^y)<0)&(r!=0));
             v_xor = hop.genop(prefix + 'xor', vlist,
                             resulttype=repr)
-            v_xor_le = hop.genop(prefix + 'le', [v_xor, c_zero],
+            v_xor_le = hop.genop(prefix + 'lt', [v_xor, c_zero],
                                resulttype=Bool)
             v_xor_le = hop.llops.convertvar(v_xor_le, bool_repr, repr)
             v_mod_ne = hop.genop(prefix + 'ne', [v_res, c_zero],

diff --git a/pypy/jit/backend/x86/regloc.py b/pypy/jit/backend/x86/regloc.py
--- a/pypy/jit/backend/x86/regloc.py
+++ b/pypy/jit/backend/x86/regloc.py
@@ -3,7 +3,7 @@
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.jit.backend.x86.arch import WORD, IS_X86_32, IS_X86_64
 from pypy.tool.sourcetools import func_with_new_name
-from pypy.rlib.objectmodel import specialize
+from pypy.rlib.objectmodel import specialize, instantiate
 from pypy.rlib.rarithmetic import intmask
 from pypy.jit.metainterp.history import FLOAT
 
@@ -175,6 +175,19 @@
                 return edx
         return eax
 
+    def add_offset(self, ofs):
+        result = instantiate(AddressLoc)
+        result._location_code = self._location_code
+        if self._location_code == 'm':
+            result.loc_m = (self.loc_m[0], self.loc_m[1] + ofs)
+        elif self._location_code == 'a':
+            result.loc_a = self.loc_a[:3] + (self.loc_a[3] + ofs,)
+        elif self._location_code == 'j':
+            result.value = self.value + ofs
+        else:
+            raise AssertionError(self._location_code)
+        return result
+
 class ConstFloatLoc(AssemblerLocation):
     # XXX: We have to use this class instead of just AddressLoc because
     # we want a width of 8  (... I think.  Check this!)
@@ -190,6 +203,47 @@
     def location_code(self):
         return 'j'
 
+if IS_X86_32:
+    class FloatImmedLoc(AssemblerLocation):
+        # This stands for an immediate float.  It cannot be directly used in
+        # any assembler instruction.  Instead, it is meant to be decomposed
+        # in two 32-bit halves.  On 64-bit, FloatImmedLoc() is a function
+        # instead; see below.
+        _immutable_ = True
+        width = 8
+
+        def __init__(self, floatvalue):
+            from pypy.rlib.longlong2float import float2longlong
+            self.aslonglong = float2longlong(floatvalue)
+
+        def low_part(self):
+            return intmask(self.aslonglong)
+
+        def high_part(self):
+            assert IS_X86_32
+            return intmask(self.aslonglong >> 32)
+
+        def low_part_loc(self):
+            return ImmedLoc(self.low_part())
+
+        def high_part_loc(self):
+            return ImmedLoc(self.high_part())
+
+        def __repr__(self):
+            from pypy.rlib.longlong2float import longlong2float
+            floatvalue = longlong2float(self.aslonglong)
+            return '<FloatImmedLoc(%s)>' % (floatvalue,)
+
+        def location_code(self):
+            raise NotImplementedError
+
+if IS_X86_64:
+    def FloatImmedLoc(floatvalue):
+        from pypy.rlib.longlong2float import float2longlong
+        value = intmask(float2longlong(floatvalue))
+        return ImmedLoc(value)
+
+
 REGLOCS = [RegLoc(i, is_xmm=False) for i in range(16)]
 XMMREGLOCS = [RegLoc(i, is_xmm=True) for i in range(16)]
 eax, ecx, edx, ebx, esp, ebp, esi, edi, r8, r9, r10, r11, r12, r13, r14, r15 = REGLOCS

diff --git a/pypy/jit/metainterp/test/test_basic.py b/pypy/jit/metainterp/test/test_basic.py
--- a/pypy/jit/metainterp/test/test_basic.py
+++ b/pypy/jit/metainterp/test/test_basic.py
@@ -372,7 +372,7 @@
         self.check_loop_count(1)
         self.check_loops({'guard_true': 1,
                           'int_add': 2, 'int_sub': 1, 'int_gt': 1,
-                          'int_mul': 1,
+                          'int_lshift': 1,
                           'jump': 1})
 
     def test_loop_invariant_mul_bridge1(self):

diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -25,7 +25,7 @@
                                          X86_64_XMM_SCRATCH_REG,
                                          RegLoc, StackLoc, ConstFloatLoc,
                                          ImmedLoc, AddressLoc, imm,
-                                         imm0, imm1)
+                                         imm0, imm1, FloatImmedLoc)
 
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.jit.backend.x86 import rx86, regloc, codebuf
@@ -823,16 +823,22 @@
             self.mc.MOVZX8_rr(result_loc.value, rl.value)
         return genop_cmp
 
-    def _cmpop_float(cond, is_ne=False):
+    def _cmpop_float(cond, rev_cond, is_ne=False):
         def genop_cmp(self, op, arglocs, result_loc):
-            self.mc.UCOMISD(arglocs[0], arglocs[1])
+            if isinstance(arglocs[0], RegLoc):
+                self.mc.UCOMISD(arglocs[0], arglocs[1])
+                checkcond = cond
+            else:
+                self.mc.UCOMISD(arglocs[1], arglocs[0])
+                checkcond = rev_cond
+
             tmp1 = result_loc.lowest8bits()
             if IS_X86_32:
                 tmp2 = result_loc.higher8bits()
             elif IS_X86_64:
                 tmp2 = X86_64_SCRATCH_REG.lowest8bits()
 
-            self.mc.SET_ir(rx86.Conditions[cond], tmp1.value)
+            self.mc.SET_ir(rx86.Conditions[checkcond], tmp1.value)
             if is_ne:
                 self.mc.SET_ir(rx86.Conditions['P'], tmp2.value)
                 self.mc.OR8_rr(tmp1.value, tmp2.value)
@@ -996,12 +1002,12 @@
     genop_ptr_eq = genop_int_eq
     genop_ptr_ne = genop_int_ne
 
-    genop_float_lt = _cmpop_float('B')
-    genop_float_le = _cmpop_float('BE')
-    genop_float_ne = _cmpop_float('NE', is_ne=True)
-    genop_float_eq = _cmpop_float('E')
-    genop_float_gt = _cmpop_float('A')
-    genop_float_ge = _cmpop_float('AE')
+    genop_float_lt = _cmpop_float('B', 'A')
+    genop_float_le = _cmpop_float('BE', 'AE')
+    genop_float_ne = _cmpop_float('NE', 'NE', is_ne=True)
+    genop_float_eq = _cmpop_float('E', 'E')
+    genop_float_gt = _cmpop_float('A', 'B')
+    genop_float_ge = _cmpop_float('AE', 'BE')
 
     genop_uint_gt = _cmpop("A", "B")
     genop_uint_lt = _cmpop("B", "A")
@@ -1252,8 +1258,13 @@
             self.mc.MOV16(dest_addr, value_loc)
         elif size == 4:
             self.mc.MOV32(dest_addr, value_loc)
-        elif IS_X86_64 and size == 8:
-            self.mc.MOV(dest_addr, value_loc)
+        elif size == 8:
+            if IS_X86_64:
+                self.mc.MOV(dest_addr, value_loc)
+            else:
+                assert isinstance(value_loc, FloatImmedLoc)
+                self.mc.MOV(dest_addr, value_loc.low_part_loc())
+                self.mc.MOV(dest_addr.add_offset(4), value_loc.high_part_loc())
         else:
             not_implemented("save_into_mem size = %d" % size)
 
@@ -1913,8 +1924,13 @@
             cls = self.cpu.gc_ll_descr.has_write_barrier_class()
             assert cls is not None and isinstance(descr, cls)
         loc_base = arglocs[0]
-        self.mc.TEST8_mi((loc_base.value, descr.jit_wb_if_flag_byteofs),
-                descr.jit_wb_if_flag_singlebyte)
+        if isinstance(loc_base, RegLoc):
+            self.mc.TEST8_mi((loc_base.value, descr.jit_wb_if_flag_byteofs),
+                             descr.jit_wb_if_flag_singlebyte)
+        else:
+            assert isinstance(loc_base, ImmedLoc)
+            self.mc.TEST8_ji(loc_base.value + descr.jit_wb_if_flag_byteofs,
+                             descr.jit_wb_if_flag_singlebyte)
         self.mc.J_il8(rx86.Conditions['Z'], 0) # patched later
         jz_location = self.mc.get_relative_pos()
         # the following is supposed to be the slow path, so whenever possible


More information about the Pypy-commit mailing list