[pypy-svn] r70273 - in pypy/branch/jit-delayed-write/pypy/jit/metainterp: . test
arigo at codespeak.net
arigo at codespeak.net
Fri Dec 25 20:29:17 CET 2009
Author: arigo
Date: Fri Dec 25 20:29:16 2009
New Revision: 70273
Modified:
pypy/branch/jit-delayed-write/pypy/jit/metainterp/effectinfo.py
pypy/branch/jit-delayed-write/pypy/jit/metainterp/optimizeopt.py
pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_effectinfo.py
pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizefindnode.py
pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizeopt.py
Log:
Get optimizeopt.py to delay some writes. All tests pass
so far but might be slightly wrong.
Modified: pypy/branch/jit-delayed-write/pypy/jit/metainterp/effectinfo.py
==============================================================================
--- pypy/branch/jit-delayed-write/pypy/jit/metainterp/effectinfo.py (original)
+++ pypy/branch/jit-delayed-write/pypy/jit/metainterp/effectinfo.py Fri Dec 25 20:29:16 2009
@@ -7,16 +7,16 @@
class EffectInfo(object):
_cache = {}
- def __new__(cls, read_descrs_fields, write_descrs_fields,
+ def __new__(cls, readonly_descrs_fields, write_descrs_fields,
write_descrs_arrays, promotes_virtualizables=False):
- key = (frozenset(read_descrs_fields),
+ key = (frozenset(readonly_descrs_fields),
frozenset(write_descrs_fields),
frozenset(write_descrs_arrays),
promotes_virtualizables)
if key in cls._cache:
return cls._cache[key]
result = object.__new__(cls)
- result.read_descrs_fields = read_descrs_fields
+ result.readonly_descrs_fields = readonly_descrs_fields
result.write_descrs_fields = write_descrs_fields
result.write_descrs_arrays = write_descrs_arrays
result.promotes_virtualizables = promotes_virtualizables
@@ -27,8 +27,8 @@
from pypy.translator.backendopt.writeanalyze import top_set
if effects is top_set:
return None
- read_descrs_fields = []
- # read_descrs_arrays = [] --- not enabled for now
+ readonly_descrs_fields = []
+ # readonly_descrs_arrays = [] --- not enabled for now
write_descrs_fields = []
write_descrs_arrays = []
@@ -48,14 +48,16 @@
if tup[0] == "struct":
add_struct(write_descrs_fields, tup)
elif tup[0] == "readstruct":
- add_struct(read_descrs_fields, tup)
+ tupw = ("struct",) + tup[1:]
+ if tupw not in effects:
+ add_struct(readonly_descrs_fields, tup)
elif tup[0] == "array":
add_array(write_descrs_arrays, tup)
elif tup[0] == "readarray":
pass
else:
assert 0
- return EffectInfo(read_descrs_fields,
+ return EffectInfo(readonly_descrs_fields,
write_descrs_fields,
write_descrs_arrays,
promotes_virtualizables)
Modified: pypy/branch/jit-delayed-write/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/branch/jit-delayed-write/pypy/jit/metainterp/optimizeopt.py (original)
+++ pypy/branch/jit-delayed-write/pypy/jit/metainterp/optimizeopt.py Fri Dec 25 20:29:16 2009
@@ -512,6 +512,9 @@
def emit_operation(self, op, must_clone=True):
self.heap_op_optimizer.emitting_operation(op)
+ self._emit_operation(op, must_clone)
+
+ def _emit_operation(self, op, must_clone=True):
for i in range(len(op.args)):
arg = op.args[i]
if arg in self.values:
@@ -836,11 +839,13 @@
class HeapOpOptimizer(object):
def __init__(self, optimizer):
self.optimizer = optimizer
- # cached OptValues for each field descr
+ # cached fields: {descr: {OptValue_instance: OptValue_fieldvalue}}
self.cached_fields = {}
-
- # cached OptValues for each field descr
+ # cached array items: {descr: CachedArrayItems}
self.cached_arrayitems = {}
+ # lazily written setfields (at most one per descr): {descr: op}
+ self.lazy_setfields = {}
+ self.lazy_setfields_descrs = [] # keys (at least) of previous dict
def clean_caches(self):
self.cached_fields.clear()
@@ -908,8 +913,6 @@
return None
def emitting_operation(self, op):
- if op.is_always_pure():
- return
if op.has_no_side_effect():
return
if op.is_ovf():
@@ -921,12 +924,16 @@
opnum == rop.SETARRAYITEM_GC or
opnum == rop.DEBUG_MERGE_POINT):
return
- if opnum == rop.CALL:
+ if (opnum == rop.CALL or
+ opnum == rop.CALL_MAY_FORCE):
effectinfo = op.descr.get_extra_info()
if effectinfo is not None:
# XXX we can get the wrong complexity here, if the lists
# XXX stored on effectinfo are large
+ for fielddescr in effectinfo.readonly_descrs_fields:
+ self.force_lazy_setfield(fielddescr)
for fielddescr in effectinfo.write_descrs_fields:
+ self.force_lazy_setfield(fielddescr)
try:
del self.cached_fields[fielddescr]
except KeyError:
@@ -937,9 +944,38 @@
except KeyError:
pass
return
+ self.force_all_lazy_setfields()
+ elif op.is_final() or (not we_are_translated() and
+ op.opnum < 0): # escape() operations
+ self.force_all_lazy_setfields()
self.clean_caches()
+ def force_lazy_setfield(self, descr):
+ try:
+ op = self.lazy_setfields[descr]
+ except KeyError:
+ return
+ del self.lazy_setfields[descr]
+ self.optimizer._emit_operation(op)
+
+ def force_all_lazy_setfields(self):
+ if len(self.lazy_setfields_descrs) > 0:
+ for descr in self.lazy_setfields_descrs:
+ self.force_lazy_setfield(descr)
+ del self.lazy_setfields_descrs[:]
+
+ def force_lazy_setfield_if_necessary(self, op, value, write=False):
+ try:
+ op1 = self.lazy_setfields[op.descr]
+ except KeyError:
+ if write:
+ self.lazy_setfields_descrs.append(op.descr)
+ else:
+ if self.optimizer.getvalue(op1.args[0]) is not value:
+ self.force_lazy_setfield(op.descr)
+
def optimize_GETFIELD_GC(self, op, value):
+ self.force_lazy_setfield_if_necessary(op, value)
# check if the field was read from another getfield_gc just before
# or has been written to recently
fieldvalue = self.read_cached_field(op.descr, value)
@@ -954,7 +990,8 @@
self.cache_field_value(op.descr, value, fieldvalue)
def optimize_SETFIELD_GC(self, op, value, fieldvalue):
- self.optimizer.emit_operation(op)
+ self.force_lazy_setfield_if_necessary(op, value, write=True)
+ self.lazy_setfields[op.descr] = op
# remember the result of future reads of the field
self.cache_field_value(op.descr, value, fieldvalue, write=True)
Modified: pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_effectinfo.py
==============================================================================
--- pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_effectinfo.py (original)
+++ pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_effectinfo.py Fri Dec 25 20:29:16 2009
@@ -13,7 +13,7 @@
S = lltype.GcStruct("S", ("a", lltype.Signed))
effects = frozenset([("readstruct", lltype.Ptr(S), "a")])
effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
- assert list(effectinfo.read_descrs_fields) == [('fielddescr', S, "a")]
+ assert list(effectinfo.readonly_descrs_fields) == [('fielddescr', S, "a")]
assert not effectinfo.write_descrs_fields
assert not effectinfo.write_descrs_arrays
@@ -22,49 +22,58 @@
effects = frozenset([("struct", lltype.Ptr(S), "a")])
effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
assert list(effectinfo.write_descrs_fields) == [('fielddescr', S, "a")]
- assert not effectinfo.read_descrs_fields
+ assert not effectinfo.readonly_descrs_fields
assert not effectinfo.write_descrs_arrays
def test_include_write_array():
A = lltype.GcArray(lltype.Signed)
effects = frozenset([("array", lltype.Ptr(A))])
effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
- assert not effectinfo.read_descrs_fields
+ assert not effectinfo.readonly_descrs_fields
assert not effectinfo.write_descrs_fields
assert list(effectinfo.write_descrs_arrays) == [('arraydescr', A)]
+def test_dont_include_read_and_write_field():
+ S = lltype.GcStruct("S", ("a", lltype.Signed))
+ effects = frozenset([("readstruct", lltype.Ptr(S), "a"),
+ ("struct", lltype.Ptr(S), "a")])
+ effectinfo = effectinfo_from_writeanalyze(effects, FakeCPU())
+ assert not effectinfo.readonly_descrs_fields
+ assert list(effectinfo.write_descrs_fields) == [('fielddescr', S, "a")]
+ assert not effectinfo.write_descrs_arrays
+
def test_filter_out_typeptr():
effects = frozenset([("struct", lltype.Ptr(OBJECT), "typeptr")])
effectinfo = effectinfo_from_writeanalyze(effects, None)
- assert not effectinfo.read_descrs_fields
+ assert not effectinfo.readonly_descrs_fields
assert not effectinfo.write_descrs_fields
assert not effectinfo.write_descrs_arrays
def test_filter_out_array_of_void():
effects = frozenset([("array", lltype.Ptr(lltype.GcArray(lltype.Void)))])
effectinfo = effectinfo_from_writeanalyze(effects, None)
- assert not effectinfo.read_descrs_fields
+ assert not effectinfo.readonly_descrs_fields
assert not effectinfo.write_descrs_fields
assert not effectinfo.write_descrs_arrays
def test_filter_out_struct_with_void():
effects = frozenset([("struct", lltype.Ptr(lltype.GcStruct("x", ("a", lltype.Void))), "a")])
effectinfo = effectinfo_from_writeanalyze(effects, None)
- assert not effectinfo.read_descrs_fields
+ assert not effectinfo.readonly_descrs_fields
assert not effectinfo.write_descrs_fields
assert not effectinfo.write_descrs_arrays
def test_filter_out_ooarray_of_void():
effects = frozenset([("array", ootype.Array(ootype.Void))])
effectinfo = effectinfo_from_writeanalyze(effects, None)
- assert not effectinfo.read_descrs_fields
+ assert not effectinfo.readonly_descrs_fields
assert not effectinfo.write_descrs_fields
assert not effectinfo.write_descrs_arrays
def test_filter_out_instance_with_void():
effects = frozenset([("struct", ootype.Instance("x", ootype.ROOT, {"a": ootype.Void}), "a")])
effectinfo = effectinfo_from_writeanalyze(effects, None)
- assert not effectinfo.read_descrs_fields
+ assert not effectinfo.readonly_descrs_fields
assert not effectinfo.write_descrs_fields
assert not effectinfo.write_descrs_arrays
Modified: pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizefindnode.py
==============================================================================
--- pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizefindnode.py (original)
+++ pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizefindnode.py Fri Dec 25 20:29:16 2009
@@ -95,6 +95,7 @@
onedescr = cpu.fielddescrof(U, 'one')
FUNC = lltype.FuncType([lltype.Signed], lltype.Signed)
+ plaincalldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
EffectInfo([], [], []))
writeadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
Modified: pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizeopt.py (original)
+++ pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizeopt.py Fri Dec 25 20:29:16 2009
@@ -606,10 +606,10 @@
p3sub = getfield_gc(p3, descr=nextdescr)
i3 = getfield_gc(p3sub, descr=valuedescr)
escape(i3)
+ p1 = new_with_vtable(ConstClass(node_vtable))
p2sub = new_with_vtable(ConstClass(node_vtable2))
setfield_gc(p2sub, i1, descr=valuedescr)
setfield_gc(p2, p2sub, descr=nextdescr)
- p1 = new_with_vtable(ConstClass(node_vtable))
jump(i1, p1, p2)
"""
# The same as test_p123_simple, but in the end the "old" p2 contains
@@ -1307,6 +1307,65 @@
"""
self.optimize_loop(ops, 'Not, Not, Not', expected)
+ def test_duplicate_setfield_2(self):
+ ops = """
+ [p1, i1, i3]
+ setfield_gc(p1, i1, descr=valuedescr)
+ i2 = getfield_gc(p1, descr=valuedescr)
+ setfield_gc(p1, i3, descr=valuedescr)
+ escape(i2)
+ jump(p1, i1, i3)
+ """
+ expected = """
+ [p1, i1, i3]
+ setfield_gc(p1, i3, descr=valuedescr)
+ escape(i1)
+ jump(p1, i1, i3)
+ """
+ self.optimize_loop(ops, 'Not, Not, Not', expected)
+
+ def test_duplicate_setfield_3(self):
+ ops = """
+ [p1, p2, i1, i3]
+ setfield_gc(p1, i1, descr=valuedescr)
+ i2 = getfield_gc(p2, descr=valuedescr)
+ setfield_gc(p1, i3, descr=valuedescr)
+ escape(i2)
+ jump(p1, p2, i1, i3)
+ """
+ # potential aliasing of p1 and p2 means that we cannot kill the
+ # the setfield_gc
+ self.optimize_loop(ops, 'Not, Not, Not, Not', ops)
+
+ def test_duplicate_setfield_4(self):
+ ops = """
+ [p1, i1, i2, p3]
+ setfield_gc(p1, i1, descr=valuedescr)
+ #
+ # some operations on which the above setfield_gc cannot have effect
+ i3 = getarrayitem_gc_pure(p3, 1, descr=arraydescr)
+ i4 = getarrayitem_gc(p3, i3, descr=arraydescr)
+ i5 = int_add(i3, i4)
+ setarrayitem_gc(p3, 0, i5, descr=arraydescr)
+ setfield_gc(p1, i4, descr=nextdescr)
+ #
+ setfield_gc(p1, i2, descr=valuedescr)
+ jump(p1, i1, i2, p3)
+ """
+ expected = """
+ [p1, i1, i2, p3]
+ #
+ i3 = getarrayitem_gc_pure(p3, 1, descr=arraydescr)
+ i4 = getarrayitem_gc(p3, i3, descr=arraydescr)
+ i5 = int_add(i3, i4)
+ setarrayitem_gc(p3, 0, i5, descr=arraydescr)
+ #
+ setfield_gc(p1, i2, descr=valuedescr)
+ setfield_gc(p1, i4, descr=nextdescr)
+ jump(p1, i1, i2, p3)
+ """
+ self.optimize_loop(ops, 'Not, Not, Not, Not', expected)
+
def test_duplicate_setfield_sideeffects_1(self):
ops = """
[p1, i1, i2]
@@ -1342,7 +1401,7 @@
setfield_gc(ConstPtr(myptr), i2, descr=valuedescr)
jump(i1, i2)
"""
- self.optimize_loop(ops, 'Constant(myptr)', expected)
+ self.optimize_loop(ops, 'Constant(myptr), Not, Not', expected)
def test_duplicate_getarrayitem_1(self):
ops = """
@@ -2082,7 +2141,7 @@
"""
self.optimize_loop(ops, 'Not, Not, Not', expected)
- def test_residual_call_invalidates_some_read_caches(self):
+ def test_residual_call_invalidates_some_read_caches_1(self):
ops = """
[p1, i1, p2, i2]
setfield_gc(p1, i1, descr=valuedescr)
@@ -2102,6 +2161,38 @@
"""
self.optimize_loop(ops, 'Not, Not, Not, Not', expected)
+ def test_residual_call_invalidates_some_read_caches_2(self):
+ ops = """
+ [p1, i1, p2, i2]
+ setfield_gc(p1, i1, descr=valuedescr)
+ setfield_gc(p2, i2, descr=adescr)
+ i3 = call(i1, descr=writeadescr)
+ setfield_gc(p1, i3, descr=valuedescr)
+ setfield_gc(p2, i3, descr=adescr)
+ jump(p1, i1, p2, i2)
+ """
+ expected = """
+ [p1, i1, p2, i2]
+ setfield_gc(p2, i2, descr=adescr)
+ i3 = call(i1, descr=writeadescr)
+ setfield_gc(p1, i3, descr=valuedescr)
+ setfield_gc(p2, i3, descr=adescr)
+ jump(p1, i1, p2, i2)
+ """
+ self.optimize_loop(ops, 'Not, Not, Not, Not', expected)
+
+ def test_residual_call_invalidates_some_read_caches_3(self):
+ ops = """
+ [p1, i1, p2, i2]
+ setfield_gc(p1, i1, descr=valuedescr)
+ setfield_gc(p2, i2, descr=adescr)
+ i3 = call(i1, descr=plaincalldescr)
+ setfield_gc(p1, i3, descr=valuedescr)
+ setfield_gc(p2, i3, descr=adescr)
+ jump(p1, i1, p2, i2)
+ """
+ self.optimize_loop(ops, 'Not, Not, Not, Not', ops)
+
class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin):
More information about the Pypy-commit
mailing list