[pypy-commit] pypy jit-short_from_state: cleared out obsolete code for generating the short preamble as well as an now incorect description of the assumptions

hakanardo noreply at buildbot.pypy.org
Wed Aug 10 16:29:06 CEST 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-short_from_state
Changeset: r46421:a2774e236690
Date: 2011-08-10 16:30 +0200
http://bitbucket.org/pypy/pypy/changeset/a2774e236690/

Log:	cleared out obsolete code for generating the short preamble as well
	as an now incorect description of the assumptions

diff --git a/pypy/jit/metainterp/optimizeopt/unroll.py b/pypy/jit/metainterp/optimizeopt/unroll.py
--- a/pypy/jit/metainterp/optimizeopt/unroll.py
+++ b/pypy/jit/metainterp/optimizeopt/unroll.py
@@ -10,68 +10,6 @@
 from pypy.jit.metainterp.resume import Snapshot
 from pypy.rlib.debug import debug_print
 
-# Assumptions
-# ===========
-#
-# For this to work some assumptions had to be made about the
-# optimizations performed. At least for the optimizations that are
-# allowed to operate across the loop boundaries. To enforce this, the
-# optimizer chain is recreated at the end of the preamble and only the
-# state of the optimizations that fulfill those assumptions are kept.
-# Since part of this state is stored in virtuals all OptValue objects
-# are also recreated to allow virtuals not supported to be forced.
-#
-# First of all, the optimizations are not allowed to introduce new
-# boxes. It is the unoptimized version of the trace that is inlined to
-# form the second iteration of the loop. Otherwise the
-# state of the virtuals would not be updated correctly. Whenever some
-# box from the first iteration is reused in the second iteration, it
-# is added to the input arguments of the loop as well as to the
-# arguments of the jump at the end of the preamble. This means that
-# inlining the jump from the unoptimized trace will not work since it
-# contains too few arguments.  Instead the jump at the end of the
-# preamble is inlined. If the arguments of that jump contains boxes
-# that were produced by one of the optimizations, and thus never seen
-# by the inliner, the inliner will not be able to inline them. There
-# is no way of known what these boxes are supposed to contain in the
-# third iteration.
-#
-# The second assumption is that the state of the optimizer should be the
-# same after the second iteration as after the first. This have forced
-# us to disable store sinking across loop boundaries. Consider the
-# following trace
-#
-#         [p1, p2]
-#         i1 = getfield_gc(p1, descr=nextdescr)
-#         i2 = int_sub(i1, 1)
-#         i2b = int_is_true(i2)
-#         guard_true(i2b) []
-#         setfield_gc(p2, i2, descr=nextdescr)
-#         p3 = new_with_vtable(ConstClass(node_vtable))
-#         jump(p2, p3)
-#
-# At the start of the preamble, p1 and p2 will be pointers. The
-# setfield_gc will be removed by the store sinking heap optimizer, and
-# p3 will become a virtual. Jumping to the loop will make p1 a pointer
-# and p2 a virtual at the start of the loop. The setfield_gc will now
-# be absorbed into the virtual p2 and never seen by the heap
-# optimizer. At the end of the loop both p2 and p3 are virtuals, but
-# the loop needs p2 to be a pointer to be able to call itself. So it
-# is forced producing the operations
-#
-#         p2 = new_with_vtable(ConstClass(node_vtable))
-#         setfield_gc(p2, i2, descr=nextdescr)
-#
-# In this case the setfield_gc is not store sinked, which means we are
-# not in the same state at the end of the loop as at the end of the
-# preamble. When we now call the loop again, the first 4 operations of
-# the trace were optimized under the wrong assumption that the
-# setfield_gc was store sinked which could lead to errors. In this
-# case what would happen is that it would be inserted once more in
-# front of the guard.
-
-
-
 # FIXME: Introduce some VirtualOptimizer super class instead
 
 def optimize_unroll(metainterp_sd, loop, optimizations):
@@ -267,12 +205,6 @@
                                 loop.inputargs, short_inputargs,
                                 virtual_state)
             
