Author: Carl Friedrich Bolz <[email protected]>
Branch: better-storesink
Changeset: r87154:2f9d46642175
Date: 2016-09-06 17:43 +0200
http://bitbucket.org/pypy/pypy/changeset/2f9d46642175/
Log: support for removing loop-invariant heap reads
diff --git a/rpython/translator/backendopt/cse.py
b/rpython/translator/backendopt/cse.py
--- a/rpython/translator/backendopt/cse.py
+++ b/rpython/translator/backendopt/cse.py
@@ -42,7 +42,7 @@
self.heapcache.copy())
- def merge(self, firstlink, tuples, backedge):
+ def merge(self, firstlink, tuples):
purecache = {}
block = firstlink.target
# copy all operations that exist in *all* blocks over. need to add a
new
@@ -102,10 +102,6 @@
# ______________________
# merge heapcache
heapcache = {}
- if backedge:
- # can't deal with heapcache and backedges yet
- return Cache(
- self.variable_families, self.analyzer, purecache,
heapcache)
# try non-straight merges
for argindex, inputarg in enumerate(block.inputargs):
@@ -138,6 +134,7 @@
block.inputargs.append(newres)
heapcache[newkey] = newres
+ # regular merge
for key, res in self.heapcache.iteritems():
for link, cache in tuples[1:]:
val = cache.heapcache.get(key, None)
@@ -162,13 +159,24 @@
if k[0].concretetype == concretetype and k[1] == fieldname:
del self.heapcache[k]
- def _clear_heapcache_for_effects(self, op):
+ def _clear_heapcache_for_effects_of_op(self, op):
effects = self.analyzer.analyze(op)
+ self._clear_heapcache_for_effects(effects)
+
+ def _clear_heapcache_for_effects(self, effects):
for k in self.heapcache.keys():
key = ('struct', k[0].concretetype, k[1])
if key in effects:
del self.heapcache[k]
+ def _clear_heapcache_for_loop_blocks(self, blocks):
+ effects = self.analyzer.bottom_result()
+ for block in blocks:
+ for op in block.operations:
+ effects = self.analyzer.join_two_results(
+ effects, self.analyzer.analyze(op))
+ self._clear_heapcache_for_effects(effects)
+
def cse_block(self, block):
def representative_arg(arg):
if isinstance(arg, Variable):
@@ -194,7 +202,7 @@
self.heapcache[target, field] = op.args[2]
continue
if has_side_effects(op):
- self._clear_heapcache_for_effects(op)
+ self._clear_heapcache_for_effects_of_op(op)
continue
# foldable operations
@@ -212,14 +220,28 @@
self.purecache[key] = op.result
return added_some_same_as
-def _merge(tuples, variable_families, analyzer, backedge=False):
+def _merge(tuples, variable_families, analyzer, loop_blocks=None):
if not tuples:
return Cache(variable_families, analyzer)
if len(tuples) == 1:
(link, cache), = tuples
- return cache.copy()
- firstlink, firstcache = tuples[0]
- return firstcache.merge(firstlink, tuples, backedge)
+ result = cache.copy()
+ else:
+ firstlink, firstcache = tuples[0]
+ result = firstcache.merge(firstlink, tuples)
+ if loop_blocks:
+ # for all blocks in the loop, clean the heapcache for their effects
+ # that way, loop-invariant reads can be removed, if no one writes to
+ # anything that can alias with them.
+ result._clear_heapcache_for_loop_blocks(loop_blocks)
+ return result
+
+def loop_blocks(graph):
+ loop_blocks = support.find_loop_blocks(graph)
+ result = {}
+ for loop_block, start in loop_blocks.iteritems():
+ result.setdefault(start, []).append(loop_block)
+ return result
class CSE(object):
def __init__(self, translator):
@@ -229,6 +251,7 @@
def transform(self, graph):
variable_families =
ssa.DataFlowFamilyBuilder(graph).get_variable_families()
entrymap = mkentrymap(graph)
+ loops = loop_blocks(graph)
backedges = support.find_backedges(graph)
todo = collections.deque([graph.startblock])
caches_to_merge = collections.defaultdict(list)
@@ -238,15 +261,11 @@
while todo:
block = todo.popleft()
- backedge = False
- for link in entrymap[block]:
- if link in backedges:
- backedge = True
- break
if block.operations:
cache = _merge(
- caches_to_merge[block], variable_families, self.analyzer,
backedge)
+ caches_to_merge[block], variable_families, self.analyzer,
+ loops.get(block, None))
changed_block = cache.cse_block(block)
added_some_same_as = changed_block or added_some_same_as
done.add(block)
diff --git a/rpython/translator/backendopt/test/test_cse.py
b/rpython/translator/backendopt/test/test_cse.py
--- a/rpython/translator/backendopt/test/test_cse.py
+++ b/rpython/translator/backendopt/test/test_cse.py
@@ -279,3 +279,17 @@
return res
self.check(f, [int], int_add=2)
+
+ def test_loopinvariant_heap(self):
+ class A(object):
+ pass
+ def f(i):
+ a = A()
+ a.x = i
+ res = 0
+ x = i
+ while x:
+ x -= 1
+ res += a.x
+ return res
+ self.check(f, [int], getfield=0)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit