[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