Author: Maciej Fijalkowski <fij...@gmail.com> Branch: optresult-unroll Changeset: r79098:49ba7cf0f814 Date: 2015-08-21 11:52 +0200 http://bitbucket.org/pypy/pypy/changeset/49ba7cf0f814/
Log: pass the first test about mul_bridge_ovf1 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 @@ -225,27 +225,14 @@ call_pure_results=call_pure_results, enable_opts=enable_opts) try: - try: - start_state, preamble_ops = optimize_trace(metainterp_sd, - jitdriver_sd, - preamble_data) - except InvalidLoop: - return None - finally: - forget_optimization_info(ops) - forget_optimization_info(inputargs) + start_state, preamble_ops = optimize_trace(metainterp_sd, jitdriver_sd, + preamble_data) + except InvalidLoop: + return None - #loop = create_empty_loop(metainterp) - #loop.inputargs = part.inputargs - #loop.operations = part.operations - #loop.quasi_immutable_deps = {} - #if part.quasi_immutable_deps: - # loop.quasi_immutable_deps.update(part.quasi_immutable_deps) - #lastopnum = preamble_ops[-1].getopnum() - #if lastopnum != rop.FINISH: - #if start_state is not None: - assert start_state is not None - end_label = ResOperation(rop.LABEL, start_state.end_args, + metainterp_sd = metainterp.staticdata + jitdriver_sd = metainterp.jitdriver_sd + end_label = ResOperation(rop.LABEL, inputargs, descr=jitcell_token) jump_op = ResOperation(rop.JUMP, jumpargs, descr=jitcell_token) loop_data = UnrolledLoopData(end_label, jump_op, ops, start_state, @@ -279,44 +266,6 @@ send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, "loop") record_loop_or_bridge(metainterp_sd, loop) return start_descr - - #part.quasi_immutable_deps = None - # part.operations = [part.operations[-1]] + \ - # [inliner.inline_op(h_ops[i]) for i in range(start, len(h_ops))] + \ - # [ResOperation(rop.JUMP, [inliner.inline_arg(a) for a in jumpargs], - # None, descr=jitcell_token)] - # target_token = part.operations[0].getdescr() - # assert isinstance(target_token, TargetToken) - # all_target_tokens.append(target_token) - # inputargs = jumpargs - # jumpargs = part.operations[-1].getarglist() - - # try: - # optimize_trace(metainterp_sd, jitdriver_sd, part, enable_opts, - # start_state=start_state, export_state=False) - # except InvalidLoop: - # return None - - # loop.operations = loop.operations[:-1] + part.operations - # if part.quasi_immutable_deps: - # loop.quasi_immutable_deps.update(part.quasi_immutable_deps) - # assert part.operations[-1].getopnum() != rop.LABEL - - # if not loop.quasi_immutable_deps: - # loop.quasi_immutable_deps = None - # for box in loop.inputargs: - # assert not isinstance(box, Const) - - # loop.original_jitcell_token = jitcell_token - # for label in all_target_tokens: - # assert isinstance(label, TargetToken) - # if label.virtual_state and label.short_preamble: - # metainterp_sd.logger_ops.log_short_preamble([], label.short_preamble) - # jitcell_token.target_tokens = all_target_tokens - # propagate_original_jitcell_token(loop) - # send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, "loop") - # record_loop_or_bridge(metainterp_sd, loop) - # return all_target_tokens[0] def compile_retrace(metainterp, greenkey, start, inputargs, jumpargs, @@ -324,7 +273,6 @@ """Try to compile a new procedure by closing the current history back to the first operation. """ - xxx from rpython.jit.metainterp.optimizeopt import optimize_trace history = metainterp.history @@ -333,24 +281,21 @@ loop_jitcell_token = metainterp.get_procedure_token(greenkey) assert loop_jitcell_token - assert partial_trace.operations[-1].getopnum() == rop.LABEL - part = create_empty_loop(metainterp) - part.inputargs = inputargs[:] - h_ops = history.operations - - part.operations = [partial_trace.operations[-1]] + \ - h_ops[start:] + \ - [ResOperation(rop.JUMP, jumpargs, descr=loop_jitcell_token)] - label = part.operations[0] - orignial_label = label.clone() - assert label.getopnum() == rop.LABEL + end_label = ResOperation(rop.LABEL, inputargs, + descr=loop_jitcell_token) + jump_op = ResOperation(rop.JUMP, jumpargs, descr=loop_jitcell_token) + enable_opts = jitdriver_sd.warmstate.enable_opts + ops = history.operations[start:] + call_pure_results = metainterp.call_pure_results + loop_data = UnrolledLoopData(end_label, jump_op, ops, start_state, + call_pure_results=call_pure_results, + enable_opts=enable_opts) try: - optimize_trace(metainterp_sd, jitdriver_sd, part, - jitdriver_sd.warmstate.enable_opts, - start_state=start_state, export_state=False) + loop_info, loop_ops = optimize_trace(metainterp_sd, jitdriver_sd, + loop_data) except InvalidLoop: - xxx # XXX forget optimizations + xxx # Fall back on jumping to preamble target_token = label.getdescr() assert isinstance(target_token, TargetToken) @@ -365,33 +310,29 @@ except InvalidLoop: xxx # XXX forget optimizations return None - assert part.operations[-1].getopnum() != rop.LABEL - target_token = label.getdescr() - assert isinstance(target_token, TargetToken) - assert loop_jitcell_token.target_tokens - loop_jitcell_token.target_tokens.append(target_token) - if target_token.short_preamble: - metainterp_sd.logger_ops.log_short_preamble([], target_token.short_preamble) loop = partial_trace - loop.operations = loop.operations[:-1] + part.operations + target_token = TargetToken(loop_jitcell_token) + target_token.original_jitcell_token = loop_jitcell_token + target_token.short_preamble = loop_info.short_preamble + target_token.virtual_state = start_state.virtual_state + loop_ops[-1].setdescr(target_token) + mid_label = ResOperation(rop.LABEL, loop_info.label_args, + descr=target_token) + loop.operations = (loop.operations + loop_info.extra_same_as + [mid_label] + + loop_ops) + loop_jitcell_token.target_tokens.append(target_token) - quasi_immutable_deps = {} - if loop.quasi_immutable_deps: - quasi_immutable_deps.update(loop.quasi_immutable_deps) - if part.quasi_immutable_deps: - quasi_immutable_deps.update(part.quasi_immutable_deps) - if quasi_immutable_deps: - loop.quasi_immutable_deps = quasi_immutable_deps + #quasi_immutable_deps = {} + #if loop.quasi_immutable_deps: + # quasi_immutable_deps.update(loop.quasi_immutable_deps) + #if part.quasi_immutable_deps: + # quasi_immutable_deps.update(part.quasi_immutable_deps) + #if quasi_immutable_deps: + # loop.quasi_immutable_deps = quasi_immutable_deps - for box in loop.inputargs: - assert isinstance(box, Box) - - target_token = loop.operations[-1].getdescr() resumekey.compile_and_attach(metainterp, loop) - target_token = label.getdescr() - assert isinstance(target_token, TargetToken) record_loop_or_bridge(metainterp_sd, loop) return target_token @@ -1036,20 +977,18 @@ call_pure_results = metainterp.call_pure_results if operations[-1].getopnum() == rop.JUMP: + jump_op = operations[-1] data = BridgeCompileData(label, operations[:], call_pure_results=call_pure_results, enable_opts=enable_opts, inline_short_preamble=inline_short_preamble) else: + jump_op = None data = SimpleCompileData(label, operations[:], call_pure_results=call_pure_results, enable_opts=enable_opts) try: - try: - info, newops = optimize_trace(metainterp_sd, jitdriver_sd, data) - finally: - forget_optimization_info(inputargs) - forget_optimization_info(operations) + info, newops = optimize_trace(metainterp_sd, jitdriver_sd, data) except InvalidLoop: debug_print("compile_new_bridge: got an InvalidLoop") # XXX I am fairly convinced that optimize_bridge cannot actually raise @@ -1058,24 +997,16 @@ return None new_trace = create_empty_loop(metainterp) - new_trace.inputargs = info.inputargs new_trace.operations = newops - target_token = new_trace.operations[-1].getdescr() - resumekey.compile_and_attach(metainterp, new_trace) - record_loop_or_bridge(metainterp_sd, new_trace) - return target_token - xxxx - if new_trace.operations[-1].getopnum() != rop.LABEL: - # We managed to create a bridge. Dispatch to resumekey to - # know exactly what we must do (ResumeGuardDescr/ResumeFromInterpDescr) + if info.final(): + new_trace.inputargs = info.inputargs target_token = new_trace.operations[-1].getdescr() resumekey.compile_and_attach(metainterp, new_trace) record_loop_or_bridge(metainterp_sd, new_trace) return target_token - else: - raise Exception("should not occur with tracing disabled") - metainterp.retrace_needed(new_trace, state) - return None + new_trace.inputargs = info.renamed_inputargs + metainterp.retrace_needed(new_trace, info) + return None # ____________________________________________________________ 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 @@ -58,6 +58,7 @@ return compile_data.optimize(metainterp_sd, jitdriver_sd, optimizations, unroll) finally: + compile_data.forget_optimization_info() debug_stop("jit-optimize") if __name__ == '__main__': 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 @@ -27,6 +27,9 @@ def __init__(self, inputargs): self.inputargs = inputargs + def final(self): + return True + class Optimization(object): next_optimization = None @@ -337,7 +340,7 @@ return op def is_inputarg(self, op): - #return True + return True return op in self.inparg_dict def get_constant_box(self, box): 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 @@ -6,7 +6,7 @@ from rpython.jit.metainterp.optimizeopt.optimizer import Optimizer,\ Optimization, LoopInfo, MININT, MAXINT from rpython.jit.metainterp.optimizeopt.virtualstate import ( - VirtualStateConstructor) + VirtualStateConstructor, VirtualStatesCantMatch) from rpython.jit.metainterp.resoperation import rop, ResOperation class UnrollableOptimizer(Optimizer): @@ -90,7 +90,7 @@ self._check_no_forwarding([[start_label, end_label], ops]) info, newops = self.optimizer.propagate_all_forward( start_label.getarglist()[:], ops, call_pure_results) - exported_state = self.export_state(start_label, end_label, + exported_state = self.export_state(start_label, end_label.getarglist(), info.inputargs) # we need to absolutely make sure that we've cleaned up all # the optimization info @@ -137,25 +137,43 @@ start_label.getarglist()[:], operations[:-1], call_pure_results, True) jump_op = operations[-1] - self.jump_to_existing_trace(jump_op, inline_short_preamble) - return info, self.optimizer._newoperations[:] + vs = self.jump_to_existing_trace(jump_op, inline_short_preamble) + if vs is None: + return info, self.optimizer._newoperations[:] + exported_state = self.export_state(start_label, + operations[-1].getarglist(), + info.inputargs) + self.optimizer._clean_optimization_info(self.optimizer._newoperations) + return exported_state, self.optimizer._newoperations def jump_to_existing_trace(self, jump_op, inline_short_preamble): jitcelltoken = jump_op.getdescr() args = [self.get_box_replacement(op) for op in jump_op.getarglist()] - target_token = jitcelltoken.target_tokens[0] virtual_state = self.get_virtual_state(args) - target_virtual_state = target_token.virtual_state - - short_preamble = target_token.short_preamble - extra = self.inline_short_preamble(args, - short_preamble[0].getarglist(), short_preamble[1:-1], - short_preamble[-1].getarglist(), self.optimizer.patchguardop) - self.send_extra_operation(jump_op.copy_and_change(rop.JUMP, - args=args + extra, - descr=jitcelltoken.target_tokens[0])) + infos = [self.optimizer.getinfo(arg) for arg in args] + for target_token in jitcelltoken.target_tokens: + target_virtual_state = target_token.virtual_state + if target_virtual_state is None: + continue + try: + extra_guards = target_virtual_state.generate_guards( + virtual_state, args, infos, self.optimizer.cpu) + assert not extra_guards.extra_guards + except VirtualStatesCantMatch: + continue + short_preamble = target_token.short_preamble + extra = self.inline_short_preamble(args, + short_preamble[0].getarglist(), short_preamble[1:-1], + short_preamble[-1].getarglist(), self.optimizer.patchguardop) + self.send_extra_operation(jump_op.copy_and_change(rop.JUMP, + args=args + extra, + descr=target_token)) + return None # explicit because the return can be non-None + return virtual_state def filter_extra_jump_args(self, label_args, jump_args): + label_args = [self.get_box_replacement(x) for x in label_args] + jump_args = [self.get_box_replacement(x) for x in jump_args] new_label_args = [] new_jump_args = [] assert len(label_args) == len(jump_args) @@ -190,8 +208,7 @@ op.set_forwarded(None) return res - def export_state(self, start_label, end_label, renamed_inputargs): - original_label_args = end_label.getarglist() + def export_state(self, start_label, original_label_args, renamed_inputargs): end_args = [self.get_box_replacement(a) for a in original_label_args] virtual_state = self.get_virtual_state(end_args) inparg_mapping = [(start_label.getarg(i), end_args[i]) @@ -222,13 +239,15 @@ 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 - for source, target in exported_state.inputarg_mapping: - if source is not target: - source.set_forwarded(target) - info = exported_state.exported_infos.get(target, None) + assert len(exported_state.inputarg_mapping) == len(targetop.getarglist()) + for i, (s, target) in enumerate(exported_state.inputarg_mapping): + source = targetop.getarg(i) + assert source is not target + source.set_forwarded(target) + info = exported_state.exported_infos.get(source, None) if info is not None: self.optimizer.setinfo_from_preamble(source, info, - exported_state.exported_infos) + exported_state.exported_infos) # import the optimizer state, starting from boxes that can be produced # by short preamble self.short_preamble_producer = ShortPreambleBuilder( @@ -262,6 +281,9 @@ self.short_preamble = short_preamble self.label_args = label_args self.extra_same_as = extra_same_as + + def final(self): + return True class ExportedState(LoopInfo): """ Exported state consists of a few pieces of information: @@ -289,3 +311,6 @@ self.short_boxes = short_boxes self.renamed_inputargs = renamed_inputargs self.short_inputargs = short_inputargs + + def final(self): + return False 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 @@ -127,6 +127,7 @@ if box is not None: fieldbox = opinfo._fields[self.fielddescrs[i].get_index()] # must be there + xxx fieldinfo = fieldbox.get_forwarded() else: fieldbox = None @@ -205,6 +206,7 @@ if box is not None: assert isinstance(opinfo, info.ArrayPtrInfo) fieldbox = opinfo._items[i] + xxx fieldinfo = fieldbox.get_forwarded() self.fieldstate[i].generate_guards(other.fieldstate[i], fieldbox, fieldinfo, state) @@ -344,7 +346,8 @@ if self.level == LEVEL_UNKNOWN: # confusingly enough, this is done also for pointers # which have the full range as the "bound", so it always works - return self._generate_guards_intbounds(other, box, extra_guards) + return self._generate_guards_intbounds(other, box, opinfo, + extra_guards) # the following conditions often peek into the runtime value that the # box had when tracing. This value is only used as an educated guess. @@ -412,13 +415,13 @@ raise VirtualStatesCantMatch("other not constant") assert 0, "unreachable" - def _generate_guards_intbounds(self, other, boxinfo, extra_guards): + def _generate_guards_intbounds(self, other, box, opinfo, extra_guards): if self.intbound is None: return if self.intbound.contains_bound(other.intbound): return - if (boxinfo is not None and isinstance(box, BoxInt) and - self.intbound.contains(box.getint())): + if (opinfo is not None and opinfo.is_constant() and + self.intbound.contains(opinfo.getint())): # this may generate a few more guards than needed, but they are # optimized away when emitting them self.intbound.make_guards(box, extra_guards) @@ -502,11 +505,11 @@ return False return True - def generate_guards(self, other, values, cpu): - assert len(self.state) == len(other.state) == len(values) + def generate_guards(self, other, boxes, infos, cpu): + assert len(self.state) == len(other.state) == len(boxes) == len(infos) state = GenerateGuardState(cpu) for i in range(len(self.state)): - self.state[i].generate_guards(other.state[i], values[i], + self.state[i].generate_guards(other.state[i], boxes[i], infos[i], state) return state diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py --- a/rpython/jit/metainterp/test/test_ajit.py +++ b/rpython/jit/metainterp/test/test_ajit.py @@ -270,6 +270,7 @@ y -= 1 return res res = self.meta_interp(f, [6, sys.maxint, 48]) + self.check_trace_count(6) assert res == f(6, sys.maxint, 48) def test_loop_invariant_mul_bridge_ovf2(self): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit