Author: Maciej Fijalkowski <fij...@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)) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit