[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