Author: Maciej Fijalkowski <fij...@gmail.com> Branch: optresult-unroll Changeset: r78456:cbf2d99e2ae8 Date: 2015-07-06 14:57 +0200 http://bitbucket.org/pypy/pypy/changeset/cbf2d99e2ae8/
Log: a completely different approach diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py --- a/rpython/jit/metainterp/compile.py +++ b/rpython/jit/metainterp/compile.py @@ -24,6 +24,37 @@ raise SwitchToBlackhole(Counters.ABORT_BRIDGE) +class LoopCompileData(object): + """ An object that accumulates all of the necessary info for + the optimization phase, but does not actually have any other state + + This is the case of label() ops label() + """ + def __init__(self, start_label, end_label, operations): + self.start_label = start_label + self.end_label = end_label + assert start_label.getopnum() == rop.LABEL + assert end_label.getopnum() == rop.LABEL + self.operations = operations + + def forget_optimization_info(self): + for arg in self.start_label.getarglist(): + arg.set_forwarded(None) + for op in self.operations: + op.set_forwarded(None) + + def optimize(self, metainterp_sd, jitdriver_sd, optimizations, unroll): + from rpython.jit.metainterp.optimizeopt.unroll import UnrollOptimizer + + if unroll: + opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, optimizations) + return opt.optimize_preamble(self.start_label, self.end_label, + self.operations) + xxx + else: + xxx + + def show_procedures(metainterp_sd, procedure=None, error=None): # debugging if option and (option.view or option.viewloops): @@ -104,10 +135,8 @@ # ____________________________________________________________ -def compile_loop(metainterp, greenkey, start, - inputargs, jumpargs, - full_preamble_needed=True, - try_disabling_unroll=False): +def compile_loop(metainterp, greenkey, start, inputargs, jumpargs, + full_preamble_needed=True, try_disabling_unroll=False): """Try to compile a new procedure by closing the current history back to the first operation. """ diff --git a/rpython/jit/metainterp/optimizeopt/__init__.py b/rpython/jit/metainterp/optimizeopt/__init__.py --- a/rpython/jit/metainterp/optimizeopt/__init__.py +++ b/rpython/jit/metainterp/optimizeopt/__init__.py @@ -4,7 +4,6 @@ from rpython.jit.metainterp.optimizeopt.virtualize import OptVirtualize from rpython.jit.metainterp.optimizeopt.heap import OptHeap from rpython.jit.metainterp.optimizeopt.vstring import OptString -from rpython.jit.metainterp.optimizeopt.unroll import optimize_unroll from rpython.jit.metainterp.optimizeopt.simplify import OptSimplify from rpython.jit.metainterp.optimizeopt.pure import OptPure from rpython.jit.metainterp.optimizeopt.earlyforce import OptEarlyForce @@ -47,26 +46,17 @@ return optimizations, unroll -def optimize_trace(metainterp_sd, jitdriver_sd, loop, enable_opts, - inline_short_preamble=True, start_state=None, - export_state=True): +def optimize_trace(metainterp_sd, jitdriver_sd, compile_data): """Optimize loop.operations to remove internal overheadish operations. """ - debug_start("jit-optimize") + #inputargs = start_label.getarglist() try: - loop.logops = metainterp_sd.logger_noopt.log_loop(loop.inputargs, - loop.operations) - optimizations, unroll = build_opt_chain(metainterp_sd, enable_opts) - if unroll: - return optimize_unroll(metainterp_sd, jitdriver_sd, loop, - optimizations, - inline_short_preamble, start_state, - export_state) - else: - optimizer = Optimizer(metainterp_sd, jitdriver_sd, loop, - optimizations) - optimizer.propagate_all_forward() + #logops = metainterp_sd.logger_noopt.log_loop(inputargs, operations) + optimizations, unroll = build_opt_chain(metainterp_sd, + compile_data.enable_opts) + return compile_data.optimize(metainterp_sd, jitdriver_sd, + optimizations, unroll) finally: debug_stop("jit-optimize") 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 @@ -211,14 +211,10 @@ class Optimizer(Optimization): - exporting_state = False - emitting_dissabled = False - - def __init__(self, metainterp_sd, jitdriver_sd, loop, optimizations=None): + def __init__(self, metainterp_sd, jitdriver_sd, optimizations=None): self.metainterp_sd = metainterp_sd self.jitdriver_sd = jitdriver_sd self.cpu = metainterp_sd.cpu - self.loop = loop self.logops = LogOperations(metainterp_sd, False) self.interned_refs = self.cpu.ts.new_ref_dict() self.interned_ints = {} @@ -234,14 +230,15 @@ self.optheap = None self.optearlyforce = None self.optunroll = None - # the following two fields is the data kept for unrolling, - # those are the operations that can go to the short_preamble - if loop is not None: - self.call_pure_results = loop.call_pure_results self.set_optimizations(optimizations) self.setup() + def init_inparg_dict_from(self, lst): + self.inparg_dict = {} + for box in lst: + self.inparg_dict[box] = None + def set_optimizations(self, optimizations): if optimizations: self.first_optimization = optimizations[0] @@ -442,18 +439,13 @@ else: return CONST_0 - def propagate_all_forward(self, clear=True, create_inp_args=True): - if clear: - self.clear_newoperations() - if create_inp_args: - self.inparg_dict = {} - for op in self.loop.inputargs: - self.inparg_dict[op] = None - for op in self.loop.operations: + def propagate_all_forward(self, inputargs, ops, create_inp_args=True): + self.init_inparg_dict_from(inputargs) + for op in ops: self._really_emitted_operation = None self.first_optimization.propagate_forward(op) - self.loop.operations = self.get_newoperations() - self.loop.quasi_immutable_deps = self.quasi_immutable_deps + #self.loop.operations = self.get_newoperations() + #self.loop.quasi_immutable_deps = self.quasi_immutable_deps # accumulate counters self.resumedata_memo.update_counters(self.metainterp_sd.profiler) 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 @@ -3,10 +3,11 @@ """ from rpython.jit.metainterp.optimizeopt.test.test_util import BaseTest,\ - LLtypeMixin, FakeMetaInterpStaticData -from rpython.jit.metainterp.history import (TreeLoop, AbstractDescr, ConstInt, + LLtypeMixin +from rpython.jit.metainterp.history import (TreeLoop, ConstInt, JitCellToken, TargetToken) from rpython.jit.metainterp.resoperation import rop, ResOperation +from rpython.jit.metainterp.compile import LoopCompileData from rpython.jit.metainterp.optimizeopt.virtualstate import \ NotVirtualStateInfo, LEVEL_CONSTANT, LEVEL_UNKNOWN @@ -18,7 +19,6 @@ def optimize(self, ops): loop = self.parse(ops, postprocess=self.postprocess) - metainterp_sd = FakeMetaInterpStaticData(self.cpu) self.add_guard_future_condition(loop) operations = loop.operations jumpop = operations[-1] @@ -34,11 +34,10 @@ token = JitCellToken() start_label = ResOperation(rop.LABEL, inputargs, descr=TargetToken(token)) stop_label = ResOperation(rop.LABEL, jump_args, descr=token) - preamble.operations = [start_label] + operations + [stop_label] - start_state = self._do_optimize_loop(preamble, None, - export_state=True) - vs = preamble.operations[-1].getdescr().virtual_state - return start_state, vs, loop, preamble + compile_data = LoopCompileData(start_label, stop_label, operations) + start_state, newops = self._do_optimize_loop(compile_data) + preamble.operations = newops + return start_state, loop, preamble class TestUnroll(BaseTestUnroll): def test_simple(self): @@ -48,7 +47,8 @@ guard_value(i1, 1) [] jump(i1) """ - es, vs, loop, preamble = self.optimize(loop) + es, loop, preamble = self.optimize(loop) + vs = es.virtual_state assert isinstance(vs.state[0], NotVirtualStateInfo) # the virtual state is constant, so we don't need to have it in # inputargs @@ -65,8 +65,9 @@ i1 = int_add(i0, 1) jump(i0) """ - es, vs, loop, preamble = self.optimize(loop) + es, loop, preamble = self.optimize(loop) + vs = es.virtual_state assert isinstance(vs.state[0], NotVirtualStateInfo) assert vs.state[0].level == LEVEL_UNKNOWN - op = preamble.operations[1] + op = preamble.operations[0] assert es.short_boxes == {op: op} diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py --- a/rpython/jit/metainterp/optimizeopt/test/test_util.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py @@ -405,15 +405,11 @@ assert equaloplists(optimized.operations, expected.operations, False, remap, text_right) - def _do_optimize_loop(self, loop, call_pure_results, start_state=None, - export_state=False): + def _do_optimize_loop(self, compile_data, call_pure_results=None): from rpython.jit.metainterp.optimizeopt import optimize_trace from rpython.jit.metainterp.optimizeopt.util import args_dict - self.loop = loop - operations = loop.operations - inputargs = loop.inputargs - loop.call_pure_results = args_dict() + # XXX if call_pure_results is not None: for k, v in call_pure_results.items(): loop.call_pure_results[list(k)] = v @@ -423,17 +419,14 @@ if hasattr(self, 'callinfocollection'): metainterp_sd.callinfocollection = self.callinfocollection # - state = optimize_trace(metainterp_sd, None, loop, - self.enable_opts, - start_state=start_state, - export_state=export_state) - compile.forget_optimization_info(operations) - compile.forget_optimization_info(inputargs) + compile_data.enable_opts = self.enable_opts + state = optimize_trace(metainterp_sd, None, compile_data) + compile_data.forget_optimization_info() return state def unroll_and_optimize(self, loop, call_pure_results=None): + xxx metainterp_sd = FakeMetaInterpStaticData(self.cpu) - logops = LogOperations(metainterp_sd, False) self.add_guard_future_condition(loop) operations = loop.operations jumpop = operations[-1] 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 @@ -13,15 +13,6 @@ from rpython.rlib.debug import debug_print, debug_start, debug_stop -# FIXME: Introduce some VirtualOptimizer super class instead - -def optimize_unroll(metainterp_sd, jitdriver_sd, loop, optimizations, - inline_short_preamble=True, start_state=None, - export_state=True): - opt = UnrollOptimizer(metainterp_sd, jitdriver_sd, loop, optimizations) - opt.inline_short_preamble = inline_short_preamble - return opt.propagate_all_forward(start_state, export_state) - class PreambleOp(AbstractResOp): def __init__(self, op, info): @@ -36,18 +27,6 @@ class UnrollableOptimizer(Optimizer): - def setup(self): - self.importable_values = {} - self.emitting_dissabled = False - self.emitted_guards = 0 - - def emit_operation(self, op): - if self.emitting_dissabled: - return - if op.is_guard(): - self.emitted_guards += 1 # FIXME: can we use counter in self._emit_operation? - self._emit_operation(op) - def force_op_from_preamble(self, preamble_op): op = preamble_op.op self.optunroll.short.append(op) @@ -63,52 +42,27 @@ inline_short_preamble = True - def __init__(self, metainterp_sd, jitdriver_sd, loop, optimizations): + def __init__(self, metainterp_sd, jitdriver_sd, optimizations): self.optimizer = UnrollableOptimizer(metainterp_sd, jitdriver_sd, - loop, optimizations) + optimizations) self.optimizer.optunroll = self - self.boxes_created_this_iteration = None def get_virtual_state(self, args): modifier = VirtualStateConstructor(self.optimizer) return modifier.get_virtual_state(args) - def propagate_all_forward(self, starting_state, export_state=True): - self.optimizer.exporting_state = export_state - loop = self.optimizer.loop - self.optimizer.clear_newoperations() - for op in loop.operations: - assert op.get_forwarded() is None - for op in loop.inputargs: - assert op.get_forwarded() is None - - start_label = loop.operations[0] - if start_label.getopnum() == rop.LABEL: - loop.operations = loop.operations[1:] - # We need to emit the label op before import_state() as emitting it - # will clear heap caches - self.optimizer.send_extra_operation(start_label) - else: - start_label = None - - patchguardop = None - if len(loop.operations) > 1: - patchguardop = loop.operations[-2] - if patchguardop.getopnum() != rop.GUARD_FUTURE_CONDITION: - patchguardop = None - - jumpop = loop.operations[-1] - if jumpop.getopnum() == rop.JUMP or jumpop.getopnum() == rop.LABEL: - loop.operations = loop.operations[:-1] - else: - jumpop = None - - self.import_state(start_label, starting_state) - self.optimizer.inparg_dict = {} - for box in start_label.getarglist(): - self.optimizer.inparg_dict[box] = None - self.optimizer.propagate_all_forward(clear=False, create_inp_args=False) - + def _check_no_forwarding(self, lsts): + for lst in lsts: + for op in lst: + assert op.get_forwarded() is None + assert not self.optimizer._newoperations + + def optimize_preamble(self, start_label, end_label, ops): + self._check_no_forwarding([[start_label, end_label], ops]) + self.optimizer.propagate_all_forward(start_label.getarglist(), ops) + exported_state = self.export_state(start_label, end_label) + return exported_state, self.optimizer._newoperations + # WTF is the rest of this function if not jumpop: return @@ -183,7 +137,7 @@ self.optimizer.send_extra_operation(stop_label) loop.operations = self.optimizer.get_newoperations() return None - final_state = self.export_state(stop_label) + final_state = self.export_state(start_label, stop_label) else: final_state = None loop.operations.append(stop_label) @@ -200,19 +154,16 @@ return stop_target.targeting_jitcell_token is start_target.targeting_jitcell_token - def export_state(self, targetop): - original_jump_args = targetop.getarglist() - label_op = self.optimizer.loop.operations[0] - jump_args = [self.get_box_replacement(a) for a in original_jump_args] - virtual_state = self.get_virtual_state(jump_args) - target_token = targetop.getdescr() - assert isinstance(target_token, TargetToken) - target_token.virtual_state = virtual_state + def export_state(self, start_label, end_label): + original_label_args = end_label.getarglist() + end_args = [self.get_box_replacement(a) for a in original_label_args] + virtual_state = self.get_virtual_state(end_args) sb = ShortBoxes() - sb.create_short_boxes(self.optimizer, jump_args) - inparg_mapping = [(label_op.getarg(i), jump_args[i]) - for i in range(len(jump_args))] - return ExportedState(inparg_mapping, [], sb.short_boxes) + sb.create_short_boxes(self.optimizer, end_args) + inparg_mapping = [(start_label.getarg(i), end_args[i]) + for i in range(len(end_args)) if + start_label.getarg(i) is not end_args[i]] + return ExportedState(inparg_mapping, virtual_state, [], sb.short_boxes) inputargs = virtual_state.make_inputargs(jump_args, self.optimizer) @@ -297,6 +248,8 @@ # think about it, it seems to be just for consts #for source, target in exported_state.inputarg_setup_ops: # source.set_forwarded(target) + for source, target in exported_state.inputarg_mapping: + source.set_forwarded(target) for op, preamble_op in exported_state.short_boxes.iteritems(): if preamble_op.is_always_pure(): @@ -709,7 +662,9 @@ * short boxes - a mapping op -> preamble_op """ - def __init__(self, inputarg_mapping, exported_infos, short_boxes): + def __init__(self, inputarg_mapping, virtual_state, exported_infos, + short_boxes): self.inputarg_mapping = inputarg_mapping + self.virtual_state = virtual_state self.exported_infos = exported_infos self.short_boxes = short_boxes _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit