[pypy-svn] pypy jit-usable_retrace: propper overflow support (work in progress, curently broken)

hakanardo commits-noreply at bitbucket.org
Sun Mar 13 12:03:13 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-usable_retrace
Changeset: r42552:1f9c0df1bc07
Date: 2011-03-13 09:39 +0100
http://bitbucket.org/pypy/pypy/changeset/1f9c0df1bc07/

Log:	propper overflow support (work in progress, curently broken)

diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -493,9 +493,14 @@
         op = self.optimizer.producer[box]
 
         ok = False
-        if op.is_always_pure() or op.is_ovf():
+        if op.is_always_pure():
             ok = True
-            # FIXME: Allow getitems if they are still in the heap cache
+        elif op.is_ovf() and op in self.optimizer.overflow_guarded:
+            ok = True
+        elif op.has_no_side_effect():
+            # FIXME: When are these safe to include? Allow getitems only
+            # if they are still in the heap cache?
+            ok = True
         elif op.getopnum() == rop.CALL:
             effectinfo = op.getdescr().get_extra_info()
             if effectinfo.extraeffect == EffectInfo.EF_LOOPINVARIANT:
@@ -507,7 +512,11 @@
                 self.produce_box_in_short_preamble(arg)
             if self.short_operations is not None:
                 self.short_operations.append(op)
+                guard = ResOperation(rop.GUARD_NO_OVERFLOW, [], None)
+                self.short_operations.append(guard)
         else:
+            import pdb; pdb.set_trace()
+            
             self.short_operations = None
         
     def create_short_preamble(self, preamble, loop):

diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -9,13 +9,19 @@
     """Keeps track of the bounds placed on integers by guards and remove
        redundant guards"""
 
+    def __init__(self):
+        self.overflow_guarded = {}
+
     def setup(self):
         self.posponedop = None
         self.nextop = None
-
+        self.optimizer.overflow_guarded = self.overflow_guarded 
+        
     def reconstruct_for_next_iteration(self, optimizer, valuemap):
         assert self.posponedop is None
-        return self 
+        new = OptIntBounds()
+        new.overflow_guarded = self.optimizer.overflow_guarded
+        return new
 
     def propagate_forward(self, op):
         if op.is_ovf():
@@ -159,6 +165,7 @@
             if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
                 # Synthesize the non overflowing op for optimize_default to reuse
                 self.pure(rop.INT_ADD, op.getarglist()[:], op.result)
+                self.optimizer.overflow_guarded[op] = True
                 
 
     def optimize_INT_SUB_OVF(self, op):
@@ -178,6 +185,7 @@
             if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
                 # Synthesize the non overflowing op for optimize_default to reuse
                 self.pure(rop.INT_SUB, op.getarglist()[:], op.result)
+                self.optimizer.overflow_guarded[op] = True
             
     def optimize_INT_MUL_OVF(self, op):
         v1 = self.getvalue(op.getarg(0))
@@ -196,6 +204,7 @@
             if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
                 # Synthesize the non overflowing op for optimize_default to reuse
                 self.pure(rop.INT_MUL, op.getarglist()[:], op.result)
+                self.optimizer.overflow_guarded[op] = True
             
 
     def optimize_INT_LT(self, op):

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
@@ -379,7 +379,7 @@
                           'int_add': 1, 'int_sub': 1, 'int_gt': 1,
                           'jump': 1})
 
-    def test_loop_invariant_mul_ovf(self):
+    def test_loop_invariant_mul_ovf1(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
         def f(x, y):
             res = 0
@@ -398,6 +398,26 @@
                           'int_lshift': 1,
                           'jump': 1})
 
+    def test_loop_invariant_mul_ovf2(self):
+        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
+        def f(x, y):
+            res = 0
+            while y > 0:
+                myjitdriver.can_enter_jit(x=x, y=y, res=res)
+                myjitdriver.jit_merge_point(x=x, y=y, res=res)
+                b = y * 2
+                try:
+                    res += ovfcheck(x * x) + b
+                except OverflowError:
+                    res += 1
+                y -= 1
+            return res
+        res = self.meta_interp(f, [sys.maxint, 7])
+        assert res == f(sys.maxint, 7)
+        self.check_loop_count(1)
+        res = self.meta_interp(f, [6, 7])
+        assert res == 308
+
     def test_loop_invariant_mul_bridge1(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
         def f(x, y):
@@ -414,6 +434,43 @@
         assert res == 3427
         self.check_loop_count(3)
 
+    def test_loop_invariant_mul_bridge_ovf1(self):
+        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x1', 'x2'])
+        def f(x1, x2, y):
+            res = 0
+            while y > 0:
+                myjitdriver.can_enter_jit(x1=x1, x2=x2, y=y, res=res)
+                myjitdriver.jit_merge_point(x1=x1, x2=x2, y=y, res=res)
+                try:
+                    res += ovfcheck(x1 * x1)
+                except OverflowError:
+                    res += 1
+                if y<32 and (y>>2)&1==0:
+                    x1, x2 = x2, x1
+                y -= 1
+            return res
+        res = self.meta_interp(f, [6, sys.maxint, 48])
+        assert res == f(6, sys.maxint, 48)
+
+    def test_loop_invariant_mul_bridge_ovf2(self):
+        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x1', 'x2', 'n'])
+        def f(x1, x2, n, y):
+            res = 0
+            while y > 0:
+                myjitdriver.can_enter_jit(x1=x1, x2=x2, y=y, res=res, n=n)
+                myjitdriver.jit_merge_point(x1=x1, x2=x2, y=y, res=res, n=n)
+                try:
+                    res += ovfcheck(x1 * x1)
+                except OverflowError:
+                    res += 1
+                #if y<n and (y>>2)&1==0:
+                y -= 1
+                if (y>>2)&1==0:
+                    x1, x2 = x2, x1
+            return res
+        res = self.meta_interp(f, [6, sys.maxint, 32, 48])
+        assert res == f(6, sys.maxint, 32, 48)
+
     def test_loop_invariant_mul_bridge_maintaining1(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
         def f(x, y):

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
@@ -13,8 +13,11 @@
        This includes already executed operations and constants.
     """
 
-    def reconstruct_for_next_iteration(self, optimizer, valuemap):
-        return self
+    def setup(self):
+        pass
+
+    def reconstruct_for_next_iteration(self, optimizer, valuemap):        
+        return OptRewrite()
     
     def propagate_forward(self, op):
         args = self.optimizer.make_args_key(op)


More information about the Pypy-commit mailing list