[pypy-commit] pypy jit-multilabel: add support for optimizing over multiple intermediate labels
hakanardo
noreply at buildbot.pypy.org
Sun Dec 18 11:14:40 CET 2011
Author: Hakan Ardo <hakan at debian.org>
Branch: jit-multilabel
Changeset: r50647:94ea6fc640c5
Date: 2011-12-18 11:01 +0100
http://bitbucket.org/pypy/pypy/changeset/94ea6fc640c5/
Log: add support for optimizing over multiple intermediate labels
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py b/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_multilabel.py
@@ -8,7 +8,7 @@
class BaseTestMultiLabel(BaseTest):
enable_opts = "intbounds:rewrite:virtualize:string:earlyforce:pure:heap:unroll"
- def optimize_loop(self, ops, expected):
+ def optimize_loop(self, ops, expected, expected_shorts=None):
loop = self.parse(ops)
if expected != "crash!":
expected = self.parse(expected)
@@ -32,15 +32,17 @@
if nxt < len(loop.operations):
label = loop.operations[nxt]
assert label.getopnum() == rop.LABEL
- jumpop = ResOperation(rop.JUMP, label.getarglist(),
- None, descr=token)
- operations.append(jumpop)
+ if label.getdescr() is None:
+ label.setdescr(token)
+ operations.append(label)
part.operations = operations
+
self._do_optimize_loop(part, None)
if part.operations[-1].getopnum() == rop.LABEL:
last_label = [part.operations.pop()]
else:
last_label = []
+
optimized.operations.extend(part.operations)
prv = nxt + 1
@@ -53,9 +55,32 @@
print 'Failed!'
print
+ shorts = [op.getdescr().short_preamble
+ for op in optimized.operations
+ if op.getopnum() == rop.LABEL]
+
+ if expected_shorts:
+ for short in shorts:
+ print
+ print "Short preamble:"
+ print '\n'.join([str(o) for o in short])
+
+
assert expected != "crash!", "should have raised an exception"
self.assert_equal(optimized, expected)
+ if expected_shorts:
+ assert len(shorts) == len(expected_shorts)
+ for short, expected_short in zip(shorts, expected_shorts):
+ expected_short = self.parse(expected_short)
+ short_preamble = TreeLoop('short preamble')
+ assert short[0].getopnum() == rop.LABEL
+ short_preamble.inputargs = short[0].getarglist()
+ short_preamble.operations = short
+ self.assert_equal(short_preamble, expected_short,
+ text_right='expected short preamble')
+
+
return optimized
def test_simple(self):
@@ -193,8 +218,168 @@
"""
with raises(InvalidLoop):
self.optimize_loop(ops, ops)
-
+
+ def test_two_intermediate_labels_basic_1(self):
+ ops = """
+ [p1, i1]
+ i2 = getfield_gc(p1, descr=valuedescr)
+ label(p1, i1)
+ i3 = getfield_gc(p1, descr=valuedescr)
+ i4 = int_add(i1, i3)
+ label(p1, i4)
+ i5 = int_add(i4, 1)
+ jump(p1, i5)
+ """
+ expected = """
+ [p1, i1]
+ i2 = getfield_gc(p1, descr=valuedescr)
+ label(p1, i1, i2)
+ i4 = int_add(i1, i2)
+ label(p1, i4)
+ i5 = int_add(i4, 1)
+ jump(p1, i5)
+ """
+ short1 = """
+ [p1, i1]
+ label(p1, i1)
+ i2 = getfield_gc(p1, descr=valuedescr)
+ jump(p1, i1, i2)
+ """
+ short2 = """
+ [p1, i1]
+ label(p1, i1)
+ jump(p1, i1)
+ """
+ self.optimize_loop(ops, expected, expected_shorts=[short1, short2])
+
+ def test_two_intermediate_labels_basic_2(self):
+ ops = """
+ [p1, i1]
+ i2 = int_add(i1, 1)
+ label(p1, i1)
+ i3 = getfield_gc(p1, descr=valuedescr)
+ i4 = int_add(i1, i3)
+ label(p1, i4)
+ i5 = getfield_gc(p1, descr=valuedescr)
+ i6 = int_add(i4, i5)
+ jump(p1, i6)
+ """
+ expected = """
+ [p1, i1]
+ i2 = int_add(i1, 1)
+ label(p1, i1)
+ i3 = getfield_gc(p1, descr=valuedescr)
+ i4 = int_add(i1, i3)
+ label(p1, i4, i3)
+ i6 = int_add(i4, i3)
+ jump(p1, i6, i3)
+ """
+ short1 = """
+ [p1, i1]
+ label(p1, i1)
+ jump(p1, i1)
+ """
+ short2 = """
+ [p1, i1]
+ label(p1, i1)
+ i2 = getfield_gc(p1, descr=valuedescr)
+ jump(p1, i1, i2)
+ """
+ self.optimize_loop(ops, expected, expected_shorts=[short1, short2])
+
+ def test_two_intermediate_labels_both(self):
+ ops = """
+ [p1, i1]
+ i2 = getfield_gc(p1, descr=valuedescr)
+ label(p1, i1)
+ i3 = getfield_gc(p1, descr=valuedescr)
+ i4 = int_add(i1, i3)
+ label(p1, i4)
+ i5 = getfield_gc(p1, descr=valuedescr)
+ i6 = int_mul(i4, i5)
+ jump(p1, i6)
+ """
+ expected = """
+ [p1, i1]
+ i2 = getfield_gc(p1, descr=valuedescr)
+ label(p1, i1, i2)
+ i4 = int_add(i1, i2)
+ label(p1, i4, i2)
+ i6 = int_mul(i4, i2)
+ jump(p1, i6, i2)
+ """
+ short = """
+ [p1, i1]
+ label(p1, i1)
+ i2 = getfield_gc(p1, descr=valuedescr)
+ jump(p1, i1, i2)
+ """
+ self.optimize_loop(ops, expected, expected_shorts=[short, short])
+
+ def test_import_across_multiple_labels_basic(self):
+ # Not supported, juts make sure we get a functional trace
+ ops = """
+ [p1, i1]
+ i2 = getfield_gc(p1, descr=valuedescr)
+ label(p1, i1)
+ i3 = int_add(i1, 1)
+ label(p1, i1)
+ i4 = getfield_gc(p1, descr=valuedescr)
+ i5 = int_add(i4, 1)
+ jump(p1, i5)
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_import_across_multiple_labels_with_duplication(self):
+ # Not supported, juts make sure we get a functional trace
+ ops = """
+ [p1, i1]
+ i2 = getfield_gc(p1, descr=valuedescr)
+ label(p1, i2)
+ i3 = int_add(i2, 1)
+ label(p1, i2)
+ i4 = getfield_gc(p1, descr=valuedescr)
+ i5 = int_add(i4, 1)
+ jump(p1, i5)
+ """
+ exported = """
+ [p1, i1]
+ i2 = getfield_gc(p1, descr=valuedescr)
+ i6 = same_as(i2)
+ label(p1, i2)
+ i3 = int_add(i2, 1)
+ label(p1, i2)
+ i4 = getfield_gc(p1, descr=valuedescr)
+ i5 = int_add(i4, 1)
+ jump(p1, i5)
+ """
+ self.optimize_loop(ops, exported)
+ def test_import_virtual_across_multiple_labels(self):
+ ops = """
+ [p0, i1]
+ i1a = int_add(i1, 1)
+ pv = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(pv, i1a, descr=valuedescr)
+ label(pv, i1)
+ i2 = int_mul(i1, 3)
+ label(pv, i2)
+ i3 = getfield_gc(pv, descr=valuedescr)
+ i4 = int_add(i3, i2)
+ jump(pv, i4)
+ """
+ expected = """
+ [p0, i1]
+ i1a = int_add(i1, 1)
+ i5 = same_as(i1a)
+ label(i1a, i1)
+ i2 = int_mul(i1, 3)
+ label(i1a, i2)
+ i4 = int_add(i1a, i2)
+ jump(i1a, i4)
+ """
+ self.optimize_loop(ops, expected)
+
class TestLLtype(BaseTestMultiLabel, LLtypeMixin):
pass
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
@@ -54,6 +54,7 @@
def __init__(self, metainterp_sd, loop, optimizations):
self.optimizer = UnrollableOptimizer(metainterp_sd, loop, optimizations)
+ self.boxes_created_this_iteration = None
def fix_snapshot(self, jump_args, snapshot):
if snapshot is None:
@@ -129,6 +130,12 @@
return
# Found nothing to jump to, emit a label instead
+
+ if self.short:
+ # Construct our short preamble
+ assert start_label
+ self.close_bridge(start_label)
+
self.optimizer.flush()
KillHugeIntBounds(self.optimizer).apply()
@@ -172,7 +179,13 @@
inputargs = virtual_state.make_inputargs(values, self.optimizer)
short_inputargs = virtual_state.make_inputargs(values, self.optimizer, keyboxes=True)
- short_boxes = ShortBoxes(self.optimizer, inputargs)
+
+ if self.boxes_created_this_iteration is not None:
+ for box in self.inputargs:
+ self.boxes_created_this_iteration[box] = True
+
+ short_boxes = ShortBoxes(self.optimizer, inputargs,
+ self.boxes_created_this_iteration)
self.optimizer.clear_newoperations()
for i in range(len(original_jump_args)):
diff --git a/pypy/jit/metainterp/optimizeopt/virtualstate.py b/pypy/jit/metainterp/optimizeopt/virtualstate.py
--- a/pypy/jit/metainterp/optimizeopt/virtualstate.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualstate.py
@@ -559,12 +559,13 @@
pass
class ShortBoxes(object):
- def __init__(self, optimizer, surviving_boxes):
+ def __init__(self, optimizer, surviving_boxes, availible_boxes=None):
self.potential_ops = {}
self.alternatives = {}
self.synthetic = {}
self.rename = {}
self.optimizer = optimizer
+ self.availible_boxes = availible_boxes
if surviving_boxes is not None:
for box in surviving_boxes:
@@ -635,6 +636,8 @@
return
if box in self.short_boxes_in_production:
raise BoxNotProducable
+ if self.availible_boxes is not None and box not in self.availible_boxes:
+ raise BoxNotProducable
self.short_boxes_in_production[box] = True
if box in self.potential_ops:
More information about the pypy-commit
mailing list