[pypy-svn] r76655 - in pypy/trunk/pypy/jit/metainterp: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Tue Aug 17 16:57:52 CEST 2010


Author: cfbolz
Date: Tue Aug 17 16:57:51 2010
New Revision: 76655

Modified:
   pypy/trunk/pypy/jit/metainterp/executor.py
   pypy/trunk/pypy/jit/metainterp/optimizeopt.py
   pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
Log:
(cfbolz, arigo checking): constant-fold ovf operations


Modified: pypy/trunk/pypy/jit/metainterp/executor.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/executor.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/executor.py	Tue Aug 17 16:57:51 2010
@@ -172,34 +172,36 @@
                   [x1box.getref_base(), x2box.getref_base()], None)
 
 def do_int_add_ovf(cpu, metainterp, box1, box2):
-    assert metainterp is not None
+    # the overflow operations can be called without a metainterp, if an
+    # overflow cannot occur
     a = box1.getint()
     b = box2.getint()
     try:
         z = ovfcheck(a + b)
     except OverflowError:
+        assert metainterp is not None
         metainterp.execute_raised(OverflowError(), constant=True)
         z = 0
     return BoxInt(z)
 
 def do_int_sub_ovf(cpu, metainterp, box1, box2):
-    assert metainterp is not None
     a = box1.getint()
     b = box2.getint()
     try:
         z = ovfcheck(a - b)
     except OverflowError:
+        assert metainterp is not None
         metainterp.execute_raised(OverflowError(), constant=True)
         z = 0
     return BoxInt(z)
 
 def do_int_mul_ovf(cpu, metainterp, box1, box2):
-    assert metainterp is not None
     a = box1.getint()
     b = box2.getint()
     try:
         z = ovfcheck(a * b)
     except OverflowError:
+        assert metainterp is not None
         metainterp.execute_raised(OverflowError(), constant=True)
         z = 0
     return BoxInt(z)

Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/optimizeopt.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/optimizeopt.py	Tue Aug 17 16:57:51 2010
@@ -526,7 +526,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]
             opnum = op.opnum
             for value, func in optimize_ops:
                 if opnum == value:
@@ -534,6 +536,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)
@@ -588,7 +591,12 @@
                 descr.make_a_counter_per_value(op)
 
     def optimize_default(self, op):
-        if op.is_always_pure():
+        canfold = op.is_always_pure()
+        is_ovf = op.is_ovf()
+        if is_ovf:
+            nextop = self.loop.operations[self.i + 1]
+            canfold = nextop.opnum == rop.GUARD_NO_OVERFLOW
+        if canfold:
             for arg in op.args:
                 if self.get_constant_box(arg) is None:
                     break
@@ -598,6 +606,8 @@
                 resbox = execute_nonspec(self.cpu, None,
                                          op.opnum, argboxes, op.descr)
                 self.make_constant(op.result, resbox.constbox())
+                if is_ovf:
+                    self.i += 1 # skip next operation, it is the unneeded guard
                 return
 
             # did we do the exact same operation already?
@@ -611,6 +621,8 @@
             if oldop is not None and oldop.descr is op.descr:
                 assert oldop.opnum == op.opnum
                 self.make_equal_to(op.result, self.getvalue(oldop.result))
+                if is_ovf:
+                    self.i += 1 # skip next operation, it is the unneeded guard
                 return
             elif self.find_rewritable_bool(op, args):
                 return

Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py	Tue Aug 17 16:57:51 2010
@@ -285,6 +285,24 @@
         """
         self.optimize_loop(ops, '', expected)
 
+    def test_constant_propagate_ovf(self):
+        ops = """
+        []
+        i0 = int_add_ovf(2, 3)
+        guard_no_overflow() []
+        i1 = int_is_true(i0)
+        guard_true(i1) []
+        i2 = int_is_zero(i1)
+        guard_false(i2) []
+        guard_value(i0, 5) []
+        jump()
+        """
+        expected = """
+        []
+        jump()
+        """
+        self.optimize_loop(ops, '', expected)
+
     def test_constfold_all(self):
         from pypy.jit.backend.llgraph.llimpl import TYPES     # xxx fish
         from pypy.jit.metainterp.executor import execute_nonspec
@@ -2098,6 +2116,33 @@
         """
         self.optimize_loop(ops, 'Not', expected)
 
+    def test_remove_duplicate_pure_op_ovf(self):
+        ops = """
+        [i1]
+        i3 = int_add_ovf(i1, 1)
+        guard_no_overflow() []
+        i3b = int_is_true(i3)
+        guard_true(i3b) []
+        i4 = int_add_ovf(i1, 1)
+        guard_no_overflow() []
+        i4b = int_is_true(i4)
+        guard_true(i4b) []
+        escape(i3)
+        escape(i4)
+        jump(i1)
+        """
+        expected = """
+        [i1]
+        i3 = int_add_ovf(i1, 1)
+        guard_no_overflow() []
+        i3b = int_is_true(i3)
+        guard_true(i3b) []
+        escape(i3)
+        escape(i3)
+        jump(i1)
+        """
+        self.optimize_loop(ops, "Not", expected)
+
     def test_int_and_or_with_zero(self):
         ops = """
         [i0, i1]



More information about the Pypy-commit mailing list