[pypy-svn] r76661 - in pypy/branch/jit-bounds/pypy: jit/metainterp jit/metainterp/test module/pypyjit/test

hakanardo at codespeak.net hakanardo at codespeak.net
Wed Aug 18 07:33:29 CEST 2010


Author: hakanardo
Date: Wed Aug 18 07:33:27 2010
New Revision: 76661

Modified:
   pypy/branch/jit-bounds/pypy/jit/metainterp/optimizeopt.py
   pypy/branch/jit-bounds/pypy/jit/metainterp/test/test_optimizeopt.py
   pypy/branch/jit-bounds/pypy/module/pypyjit/test/test_pypy_c.py
Log:
Removing guard_no_overflow, intbound support for int_add_ovf, int_sub_ovf, int_and

Modified: pypy/branch/jit-bounds/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/branch/jit-bounds/pypy/jit/metainterp/optimizeopt.py	(original)
+++ pypy/branch/jit-bounds/pypy/jit/metainterp/optimizeopt.py	Wed Aug 18 07:33:27 2010
@@ -19,6 +19,10 @@
 from pypy.jit.metainterp.history import AbstractDescr, make_hashable_int
 from pypy.rlib.rarithmetic import ovfcheck
 
+import sys
+MAXINT = sys.maxint
+MININT = -sys.maxint - 1
+
 def optimize_loop_1(metainterp_sd, loop):
     """Optimize loop.operations to make it match the input of loop.specnodes
     and to remove internal overheadish operations.  Note that loop.specnodes
@@ -118,25 +122,37 @@
     def add_bound(self, other):
         res = self.copy()
         if other.has_upper:
-            res.upper += other.upper
+            try:
+                res.upper = ovfcheck(res.upper + other.upper)
+            except OverflowError:
+                res.has_upper = False
         else:
             res.has_upper = False
         if other.has_lower:
-            res.lower += other.lower
+            try:
+                res.lower = ovfcheck(res.lower + other.lower)
+            except OverflowError:
+                res.has_lower = False            
         else:
             res.has_lower = False
         return res
 
     def sub_bound(self, other):
         res = self.copy()
-        if other.has_upper:
-            res.lower -= other.upper
-        else:
-            res.has_lower = False
         if other.has_lower:
-            res.upper -= other.lower
+            try:
+                res.upper = ovfcheck(res.upper - other.lower)
+            except OverflowError:
+                res.has_upper = False
         else:
             res.has_upper = False
+        if other.has_upper:
+            try:
+                res.lower = ovfcheck(res.lower - other.upper)
+            except OverflowError:
+                res.has_lower = False            
+        else:
+            res.has_lower = False
         return res
 
     def contains(self, val):
@@ -201,7 +217,7 @@
 
     def __init__(self, box):
         self.box = box
-        self.intbound = IntUnbounded()
+        self.intbound = IntBound(MININT, MAXINT) #IntUnbounded()
         if isinstance(box, Const):
             self.make_constant(box)
         # invariant: box is a Const if and only if level == LEVEL_CONSTANT
@@ -678,7 +694,9 @@
     def propagate_forward(self):
         self.exception_might_have_happened = False
         self.newoperations = []
-        for op in self.loop.operations:
+        self.i = 0
+        while self.i < len(self.loop.operations):
+            op = self.loop.operations[self.i]
             self.producer[op.result] = op
             opnum = op.opnum
             for value, func in optimize_ops:
@@ -687,6 +705,7 @@
                     break
             else:
                 self.optimize_default(op)
+            self.i += 1
         self.loop.operations = self.newoperations
         # accumulate counters
         self.resumedata_memo.update_counters(self.metainterp_sd.profiler)
@@ -757,7 +776,7 @@
             arg = args[i]
             if arg in self.values:
                 args[i] = self.values[arg].get_key_box()
-            args.append(ConstInt(op.opnum))
+        args.append(ConstInt(op.opnum))
         return args
             
     def optimize_default(self, op):
@@ -1199,6 +1218,15 @@
             self.make_constant_int(op.result, 0)
         else:
             self.optimize_default(op)
+            r = self.getvalue(op.result)
+            if v2.is_constant():
+                val = v2.box.getint()
+                if val >= 0:
+                    r.intbound.intersect(IntBound(0,val))
+            elif v1.is_constant():
+                val = v1.box.getint()
+                if val >= 0:
+                    r.intbound.intersect(IntBound(0,val))
 
     def optimize_INT_OR(self, op):
         v1 = self.getvalue(op.args[0])
@@ -1209,6 +1237,10 @@
             self.make_equal_to(op.result, v1)
         else:
             self.optimize_default(op)
+
+    def pure(self, opnum, args, result):
+        op = ResOperation(opnum, args, result)
+        self.pure_operations[self.make_args_key(op)] = op 
     
     def optimize_INT_SUB(self, op):
         v1 = self.getvalue(op.args[0])
@@ -1218,8 +1250,11 @@
         else:
             self.optimize_default(op)
         r = self.getvalue(op.result)
-        print v1.intbound.sub_bound(v2.intbound)
         r.intbound.intersect(v1.intbound.sub_bound(v2.intbound))
+
+        # Synthesize the reverse ops for optimize_default to reuse
+        self.pure(rop.INT_ADD, [op.result, op.args[1]], op.args[0])
+        self.pure(rop.INT_SUB, [op.args[0], op.result], op.args[1])
     
     def optimize_INT_ADD(self, op):
         v1 = self.getvalue(op.args[0])
@@ -1235,13 +1270,38 @@
         r.intbound.intersect(v1.intbound.add_bound(v2.intbound))
 
         # Synthesize the reverse op for optimize_default to reuse
-        revop = ResOperation(rop.INT_SUB, [op.result, op.args[1]], \
-                             op.args[0], op.descr)
-        self.pure_operations[self.make_args_key(revop)] = revop            
-        revop = ResOperation(rop.INT_SUB, [op.result, op.args[0]], \
-                             op.args[1], op.descr)
-        self.pure_operations[self.make_args_key(revop)] = revop            
+        self.pure(rop.INT_SUB, [op.result, op.args[1]], op.args[0])
+        self.pure(rop.INT_SUB, [op.result, op.args[0]], op.args[1])
 
+    def optimize_INT_ADD_OVF(self, op):
+        v1 = self.getvalue(op.args[0])
+        v2 = self.getvalue(op.args[1])
+        resbound = v1.intbound.add_bound(v2.intbound)
+        if resbound.has_lower and resbound.has_upper and \
+               self.loop.operations[self.i+1].opnum == rop.GUARD_NO_OVERFLOW:
+            # Transform into INT_SUB and remove guard
+            op.opnum = rop.INT_ADD
+            self.i += 1
+            self.optimize_INT_ADD(op)
+        else:
+            self.optimize_default(op)
+            r = self.getvalue(op.result)
+            r.intbound.intersect(resbound)
+        
+    def optimize_INT_SUB_OVF(self, op):
+        v1 = self.getvalue(op.args[0])
+        v2 = self.getvalue(op.args[1])
+        resbound = v1.intbound.sub_bound(v2.intbound)
+        if resbound.has_lower and resbound.has_upper and \
+               self.loop.operations[self.i+1].opnum == rop.GUARD_NO_OVERFLOW:
+            # Transform into INT_SUB and remove guard
+            op.opnum = rop.INT_SUB
+            self.i += 1
+            self.optimize_INT_SUB(op)
+        else:
+            self.optimize_default(op)
+            r = self.getvalue(op.result)
+            r.intbound.intersect(resbound)
 
     def optimize_INT_LT(self, op):
         v1 = self.getvalue(op.args[0])
@@ -1360,6 +1420,9 @@
         # b = r.intbound.sub_bound(v1.intbound).mul(-1)
         # if v2.intbound.intersect(b):
 
+    propagate_bounds_INT_ADD_OVF  = propagate_bounds_INT_ADD
+    propagate_bounds_INT_SUB_OVF  = propagate_bounds_INT_SUB
+
 optimize_ops = _findall(Optimizer, 'optimize_')
 propagate_bounds_ops = _findall(Optimizer, 'propagate_bounds_')
 

Modified: pypy/branch/jit-bounds/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/jit-bounds/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/branch/jit-bounds/pypy/jit/metainterp/test/test_optimizeopt.py	Wed Aug 18 07:33:27 2010
@@ -3169,6 +3169,47 @@
         """
         self.optimize_loop(ops, 'Not', expected)
         
