[pypy-svn] r65464 - in pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp: . test

fijal at codespeak.net fijal at codespeak.net
Wed May 27 23:27:06 CEST 2009


Author: fijal
Date: Wed May 27 23:27:02 2009
New Revision: 65464

Modified:
   pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py
   pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py
Log:
implement escape analysis (all startboxes do escape as of now)


Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/optimize2.py	Wed May 27 23:27:02 2009
@@ -13,7 +13,7 @@
     pass
 
 class InstanceNode(object):
-    def __init__(self, source, const=False):
+    def __init__(self, source, const=False, escaped=False):
         self.source = source
         if const:
             assert isinstance(source, Const)
@@ -24,10 +24,11 @@
         self.virtualized = False
         self.allocated_in_loop = False
         self.vdesc = None
+        self.escaped = escaped
 
     def __repr__(self):
         flags = ''
-        #if self.escaped:           flags += 'e'
+        if self.escaped:           flags += 'e'
         #if self.startbox:          flags += 's'
         if self.const:             flags += 'c'
         #if self.virtual:           flags += 'v'
@@ -41,11 +42,17 @@
     def __init__(self, opts):
         # NOT_RPYTHON
         self.optimizations = [[] for i in range(rop._LAST)]
+        self.find_nodes_funcs = [[] for i in range(rop._LAST)]
         for opt in opts:
             for opnum, name in opname.iteritems():
                 meth = getattr(opt, 'optimize_' + name.lower(), None)
                 if meth is not None:
                     self.optimizations[opnum].append(meth)
+        for opt in opts:
+            for opnum, name in opname.iteritems():
+                meth = getattr(opt, 'find_nodes_' + name.lower(), None)
+                if meth is not None:
+                    self.find_nodes_funcs[opnum].append(meth)
 
     def getnode(self, box):
         try:
@@ -54,7 +61,7 @@
             if isinstance(box, Const):
                 node = InstanceNode(box, const=True)
             else:
-                node = InstanceNode(box)
+                node = InstanceNode(box, escaped=True)
             self.nodes[box] = node
             return node
 
@@ -65,6 +72,13 @@
 
     def find_nodes(self):
         for op in self.loop.operations:
+            res = False
+            for f in self.find_nodes_funcs[op.opnum]:
+                res = f(op, self)
+                if res:
+                    break
+            if res:
+                continue
             if op.is_always_pure():
                 is_pure = True
                 for arg in op.args:
@@ -81,10 +95,13 @@
                         self.getnode(arg)
                 # default case
                 for box in op.args:
-                    self.getnode(box)
+                    node = self.getnode(box)
+                    if not op.has_no_side_effect() and not op.is_guard():
+                        node.escaped = True
             box = op.result
             if box is not None:
                 node = self.getnode(box)
+                node.escaped = False
                 if op.opnum == rop.NEW or op.opnum == rop.NEW_WITH_VTABLE:
                     node.allocated_in_loop = True
                 self.nodes[box] = node
@@ -190,11 +207,40 @@
 
 class SimpleVirtualizableOpt(object):
     @staticmethod
-    def optimize_guard_nonvirtualized(op, spec):
+    def find_nodes_setfield_gc(op, spec):
+        instnode = spec.getnode(op.args[0])
+        if not instnode.virtualized:
+            return False
+        field = op.descr
+        if field not in instnode.vdesc.virtuals:
+            return False
+        return True
+
+    @staticmethod
+    def find_nodes_getfield_gc(op, spec):
+        instnode = spec.getnode(op.args[0])
+        if not instnode.virtualized:
+            return False
+        field = op.descr
+        if field not in instnode.vdesc.virtuals:
+            return False
+        spec.getnode(op.result).virtualized = True
+        return False
+
+    @staticmethod
+    def find_nodes_setarrayitem_gc(op, spec):
+        return False
+
+    @staticmethod
+    def find_nodes_guard_nonvirtualized(op, spec):
         instnode = spec.getnode(op.args[0])
         if not instnode.allocated_in_loop:
             instnode.virtualized = True
             instnode.vdesc = op.vdesc
