[pypy-svn] r66417 - in pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp: . test

arigo at codespeak.net arigo at codespeak.net
Sun Jul 19 19:30:51 CEST 2009


Author: arigo
Date: Sun Jul 19 19:30:51 2009
New Revision: 66417

Modified:
   pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeopt.py
   pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeopt.py
Log:
Progress.  Implement GUARD_CLASS and replace the _consts dict
with an _equals mapping.


Modified: pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeopt.py	(original)
+++ pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/optimizeopt.py	Sun Jul 19 19:30:51 2009
@@ -17,43 +17,57 @@
 class Optimizer(object):
 
     def __init__(self):
-        # set of Boxes; the value is not stored in the dict, but can
-        # be accessed as the Box.getint() or get_().
-        self._consts = {}
+        self._equals = {}          # mapping Box -> Box-or-Const
+        self._known_classes = {}   # mapping Box -> ConstClass
 
-    def is_constant(self, box):
-        return isinstance(box, Const) or box in self._consts
+    def deref(self, box):
+        while box in self._equals:
+            # follow the chain: box -> box2 -> box3 -> ...
+            box2 = self._equals[box]
+            if box2 not in self._equals:
+                return box2
+            # compress the mapping one step (rare case)
+            box3 = self._equals[box2]
+            self._equals[box] = box3
+            box = box3
+        return box
 
     def make_constant(self, box):
         assert isinstance(box, Box)
-        self._consts[box] = box.constbox()
+        assert box not in self._equals
+        self._equals[box] = box.constbox()
 
-    def rename_argument(self, box):
-        return self._consts.get(box, box)
+    def has_constant_class(self, box):
+        return isinstance(box, Const) or box in self._known_classes
+
+    def make_constant_class(self, box, clsbox):
+        assert isinstance(box, Box)
+        assert isinstance(clsbox, Const)
+        self._known_classes[box] = clsbox
 
     # ----------
 
     def optimize(self, loop):
         self.newoperations = []
         for op in loop.operations:
-            opnum = op.opnum
+            op2 = op.clone()
+            op2.args = [self.deref(box) for box in op.args]
+            opnum = op2.opnum
             for value, func in optimize_ops:
                 if opnum == value:
-                    func(self, op)
+                    func(self, op2)
                     break
             else:
-                self.optimize_default(op)
+                self.optimize_default(op2)
         loop.operations = self.newoperations
 
     def emit_operation(self, op):
-        op2 = op.clone()
-        op2.args = [self.rename_argument(box) for box in op.args]
-        self.newoperations.append(op2)
+        self.newoperations.append(op)
 
     def optimize_default(self, op):
         if op.is_always_pure():
             for box in op.args:
-                if not self.is_constant(box):
+                if not isinstance(box, Const):
                     break
             else:
                 # all constant arguments: constant-fold away
@@ -63,23 +77,31 @@
         self.emit_operation(op)
 
     def optimize_GUARD_VALUE(self, op):
-        if self.is_constant(op.args[0]):
-            assert isinstance(op.args[1], Const)
-            assert self.rename_argument(op.args[0]).get_() == op.args[1].get_()
-        else:
+        assert isinstance(op.args[1], Const)
+        assert op.args[0].get_() == op.args[1].get_()
+        if not isinstance(op.args[0], Const):
             self.emit_operation(op)
+            self.make_constant(op.args[0])
 
     def optimize_GUARD_TRUE(self, op):
-        if self.is_constant(op.args[0]):
-            assert self.rename_argument(op.args[0]).getint()
-        else:
+        assert op.args[0].getint()
+        if not isinstance(op.args[0], Const):
             self.emit_operation(op)
+            self.make_constant(op.args[0])
 
     def optimize_GUARD_FALSE(self, op):
-        if self.is_constant(op.args[0]):
-            assert not self.rename_argument(op.args[0]).getint()
-        else:
+        assert not op.args[0].getint()
+        if not isinstance(op.args[0], Const):
+            self.emit_operation(op)
+            self.make_constant(op.args[0])
+
+    def optimize_GUARD_CLASS(self, op):
+        instbox = op.args[0]
+        clsbox = op.args[1]
+        # XXX should probably assert that the class is right
+        if not self.has_constant_class(instbox):
             self.emit_operation(op)
+            self.make_constant_class(instbox, clsbox)
 
 
 optimize_ops = _findall(Optimizer, 'optimize_')

Modified: pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/branch/pyjitpl5-optimize4/pypy/jit/metainterp/test/test_optimizeopt.py	Sun Jul 19 19:30:51 2009
@@ -3,6 +3,7 @@
                                                             OOtypeMixin,
                                                             BaseTest)
 from pypy.jit.metainterp.optimizeopt import optimize
+from pypy.jit.metainterp.resoperation import rop, opname
 from pypy.jit.metainterp.test.oparser import parse
 
 # ____________________________________________________________
@@ -67,7 +68,7 @@
         i0 = int_sub(i, 1)
         guard_value(i0, 0)
           fail(i0)
-        jump(i0)
+        jump(i)
         """
         self.optimize(ops, 'Not', ops)
 
@@ -91,6 +92,61 @@
         """
         self.optimize(ops, '', expected, i0=5, i1=1, i2=0)
 
+    def test_constfold_all(self):
+        for op in range(rop.INT_ADD, rop.BOOL_NOT+1):
+            try:
+                op = opname[op]
+            except KeyError:
+                continue
+            ops = """
+            []
+            i1 = %s(3, 2)
+            jump()
+            """ % op.lower()
+            expected = """
+            []
+            jump()
+            """
+            self.optimize(ops, '', expected)
+
+    # ----------
+
+    def test_remove_guard_class(self):
+        ops = """
+        [p0]
+        guard_class(p0, ConstClass(node_vtable))
+          fail()
+        guard_class(p0, ConstClass(node_vtable))
+          fail()
+        jump(p0)
+        """
+        expected = """
+        [p0]
+        guard_class(p0, ConstClass(node_vtable))
+          fail()
+        jump(p0)
+        """
+        self.optimize(ops, 'Not', expected)
+
+    def test_remove_consecutive_guard_value_constfold(self):
+        ops = """
+        [i0]
+        guard_value(i0, 0)
+          fail()
+        i1 = int_add(i0, 1)
+        guard_value(i1, 1)
+          fail()
+        i2 = int_add(i1, 2)
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        guard_value(i0, 0)
+            fail()
+        jump(3)
+        """
+        self.optimize(ops, 'Not', expected, i0=0, i1=1, i2=3)
+
 
 class TestLLtype(BaseTestOptimizeOpt, LLtypeMixin):
     pass



More information about the Pypy-commit mailing list