[pypy-svn] r69330 - in pypy/trunk/pypy: config translator/backendopt translator/backendopt/test

fijal at codespeak.net fijal at codespeak.net
Tue Nov 17 08:56:12 CET 2009


Author: fijal
Date: Tue Nov 17 08:56:11 2009
New Revision: 69330

Added:
   pypy/trunk/pypy/translator/backendopt/storesink.py   (contents, props changed)
   pypy/trunk/pypy/translator/backendopt/test/test_storesink.py   (contents, props changed)
Modified:
   pypy/trunk/pypy/config/translationoption.py
   pypy/trunk/pypy/translator/backendopt/all.py
Log:
implement extremely dummy store sinking (well, for starters
reading only)


Modified: pypy/trunk/pypy/config/translationoption.py
==============================================================================
--- pypy/trunk/pypy/config/translationoption.py	(original)
+++ pypy/trunk/pypy/config/translationoption.py	Tue Nov 17 08:56:11 2009
@@ -246,7 +246,7 @@
                    "Tranform graphs in SSI form into graphs tailored for "
                    "stack based virtual machines (only for backends that support it)",
                    default=True),
-
+        BoolOption("storesink", "Perform store sinking", default=False),
         BoolOption("none",
                    "Do not run any backend optimizations",
                    requires=[('translation.backendopt.inline', False),

Modified: pypy/trunk/pypy/translator/backendopt/all.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/all.py	(original)
+++ pypy/trunk/pypy/translator/backendopt/all.py	Tue Nov 17 08:56:11 2009
@@ -10,6 +10,7 @@
 from pypy.translator.backendopt.removeassert import remove_asserts
 from pypy.translator.backendopt.support import log
 from pypy.translator.backendopt.checkvirtual import check_virtual_methods
+from pypy.translator.backendopt.storesink import storesink_graph
 from pypy.objspace.flow.model import checkgraph
 
 INLINE_THRESHOLD_FOR_TEST = 33
@@ -104,6 +105,9 @@
             print "after clever inlining and malloc removal"
             print_statistics(translator.graphs[0], translator)        
 
+    if config.storesink:
+        for graph in graphs:
+            storesink_graph(graph)
 
     if config.profile_based_inline and not secondary:
         threshold = config.profile_based_inline_threshold

Added: pypy/trunk/pypy/translator/backendopt/storesink.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/translator/backendopt/storesink.py	Tue Nov 17 08:56:11 2009
@@ -0,0 +1,49 @@
+
+from pypy.rpython.lltypesystem.lloperation import llop
+
+def has_side_effects(op):
+    if op.opname == 'debug_assert':
+        return False
+    try:
+        return getattr(llop, op.opname).sideeffects
+    except AttributeError:
+        return True
+
+def storesink_graph(graph):
+    def rename(op, renaming):
+        for i, arg in enumerate(op.args):
+            r = renaming.get(arg, None)
+            if r is not None:
+                op.args[i] = r
+        return op
+
+    def clear_cache_for(cache, concretetype, fieldname):
+        for k in cache.keys():
+            if k[0].concretetype == concretetype and k[1] == fieldname:
+                del cache[k]
+    
+    for block in graph.iterblocks():
+        newops = []
+        cache = {}
+        renaming = {}
+        for op in block.operations:
+            if op.opname == 'getfield':
+                tup = (op.args[0], op.args[1].value)
+                res = cache.get(tup, None)
+                if res is not None:
+                    renaming[op.result] = res
+                    continue
+                cache[tup] = op.result
+            elif op.opname in ['setarrayitem', 'setinteriorfield']:
+                pass
+            elif op.opname == 'setfield':
+                clear_cache_for(cache, op.args[0].concretetype,
+                                op.args[1].value)
+            elif has_side_effects(op):
+                cache = {}
+            newops.append(rename(op, renaming))
+        if block.operations:
+            block.operations = newops
+        for exit in block.exits:
+            rename(exit, renaming)
+        

Added: pypy/trunk/pypy/translator/backendopt/test/test_storesink.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/translator/backendopt/test/test_storesink.py	Tue Nov 17 08:56:11 2009
@@ -0,0 +1,121 @@
+
+import py
+from pypy.translator.translator import TranslationContext, graphof
+from pypy.translator.backendopt.storesink import storesink_graph
+from pypy.objspace.flow.model import last_exception, checkgraph
+from pypy.conftest import option
+
+class TestStoreSink(object):
+    # not sure if it makes any sense on ootype, maybe worth trying
+    type_system = 'lltype'
+    
+    def translate(self, func, argtypes):
+        t = TranslationContext()
+        t.buildannotator().build_types(func, argtypes)
+        t.buildrtyper(type_system=self.type_system).specialize()
+        return t
+
+    def check(self, f, argtypes, no_getfields=0):
+        t = self.translate(f, argtypes)
+        getfields = 0
+        graph = graphof(t, f)
+        checkgraph(graph)
+        storesink_graph(graph)
+        checkgraph(graph)
+        if option.view:
+            t.view()
+        for block in graph.iterblocks():
+            for op in block.operations:
+                if op.opname == 'getfield':
+                    getfields += 1
+        if no_getfields != getfields:
+            py.test.fail("Expected %d, got %d getfields" %
+                         (no_getfields, getfields))
+
+    def test_infrastructure(self):
+        class A(object):
+            pass
+        
+        def f(i):
+            a = A()
+            a.x = i
+            return a.x
+
+        self.check(f, [int], 1)
+
+    def test_simple(self):
+        class A(object):
+            pass
+
+        def f(i):
+            a = A()
+            a.x = i
+            return a.x + a.x
+
+        self.check(f, [int], 1)
+                
+    def test_irrelevant_setfield(self):
+        class A(object):
+            pass
+
+        def f(i):
+            a = A()
+            a.x = i
+            one = a.x
+            a.y = 3
+            two = a.x
+            return one + two
+
+        self.check(f, [int], 1)
+
+    def test_relevant_setfield(self):
+        class A(object):
+            pass
+
+        def f(i):
+            a = A()
+            b = A()
+            a.x = i
+            b.x = i + 1
+            one = a.x
+            b.x = i
+            two = a.x
+            return one + two
+
+        self.check(f, [int], 2)
+
+    def test_different_concretetype(self):
+        class A(object):
+            pass
+
+        class B(object):
+            pass
+
+        def f(i):
+            a = A()
+            b = B()
+            a.x = i
+            one = a.x
+            b.x = i + 1
+            two = a.x
+            return one + two
+
+        self.check(f, [int], 1)
+
+    def test_subclass(self):
+        class A(object):
+            pass
+
+        class B(A):
+            pass
+
+        def f(i):
+            a = A()
+            b = B()
+            a.x = i
+            one = a.x
+            b.x = i + 1
+            two = a.x
+            return one + two
+
+        self.check(f, [int], 2)



More information about the Pypy-commit mailing list