+        return False
+    
+    @staticmethod
+    def optimize_guard_nonvirtualized(op, spec):
         return True
 
     @staticmethod
@@ -210,7 +256,6 @@
             spec.nodes[op.result] = node
             return True
         node = spec.getnode(op.result)
-        node.virtualized = True
         instnode.cleanfields[field] = node
         return False
 
@@ -260,6 +305,12 @@
         d[field] = (fieldnode, op.descr)
         return True
 
+class SimpleVirtualOpt(object):
+    def optimize_new_with_vtable(op, spec):
+        xxx
+        node = spec.getnode(op.result)
+        node.escaped = False
+
 specializer = Specializer([SimpleVirtualizableOpt(),
                            ConsecutiveGuardClassRemoval()])
 

Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/metainterp/test/test_optimize2.py	Wed May 27 23:27:02 2009
@@ -9,7 +9,8 @@
 from pypy.jit.backend.llgraph import runner
 
 from pypy.jit.metainterp.optimize2 import (optimize_loop,
-     ConsecutiveGuardClassRemoval, Specializer, SimpleVirtualizableOpt)
+     ConsecutiveGuardClassRemoval, Specializer, SimpleVirtualizableOpt,
+     SimpleVirtualOpt)
 from pypy.jit.metainterp.test.test_optimize import ANY
 
 from pypy.jit.metainterp.test.oparser import parse
@@ -309,6 +310,72 @@
         self.assert_equal(self.optimize(pre_op, [SimpleVirtualizableOpt()]),
                           expected)
 
+    def test_escape_analysis(self):
+        ops = """
+        [i0]
+        i1 = int_add(i0, i0)
+        """
+        spec = Specializer([])
+        loop = self.parse(ops)
+        optimize_loop(None, [], loop, self.cpu, spec=spec)
+        assert spec.nodes[loop.operations[0].args[0]].escaped
+        ops = """
+        [p0]
+        i1 = getfield_gc(p0, descr=field_desc)
+        i2 = int_add(i1, i1)
+        """
+        spec = Specializer([])
+        loop = self.parse(ops)
+        optimize_loop(None, [], loop, self.cpu, spec=spec)
+        assert not spec.nodes[loop.operations[0].result].escaped
+        ops = """
+        [p0]
+        i1 = getfield_gc(p0, descr=field_desc)
+        fail(i1)
+        """
+        spec = Specializer([])
+        loop = self.parse(ops)
+        optimize_loop(None, [], loop, self.cpu, spec=spec)
+        assert spec.nodes[loop.operations[0].result].escaped
+        ops = """
+        [p0]
+        i1 = getfield_gc(p0, descr=field_desc)
+        guard_true(i1)
+            fail()
+        """
+        spec = Specializer([])
+        loop = self.parse(ops)
+        optimize_loop(None, [], loop, self.cpu, spec=spec)
+        assert not spec.nodes[loop.operations[0].result].escaped
+
+    def test_escape_analysis_on_virtualizable(self):
+        ops = """
+        [p0]
+        guard_nonvirtualized(p0, vdesc=vdesc)
+            fail()
+        i1 = getfield_gc(p0, descr=field_desc)
+        setfield_gc(p0, i1, descr=field_desc)
+        i2 = int_add(i1, i1)
+        """
+        spec = Specializer([SimpleVirtualizableOpt()])
+        loop = self.parse(ops)
+        optimize_loop(None, [], loop, self.cpu, spec=spec)
+        assert not spec.nodes[loop.operations[0].result].escaped
+
+#     def test_simple_virtual(self):
+#         pre_op = """
+#         []
+#         p0 = new_with_vtable(13, ConstClass(node_vtable))
+#         setfield_gc(p0, 1, descr=field_desc)
+#         i2 = getfield_gc(p0, descr=field_desc)
+#         fail(i2)
+#         """
+#         expected = """
+#         []
+#         fail(1)
+#         """
+#         self.assert_equal(self.optimize(pre_op, [SimpleVirtualOpt()]),
+#                                         expected)
 
 class TestLLtype(LLtypeMixin, BaseTestOptimize2):
     pass



More information about the Pypy-commit mailing list