[pypy-commit] pypy optresult-unroll: progress
fijal
noreply at buildbot.pypy.org
Sat Jul 11 20:30:52 CEST 2015
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: optresult-unroll
Changeset: r78528:d702dcbd242c
Date: 2015-07-11 20:29 +0200
http://bitbucket.org/pypy/pypy/changeset/d702dcbd242c/
Log: progress
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -34,10 +34,12 @@
# 'cached_infos'.
#
self.cached_infos = []
+ self.cached_structs = []
self._lazy_setfield = None
self._lazy_setfield_registered = False
- def register_dirty_field(self, info):
+ def register_dirty_field(self, structop, info):
+ self.cached_structs.append(structop)
self.cached_infos.append(info)
def invalidate(self, descr):
@@ -45,7 +47,50 @@
assert isinstance(opinfo, info.AbstractStructPtrInfo)
opinfo._fields[descr.get_index()] = None
self.cached_infos = []
+ self.cached_structs = []
+ def produce_potential_short_preamble_ops(self, optimizer, shortboxes,
+ descr):
+ assert self._lazy_setfield is None
+ for i, info in enumerate(self.cached_infos):
+ structbox = self.cached_structs[i]
+ op = info._fields[descr.get_index()]
+ op = optimizer.get_box_replacement(op)
+ opnum = OpHelpers.getfield_for_descr(descr)
+ getfield_op = ResOperation(opnum, [structbox], descr=descr)
+ shortboxes.add_potential(op, getfield_op)
+ return
+ for structvalue in self._cached_fields_getfield_op.keys():
+ op = self._cached_fields_getfield_op[structvalue]
+ if not op:
+ continue
+ value = optimizer.getvalue(op.getarg(0))
+ if value in optimizer.opaque_pointers:
+ if value.getlevel() < LEVEL_KNOWNCLASS:
+ continue
+ if op.getopnum() != rop.SETFIELD_GC and op.getopnum() != rop.GETFIELD_GC:
+ continue
+ if structvalue in self._cached_fields:
+ if op.getopnum() == rop.SETFIELD_GC:
+ result = op.getarg(1)
+ if isinstance(result, Const):
+ newresult = result.clonebox()
+ optimizer.make_constant(newresult, result)
+ result = newresult
+ getop = ResOperation(rop.GETFIELD_GC, [op.getarg(0)],
+ result, op.getdescr())
+ shortboxes.add_potential(getop, synthetic=True)
+ if op.getopnum() == rop.SETARRAYITEM_GC:
+ result = op.getarg(2)
+ if isinstance(result, Const):
+ newresult = result.clonebox()
+ optimizer.make_constant(newresult, result)
+ result = newresult
+ getop = ResOperation(rop.GETARRAYITEM_GC, [op.getarg(0), op.getarg(1)],
+ result, op.getdescr())
+ shortboxes.add_potential(getop, synthetic=True)
+ elif op.result is not None:
+ shortboxes.add_potential(op)
def possible_aliasing(self, optheap, opinfo):
# If lazy_setfield is set and contains a setfield on a different
@@ -135,7 +180,7 @@
def _setfield(self, op, opinfo, optheap):
arg = optheap.get_box_replacement(op.getarg(1))
- opinfo.setfield(op.getdescr(), arg, optheap, self)
+ opinfo.setfield(op.getdescr(), op, arg, optheap, self)
class ArrayCachedField(CachedField):
def __init__(self, index):
@@ -150,13 +195,15 @@
def _setfield(self, op, opinfo, optheap):
arg = optheap.get_box_replacement(op.getarg(2))
- opinfo.setitem(self.index, arg, self, optheap)
+ struct = optheap.get_box_replacement(op.getarg(0))
+ opinfo.setitem(self.index, struct, arg, self, optheap)
def invalidate(self, descr):
for opinfo in self.cached_infos:
assert isinstance(opinfo, info.ArrayPtrInfo)
opinfo._items = None
self.cached_infos = []
+ self.cached_structs = []
class OptHeap(Optimization):
"""Cache repeated heap accesses"""
@@ -203,7 +250,6 @@
self.next_optimization.propagate_forward(postponed_op)
def produce_potential_short_preamble_ops(self, sb):
- return
descrkeys = self.cached_fields.keys()
if not we_are_translated():
# XXX Pure operation of boxes that are cached in several places will
@@ -221,11 +267,11 @@
for index, d in submap.items():
d.produce_potential_short_preamble_ops(self.optimizer, sb, descr)
- def register_dirty_field(self, descr, info):
- self.field_cache(descr).register_dirty_field(info)
+ def register_dirty_field(self, descr, op, info):
+ self.field_cache(descr).register_dirty_field(op, info)
- def register_dirty_array_field(self, arraydescr, index, info):
- self.arrayitem_cache(arraydescr, index).register_dirty_field(info)
+ def register_dirty_array_field(self, arraydescr, op, index, info):
+ self.arrayitem_cache(arraydescr, index).register_dirty_field(op, info)
def clean_caches(self):
del self._lazy_setfields_and_arrayitems[:]
@@ -467,7 +513,7 @@
self.make_nonnull(op.getarg(0))
self.emit_operation(op)
# then remember the result of reading the field
- structinfo.setfield(op.getdescr(), op, self, cf)
+ structinfo.setfield(op.getdescr(), op.getarg(0), op, self, cf)
optimize_GETFIELD_GC_R = optimize_GETFIELD_GC_I
optimize_GETFIELD_GC_F = optimize_GETFIELD_GC_I
@@ -518,7 +564,9 @@
self.emit_operation(op)
# the remember the result of reading the array item
if cf is not None:
- arrayinfo.setitem(indexb.getint(), self.get_box_replacement(op), cf,
+ arrayinfo.setitem(indexb.getint(),
+ self.get_box_replacement(op.getarg(0)),
+ self.get_box_replacement(op), cf,
self)
optimize_GETARRAYITEM_GC_R = optimize_GETARRAYITEM_GC_I
optimize_GETARRAYITEM_GC_F = optimize_GETARRAYITEM_GC_I
diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -122,12 +122,13 @@
assert not self.is_virtual()
self._fields = [None] * len(self._fields)
- def setfield(self, descr, op, optheap=None, cf=None):
+ def setfield(self, descr, struct, op, optheap=None, cf=None):
self.init_fields(descr.get_parent_descr(), descr.get_index())
+ assert isinstance(op, AbstractValue)
self._fields[descr.get_index()] = op
if cf is not None:
assert not self.is_virtual()
- cf.register_dirty_field(self)
+ cf.register_dirty_field(struct, self)
def getfield(self, descr, optheap=None):
self.init_fields(descr.get_parent_descr(), descr.get_index())
@@ -144,7 +145,7 @@
descr=flddescr)
optforce._emit_operation(setfieldop)
if optforce.optheap is not None:
- optforce.optheap.register_dirty_field(flddescr, self)
+ optforce.optheap.register_dirty_field(flddescr, op, self)
def _visitor_walk_recursive(self, instbox, visitor, optimizer):
lst = self.vdescr.get_all_fielddescrs()
@@ -313,11 +314,11 @@
descr=arraydescr)
optforce._emit_operation(setop)
if optforce.optheap is not None:
- optforce.optheap.register_dirty_array_field(
+ optforce.optheap.register_dirty_array_field(op,
arraydescr, i, self)
optforce.pure_from_args(rop.ARRAYLEN_GC, [op], ConstInt(len(self._items)))
- def setitem(self, index, op, cf=None, optheap=None):
+ def setitem(self, index, struct_op, op, cf=None, optheap=None):
if self._items is None:
self._items = [None] * (index + 1)
if index >= len(self._items):
@@ -325,7 +326,7 @@
self._items[index] = op
if cf is not None:
assert not self.is_virtual()
- cf.register_dirty_field(self)
+ cf.register_dirty_field(struct_op, self)
def getitem(self, index, optheap=None):
if self._items is None or index >= len(self._items):
@@ -450,9 +451,9 @@
info = self._get_array_info(optheap)
info.setitem(index, op, cf)
- def setfield(self, descr, op, optheap=None, cf=None):
+ def setfield(self, descr, struct, op, optheap=None, cf=None):
info = self._get_info(descr, optheap)
- info.setfield(descr, op, optheap, cf)
+ info.setfield(descr, struct, op, optheap, cf)
def is_null(self):
return not bool(self._const.getref_base())
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -555,7 +555,9 @@
if val is None:
continue
if dest_info and dest_info.is_virtual():
- dest_info.setitem(index + dest_start, val)
+ dest_info.setitem(index + dest_start,
+ self.get_box_replacement(op.getarg(2)),
+ val)
else:
newop = ResOperation(rop.SETARRAYITEM_GC,
[op.getarg(2),
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_unroll.py b/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_unroll.py
@@ -123,3 +123,12 @@
ptrinfo._fields = [None, None, None, p2]
p.set_forwarded(ptrinfo)
vs.make_inputargs([p, p], FakeOptimizer())
+
+ def test_short_boxes_heapcache(self):
+ loop = """
+ [p0, i1]
+ i0 = getfield_gc_i(p0, descr=valuedescr)
+ jump(p0, i0)
+ """
+ es, loop, preamble = self.optimize(loop)
+ assert es.short_boxes[preamble.operations[0]]
diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py b/rpython/jit/metainterp/optimizeopt/unroll.py
--- a/rpython/jit/metainterp/optimizeopt/unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/unroll.py
@@ -36,14 +36,19 @@
preamble_op.info.make_guards(op, self.optunroll.short)
return op
- def setinfo_from_preamble(self, op, old_info):
+ def setinfo_from_preamble(self, op, preamble_info):
op = self.get_box_replacement(op)
- if isinstance(old_info, info.PtrInfo):
+ if isinstance(preamble_info, info.PtrInfo):
+ if preamble_info.is_virtual():
+ op.set_forwarded(preamble_info)
+ return
if op.is_constant():
return # nothing we can learn
- known_class = old_info.get_known_class(self.cpu)
+ known_class = preamble_info.get_known_class(self.cpu)
if known_class:
self.make_constant_class(op, known_class, False)
+ if preamble_info.is_nonnull():
+ self.make_nonnull(op)
class UnrollOptimizer(Optimization):
@@ -72,6 +77,7 @@
self._check_no_forwarding([[start_label, end_label], ops])
info, newops = self.optimizer.propagate_all_forward(
start_label.getarglist()[:], ops)
+ self.flush()
exported_state = self.export_state(start_label, end_label,
info.inputargs)
return exported_state, self.optimizer._newoperations
@@ -87,6 +93,7 @@
jump_args = state.virtual_state.make_inputargs(jump_args,
self.optimizer,
force_boxes=True)
+ self.flush()
jump_op = ResOperation(rop.JUMP, jump_args)
self.optimizer._newoperations.append(jump_op)
return (UnrollInfo(self.make_short_preamble(start_label.getarglist())),
@@ -202,6 +209,10 @@
for arg in end_args:
infos[arg] = self.optimizer.getinfo(arg)
label_args = virtual_state.make_inputargs(end_args, self.optimizer)
+ for arg in end_args:
+ if arg.get_forwarded() is not None:
+ arg.set_forwarded(None) # forget the optimization info
+ # (it's by infos exported)
return ExportedState(label_args, inparg_mapping, virtual_state, infos,
sb.short_boxes, renamed_inputargs)
diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py
--- a/rpython/jit/metainterp/optimizeopt/virtualize.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualize.py
@@ -113,8 +113,9 @@
newop.set_forwarded(vrefvalue)
token = ResOperation(rop.FORCE_TOKEN, [])
self.emit_operation(token)
- vrefvalue.setfield(descr_virtual_token, token)
- vrefvalue.setfield(descr_forced, self.optimizer.cpu.ts.CONST_NULLREF)
+ vrefvalue.setfield(descr_virtual_token, newop, token)
+ vrefvalue.setfield(descr_forced, newop,
+ self.optimizer.cpu.ts.CONST_NULLREF)
def optimize_VIRTUAL_REF_FINISH(self, op):
# This operation is used in two cases. In normal cases, it
@@ -198,12 +199,13 @@
optimize_GETFIELD_GC_PURE_F = optimize_GETFIELD_GC_I
def optimize_SETFIELD_GC(self, op):
- opinfo = self.getptrinfo(op.getarg(0))
+ struct = op.getarg(0)
+ opinfo = self.getptrinfo(struct)
if opinfo is not None and opinfo.is_virtual():
- opinfo.setfield(op.getdescr(),
+ opinfo.setfield(op.getdescr(), struct,
self.get_box_replacement(op.getarg(1)))
else:
- self.make_nonnull(op.getarg(0))
+ self.make_nonnull(struct)
self.emit_operation(op)
def optimize_NEW_WITH_VTABLE(self, op):
@@ -309,6 +311,7 @@
indexbox = self.get_constant_box(op.getarg(1))
if indexbox is not None:
opinfo.setitem(indexbox.getint(),
+ self.get_box_replacement(op.getarg(0)),
self.get_box_replacement(op.getarg(2)))
return
self.make_nonnull(op.getarg(0))
More information about the pypy-commit
mailing list