[pypy-commit] pypy better-storesink: use the write analyzer to know when to invalidate the cache
cfbolz
pypy.commits at gmail.com
Fri Sep 16 17:12:48 EDT 2016
Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: better-storesink
Changeset: r87151:e53758af61e3
Date: 2016-08-22 13:59 +0100
http://bitbucket.org/pypy/pypy/changeset/e53758af61e3/
Log: use the write analyzer to know when to invalidate the cache
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
@@ -6,10 +6,9 @@
from rpython.translator.backendopt import removenoops
from rpython.translator import simplify
from rpython.translator.backendopt import ssa
+from rpython.translator.backendopt.writeanalyze import WriteAnalyzer
def has_side_effects(op):
- if op.opname == 'debug_assert' or op.opname == 'jit_force_virtualizable':
- return False
try:
return getattr(llop, op.opname).sideeffects
except AttributeError:
@@ -22,7 +21,7 @@
return getattr(llop, op.opname).canfold
class Cache(object):
- def __init__(self, variable_families, purecache=None, heapcache=None):
+ def __init__(self, variable_families, analyzer, purecache=None, heapcache=None):
if purecache is None:
purecache = {}
if heapcache is None:
@@ -30,10 +29,12 @@
self.purecache = purecache
self.heapcache = heapcache
self.variable_families = variable_families
+ self.analyzer = analyzer
def copy(self):
return Cache(
- self.variable_families, self.purecache.copy(),
+ self.variable_families, self.analyzer,
+ self.purecache.copy(),
self.heapcache.copy())
@@ -72,13 +73,21 @@
block.inputargs.append(newres)
heapcache[key] = newres
- return Cache(self.variable_families, purecache, heapcache)
+ return Cache(
+ self.variable_families, self.analyzer, purecache, heapcache)
def _clear_heapcache_for(self, concretetype, fieldname):
for k in self.heapcache.keys():
if k[0].concretetype == concretetype and k[1] == fieldname:
del self.heapcache[k]
+ def _clear_heapcache_for_effects(self, op):
+ effects = self.analyzer.analyze(op)
+ for k in self.heapcache.keys():
+ key = ('struct', k[0].concretetype, k[1])
+ if key in effects:
+ del self.heapcache[k]
+
def cse_block(self, block):
def representative_arg(arg):
if isinstance(arg, Variable):
@@ -97,8 +106,6 @@
else:
self.heapcache[tup] = op.result
continue
- if op.opname in ('setarrayitem', 'setinteriorfield', "malloc", "malloc_varsize"):
- continue
if op.opname == 'setfield':
target = representative_arg(op.args[0])
field = op.args[1].value
@@ -106,7 +113,7 @@
self.heapcache[target, field] = op.args[2]
continue
if has_side_effects(op):
- self.heapcache.clear()
+ self._clear_heapcache_for_effects(op)
continue
# foldable operations
@@ -124,9 +131,9 @@
self.purecache[key] = op.result
return added_some_same_as
-def _merge(tuples, variable_families):
+def _merge(tuples, variable_families, analyzer):
if not tuples:
- return Cache(variable_families)
+ return Cache(variable_families, analyzer)
if len(tuples) == 1:
(link, cache), = tuples
return cache.copy()
@@ -136,6 +143,7 @@
class CSE(object):
def __init__(self, translator):
self.translator = translator
+ self.analyzer = WriteAnalyzer(translator)
def transform(self, graph):
variable_families = ssa.DataFlowFamilyBuilder(graph).get_variable_families()
@@ -156,9 +164,10 @@
if block.operations:
if not can_cache:
- cache = Cache(variable_families)
+ cache = Cache(variable_families, self.analyzer)
else:
- cache = _merge(caches_to_merge[block], variable_families)
+ cache = _merge(
+ caches_to_merge[block], variable_families, self.analyzer)
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
@@ -212,3 +212,23 @@
return j
self.check(f, [int], getfield=0)
+
+ def test_dont_invalidate_on_call(self):
+ class A(object):
+ pass
+ class B(object):
+ pass
+ def g(b, a):
+ b.x = 1
+ a.y = 2
+
+ def f(i):
+ a = A()
+ a.x = i
+ a.y = i + 1
+ b = B()
+ g(b, a)
+ return a.x + a.y
+
+ self.check(f, [int], getfield=1)
+
More information about the pypy-commit
mailing list