[pypy-commit] pypy default: extend storesink to be super-local, ie to follow links that are not merge links
cfbolz
noreply at buildbot.pypy.org
Tue Sep 23 11:46:28 CEST 2014
Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch:
Changeset: r73659:9f2eaab7ceeb
Date: 2014-09-06 18:56 +0200
http://bitbucket.org/pypy/pypy/changeset/9f2eaab7ceeb/
Log: extend storesink to be super-local, ie to follow links that are not
merge links
diff --git a/rpython/translator/backendopt/storesink.py b/rpython/translator/backendopt/storesink.py
--- a/rpython/translator/backendopt/storesink.py
+++ b/rpython/translator/backendopt/storesink.py
@@ -1,6 +1,8 @@
from rpython.rtyper.lltypesystem.lloperation import llop
+from rpython.flowspace.model import mkentrymap, Variable
from rpython.translator.backendopt import removenoops
+from rpython.translator import simplify
def has_side_effects(op):
if op.opname == 'debug_assert':
@@ -12,22 +14,63 @@
def storesink_graph(graph):
+ """ remove superfluous getfields. use a super-local method: all non-join
+ blocks inherit the heap information from their (single) predecessor
+ """
added_some_same_as = False
+ entrymap = mkentrymap(graph)
- for block in graph.iterblocks():
- newops = []
- cache = {}
+ # all merge blocks are starting points
+ todo = [(block, None, None) for (block, prev_blocks) in entrymap.iteritems()
+ if len(prev_blocks) > 1 or block is graph.startblock]
- newops, _some_same_as = _storesink_block(block, cache)
- added_some_same_as = _some_same_as or added_some_same_as
+ visited = 0
+
+ while todo:
+ block, cache, inputlink = todo.pop()
+ visited += 1
+ if cache is None:
+ cache = {}
+
if block.operations:
- block.operations = newops
+ newops, changed_block = _storesink_block(block, cache, inputlink)
+ added_some_same_as = changed_block or added_some_same_as
+ if changed_block:
+ block.operations = newops
+ for link in block.exits:
+ if len(entrymap[link.target]) == 1:
+ new_cache = _translate_cache(cache, link)
+ todo.append((link.target, new_cache, link))
+ assert visited == len(entrymap)
if added_some_same_as:
removenoops.remove_same_as(graph)
+ simplify.transform_dead_op_vars(graph)
+def _translate_cache(cache, link):
+ if link.target.operations == (): # exit or except block:
+ return {}
+ block = link.target
+ local_versions = {var1: var2 for var1, var2 in zip(link.args, block.inputargs)}
+ def _translate_arg(arg):
+ if isinstance(arg, Variable):
+ res = local_versions.get(arg, None)
+ if res is None:
+ res = Variable(arg)
+ res.concretetype = arg.concretetype
+ link.args.append(arg)
+ block.inputargs.append(res)
+ local_versions[arg] = res
+ return res
+ else:
+ return arg
+ new_cache = {}
+ for (var, field), res in cache.iteritems():
+ if var in local_versions or not isinstance(var, Variable):
+ new_cache[_translate_arg(var), field] = _translate_arg(res)
+ return new_cache
-def _storesink_block(block, cache):
+def _storesink_block(block, cache, inputlink):
def clear_cache_for(cache, concretetype, fieldname):
for k in cache.keys():
if k[0].concretetype == concretetype and k[1] == fieldname:
@@ -53,6 +96,6 @@
clear_cache_for(cache, target.concretetype, field)
cache[target, field] = op.args[2]
elif has_side_effects(op):
- cache = {}
+ cache.clear()
newops.append(op)
return newops, added_some_same_as
diff --git a/rpython/translator/backendopt/test/test_storesink.py b/rpython/translator/backendopt/test/test_storesink.py
--- a/rpython/translator/backendopt/test/test_storesink.py
+++ b/rpython/translator/backendopt/test/test_storesink.py
@@ -134,3 +134,22 @@
return n
self.check(f, [int], 0)
+
+
+ def test_cfg_splits(self):
+ class A(object):
+ pass
+
+ def f(i):
+ a = A()
+ j = i
+ for i in range(i):
+ a.x = i
+ if i:
+ j = a.x + a.x
+ else:
+ j = a.x * 5
+ return j
+
+ self.check(f, [int], 0)
+
More information about the pypy-commit
mailing list