+    def test_bound_lt_add_ovf(self):
+        ops = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        i2 = int_add_ovf(i0, 10)
+        guard_no_overflow() []
+        i3 = int_lt(i2, 15)
+        guard_true(i3) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_lt(i0, 4)
+        guard_true(i1) []
+        i2 = int_add(i0, 10)        
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
+    def test_bound_lt_add_ovf_before(self):
+        ops = """
+        [i0]
+        i2 = int_add_ovf(i0, 10)
+        guard_no_overflow() []
+        i3 = int_lt(i2, 15)
+        guard_true(i3) []
+        i1 = int_lt(i0, 6)
+        guard_true(i1) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i2 = int_add_ovf(i0, 10)
+        guard_no_overflow() []
+        i3 = int_lt(i2, 15)
+        guard_true(i3) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+        
     def test_bound_lt_sub(self):
         ops = """
         [i0]
@@ -3292,6 +3333,79 @@
         """
         self.optimize_loop(ops, 'Not', expected)
 
+    def test_bound_ovf(self):
+        ops = """
+        [i0]
+        i1 = int_ge(i0, 0)
+        guard_true(i1) []
+        i2 = int_lt(i0, 10)
+        guard_true(i2) []
+        i3 = int_add_ovf(i0, 1)
+        guard_no_overflow() []
+        jump(i3)
+        """
+        expected = """
+        [i0]
+        i1 = int_ge(i0, 0)
+        guard_true(i1) []
+        i2 = int_lt(i0, 10)
+        guard_true(i2) []
+        i3 = int_add(i0, 1)
+        jump(i3)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_addsub_const(self):
+        ops = """
+        [i0]
+        i1 = int_add(i0, 1)
+        i2 = int_sub(i1, 1)
+        i3 = int_add(i2, 1)
+        i4 = int_mul(i2, i3)
+        jump(i4)
+        """
+        expected = """
+        [i0]
+        i1 = int_add(i0, 1)
+        i4 = int_mul(i0, i1)
+        jump(i4)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_addsub_int(self):
+        ops = """
+        [i0, i10]
+        i1 = int_add(i0, i10)
+        i2 = int_sub(i1, i10)
+        i3 = int_add(i2, i10)
+        i4 = int_add(i2, i3)
+        jump(i4, i10)
+        """
+        expected = """
+        [i0, i10]
+        i1 = int_add(i0, i10)
+        i4 = int_add(i0, i1)
+        jump(i4, i10)
+        """
+        self.optimize_loop(ops, 'Not, Not', expected)
+
+    def test_addsub_int2(self):
+        ops = """
+        [i0, i10]
+        i1 = int_add(i10, i0)
+        i2 = int_sub(i1, i10)
+        i3 = int_add(i10, i2)
+        i4 = int_add(i2, i3)
+        jump(i4, i10)
+        """
+        expected = """
+        [i0, i10]
+        i1 = int_add(i10, i0)
+        i4 = int_add(i0, i1)
+        jump(i4, i10)
+        """
+        self.optimize_loop(ops, 'Not, Not', expected)
+
     def test_framestackdepth_overhead(self):
         ops = """
         [p0, i22]
