[pypy-commit] pypy jit-targets: refactor unrolling to use the new target resop
hakanardo
noreply at buildbot.pypy.org
Fri Nov 4 21:14:45 CET 2011
Author: Hakan Ardo <hakan at debian.org>
Branch: jit-targets
Changeset: r48763:9ef690e84b21
Date: 2011-11-04 21:14 +0100
http://bitbucket.org/pypy/pypy/changeset/9ef690e84b21/
Log: refactor unrolling to use the new target resop
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -766,10 +766,10 @@
self.compiled_loop_token.cpu.dump_loop_token(self)
class TargetToken(AbstractDescr):
- pass
+ def __init__(self):
+ self.exported_state = None
class TreeLoop(object):
- inputargs = None
operations = None
token = None
call_pure_results = None
@@ -778,11 +778,24 @@
def __init__(self, name):
self.name = name
- # self.inputargs = list of distinct Boxes
# self.operations = list of ResOperations
# ops of the kind 'guard_xxx' contain a further list of operations,
# which may itself contain 'guard_xxx' and so on, making a tree.
+ _inputargs = None
+
+ def get_inputargs(self):
+ "NOT_RPYTHON"
+ if self._inputargs is not None:
+ return self._inputargs
+ assert self.operations[0].getopnum() == rop.TARGET
+ return self.operations[0].getarglist()
+
+ def set_inputargs(self, inputargs):
+ self._inputargs = inputargs
+
+ inputargs = property(get_inputargs, set_inputargs)
+
def _all_operations(self, omit_finish=False):
"NOT_RPYTHON"
result = []
@@ -801,7 +814,7 @@
return self.operations
def get_display_text(self): # for graphpage.py
- return self.name + '\n' + repr(self.inputargs)
+ return self.name
def show(self, errmsg=None):
"NOT_RPYTHON"
@@ -810,15 +823,13 @@
def check_consistency(self): # for testing
"NOT_RPYTHON"
- self.check_consistency_of(self.inputargs, self.operations)
+ self.check_consistency_of(self.operations)
@staticmethod
- def check_consistency_of(inputargs, operations):
- for box in inputargs:
- assert isinstance(box, Box), "Loop.inputargs contains %r" % (box,)
+ def check_consistency_of(operations):
+ assert operations[0].getopnum() == rop.TARGET
+ inputargs = operations[0].getarglist()
seen = dict.fromkeys(inputargs)
- assert len(seen) == len(inputargs), (
- "duplicate Box in the Loop.inputargs")
TreeLoop.check_consistency_of_branch(operations, seen)
@staticmethod
@@ -845,6 +856,14 @@
assert isinstance(box, Box)
assert box not in seen
seen[box] = True
+ if op.getopnum() == rop.TARGET:
+ inputargs = op.getarglist()
+ for box in inputargs:
+ assert isinstance(box, Box), "TARGET contains %r" % (box,)
+ seen = dict.fromkeys(inputargs)
+ assert len(seen) == len(inputargs), (
+ "duplicate Box in the TARGET arguments")
+
assert operations[-1].is_final()
if operations[-1].getopnum() == rop.JUMP:
target = operations[-1].getdescr()
@@ -853,7 +872,7 @@
def dump(self):
# RPython-friendly
- print '%r: inputargs =' % self, self._dump_args(self.inputargs)
+ print '%r: ' % self
for op in self.operations:
args = op.getarglist()
print '\t', op.getopname(), self._dump_args(args), \
diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -80,3 +80,14 @@
if __name__ == '__main__':
print ALL_OPTS_NAMES
+
+def optimize_trace(metainterp_sd, loop, enable_opts):
+ """Optimize loop.operations to remove internal overheadish operations.
+ """
+
+ optimizations, unroll = build_opt_chain(metainterp_sd, enable_opts, False, False)
+ if unroll:
+ optimize_unroll(metainterp_sd, loop, optimizations)
+ else:
+ optimizer = Optimizer(metainterp_sd, loop, optimizations, bridge)
+ optimizer.propagate_all_forward()
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -497,9 +497,10 @@
else:
return CVAL_ZERO
- def propagate_all_forward(self):
+ def propagate_all_forward(self, clear=True):
self.exception_might_have_happened = self.bridge
- self.clear_newoperations()
+ if clear:
+ self.clear_newoperations()
for op in self.loop.operations:
self.first_optimization.propagate_forward(op)
self.loop.operations = self.get_newoperations()
@@ -556,6 +557,7 @@
def store_final_boxes_in_guard(self, op):
descr = op.getdescr()
+ print 'HHHHHHHHHHHH', descr, id(descr)
assert isinstance(descr, compile.ResumeGuardDescr)
modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo)
newboxes = modifier.finish(self.values, self.pendingfields)
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -7,7 +7,7 @@
from pypy.jit.metainterp.optimizeopt import optimize_loop_1, ALL_OPTS_DICT, build_opt_chain
from pypy.jit.metainterp.optimize import InvalidLoop
from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt
-from pypy.jit.metainterp.history import TreeLoop, LoopToken
+from pypy.jit.metainterp.history import TreeLoop, LoopToken, TargetToken
from pypy.jit.metainterp.jitprof import EmptyProfiler
from pypy.jit.metainterp import executor, compile, resume, history
from pypy.jit.metainterp.resoperation import rop, opname, ResOperation
@@ -15,7 +15,7 @@
from pypy.jit.metainterp.optimizeopt.util import args_dict
from pypy.jit.metainterp.optimizeopt.test.test_optimizebasic import FakeMetaInterpStaticData
from pypy.config.pypyoption import get_pypy_config
-
+from pypy.jit.metainterp.optimizeopt.unroll import Inliner
def test_build_opt_chain():
def check(chain, expected_names):
@@ -79,43 +79,83 @@
expected_preamble = self.parse(expected_preamble)
if expected_short:
expected_short = self.parse(expected_short)
- loop.preamble = TreeLoop('preamble')
- loop.preamble.inputargs = loop.inputargs
- loop.preamble.token = LoopToken()
- loop.preamble.start_resumedescr = FakeDescr()
- #
+ operations = loop.operations
+ cloned_operations = [op.clone() for op in operations]
+
+ preamble = TreeLoop('preamble')
+ #loop.preamble.inputargs = loop.inputargs
+ #loop.preamble.token = LoopToken()
+ preamble.start_resumedescr = FakeDescr()
+ assert operations[-1].getopnum() == rop.JUMP
+ inputargs = loop.inputargs
+ jump_args = operations[-1].getarglist()
+ targettoken = TargetToken()
+ operations[-1].setdescr(targettoken)
+ cloned_operations[-1].setdescr(targettoken)
+ preamble.operations = [ResOperation(rop.TARGET, inputargs, None, descr=TargetToken())] + \
+ operations[:-1] + \
+ [ResOperation(rop.TARGET, jump_args, None, descr=targettoken)]
+ self._do_optimize_loop(preamble, call_pure_results)
+
+ jump_args = preamble.operations[-1].getdescr().exported_state.jump_args # FIXME!!
+ inliner = Inliner(inputargs, jump_args)
+ loop.inputargs = None
+ loop.start_resumedescr = preamble.start_resumedescr
+ loop.operations = [preamble.operations[-1]] + \
+ [inliner.inline_op(op, clone=False) for op in cloned_operations]
self._do_optimize_loop(loop, call_pure_results)
+ extra_same_as = []
+ while loop.operations[0].getopnum() != rop.TARGET:
+ extra_same_as.append(loop.operations[0])
+ del loop.operations[0]
+
+ # Hack to prevent random order of same_as ops
+ extra_same_as.sort(key=lambda op: str(preamble.operations).find(str(op.getarg(0))))
+
+ for op in extra_same_as:
+ preamble.operations.insert(-1, op)
+
#
print
print "Preamble:"
- print loop.preamble.inputargs
- if loop.preamble.operations:
- print '\n'.join([str(o) for o in loop.preamble.operations])
+ if preamble.operations:
+ print '\n'.join([str(o) for o in preamble.operations])
else:
print 'Failed!'
print
print "Loop:"
- print loop.inputargs
print '\n'.join([str(o) for o in loop.operations])
print
if expected_short:
print "Short Preamble:"
- short = loop.preamble.token.short_preamble[0]
+ short = loop.token.short_preamble[0]
print short.inputargs
print '\n'.join([str(o) for o in short.operations])
print
assert expected != "crash!", "should have raised an exception"
- self.assert_equal(loop, expected)
+ self.assert_equal(loop, convert_old_style_to_targets(expected, jump=True))
+ assert loop.operations[0].getdescr() == loop.operations[-1].getdescr()
if expected_preamble:
- self.assert_equal(loop.preamble, expected_preamble,
+ self.assert_equal(preamble, convert_old_style_to_targets(expected_preamble, jump=False),
text_right='expected preamble')
+ assert preamble.operations[-1].getdescr() == loop.operations[0].getdescr()
if expected_short:
- self.assert_equal(short, expected_short,
+ self.assert_equal(short, convert_old_style_to_targets(expected_short, jump=True),
text_right='expected short preamble')
+ assert short.operations[-1].getdescr() == loop.operations[0].getdescr()
return loop
+def convert_old_style_to_targets(loop, jump):
+ newloop = TreeLoop(loop.name)
+ newloop.operations = [ResOperation(rop.TARGET, loop.inputargs, None, descr=FakeDescr())] + \
+ loop.operations
+ if not jump:
+ assert newloop.operations[-1].getopnum() == rop.JUMP
+ newloop.operations[-1] = ResOperation(rop.TARGET, newloop.operations[-1].getarglist(), None, descr=FakeDescr())
+ return newloop
+
class OptimizeOptTest(BaseTestWithUnroll):
def setup_method(self, meth=None):
@@ -234,7 +274,7 @@
""" % expected_value
self.optimize_loop(ops, expected)
- def test_reverse_of_cast(self):
+ def test_reverse_of_cast_1(self):
ops = """
[i0]
p0 = cast_int_to_ptr(i0)
@@ -246,6 +286,8 @@
jump(i0)
"""
self.optimize_loop(ops, expected)
+
+ def test_reverse_of_cast_2(self):
ops = """
[p0]
i1 = cast_ptr_to_int(p0)
@@ -1166,6 +1208,7 @@
i1 = getfield_gc(p0, descr=valuedescr)
i2 = int_sub(i1, 1)
i3 = int_add(i0, i1)
+ i4 = same_as(i2) # This same_as should be killed by backend
jump(i3, i2, i1)
"""
expected = """
@@ -1233,6 +1276,7 @@
p30 = new_with_vtable(ConstClass(node_vtable))
setfield_gc(p30, i28, descr=nextdescr)
setfield_gc(p3, p30, descr=valuedescr)
+ p46 = same_as(p30) # This same_as should be killed by backend
jump(i29, p30, p3)
"""
expected = """
@@ -1240,8 +1284,8 @@
i28 = int_add(i0, 1)
i29 = int_add(i28, 1)
p30 = new_with_vtable(ConstClass(node_vtable))
+ setfield_gc(p30, i28, descr=nextdescr)
setfield_gc(p3, p30, descr=valuedescr)
- setfield_gc(p30, i28, descr=nextdescr)
jump(i29, p30, p3)
"""
self.optimize_loop(ops, expected, preamble)
@@ -2034,7 +2078,9 @@
guard_true(i3) []
i4 = int_neg(i2)
setfield_gc(p1, i2, descr=valuedescr)
- jump(p1, i1, i2, i4, i4)
+ i7 = same_as(i2) # This same_as should be killed by backend
+ i6 = same_as(i4)
+ jump(p1, i1, i2, i4, i6)
"""
expected = """
[p1, i1, i2, i4, i5]
@@ -2064,7 +2110,8 @@
i4 = int_neg(i2)
setfield_gc(p1, NULL, descr=nextdescr)
escape()
- jump(p1, i2, i4, i4)
+ i5 = same_as(i4)
+ jump(p1, i2, i4, i5)
"""
expected = """
[p1, i2, i4, i5]
@@ -2093,7 +2140,8 @@
i4 = int_neg(i2)
setfield_gc(p1, NULL, descr=nextdescr)
escape()
- jump(p1, i2, i4, i4)
+ i5 = same_as(i4)
+ jump(p1, i2, i4, i5)
"""
expected = """
[p1, i2, i4, i5]
@@ -2123,7 +2171,9 @@
guard_true(i5) []
i4 = int_neg(i2)
setfield_gc(p1, i2, descr=valuedescr)
- jump(p1, i1, i2, i4, i4)
+ i8 = same_as(i2) # This same_as should be killed by backend
+ i7 = same_as(i4)
+ jump(p1, i1, i2, i4, i7)
"""
expected = """
[p1, i1, i2, i4, i7]
@@ -2349,7 +2399,8 @@
p2 = new_with_vtable(ConstClass(node_vtable))
setfield_gc(p2, p4, descr=nextdescr)
setfield_gc(p1, p2, descr=nextdescr)
- jump(p1, i2, i4, p4, i4)
+ i101 = same_as(i4)
+ jump(p1, i2, i4, p4, i101)
"""
expected = """
[p1, i2, i4, p4, i5]
@@ -3192,7 +3243,15 @@
setfield_gc(p1, i3, descr=valuedescr)
jump(p1, i4, i3)
'''
- self.optimize_loop(ops, ops, ops)
+ preamble = '''
+ [p1, i1, i4]
+ setfield_gc(p1, i1, descr=valuedescr)
+ i3 = call_assembler(i1, descr=asmdescr)
+ setfield_gc(p1, i3, descr=valuedescr)
+ i143 = same_as(i3) # Should be killed by backend
+ jump(p1, i4, i3)
+ '''
+ self.optimize_loop(ops, ops, preamble)
def test_call_assembler_invalidates_heap_knowledge(self):
ops = '''
@@ -3223,7 +3282,9 @@
setfield_gc(p1, i1, descr=valuedescr)
i3 = call(p1, descr=plaincalldescr)
setfield_gc(p1, i3, descr=valuedescr)
- jump(p1, i4, i3, i3)
+ i148 = same_as(i3)
+ i147 = same_as(i3)
+ jump(p1, i4, i3, i148)
'''
self.optimize_loop(ops, expected, preamble)
@@ -3246,7 +3307,8 @@
setfield_gc(p1, i1, descr=valuedescr)
i3 = call(p1, descr=plaincalldescr)
setfield_gc(p1, i1, descr=valuedescr)
- jump(p1, i4, i3, i3)
+ i151 = same_as(i3)
+ jump(p1, i4, i3, i151)
'''
self.optimize_loop(ops, expected, preamble)
@@ -3266,7 +3328,8 @@
escape(i1)
escape(i2)
i4 = call(123456, 4, i0, 6, descr=plaincalldescr)
- jump(i0, i4, i4)
+ i153 = same_as(i4)
+ jump(i0, i4, i153)
'''
expected = '''
[i0, i4, i5]
@@ -3296,7 +3359,8 @@
escape(i2)
i4 = call(123456, 4, i0, 6, descr=plaincalldescr)
guard_no_exception() []
- jump(i0, i4, i4)
+ i155 = same_as(i4)
+ jump(i0, i4, i155)
'''
expected = '''
[i0, i2, i3]
@@ -4114,6 +4178,7 @@
preamble = """
[p0]
i0 = strlen(p0)
+ i3 = same_as(i0) # Should be killed by backend
jump(p0)
"""
expected = """
@@ -5334,6 +5399,7 @@
[p0]
p1 = getfield_gc(p0, descr=valuedescr)
setfield_gc(p0, p0, descr=valuedescr)
+ p4450 = same_as(p0) # Should be killed by backend
jump(p0)
"""
expected = """
@@ -5479,7 +5545,8 @@
p3 = newstr(i3)
copystrcontent(p1, p3, 0, 0, i1)
copystrcontent(p2, p3, 0, i1, i2)
- jump(p2, p3, i2)
+ i7 = same_as(i2)
+ jump(p2, p3, i7)
"""
expected = """
[p1, p2, i1]
@@ -5554,7 +5621,9 @@
copystrcontent(p1, p5, 0, 0, i1)
copystrcontent(p2, p5, 0, i1, i2)
copystrcontent(p3, p5, 0, i12, i3)
- jump(p2, p3, p5, i2, i3)
+ i129 = same_as(i2)
+ i130 = same_as(i3)
+ jump(p2, p3, p5, i129, i130)
"""
expected = """
[p1, p2, p3, i1, i2]
@@ -5614,7 +5683,8 @@
[p1, i1, i2, i3]
escape(i3)
i4 = int_sub(i2, i1)
- jump(p1, i1, i2, i4, i4)
+ i5 = same_as(i4)
+ jump(p1, i1, i2, i4, i5)
"""
expected = """
[p1, i1, i2, i3, i4]
@@ -5639,7 +5709,8 @@
escape(i5)
i4 = int_sub(i2, i1)
setfield_gc(p2, i4, descr=valuedescr)
- jump(p1, i1, i2, p2, i4, i4)
+ i8 = same_as(i4)
+ jump(p1, i1, i2, p2, i8, i4)
"""
expected = """
[p1, i1, i2, p2, i5, i6]
@@ -5765,7 +5836,8 @@
p4 = newstr(i5)
copystrcontent(p1, p4, i1, 0, i3)
copystrcontent(p2, p4, 0, i3, i4)
- jump(p4, i1, i2, p2, i5, i3, i4)
+ i9 = same_as(i4)
+ jump(p4, i1, i2, p2, i5, i3, i9)
"""
expected = """
[p1, i1, i2, p2, i5, i3, i4]
@@ -5887,7 +5959,9 @@
copystrcontent(p2, p4, 0, i1, i2)
i0 = call(0, p3, p4, descr=strequaldescr)
escape(i0)
- jump(p1, p2, p3, i3, i1, i2)
+ i11 = same_as(i1)
+ i12 = same_as(i2)
+ jump(p1, p2, p3, i3, i11, i12)
"""
expected = """
[p1, p2, p3, i3, i1, i2]
@@ -6107,6 +6181,7 @@
i1 = strlen(p1)
i0 = int_eq(i1, 0)
escape(i0)
+ i3 = same_as(i1)
jump(p1, i0)
"""
self.optimize_strunicode_loop_extradescrs(ops, expected, preamble)
@@ -6152,7 +6227,9 @@
copystrcontent(p2, p4, 0, i1, i2)
i0 = call(0, s"hello world", p4, descr=streq_nonnull_descr)
escape(i0)
- jump(p1, p2, i3, i1, i2)
+ i11 = same_as(i1)
+ i12 = same_as(i2)
+ jump(p1, p2, i3, i11, i12)
"""
expected = """
[p1, p2, i3, i1, i2]
@@ -6436,7 +6513,8 @@
p188 = getarrayitem_gc(p187, 42, descr=<GcPtrArrayDescr>)
guard_value(p188, ConstPtr(myptr)) []
p25 = getfield_gc(ConstPtr(myptr), descr=otherdescr)
- jump(p25, p187, i184, p25)
+ p26 = same_as(p25)
+ jump(p25, p187, i184, p26)
"""
short = """
[p1, p187, i184]
@@ -6705,7 +6783,8 @@
[p9]
i843 = strlen(p9)
call(i843, descr=nonwritedescr)
- jump(p9, i843)
+ i0 = same_as(i843)
+ jump(p9, i0)
"""
short = """
[p9]
@@ -7397,7 +7476,8 @@
call(i2, descr=nonwritedescr)
setfield_gc(p22, i1, descr=valuedescr)
guard_nonnull_class(p18, ConstClass(node_vtable)) []
- jump(p22, p18, i1, i1)
+ i10 = same_as(i1)
+ jump(p22, p18, i1, i10)
"""
short = """
[p22, p18, i1]
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_util.py b/pypy/jit/metainterp/optimizeopt/test/test_util.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_util.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_util.py
@@ -384,7 +384,7 @@
expected.operations, False, remap, text_right)
def _do_optimize_loop(self, loop, call_pure_results):
- from pypy.jit.metainterp.optimizeopt import optimize_loop_1
+ from pypy.jit.metainterp.optimizeopt import optimize_trace
from pypy.jit.metainterp.optimizeopt.util import args_dict
self.loop = loop
@@ -398,7 +398,7 @@
if hasattr(self, 'callinfocollection'):
metainterp_sd.callinfocollection = self.callinfocollection
#
- optimize_loop_1(metainterp_sd, loop, self.enable_opts)
+ optimize_trace(metainterp_sd, loop, self.enable_opts)
# ____________________________________________________________
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
@@ -1,7 +1,7 @@
from pypy.jit.codewriter.effectinfo import EffectInfo
from pypy.jit.metainterp.optimizeopt.virtualstate import VirtualStateAdder, ShortBoxes
from pypy.jit.metainterp.compile import ResumeGuardDescr
-from pypy.jit.metainterp.history import TreeLoop, LoopToken
+from pypy.jit.metainterp.history import TreeLoop, LoopToken, TargetToken
from pypy.jit.metainterp.jitexc import JitException
from pypy.jit.metainterp.optimize import InvalidLoop, RetraceLoop
from pypy.jit.metainterp.optimizeopt.optimizer import *
@@ -103,12 +103,8 @@
def __init__(self, metainterp_sd, loop, optimizations):
self.optimizer = UnrollableOptimizer(metainterp_sd, loop, optimizations)
- self.cloned_operations = []
- for op in self.optimizer.loop.operations:
- newop = op.clone()
- self.cloned_operations.append(newop)
- def fix_snapshot(self, loop, jump_args, snapshot):
+ def fix_snapshot(self, jump_args, snapshot):
if snapshot is None:
return None
snapshot_args = snapshot.boxes
@@ -116,233 +112,170 @@
for a in snapshot_args:
a = self.getvalue(a).get_key_box()
new_snapshot_args.append(a)
- prev = self.fix_snapshot(loop, jump_args, snapshot.prev)
+ prev = self.fix_snapshot(jump_args, snapshot.prev)
return Snapshot(prev, new_snapshot_args)
def propagate_all_forward(self):
loop = self.optimizer.loop
- jumpop = loop.operations[-1]
- if jumpop.getopnum() == rop.JUMP:
+ start_targetop = loop.operations[0]
+ assert start_targetop.getopnum() == rop.TARGET
+ loop.operations = loop.operations[1:]
+ self.optimizer.clear_newoperations()
+ self.optimizer.send_extra_operation(start_targetop)
+
+ self.import_state(start_targetop)
+
+ lastop = loop.operations[-1]
+ if lastop.getopnum() == rop.TARGET or lastop.getopnum() == rop.JUMP:
loop.operations = loop.operations[:-1]
- else:
- loopop = None
-
- self.optimizer.propagate_all_forward()
-
-
- if jumpop:
- assert jumpop.getdescr() is loop.token
- jump_args = jumpop.getarglist()
- jumpop.initarglist([])
+ #FIXME: FINISH
+
+ self.optimizer.propagate_all_forward(clear=False)
+
+ if lastop.getopnum() == rop.TARGET:
self.optimizer.flush()
-
KillHugeIntBounds(self.optimizer).apply()
-
- loop.preamble.operations = self.optimizer.get_newoperations()
- jump_args = [self.getvalue(a).get_key_box() for a in jump_args]
-
- start_resumedescr = loop.preamble.start_resumedescr.clone_if_mutable()
- self.start_resumedescr = start_resumedescr
- assert isinstance(start_resumedescr, ResumeGuardDescr)
- start_resumedescr.rd_snapshot = self.fix_snapshot(loop, jump_args,
- start_resumedescr.rd_snapshot)
-
- modifier = VirtualStateAdder(self.optimizer)
- virtual_state = modifier.get_virtual_state(jump_args)
-
- values = [self.getvalue(arg) for arg in jump_args]
- inputargs = virtual_state.make_inputargs(values, self.optimizer)
- short_inputargs = virtual_state.make_inputargs(values, self.optimizer,
- keyboxes=True)
-
- self.constant_inputargs = {}
- for box in jump_args:
- const = self.get_constant_box(box)
- if const:
- self.constant_inputargs[box] = const
-
- sb = ShortBoxes(self.optimizer, inputargs + self.constant_inputargs.keys())
- self.short_boxes = sb
- preamble_optimizer = self.optimizer
- loop.preamble.quasi_immutable_deps = (
- self.optimizer.quasi_immutable_deps)
- self.optimizer = self.optimizer.new()
- loop.quasi_immutable_deps = self.optimizer.quasi_immutable_deps
-
- logops = self.optimizer.loop.logops
- if logops:
- args = ", ".join([logops.repr_of_arg(arg) for arg in inputargs])
- debug_print('inputargs: ' + args)
- args = ", ".join([logops.repr_of_arg(arg) for arg in short_inputargs])
- debug_print('short inputargs: ' + args)
- self.short_boxes.debug_print(logops)
-
-
- # Force virtuals amoung the jump_args of the preamble to get the
- # operations needed to setup the proper state of those virtuals
- # in the peeled loop
- inputarg_setup_ops = []
- preamble_optimizer.clear_newoperations()
- seen = {}
- for box in inputargs:
- if box in seen:
- continue
- seen[box] = True
- preamble_value = preamble_optimizer.getvalue(box)
- value = self.optimizer.getvalue(box)
- value.import_from(preamble_value, self.optimizer)
- for box in short_inputargs:
- if box in seen:
- continue
- seen[box] = True
- value = preamble_optimizer.getvalue(box)
- value.force_box(preamble_optimizer)
- inputarg_setup_ops += preamble_optimizer.get_newoperations()
-
- # Setup the state of the new optimizer by emiting the
- # short preamble operations and discarding the result
- self.optimizer.emitting_dissabled = True
- for op in inputarg_setup_ops:
- self.optimizer.send_extra_operation(op)
- seen = {}
- for op in self.short_boxes.operations():
- self.ensure_short_op_emitted(op, self.optimizer, seen)
- if op and op.result:
- preamble_value = preamble_optimizer.getvalue(op.result)
- value = self.optimizer.getvalue(op.result)
- if not value.is_virtual():
- imp = ValueImporter(self, preamble_value, op)
- self.optimizer.importable_values[value] = imp
- newresult = self.optimizer.getvalue(op.result).get_key_box()
- if newresult is not op.result:
- self.short_boxes.alias(newresult, op.result)
- self.optimizer.flush()
- self.optimizer.emitting_dissabled = False
-
- initial_inputargs_len = len(inputargs)
- self.inliner = Inliner(loop.inputargs, jump_args)
-
-
- short = self.inline(inputargs, self.cloned_operations,
- loop.inputargs, short_inputargs,
- virtual_state)
-
- loop.inputargs = inputargs
- args = [preamble_optimizer.getvalue(self.short_boxes.original(a)).force_box(preamble_optimizer)\
- for a in inputargs]
- jmp = ResOperation(rop.JUMP, args, None)
- jmp.setdescr(loop.token)
- loop.preamble.operations.append(jmp)
loop.operations = self.optimizer.get_newoperations()
- maxguards = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.max_retrace_guards
+ self.export_state(lastop)
+ loop.operations.append(lastop)
+ elif lastop.getopnum() == rop.JUMP:
+ assert lastop.getdescr() is start_targetop.getdescr()
+ self.close_loop(lastop)
+ short_preamble_loop = self.produce_short_preamble(lastop)
+ assert isinstance(loop.token, LoopToken)
+ if loop.token.short_preamble:
+ loop.token.short_preamble.append(short_preamble_loop) # FIXME: ??
+ else:
+ loop.token.short_preamble = [short_preamble_loop]
+ else:
+ loop.operations = self.optimizer.get_newoperations()
+
+ def export_state(self, targetop):
+ jump_args = targetop.getarglist()
+ jump_args = [self.getvalue(a).get_key_box() for a in jump_args]
+
+ start_resumedescr = self.optimizer.loop.start_resumedescr.clone_if_mutable()
+ assert isinstance(start_resumedescr, ResumeGuardDescr)
+ start_resumedescr.rd_snapshot = self.fix_snapshot(jump_args, start_resumedescr.rd_snapshot)
+
+ modifier = VirtualStateAdder(self.optimizer)
+ virtual_state = modifier.get_virtual_state(jump_args)
- if self.optimizer.emitted_guards > maxguards:
- loop.preamble.token.retraced_count = sys.maxint
+ values = [self.getvalue(arg) for arg in jump_args]
+ inputargs = virtual_state.make_inputargs(values, self.optimizer)
+ short_inputargs = virtual_state.make_inputargs(values, self.optimizer, keyboxes=True)
- if short:
- assert short[-1].getopnum() == rop.JUMP
- short[-1].setdescr(loop.token)
+ constant_inputargs = {}
+ for box in jump_args:
+ const = self.get_constant_box(box)
+ if const:
+ constant_inputargs[box] = const
- # Turn guards into conditional jumps to the preamble
- for i in range(len(short)):
- op = short[i]
- if op.is_guard():
- op = op.clone()
- op.setfailargs(None)
- descr = self.start_resumedescr.clone_if_mutable()
- op.setdescr(descr)
- short[i] = op
+ short_boxes = ShortBoxes(self.optimizer, inputargs + constant_inputargs.keys())
- short_loop = TreeLoop('short preamble')
- short_loop.inputargs = short_inputargs
- short_loop.operations = short
+ self.optimizer.clear_newoperations()
+ for box in short_inputargs:
+ value = self.getvalue(box)
+ if value.is_virtual():
+ value.force_box(self.optimizer)
+ inputarg_setup_ops = self.optimizer.get_newoperations()
- # Clone ops and boxes to get private versions and
- boxmap = {}
- newargs = [None] * len(short_loop.inputargs)
- for i in range(len(short_loop.inputargs)):
- a = short_loop.inputargs[i]
- if a in boxmap:
- newargs[i] = boxmap[a]
- else:
- newargs[i] = a.clonebox()
- boxmap[a] = newargs[i]
- inliner = Inliner(short_loop.inputargs, newargs)
- for box, const in self.constant_inputargs.items():
- inliner.argmap[box] = const
- short_loop.inputargs = newargs
- ops = [inliner.inline_op(op) for op in short_loop.operations]
- short_loop.operations = ops
- descr = self.start_resumedescr.clone_if_mutable()
- inliner.inline_descr_inplace(descr)
- short_loop.start_resumedescr = descr
+ target_token = targetop.getdescr()
+ assert isinstance(target_token, TargetToken)
+ targetop.initarglist(inputargs)
+ target_token.exported_state = ExportedState(values, short_inputargs,
+ constant_inputargs, short_boxes,
+ inputarg_setup_ops, self.optimizer,
+ jump_args, virtual_state,
+ start_resumedescr)
- assert isinstance(loop.preamble.token, LoopToken)
- if loop.preamble.token.short_preamble:
- loop.preamble.token.short_preamble.append(short_loop)
- else:
- loop.preamble.token.short_preamble = [short_loop]
- short_loop.virtual_state = virtual_state
+ def import_state(self, targetop):
+ target_token = targetop.getdescr()
+ assert isinstance(target_token, TargetToken)
+ exported_state = target_token.exported_state
+ if not exported_state:
+ # FIXME: Set up some sort of empty state with no virtuals
+ return
- # Forget the values to allow them to be freed
- for box in short_loop.inputargs:
- box.forget_value()
- for op in short_loop.operations:
- if op.result:
- op.result.forget_value()
+ self.short = []
+ self.short_seen = {}
+ self.short_boxes = exported_state.short_boxes
+ for box, const in exported_state.constant_inputargs.items():
+ self.short_seen[box] = True
+ self.imported_state = exported_state
+ self.inputargs = targetop.getarglist()
+ self.start_resumedescr = exported_state.start_resumedescr
- def inline(self, inputargs, loop_operations, loop_args, short_inputargs, virtual_state):
- inliner = self.inliner
+ seen = {}
+ for box in self.inputargs:
+ if box in seen:
+ continue
+ seen[box] = True
+ preamble_value = exported_state.optimizer.getvalue(box)
+ value = self.optimizer.getvalue(box)
+ value.import_from(preamble_value, self.optimizer)
+
+ # Setup the state of the new optimizer by emiting the
+ # short operations and discarding the result
+ self.optimizer.emitting_dissabled = True
+ for op in exported_state.inputarg_setup_ops:
+ self.optimizer.send_extra_operation(op)
+ seen = {}
+ for op in self.short_boxes.operations():
+ self.ensure_short_op_emitted(op, self.optimizer, seen)
+ if op and op.result:
+ preamble_value = exported_state.optimizer.getvalue(op.result)
+ value = self.optimizer.getvalue(op.result)
+ if not value.is_virtual():
+ imp = ValueImporter(self, preamble_value, op)
+ self.optimizer.importable_values[value] = imp
+ newvalue = self.optimizer.getvalue(op.result)
+ newresult = newvalue.get_key_box()
+ if newresult is not op.result and not newvalue.is_constant():
+ self.short_boxes.alias(newresult, op.result)
+ op = ResOperation(rop.SAME_AS, [op.result], newresult)
+ self.optimizer._newoperations = [op] + self.optimizer._newoperations # XXX
+ #self.optimizer.getvalue(op.result).box = op.result # FIXME: HACK!!!
+ self.optimizer.flush()
+ self.optimizer.emitting_dissabled = False
+ def close_loop(self, jumpop):
+ assert jumpop
+ virtual_state = self.imported_state.virtual_state
+ short_inputargs = self.imported_state.short_inputargs
+ constant_inputargs = self.imported_state.constant_inputargs
+ inputargs = self.inputargs
short_jumpargs = inputargs[:]
- short = self.short = []
- short_seen = self.short_seen = {}
- for box, const in self.constant_inputargs.items():
- short_seen[box] = True
-
- # This loop is equivalent to the main optimization loop in
- # Optimizer.propagate_all_forward
- jumpop = None
- for newop in loop_operations:
- newop = inliner.inline_op(newop, clone=False)
- if newop.getopnum() == rop.JUMP:
- jumpop = newop
- break
-
- #self.optimizer.first_optimization.propagate_forward(newop)
- self.optimizer.send_extra_operation(newop)
-
- self.boxes_created_this_iteration = {}
-
- assert jumpop
+ # Construct jumpargs from the virtual state
original_jumpargs = jumpop.getarglist()[:]
values = [self.getvalue(arg) for arg in jumpop.getarglist()]
jumpargs = virtual_state.make_inputargs(values, self.optimizer)
jumpop.initarglist(jumpargs)
- jmp_to_short_args = virtual_state.make_inputargs(values, self.optimizer,
- keyboxes=True)
+
+ # Inline the short preamble at the end of the loop
+ jmp_to_short_args = virtual_state.make_inputargs(values, self.optimizer, keyboxes=True)
self.short_inliner = Inliner(short_inputargs, jmp_to_short_args)
-
- for box, const in self.constant_inputargs.items():
+ for box, const in constant_inputargs.items():
self.short_inliner.argmap[box] = const
-
- for op in short:
+ for op in self.short:
newop = self.short_inliner.inline_op(op)
self.optimizer.send_extra_operation(newop)
-
+
+ # Import boxes produced in the preamble but used in the loop
newoperations = self.optimizer.get_newoperations()
-
+ self.boxes_created_this_iteration = {}
i = j = 0
+ while newoperations[i].getopnum() != rop.TARGET:
+ i += 1
while i < len(newoperations) or j < len(jumpargs):
if i == len(newoperations):
while j < len(jumpargs):
a = jumpargs[j]
if self.optimizer.loop.logops:
debug_print('J: ' + self.optimizer.loop.logops.repr_of_arg(a))
- self.import_box(a, inputargs, short, short_jumpargs,
- jumpargs, short_seen)
+ self.import_box(a, inputargs, short_jumpargs, jumpargs)
j += 1
else:
op = newoperations[i]
@@ -357,15 +290,16 @@
for a in args:
if self.optimizer.loop.logops:
debug_print('A: ' + self.optimizer.loop.logops.repr_of_arg(a))
- self.import_box(a, inputargs, short, short_jumpargs,
- jumpargs, short_seen)
+ self.import_box(a, inputargs, short_jumpargs, jumpargs)
i += 1
newoperations = self.optimizer.get_newoperations()
jumpop.initarglist(jumpargs)
self.optimizer.send_extra_operation(jumpop)
- short.append(ResOperation(rop.JUMP, short_jumpargs, None))
+ self.short.append(ResOperation(rop.JUMP, short_jumpargs, None, descr=jumpop.getdescr()))
+ # Verify that the virtual state at the end of the loop is one
+ # that is compatible with the virtual state at the start of the loop
modifier = VirtualStateAdder(self.optimizer)
final_virtual_state = modifier.get_virtual_state(original_jumpargs)
debug_start('jit-log-virtualstate')
@@ -382,8 +316,79 @@
debug_stop('jit-log-virtualstate')
raise InvalidLoop
debug_stop('jit-log-virtualstate')
+
+ def produce_short_preamble(self, lastop):
+ short = self.short
+ assert short[-1].getopnum() == rop.JUMP
+
+ # Turn guards into conditional jumps to the preamble
+ for i in range(len(short)):
+ op = short[i]
+ if op.is_guard():
+ op = op.clone()
+ op.setfailargs(None)
+ descr = self.start_resumedescr.clone_if_mutable()
+ op.setdescr(descr)
+ short[i] = op
+
+ short_loop = TreeLoop('short preamble')
+ short_inputargs = self.imported_state.short_inputargs
+ short_loop.operations = [ResOperation(rop.TARGET, short_inputargs, None)] + \
+ short
+
+ # Clone ops and boxes to get private versions and
+ boxmap = {}
+ newargs = [None] * len(short_inputargs)
+ for i in range(len(short_inputargs)):
+ a = short_inputargs[i]
+ if a in boxmap:
+ newargs[i] = boxmap[a]
+ else:
+ newargs[i] = a.clonebox()
+ boxmap[a] = newargs[i]
+ inliner = Inliner(short_inputargs, newargs)
+ for box, const in self.imported_state.constant_inputargs.items():
+ inliner.argmap[box] = const
+ ops = [inliner.inline_op(op) for op in short_loop.operations]
+ short_loop.operations = ops
+ descr = self.start_resumedescr.clone_if_mutable()
+ inliner.inline_descr_inplace(descr)
+ short_loop.start_resumedescr = descr
+
+ short_loop.virtual_state = self.imported_state.virtual_state
+
+ # Forget the values to allow them to be freed
+ for box in short_loop.inputargs:
+ box.forget_value()
+ for op in short_loop.operations:
+ if op.result:
+ op.result.forget_value()
+
+ return short_loop
- return short
+ def FIXME_old_stuff():
+ preamble_optimizer = self.optimizer
+ loop.preamble.quasi_immutable_deps = (
+ self.optimizer.quasi_immutable_deps)
+ self.optimizer = self.optimizer.new()
+ loop.quasi_immutable_deps = self.optimizer.quasi_immutable_deps
+
+
+ loop.inputargs = inputargs
+ args = [preamble_optimizer.getvalue(self.short_boxes.original(a)).force_box(preamble_optimizer)\
+ for a in inputargs]
+ jmp = ResOperation(rop.JUMP, args, None)
+ jmp.setdescr(loop.token)
+ loop.preamble.operations.append(jmp)
+
+ loop.operations = self.optimizer.get_newoperations()
+ maxguards = self.optimizer.metainterp_sd.warmrunnerdesc.memory_manager.max_retrace_guards
+
+ if self.optimizer.emitted_guards > maxguards:
+ loop.preamble.token.retraced_count = sys.maxint
+
+ if short:
+ pass
def ensure_short_op_emitted(self, op, optimizer, seen):
if op is None:
@@ -399,19 +404,18 @@
guard = ResOperation(rop.GUARD_NO_OVERFLOW, [], None)
optimizer.send_extra_operation(guard)
- def add_op_to_short(self, op, short, short_seen, emit=True, guards_needed=False):
+ def add_op_to_short(self, op, emit=True, guards_needed=False):
if op is None:
return None
- if op.result is not None and op.result in short_seen:
+ if op.result is not None and op.result in self.short_seen:
if emit:
return self.short_inliner.inline_arg(op.result)
else:
return None
for a in op.getarglist():
- if not isinstance(a, Const) and a not in short_seen:
- self.add_op_to_short(self.short_boxes.producer(a), short, short_seen,
- emit, guards_needed)
+ if not isinstance(a, Const) and a not in self.short_seen:
+ self.add_op_to_short(self.short_boxes.producer(a), emit, guards_needed)
if op.is_guard():
descr = self.start_resumedescr.clone_if_mutable()
op.setdescr(descr)
@@ -421,8 +425,8 @@
else:
value_guards = []
- short.append(op)
- short_seen[op.result] = True
+ self.short.append(op)
+ self.short_seen[op.result] = True
if emit:
newop = self.short_inliner.inline_op(op)
self.optimizer.send_extra_operation(newop)
@@ -432,23 +436,22 @@
if op.is_ovf():
# FIXME: ensure that GUARD_OVERFLOW:ed ops not end up here
guard = ResOperation(rop.GUARD_NO_OVERFLOW, [], None)
- self.add_op_to_short(guard, short, short_seen, emit, guards_needed)
+ self.add_op_to_short(guard, emit, guards_needed)
for guard in value_guards:
- self.add_op_to_short(guard, short, short_seen, emit, guards_needed)
+ self.add_op_to_short(guard, emit, guards_needed)
if newop:
return newop.result
return None
- def import_box(self, box, inputargs, short, short_jumpargs,
- jumpargs, short_seen):
+ def import_box(self, box, inputargs, short_jumpargs, jumpargs):
if isinstance(box, Const) or box in inputargs:
return
if box in self.boxes_created_this_iteration:
return
short_op = self.short_boxes.producer(box)
- newresult = self.add_op_to_short(short_op, short, short_seen)
+ newresult = self.add_op_to_short(short_op)
short_jumpargs.append(short_op.result)
inputargs.append(box)
@@ -468,7 +471,7 @@
def propagate_forward(self, op):
if op.getopnum() == rop.JUMP:
loop_token = op.getdescr()
- assert isinstance(loop_token, LoopToken)
+ assert isinstance(loop_token, TargetToken)
short = loop_token.short_preamble
if short:
args = op.getarglist()
@@ -557,5 +560,19 @@
def import_value(self, value):
value.import_from(self.preamble_value, self.unroll.optimizer)
- self.unroll.add_op_to_short(self.op, self.unroll.short, self.unroll.short_seen, False, True)
+ self.unroll.add_op_to_short(self.op, False, True)
+
+class ExportedState(object):
+ def __init__(self, values, short_inputargs, constant_inputargs,
+ short_boxes, inputarg_setup_ops, optimizer, jump_args, virtual_state,
+ start_resumedescr):
+ self.values = values
+ self.short_inputargs = short_inputargs
+ self.constant_inputargs = constant_inputargs
+ self.short_boxes = short_boxes
+ self.inputarg_setup_ops = inputarg_setup_ops
+ self.optimizer = optimizer
+ self.jump_args = jump_args
+ self.virtual_state = virtual_state
+ self.start_resumedescr = start_resumedescr
diff --git a/pypy/jit/metainterp/optimizeopt/util.py b/pypy/jit/metainterp/optimizeopt/util.py
--- a/pypy/jit/metainterp/optimizeopt/util.py
+++ b/pypy/jit/metainterp/optimizeopt/util.py
@@ -148,7 +148,7 @@
assert op1.result.same_box(remap[op2.result])
else:
remap[op2.result] = op1.result
- if op1.getopnum() != rop.JUMP: # xxx obscure
+ if op1.getopnum() not in (rop.JUMP, rop.TARGET): # xxx obscure
assert op1.getdescr() == op2.getdescr()
if op1.getfailargs() or op2.getfailargs():
assert len(op1.getfailargs()) == len(op2.getfailargs())
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
@@ -598,6 +598,7 @@
newbox = newop.result = op.result.clonebox()
self.short_boxes[newop.result] = newop
value = self.optimizer.getvalue(box)
+ self.optimizer.emit_operation(ResOperation(rop.SAME_AS, [box], newbox))
self.optimizer.make_equal_to(newbox, value)
else:
self.short_boxes[box] = op
More information about the pypy-commit
mailing list