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

cfbolz at codespeak.net cfbolz at codespeak.net
Sun Jan 24 20:19:23 CET 2010


Author: cfbolz
Date: Sun Jan 24 20:19:22 2010
New Revision: 70806

Modified:
   pypy/trunk/pypy/jit/metainterp/optimizeopt.py
   pypy/trunk/pypy/jit/metainterp/optimizeutil.py
   pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
Log:
Finally I found a good reason to have folding of pure ops with identical
arguments:

When using generators, the residual code of the function using the generator is
handling the generator frame. Doing this produces many oois instructions, that
check again and again whether the generator frame is the virtualizable or not.


Modified: pypy/trunk/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/optimizeopt.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/optimizeopt.py	Sun Jan 24 20:19:22 2010
@@ -11,7 +11,7 @@
 from pypy.jit.metainterp.specnode import VirtualStructSpecNode
 from pypy.jit.metainterp.optimizeutil import _findall, sort_descrs
 from pypy.jit.metainterp.optimizeutil import descrlist_dict
-from pypy.jit.metainterp.optimizeutil import InvalidLoop
+from pypy.jit.metainterp.optimizeutil import InvalidLoop, args_dict
 from pypy.jit.metainterp import resume, compile
 from pypy.jit.metainterp.typesystem import llhelper, oohelper
 from pypy.rlib.objectmodel import we_are_translated
@@ -389,6 +389,7 @@
         self.heap_op_optimizer = HeapOpOptimizer(self)
         self.bool_boxes = {}
         self.loop_invariant_results = {}
+        self.pure_operations = args_dict()
 
     def forget_numberings(self, virtualbox):
         self.metainterp_sd.profiler.count(jitprof.OPT_FORCINGS)
@@ -571,6 +572,23 @@
                 resbox = execute_nonspec(self.cpu, op.opnum, argboxes, op.descr)
                 self.make_constant(op.result, resbox.constbox())
                 return
+
+            if op.descr is None:
+                # did we do the exact same operation already?
+                args = op.args[:]
+                for i in range(len(args)):
+                    arg = args[i]
+                    if arg in self.values:
+                        args[i] = self.values[arg].get_key_box()
+                args.append(ConstInt(op.opnum))
+                oldop = self.pure_operations.get(args, None)
+                if oldop is not None:
+                    assert oldop.opnum == op.opnum
+                    self.make_equal_to(op.result, self.getvalue(oldop.result))
+                    return
+                else:
+                    self.pure_operations[args] = op
+
         # otherwise, the operation remains
         self.emit_operation(op)
 
@@ -700,7 +718,7 @@
         elif value.is_null():
             self.make_constant_int(op.result, not expect_nonnull)
         else:
-            self.emit_operation(op)
+            self.optimize_default(op)
 
     def optimize_INT_IS_TRUE(self, op):
         self._optimize_nullness(op, op.args[0], True)

Modified: pypy/trunk/pypy/jit/metainterp/optimizeutil.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/optimizeutil.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/optimizeutil.py	Sun Jan 24 20:19:22 2010
@@ -1,7 +1,7 @@
 from pypy.rlib.objectmodel import r_dict, compute_identity_hash
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.unroll import unrolling_iterable
-from pypy.jit.metainterp import resoperation
+from pypy.jit.metainterp import resoperation, history
 
 class InvalidLoop(Exception):
     """Raised when the optimize*.py detect that the loop that
@@ -59,3 +59,35 @@
 def descrlist_dict():
     return r_dict(descrlist_eq, descrlist_hash)
 
+# ____________________________________________________________
+
+def args_eq(args1, args2):
+    if len(args1) != len(args2):
+        return False
+    for i in range(len(args1)):
+        arg1 = args1[i]
+        arg2 = args2[i]
+        if isinstance(arg1, history.Const):
+            if arg1.__class__ is not arg2.__class__:
+                return False
+            if not arg1.same_constant(arg2):
+                return False
+        else:
+            if not arg1 is arg2:
+                return False
+    return True
+
+def args_hash(args):
+    res = 0x345678
+    for arg in args:
+        if isinstance(arg, history.Const):
+            y = arg._get_hash_()
+        else:
+            y = compute_identity_hash(arg)
+        res = intmask((1000003 * res) ^ y)
+    return res
+
+def args_dict():
+    return r_dict(args_eq, args_hash)
+
+

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	Sun Jan 24 20:19:22 2010
@@ -1861,6 +1861,36 @@
         """
         self.optimize_loop(ops, "Not", expected)
 
+    def test_remove_duplicate_pure_op(self):
+        ops = """
+        [p1, p2]
+        i1 = oois(p1, p2)
+        i2 = oois(p1, p2)
+        i3 = int_add(i1, 1)
+        i3b = int_is_true(i3)
+        guard_true(i3b) []
+        i4 = int_add(i2, 1)
+        i4b = int_is_true(i4)
+        guard_true(i4b) []
+        escape(i3)
+        escape(i4)
+        guard_true(i1) []
+        guard_true(i2) []
+        jump(p1, p2)
+        """
+        expected = """
+        [p1, p2]
+        i1 = oois(p1, p2)
+        i3 = int_add(i1, 1)
+        i3b = int_is_true(i3)
+        guard_true(i3b) []
+        escape(i3)
+        escape(i3)
+        guard_true(i1) []
+        jump(p1, p2)
+        """
+        self.optimize_loop(ops, "Not, Not", expected)
+
     # ----------
 
     def make_fail_descr(self):



More information about the Pypy-commit mailing list