[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