@@ -3321,6 +3435,115 @@
         jump(p0, i22)
         """
         self.optimize_loop(ops, 'Not, Not', expected)
+
+    def test_addsub_ovf(self):
+        ops = """
+        [i0]
+        i1 = int_add_ovf(i0, 10)
+        guard_no_overflow() []
+        i2 = int_sub_ovf(i1, 5)
+        guard_no_overflow() []
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        i1 = int_add_ovf(i0, 10)
+        guard_no_overflow() []
+        i2 = int_sub(i1, 5)
+        jump(i2)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_subadd_ovf(self):
+        ops = """
+        [i0]
+        i1 = int_sub_ovf(i0, 10)
+        guard_no_overflow() []
+        i2 = int_add_ovf(i1, 5)
+        guard_no_overflow() []
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        i1 = int_sub_ovf(i0, 10)
+        guard_no_overflow() []
+        i2 = int_add(i1, 5)
+        jump(i2)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_bound_and(self):
+        ops = """
+        [i0]
+        i1 = int_and(i0, 255)
+        i2 = int_lt(i1, 500)
+        guard_true(i2) []
+        i3 = int_le(i1, 255)
+        guard_true(i3) []
+        i4 = int_gt(i1, -1)
+        guard_true(i4) []
+        i5 = int_ge(i1, 0)
+        guard_true(i5) []
+        i6 = int_lt(i1, 0)
+        guard_false(i6) []
+        i7 = int_le(i1, -1)
+        guard_false(i7) []
+        i8 = int_gt(i1, 255)
+        guard_false(i8) []
+        i9 = int_ge(i1, 500)
+        guard_false(i9) []
+        i12 = int_lt(i1, 100)
+        guard_true(i12) []
+        i13 = int_le(i1, 90)
+        guard_true(i13) []
+        i14 = int_gt(i1, 10)
+        guard_true(i14) []
+        i15 = int_ge(i1, 20)
+        guard_true(i15) []        
+        jump(i1)
+        """
+        expected = """
+        [i0]
+        i1 = int_and(i0, 255)
+        i12 = int_lt(i1, 100)
+        guard_true(i12) []
+        i13 = int_le(i1, 90)
+        guard_true(i13) []
+        i14 = int_gt(i1, 10)
+        guard_true(i14) []
+        i15 = int_ge(i1, 20)
+        guard_true(i15) []        
+        jump(i1)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
+    def test_subsub_ovf(self):
+        ops = """
+        [i0]
+        i1 = int_sub_ovf(1, i0)
+        guard_no_overflow() []
+        i2 = int_gt(i1, 1)
+        guard_true(i2) []
+        i3 = int_sub_ovf(1, i0)
+        guard_no_overflow() []
+        i4 = int_gt(i3, 1)
+        guard_true(i4) []
+        jump(i0)
+        """
+        expected = """
+        [i0]
+        i1 = int_sub_ovf(1, i0)
+        guard_no_overflow() []
+        i2 = int_gt(i1, 1)
+        guard_true(i2) []
+        i3 = int_sub_ovf(1, i0)
+        guard_no_overflow() []
+        i4 = int_gt(i3, 1)
+        guard_true(i4) []
+        jump(i0)
+        """
+        self.optimize_loop(ops, 'Not', expected)
+
         
 
 

