Author: Maciej Fijalkowski <[email protected]>
Branch: optresult-unroll
Changeset: r78575:8a00142bfe8a
Date: 2015-07-17 11:45 +0200
http://bitbucket.org/pypy/pypy/changeset/8a00142bfe8a/
Log: dance around to the music
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py
b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -30,6 +30,7 @@
class Optimization(object):
next_optimization = None
+ potential_extra_ops = None
def __init__(self):
pass # make rpython happy
@@ -302,16 +303,15 @@
def force_box(self, op):
op = self.get_box_replacement(op)
info = op.get_forwarded()
- if self.optunroll and self.optunroll.ops_to_import:
- # XXX hack, use stuff on info somehow, a bit on the hard side
- # but doable :-)
+ if self.optunroll and self.optunroll.potential_extra_ops:
+ # XXX hack
try:
- self.optunroll.ops_to_import[op]
+ preamble_op = self.optunroll.potential_extra_ops.popitem(op)
except KeyError:
pass
else:
- self.optunroll.extra_label_args.append(op)
- del self.optunroll.ops_to_import[op]
+ sb = self.optunroll.short_preamble_producer
+ sb.add_preamble_op(op, preamble_op)
if info is not None:
return info.force_box(op, self)
return op
diff --git a/rpython/jit/metainterp/optimizeopt/shortpreamble.py
b/rpython/jit/metainterp/optimizeopt/shortpreamble.py
--- a/rpython/jit/metainterp/optimizeopt/shortpreamble.py
+++ b/rpython/jit/metainterp/optimizeopt/shortpreamble.py
@@ -33,8 +33,17 @@
#
for op, (getfield_op, preamble_op) in
self.produced_short_boxes.iteritems():
if getfield_op is not placeholder:
- short_boxes.append((op, preamble_op))
- return short_boxes + self.const_short_boxes
+ if getfield_op is None:
+ short_boxes.append((op, None, preamble_op))
+ else:
+ short_boxes.append((op, getfield_op.getarg(0),
preamble_op))
+ for op, getfield_op in self.const_short_boxes:
+ preamble_arg = self.produce_arg(getfield_op.getarg(0))
+ if preamble_arg is not None:
+ short_boxes.append((op, getfield_op.getarg(0),
+ getfield_op.copy_and_change(getfield_op.getopnum(),
+ [preamble_arg])))
+ return short_boxes
def produce_short_inputargs(self):
return self.short_inputargs
@@ -53,7 +62,7 @@
if sop:
preamble_arg = self.produce_arg(sop.getarg(0))
if preamble_arg is None:
- return False
+ return None
preamble_op = ResOperation(sop.getopnum(), [preamble_arg],
descr=sop.getdescr())
else:
@@ -61,11 +70,11 @@
for arg in op.getarglist():
newarg = self.produce_arg(arg)
if newarg is None:
- return False
+ return None
arglist.append(newarg)
preamble_op = op.copy_and_change(op.getopnum(), args=arglist)
self.produced_short_boxes[op] = (sop, preamble_op)
- return True
+ return preamble_op
def add_pure_op(self, op):
assert not self.potential_ops.get(op, None)
@@ -84,16 +93,24 @@
empty_info = EmptyInfo()
class ShortPreambleBuilder(object):
- def __init__(self, short_boxes, short_inputargs, exported_infos):
+ def __init__(self, short_boxes, short_inputargs, exported_infos,
+ optimizer=None):
self.producable_ops = {}
- for op, preamble_op in short_boxes:
+ for op, sop, preamble_op in short_boxes:
self.producable_ops[op] = preamble_op
- preamble_op.set_forwarded(exported_infos.get(op, empty_info))
+ if isinstance(op, Const):
+ info = optimizer.getinfo(op)
+ else:
+ info = exported_infos[op]
+ if info is None:
+ info = empty_info
+ preamble_op.set_forwarded(info)
self.short = []
self.used_boxes = []
+ self.short_preamble_jump = []
self.short_inputargs = short_inputargs
- def use_box(self, box):
+ def use_box(self, box, optimizer=None):
preamble_op = self.producable_ops.get(box, None)
if preamble_op is None:
return
@@ -104,16 +121,25 @@
elif arg.get_forwarded() is None:
pass
else:
- xxx
+ self.short.append(arg)
+ info = arg.get_forwarded()
+ if info is not empty_info:
+ info.make_guards(arg, self.short)
+ arg.set_forwarded(None)
+ self.force_info_from(arg)
self.short.append(preamble_op)
info = preamble_op.get_forwarded()
+ preamble_op.set_forwarded(None)
if info is not empty_info:
info.make_guards(preamble_op, self.short)
- if info.is_constant():
- return
- self.used_boxes.append(preamble_op)
+ if optimizer is not None:
+ optimizer.setinfo_from_preamble(box, info)
+
+ def add_preamble_op(self, op, preamble_op):
+ self.used_boxes.append(op)
+ self.short_preamble_jump.append(preamble_op)
def build_short_preamble(self):
label_op = ResOperation(rop.LABEL, self.short_inputargs[:])
- jump_op = ResOperation(rop.JUMP, self.used_boxes)
+ jump_op = ResOperation(rop.JUMP, self.short_preamble_jump)
return [label_op] + self.short + [jump_op]
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -191,7 +191,7 @@
short = """
[i2]
p3 = cast_int_to_ptr(i2)
- #jump(i2) <- think about it
+ jump()
"""
self.optimize_loop(ops, expected, expected_short=short)
@@ -450,7 +450,7 @@
[i0]
i1 = int_is_true(i0)
guard_value(i1, 1) []
- #jump(i0) <- xxx
+ jump()
"""
self.optimize_loop(ops, expected, preamble, expected_short=short)
@@ -851,7 +851,8 @@
p2sub = new_with_vtable(descr=nodesize2)
setfield_gc(p2sub, i1, descr=valuedescr)
setfield_gc(p2, p2sub, descr=nextdescr)
- jump(i1, p2, p2sub)
+ i3 = same_as(i1)
+ jump(i1, p2, i3)
"""
expected = """
[i1, p2, i3]
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
@@ -214,3 +214,17 @@
# both getfields are available as
# well as getfield_gc_pure
+ def test_p123_anti_nested(self):
+ loop = """
+ [i1, p2, p3]
+ p3sub = getfield_gc_r(p3, descr=nextdescr)
+ i3 = getfield_gc_i(p3sub, descr=valuedescr)
+ escape_n(i3)
+ p1 = new_with_vtable(descr=nodesize)
+ p2sub = new_with_vtable(descr=nodesize2)
+ setfield_gc(p2sub, i1, descr=valuedescr)
+ setfield_gc(p2, p2sub, descr=nextdescr)
+ jump(i1, p1, p2)
+ """
+ es, loop, preamble = self.optimize(loop)
+ xxx
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
@@ -27,10 +27,9 @@
See force_op_from_preamble for details how the extra things are put.
"""
- def __init__(self, op, preamble_op, info):
+ def __init__(self, op, preamble_op):
self.op = op
self.preamble_op = preamble_op
- self.info = info
def getarg(self, i):
return self.op.getarg(i)
@@ -42,10 +41,8 @@
class UnrollableOptimizer(Optimizer):
def force_op_from_preamble(self, preamble_op):
op = preamble_op.op
- self.optunroll.short.append(preamble_op.preamble_op)
- if preamble_op.info:
- self.setinfo_from_preamble(op, preamble_op.info)
- preamble_op.info.make_guards(op, self.optunroll.short)
+ self.optunroll.short_preamble_producer.use_box(op, self)
+ self.potential_extra_ops[op] = preamble_op
return op
def setinfo_from_preamble(self, op, preamble_info):
@@ -108,29 +105,36 @@
return exported_state, self.optimizer._newoperations
def optimize_peeled_loop(self, start_label, end_jump, ops, state):
- self.short = []
- self.extra_label_args = []
self._check_no_forwarding([[start_label, end_jump], ops])
self.import_state(start_label, state)
+ self.optimizer.potential_extra_ops = {}
self.optimizer.propagate_all_forward(start_label.getarglist()[:], ops,
rename_inputargs=False)
jump_args = [self.get_box_replacement(op)
for op in end_jump.getarglist()]
- args_from_extras = [self.get_box_replacement(op) for op in
- self.extra_label_args]
jump_args = state.virtual_state.make_inputargs(jump_args,
- self.optimizer, force_boxes=True) + args_from_extras
+ self.optimizer, force_boxes=True)
+ jump_args += self.inline_short_preamble(jump_args)
jump_op = ResOperation(rop.JUMP, jump_args)
self.optimizer._newoperations.append(jump_op)
- return (UnrollInfo(self.make_short_preamble(start_label.getarglist()),
- self.extra_label_args),
+ return (UnrollInfo(self.short_preamble_producer.build_short_preamble(),
+ self.short_preamble_producer.used_boxes),
self.optimizer._newoperations)
- def make_short_preamble(self, args):
- label = ResOperation(rop.LABEL, args)
- short = [label] + self.short
- return short
+ def inline_short_preamble(self, jump_args):
+ sb = self.short_preamble_producer
+ assert len(sb.short_inputargs) == len(jump_args)
+ for i in range(len(jump_args)):
+ sb.short_inputargs[i].set_forwarded(None)
+ self.make_equal_to(sb.short_inputargs[i], jump_args[i])
+ for op in sb.short:
+ self.optimizer.send_extra_operation(op)
+ res = [self.optimizer.get_box_replacement(op) for op in
+ sb.short_preamble_jump]
+ for op in sb.short_inputargs:
+ op.set_forwarded(None)
+ return res
def random_garbage(self):
# WTF is the rest of this function
@@ -236,7 +240,7 @@
infos = {}
for arg in end_args:
infos[arg] = self.optimizer.getinfo(arg)
- for box, _ in short_boxes:
+ for box, _, _ in short_boxes:
if not isinstance(box, Const):
infos[box] = self.optimizer.getinfo(box)
label_args = virtual_state.make_inputargs(end_args, self.optimizer)
@@ -295,7 +299,8 @@
def import_state(self, targetop, exported_state):
# the mapping between input args (from old label) and what we need
# to actually emit. Update the info
- self.ops_to_import = {}
+ #self.ops_to_import = {}
+ virtual_state = exported_state.virtual_state
for source, target in exported_state.inputarg_mapping:
if source is not target:
source.set_forwarded(target)
@@ -304,23 +309,27 @@
self.optimizer.setinfo_from_preamble(source, info)
# import the optimizer state, starting from boxes that can be produced
# by short preamble
- self.short_preamble_producer = ShortPreambleProducer()
- for op, getfield_op in exported_state.short_boxes:
- if getfield_op is None:
+ short_inpargs = virtual_state.make_inputargs(
+ exported_state.short_inputargs, None)
+ self.short_preamble_producer = ShortPreambleBuilder(
+ exported_state.short_boxes, short_inpargs,
+ exported_state.exported_infos, self.optimizer)
+ for op, structop, preamble_op in exported_state.short_boxes:
+ if structop is None:
optpure = self.optimizer.optpure
if optpure is None:
continue
- self.pure(op.getopnum(), PreambleOp(op, None,
- exported_state.exported_infos.get(op, None)))
+ self.pure(op.getopnum(), PreambleOp(op, preamble_op))
else:
optheap = self.optimizer.optheap
if optheap is None:
continue
- opinfo = self.optimizer.ensure_ptr_info_arg0(getfield_op)
- pre_info = exported_state.exported_infos.get(op, None)
- pop = PreambleOp(op, None, pre_info)
+ g = preamble_op.copy_and_change(preamble_op.getopnum(),
+ args=[structop])
+ opinfo = self.optimizer.ensure_ptr_info_arg0(g)
+ pop = PreambleOp(op, preamble_op)
assert not opinfo.is_virtual()
- opinfo._fields[getfield_op.getdescr().get_index()] = pop
+ opinfo._fields[preamble_op.getdescr().get_index()] = pop
#if not isinstance(op, Const):
# self.ops_to_import[op] = None
# XXX think later about the short preamble
@@ -776,7 +785,7 @@
""" A state after optimizing the peeled loop, contains the following:
* short_preamble - list of operations that go into short preamble
- * extra_label_args - list of extra operations that go into the label
+ * extra_label_args - additional things to put in the label
"""
def __init__(self, short_preamble, extra_label_args):
self.short_preamble = short_preamble
diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py
b/rpython/jit/metainterp/optimizeopt/virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py
@@ -133,10 +133,11 @@
raise NotImplementedError
def enum_forced_boxes(self, boxes, box, optimizer, force_boxes=False):
- info = optimizer.getptrinfo(box)
- box = optimizer.get_box_replacement(box)
- if info is None or not info.is_virtual():
- raise BadVirtualState()
+ if optimizer is not None:
+ info = optimizer.getptrinfo(box)
+ box = optimizer.get_box_replacement(box)
+ if info is None or not info.is_virtual():
+ raise BadVirtualState()
for i in range(len(self.fielddescrs)):
state = self.fieldstate[i]
if not state:
@@ -427,14 +428,15 @@
if self.level == LEVEL_CONSTANT:
return
assert 0 <= self.position_in_notvirtuals
- box = optimizer.get_box_replacement(box)
- if box.type == 'r':
- info = optimizer.getptrinfo(box)
- if info and info.is_virtual():
- if force_boxes:
- info.force_box(box, optimizer)
- else:
- raise BadVirtualState
+ if optimizer is not None:
+ box = optimizer.get_box_replacement(box)
+ if box.type == 'r':
+ info = optimizer.getptrinfo(box)
+ if info and info.is_virtual():
+ if force_boxes:
+ info.force_box(box, optimizer)
+ else:
+ raise BadVirtualState
boxes[self.position_in_notvirtuals] = box
def _enum(self, virtual_state):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit