[pypy-svn] pypy arm-backend-2: Merge default and update moved compute_vars_longevity

bivab commits-noreply at bitbucket.org
Fri Jan 14 12:55:44 CET 2011


Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r40665:a91dd51ccfca
Date: 2011-01-14 11:52 +0100
http://bitbucket.org/pypy/pypy/changeset/a91dd51ccfca/

Log:	Merge default and update moved compute_vars_longevity

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
@@ -353,38 +353,45 @@
 def compute_vars_longevity(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 compute_loop_consts(inputargs, jump, looptoken):
     if jump.getopnum() != rop.JUMP or jump.getdescr() is not looptoken:
         loop_consts = {}
@@ -395,6 +402,7 @@
                 loop_consts[inputargs[i]] = i
     return loop_consts
 
+
 def not_implemented(msg):
     os.write(2, '[llsupport/regalloc] %s\n' % msg)
     raise NotImplementedError(msg)

diff --git a/pypy/module/pypyjit/test/test_pypy_c.py b/pypy/module/pypyjit/test/test_pypy_c.py
--- a/pypy/module/pypyjit/test/test_pypy_c.py
+++ b/pypy/module/pypyjit/test/test_pypy_c.py
@@ -1378,6 +1378,98 @@
                         i += 1
                     return sa
                 ''', ops, ([a, b], r), count_debug_merge_point=False)
+
+    def test_revert_shift(self):
+        from sys import maxint
+        tests = []
+        for a in (1, 4, 8, 100):
+            for b in (-10, 10, -201, 201, -maxint/3, maxint/3):
+                for c in (-10, 10, -maxint/3, maxint/3):
+                    tests.append(([a, b, c], long(4000*(a+b+c))))
+        self.run_source('''
+        def main(a, b, c):
+            from sys import maxint
+            i = sa = 0
+            while i < 2000:
+                if 0 < a < 10: pass
+                if -100 < b < 100: pass
+                if -maxint/2 < c < maxint/2: pass
+                sa += (a<<a)>>a
+                sa += (b<<a)>>a
+                sa += (c<<a)>>a
+                sa += (a<<100)>>100
+                sa += (b<<100)>>100
+                sa += (c<<100)>>100
+                i += 1
+            return long(sa)
+        ''', 93, count_debug_merge_point=False, *tests)
+        
+    def test_division_to_rshift(self):
+        avalues = ('a', 'b', 7, -42, 8)
+        bvalues = ['b'] + range(-10, 0) + range(1,10)
+        code = ''
+        a1, b1, res1 = 10, 20, 0
+        a2, b2, res2 = 10, -20, 0
+        a3, b3, res3 = -10, -20, 0
+        def dd(a, b, aval, bval):
+            m = {'a': aval, 'b': bval}
+            if not isinstance(a, int):
+                a=m[a]
+            if not isinstance(b, int):
+                b=m[b]
+            return a/b
+        for a in avalues:
+            for b in bvalues:
+                code += '                sa += %s / %s\n' % (a, b)
+                res1 += dd(a, b, a1, b1)
+                res2 += dd(a, b, a2, b2)
+                res3 += dd(a, b, a3, b3)
+        self.run_source('''
+        def main(a, b):
+            i = sa = 0
+            while i < 2000:
+%s                
+                i += 1
+            return sa
+        ''' % code, 179, ([a1, b1], 2000 * res1),
+                         ([a2, b2], 2000 * res2),
+                         ([a3, b3], 2000 * res3),
+                         count_debug_merge_point=False)
+        
+    def test_mod(self):
+        py.test.skip('Results are correct, but traces 1902 times (on trunk too).')
+        avalues = ('a', 'b', 7, -42, 8)
+        bvalues = ['b'] + range(-10, 0) + range(1,10)
+        code = ''
+        a1, b1, res1 = 10, 20, 0
+        a2, b2, res2 = 10, -20, 0
+        a3, b3, res3 = -10, -20, 0
+        def dd(a, b, aval, bval):
+            m = {'a': aval, 'b': bval}
+            if not isinstance(a, int):
+                a=m[a]
+            if not isinstance(b, int):
+                b=m[b]
+            return a % b
+        for a in avalues:
+            for b in bvalues:
+                code += '                sa += %s %% %s\n' % (a, b)
+                res1 += dd(a, b, a1, b1)
+                res2 += dd(a, b, a2, b2)
+                res3 += dd(a, b, a3, b3)
+        self.run_source('''
+        def main(a, b):
+            i = sa = 0
+            while i < 2000:
+                if a > 0: pass
+                if 1 < b < 2: pass
+%s
+                i += 1
+            return sa
+        ''' % code, 0, ([a1, b1], 2000 * res1),
+                         ([a2, b2], 2000 * res2),
+                         ([a3, b3], 2000 * res3),
+                         count_debug_merge_point=False)
         
 
 class AppTestJIT(PyPyCJITTests):


diff --git a/pypy/jit/backend/arm/arch.py b/pypy/jit/backend/arm/arch.py
--- a/pypy/jit/backend/arm/arch.py
+++ b/pypy/jit/backend/arm/arch.py
@@ -8,6 +8,7 @@
 
 arm_int_div_sign = lltype.Ptr(lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
 def arm_int_div(a, b):
+    print 'DIV'
     return int(a/float(b))
 
 arm_uint_div_sign = lltype.Ptr(lltype.FuncType([lltype.Unsigned, lltype.Unsigned], lltype.Unsigned))

diff --git a/pypy/jit/tool/showstats.py b/pypy/jit/tool/showstats.py
--- a/pypy/jit/tool/showstats.py
+++ b/pypy/jit/tool/showstats.py
@@ -10,7 +10,6 @@
 
 def main(argv):
     log = logparser.parse_log_file(argv[0])
-    log_count_lines = open(argv[0] + '.count').readlines()
     parts = logparser.extract_category(log, "jit-log-opt-")
     for i, oplist in enumerate(parts):
         loop = parse(oplist, no_namespace=True, nonstrict=True)
@@ -28,7 +27,6 @@
             print "Loop #%d, length: %d, opcodes: %d, guards: %d" % (i, num_ops, num_dmp, num_guards)
         else:
             print "Loop #%d, length: %d, opcodes: %d, guards: %d, %f" % (i, num_ops, num_dmp, num_guards, num_ops/num_dmp)
-        print loop.comment, "run", log_count_lines[i].split(":")[1].strip(), "times"
         
 if __name__ == '__main__':
     main(sys.argv[1:])

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
@@ -342,7 +342,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/metainterp/optimizeopt/rewrite.py b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -4,6 +4,9 @@
 from pypy.jit.metainterp.optimizeutil import _findall
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.jit.codewriter.effectinfo import EffectInfo
+from pypy.jit.metainterp.optimizeopt.intutils import IntBound
+from pypy.rlib.rarithmetic import highest_bit
+
 
 class OptRewrite(Optimization):
     """Rewrite operations into equivalent, cheaper operations.
@@ -141,6 +144,14 @@
              (v2.is_constant() and v2.box.getint() == 0):
             self.make_constant_int(op.result, 0)
         else:
+            for lhs, rhs in [(v1, v2), (v2, v1)]:
+                # x & (x -1) == 0 is a quick test for power of 2
+                if (lhs.is_constant() and
+                    (lhs.box.getint() & (lhs.box.getint() - 1)) == 0):
+                    new_rhs = ConstInt(highest_bit(lhs.box.getint()))
+                    op = op.copy_and_change(rop.INT_LSHIFT, args=[rhs.box, new_rhs])
+                    break
+
             self.emit_operation(op)
 
     def optimize_CALL_PURE(self, op):
@@ -379,5 +390,17 @@
             return True # 0-length arraycopy
         return False
 
+    def optimize_INT_FLOORDIV(self, op):
+        v1 = self.getvalue(op.getarg(0))
+        v2 = self.getvalue(op.getarg(1))
+
+        if v1.intbound.known_ge(IntBound(0, 0)) and v2.is_constant():
+            val = v2.box.getint()
+            if val & (val - 1) == 0 and val > 0: # val == 2**shift
+                op = op.copy_and_change(rop.INT_RSHIFT,
+                                        args = [op.getarg(0), ConstInt(highest_bit(val))])
+        self.emit_operation(op)
+
+
 optimize_ops = _findall(OptRewrite, 'optimize_')
 optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')

diff --git a/pypy/module/pypyjit/policy.py b/pypy/module/pypyjit/policy.py
--- a/pypy/module/pypyjit/policy.py
+++ b/pypy/module/pypyjit/policy.py
@@ -7,7 +7,8 @@
                 modname == '__builtin__.abstractinst' or
                 modname == '__builtin__.interp_classobj' or
                 modname == '__builtin__.functional' or
-                modname == '__builtin__.descriptor'):
+                modname == '__builtin__.descriptor' or
+                modname == 'thread.os_local'):
             return True
         if '.' in modname:
             modname, _ = modname.split('.', 1)

diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -4035,8 +4035,110 @@
         """
         self.optimize_loop(ops, expected, preamble)
 
-
-
+    def test_division_to_rshift(self):
+        ops = """
+        [i1, i2]
+        it = int_gt(i1, 0) 
+        guard_true(it)[]
+        i3 = int_floordiv(i1, i2)
+        i4 = int_floordiv(2, i2)
+        i5 = int_floordiv(i1, 2)
+        i6 = int_floordiv(3, i2)
+        i7 = int_floordiv(i1, 3)
+        i8 = int_floordiv(4, i2)
+        i9 = int_floordiv(i1, 4)
+        i10 = int_floordiv(i1, 0)
+        i11 = int_floordiv(i1, 1)
+        i12 = int_floordiv(i2, 2)
+        i13 = int_floordiv(i2, 3)
+        i14 = int_floordiv(i2, 4)
+        jump(i5, i14)
+        """
+        expected = """
+        [i1, i2]
+        it = int_gt(i1, 0) 
+        guard_true(it)[]        
+        i3 = int_floordiv(i1, i2)
+        i4 = int_floordiv(2, i2)
+        i5 = int_rshift(i1, 1)
+        i6 = int_floordiv(3, i2)
+        i7 = int_floordiv(i1, 3)
+        i8 = int_floordiv(4, i2)
+        i9 = int_rshift(i1, 2)        
+        i10 = int_floordiv(i1, 0)
+        i11 = int_rshift(i1, 0)
+        i12 = int_floordiv(i2, 2)
+        i13 = int_floordiv(i2, 3)
+        i14 = int_floordiv(i2, 4)
+        jump(i5, i14)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_mul_to_lshift(self):
+        ops = """
+        [i1, i2]
+        i3 = int_mul(i1, 2)
+        i4 = int_mul(2, i2)
+        i5 = int_mul(i1, 32)
+        i6 = int_mul(i1, i2)
+        jump(i5, i6)
+        """
+        expected = """
+        [i1, i2]
+        i3 = int_lshift(i1, 1)
+        i4 = int_lshift(i2, 1)
+        i5 = int_lshift(i1, 5)
+        i6 = int_mul(i1, i2)
+        jump(i5, i6)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_lshift_rshift(self):
+        ops = """
+        [i1, i2, i2b, i1b]
+        i3 = int_lshift(i1, i2)
+        i4 = int_rshift(i3, i2)
+        i5 = int_lshift(i1, 2)
+        i6 = int_rshift(i5, 2)
+        i7 = int_lshift(i1, 100)
+        i8 = int_rshift(i7, 100)
+        i9 = int_lt(i1b, 100)
+        guard_true(i9) []
+        i10 = int_gt(i1b, -100)
+        guard_true(i10) []        
+        i13 = int_lshift(i1b, i2)
+        i14 = int_rshift(i13, i2)
+        i15 = int_lshift(i1b, 2)
+        i16 = int_rshift(i15, 2)
+        i17 = int_lshift(i1b, 100)
+        i18 = int_rshift(i17, 100)
+        i19 = int_eq(i1b, i16)
+        guard_true(i19) []
+        i20 = int_ne(i1b, i16)
+        guard_false(i20) []
+        jump(i2, i3, i1b, i2b)
+        """
+        expected = """
+        [i1, i2, i2b, i1b]
+        i3 = int_lshift(i1, i2)
+        i4 = int_rshift(i3, i2)
+        i5 = int_lshift(i1, 2)
+        i6 = int_rshift(i5, 2)
+        i7 = int_lshift(i1, 100)
+        i8 = int_rshift(i7, 100)
+        i9 = int_lt(i1b, 100)
+        guard_true(i9) []
+        i10 = int_gt(i1b, -100)
+        guard_true(i10) []        
+        i13 = int_lshift(i1b, i2)
+        i14 = int_rshift(i13, i2)
+        i15 = int_lshift(i1b, 2)
+        i17 = int_lshift(i1b, 100)
+        i18 = int_rshift(i17, 100)
+        jump(i2, i3, i1b, i2b)
+        """
+        self.optimize_loop(ops, expected)
+        
     def test_subsub_ovf(self):
         ops = """
         [i0]


More information about the Pypy-commit mailing list