Modified: pypy/branch/jit-bounds/pypy/module/pypyjit/test/test_pypy_c.py
==============================================================================
--- pypy/branch/jit-bounds/pypy/module/pypyjit/test/test_pypy_c.py	(original)
+++ pypy/branch/jit-bounds/pypy/module/pypyjit/test/test_pypy_c.py	Wed Aug 18 07:33:27 2010
@@ -110,6 +110,7 @@
 
         if sys.platform.startswith('win'):
             py.test.skip("XXX this is not Windows-friendly")
+        print logfilepath
         child_stdout = os.popen('PYPYLOG=":%s" "%s" "%s"' % (
             logfilepath, self.pypy_c, filepath), 'r')
         result = child_stdout.read()
@@ -847,7 +848,7 @@
                 return intimg[i - 1]
             ''', maxops, ([tc], res))
 
-    def test_intbound(self):
+    def test_intbound_simple(self):
         ops = ('<', '>', '<=', '>=')
         nbr = (3, 7)
         for o1 in ops:
@@ -881,11 +882,12 @@
                             res[f(i)] += 1500
                         self.run_source(src, 220, ([], res))
 
-    def test_intbound_addsub(self):
+    def test_intbound_addsub_mix(self):
         tests = ('i > 4', 'i > 2', 'i + 1 > 2', '1 + i > 4',
                  'i - 1 > 1', '1 - i > 1', '1 - i < -3')
         for t1 in tests:
             for t2 in tests:
+                print t1, t2
                 src = '''
                 def f(i):
                     a, b = 3, 3
@@ -926,6 +928,16 @@
             return (a, b)
         ''', 48, ([], (2000, 2000)))
 
+    def test_intbound_sub_lt(self):
+        self.run_source('''
+        def main():
+            i, a, b = 0, 0, 0
+            while i < 2000:
+                if i - 10 < 1995:
+                    a += 1
+                i += 1
+            return (a, b)
+        ''', 38, ([], (2000, 0)))
 
     def test_intbound_addsub_ge(self):
         self.run_source('''
@@ -934,24 +946,38 @@
             while i < 2000:
                 if i + 5 >= 5:
                     a += 1
-                #if i - 1 >= -1:
                 if i - 1 >= -1:
                     b += 1
                 i += 1
             return (a, b)
-        ''', 0, ([], (2000, 2000)))
+        ''', 56, ([], (2000, 2000)))
 
-    def test_intbound_sub_lt(self):
+    def test_zeropadded(self):
         self.run_source('''
+        from array import array
+        class ZeroPadded(array):
+            def __new__(cls, l):
+                self = array.__new__(cls, 'd', range(l))
+                return self
+
+            def __getitem__(self, i):
+                if i < 0 or i >= self.__len__():
+                    return 0
+                return array.__getitem__(self, i)
+
+
         def main():
-            i, a, b = 0, 0, 0
-            while i < 2000:
-                if i - 10 < 1995:
-                    a += 1
+            buf = ZeroPadded(2000)
+            i = 10
+            sa = 0
+            while i < 2000 - 10:
+                sa += buf[i-2] + buf[i-1] + buf[i] + buf[i+1] + buf[i+2]
                 i += 1
-            return (a, b)
-        ''', 0, ([], (2000, 0)))
+            return sa
+
+        ''', 232, ([], 9895050.0))
 
+    # test_circular
 
 class AppTestJIT(PyPyCJITTests):
     def setup_class(cls):



More information about the Pypy-commit mailing list