-            #except KeyError:
-            #    debug_print("Unrolling failed.")
-            #    loop.preamble.operations = None
-            #    jumpop.initarglist(jump_args)
-            #    preamble_optimizer.send_extra_operation(jumpop)
-            #    return
             loop.inputargs = inputargs
             args = [preamble_optimizer.getvalue(self.short_boxes.original(a)).force_box()\
                     for a in inputargs]
@@ -282,7 +214,6 @@
 
             loop.operations = self.optimizer.newoperations
 
-            #short = self.create_short_preamble(loop.preamble, loop)
             if short:
                 assert short[-1].getopnum() == rop.JUMP
                 short[-1].setdescr(loop.token)
@@ -529,218 +460,6 @@
 
         return True
 
-    def create_short_preamble(self, preamble, loop):
-        #return None # Dissable
-
-        preamble_ops = preamble.operations
-        loop_ops = loop.operations
-
-        boxmap = BoxMap()
-        state = ExeState(self.optimizer)
-        short_preamble = []
-        loop_i = preamble_i = 0
-        while preamble_i < len(preamble_ops):
-
-            op = preamble_ops[preamble_i]
-            try:
-                newop = self.inliner.inline_op(op, ignore_result=True,
-                                               ignore_failargs=True)
-            except KeyError:
-                debug_print("create_short_preamble failed due to",
-                            "new boxes created during optimization.",
-                            "op:", op.getopnum(),
-                            "at preamble position: ", preamble_i,
-                            "loop position: ", loop_i)
-                return None
-
-            if self.sameop(newop, loop_ops[loop_i]) \
-               and loop_i < len(loop_ops):
-                try:
-                    boxmap.link_ops(op, loop_ops[loop_i])
-                except ImpossibleLink:
-                    debug_print("create_short_preamble failed due to",
-                                "impossible link of "
-                                "op:", op.getopnum(),
-                                "at preamble position: ", preamble_i,
-                                "loop position: ", loop_i)
-                    return None
-                loop_i += 1
-            else:
-                if not state.safe_to_move(op):
-                    debug_print("create_short_preamble failed due to",
-                                "unsafe op:", op.getopnum(),
-                                "at preamble position: ", preamble_i,
-                                "loop position: ", loop_i)
-                    return None
-                short_preamble.append(op)
-
-            state.update(op)
-            preamble_i += 1
-
-        if loop_i < len(loop_ops):
-            debug_print("create_short_preamble failed due to",
-                        "loop contaning ops not in preamble"
-                        "at position", loop_i)
-            return None
-
-
-        jumpargs = []
-        for i in range(len(loop.inputargs)):
-            try:
-                jumpargs.append(boxmap.get_preamblebox(loop.inputargs[i]))
-            except KeyError:
-                debug_print("create_short_preamble failed due to",
-                            "input arguments not located")
-                return None
-
-        jmp = ResOperation(rop.JUMP, jumpargs[:], None)
-        jmp.setdescr(loop.token)
-        short_preamble.append(jmp)
-
-        # Check that boxes used as arguemts are produced.
-        seen = {}
-        for box in preamble.inputargs:
-            seen[box] = True
-        for op in short_preamble:
-            for box in op.getarglist():
-                if isinstance(box, Const):
-                    continue
-                if box not in seen:
-                    debug_print("create_short_preamble failed due to",
-                                "op arguments not produced")
-                    return None
-            if op.result:
-                seen[op.result] = True
-
-        return short_preamble
-
-class ExeState(object):
-    def __init__(self, optimizer):
-        self.optimizer = optimizer
-        self.heap_dirty = False
-        self.unsafe_getitem = {}
-        self.unsafe_getarrayitem = {}
-        self.unsafe_getarrayitem_indexes = {}
-
-    # Make sure it is safe to move the instrucions in short_preamble
-    # to the top making short_preamble followed by loop equvivalent
-    # to preamble
-    def safe_to_move(self, op):
-        opnum = op.getopnum()
-        descr = op.getdescr()
-        for box in op.getarglist():
-            if self.optimizer.getvalue(box) in self.optimizer.opaque_pointers:
-                return False
-        if op.is_always_pure() or op.is_foldable_guard():
-            return True
-        elif opnum == rop.JUMP:
-            return True
-        elif (opnum == rop.GETFIELD_GC or
-              opnum == rop.GETFIELD_RAW):
-            if self.heap_dirty:
-                return False
-            if descr in self.unsafe_getitem:
-                return False
-            return True
-        elif (opnum == rop.GETARRAYITEM_GC or
-              opnum == rop.GETARRAYITEM_RAW):
-            if self.heap_dirty:
-                return False
-            if descr in self.unsafe_getarrayitem:
-                return False
-            index = op.getarg(1)
-            if isinstance(index, Const):
-                d = self.unsafe_getarrayitem_indexes.get(descr, None)
-                if d is not None:
-                    if index.getint() in d:
-                        return False
-            else:
-                if descr in self.unsafe_getarrayitem_indexes:
-                    return False
-            return True
-        elif opnum == rop.CALL:
-            effectinfo = descr.get_extra_info()
-            if effectinfo is not None:
-                ef = effectinfo.extraeffect
-                if ef == EffectInfo.EF_LOOPINVARIANT or \
-                   ef == EffectInfo.EF_ELIDABLE_CANNOT_RAISE or \
-                   ef == EffectInfo.EF_ELIDABLE_CAN_RAISE:
-                    return True
-        return False
-
-    def update(self, op):
-        if (op.has_no_side_effect() or
-            op.is_ovf() or
-            op.is_guard()):
-            return
-        opnum = op.getopnum()
-        descr = op.getdescr()
-        if (opnum == rop.DEBUG_MERGE_POINT):
-            return
-        if (opnum == rop.SETFIELD_GC or
-            opnum == rop.SETFIELD_RAW):
-            self.unsafe_getitem[descr] = True
-            return
-        if (opnum == rop.SETARRAYITEM_GC or
-            opnum == rop.SETARRAYITEM_RAW):
-            index = op.getarg(1)
-            if isinstance(index, Const):
-                d = self.unsafe_getarrayitem_indexes.get(descr, None)
-                if d is None:
-                    d = self.unsafe_getarrayitem_indexes[descr] = {}
-                d[index.getint()] = True
-            else:
-                self.unsafe_getarrayitem[descr] = True
-            return
-        if opnum == rop.CALL:
-            effectinfo = descr.get_extra_info()
-            if effectinfo is not None:
-                for fielddescr in effectinfo.write_descrs_fields:
-                    self.unsafe_getitem[fielddescr] = True
-                for arraydescr in effectinfo.write_descrs_arrays:
-                    self.unsafe_getarrayitem[arraydescr] = True
-                return
-        debug_print("heap dirty due to op ", opnum)
-        self.heap_dirty = True
-
-class ImpossibleLink(JitException):
-    pass
-
-class BoxMap(object):
-    def __init__(self):
-        self.map = {}
-
-
-    def link_ops(self, preambleop, loopop):
-        pargs = preambleop.getarglist()
-        largs = loopop.getarglist()
-        if len(pargs) != len(largs):
-            raise ImpossibleLink
-        for i in range(len(largs)):
-            pbox, lbox = pargs[i], largs[i]
-            self.link_boxes(pbox, lbox)
-
-        if preambleop.result:
-            if not loopop.result:
-                raise ImpossibleLink
-            self.link_boxes(preambleop.result, loopop.result)
-
-
-    def link_boxes(self, pbox, lbox):
-        if lbox in self.map:
-            if self.map[lbox] is not pbox:
-                raise ImpossibleLink
-        else:
-            if isinstance(lbox, Const):
-                if not isinstance(pbox, Const) or not pbox.same_constant(lbox):
-                    raise ImpossibleLink
-            else:
-                self.map[lbox] = pbox
-
-
-    def get_preamblebox(self, loopbox):
-        return self.map[loopbox]
-
 class OptInlineShortPreamble(Optimization):
     def __init__(self, retraced):
         self.retraced = retraced


More information about the pypy-commit mailing list