Author: Richard Plangger <r...@pasra.at> Branch: vecopt-merge Changeset: r79092:27ddd5637fb8 Date: 2015-08-21 10:28 +0200 http://bitbucket.org/pypy/pypy/changeset/27ddd5637fb8/
Log: moved the collection of compile loop version descr to guard opt. the assembler writes the correct offset into memory but it is not visible in the resulting memory block (e.g. jitviewer?). something is wrong diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -265,8 +265,8 @@ self.stats = stats or MiniStats() self.vinfo_for_tests = kwds.get('vinfo_for_tests', None) - def stitch_bridge(self, faildescr, compiled_faildescr, jitcell_token): - faildescr._llgraph_bridge = compiled_faildescr._llgraph_bridge + def stitch_bridge(self, faildescr, target): + faildescr._llgraph_bridge = target def compile_loop(self, inputargs, operations, looptoken, jd_id=0, unique_id=0, log=True, name='', logger=None): @@ -285,6 +285,7 @@ faildescr._llgraph_bridge = lltrace clt._llgraph_alltraces.append(lltrace) self._record_labels(lltrace) + return lltrace def _record_labels(self, lltrace): for i, op in enumerate(lltrace.operations): diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -35,7 +35,6 @@ self.exc = exc self.is_guard_not_invalidated = is_guard_not_invalidated self.is_guard_not_forced = is_guard_not_forced - self.rawstart = 0 def compute_gcmap(self, gcmap, failargs, fail_locs, frame_depth): # note that regalloc has a very similar compute, but @@ -70,7 +69,7 @@ self.rtyper = cpu.rtyper self._debug = False - def stitch_bridge(self, faildescr, compiled_faildescr, token): + def stitch_bridge(self, faildescr, target): raise NotImplementedError def setup_once(self): diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -97,8 +97,8 @@ inputargs, operations, looptoken, log=log) - def stitch_bridge(self, faildescr, compiled_faildescr, token): - self.assembler.stitch_bridge(faildescr, compiled_faildescr, token) + def stitch_bridge(self, faildescr, target): + self.assembler.stitch_bridge(faildescr, target) def _setup_frame_realloc(self, translate_support_code): FUNC_TP = lltype.Ptr(lltype.FuncType([llmemory.GCREF, lltype.Signed], diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -569,7 +569,7 @@ fullsize = self.mc.get_relative_pos() # rawstart = self.materialize_loop(original_loop_token) - faildescr.rawstart = rawstart + faildescr.bridge_rawstart = rawstart self.patch_stack_checks(frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE, rawstart) debug_bridge(descr_number, rawstart, codeendpos) @@ -592,8 +592,9 @@ rawstart, fullsize) return AsmInfo(ops_offset, startpos + rawstart, codeendpos - startpos) - def stitch_bridge(self, faildescr, compiled_faildescr, token): - self.patch_jump_for_descr(faildescr, compiled_faildescr.rawstart) + def stitch_bridge(self, faildescr, target): + assert target != 0 + self.patch_jump_for_descr(faildescr, target) def write_pending_failure_recoveries(self, regalloc): # for each pending guard, generate the code of the recovery stub @@ -604,7 +605,8 @@ regalloc.position = tok.position tok.pos_recovery_stub = self.generate_quick_failure(tok, regalloc) else: - self.store_info_on_descr(0, tok) + startpos = self.mc.get_relative_pos() + self.store_info_on_descr(startpos, tok) if WORD == 8 and len(self.pending_memoryerror_trampoline_from) > 0: self.error_trampoline_64 = self.generate_propagate_error_64() diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -322,7 +322,6 @@ if accum: loc = self.loc(accum.getoriginalbox()) faillocs.append(loc) - import pdb; pdb.set_trace() self.update_accumulation_loc(arg, accum, descr, i) else: faillocs.append(self.loc(arg)) 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 @@ -192,6 +192,8 @@ metainterp_sd = metainterp.staticdata cpu = metainterp_sd.cpu if loop.versions is not None: + # compile each version once for the first fail descr! + # this assumes that the root trace (= loop) is already compiled for version in loop.versions: if len(version.faildescrs) == 0: continue @@ -200,12 +202,16 @@ vl.inputargs = version.inputargs vl.operations = version.operations vl.original_jitcell_token = jitcell_token - send_bridge_to_backend(jitdriver_sd, metainterp_sd, - faildescr, version.inputargs, - version.operations, jitcell_token) + asminfo = send_bridge_to_backend(jitdriver_sd, metainterp_sd, + faildescr, version.inputargs, + version.operations, jitcell_token) record_loop_or_bridge(metainterp_sd, vl) - for fd in version.faildescrs[1:]: - cpu.stitch_bridge(fd, faildescr, jitcell_token) + version.compiled = faildescr.bridge_rawstart + assert asminfo is not None + # stitch the rest of the traces + for version in loop.versions: + for faildescr in version.faildescrs[1:]: + cpu.stitch_bridge(faildescr, version.compiled) loop.versions = None def compile_retrace(metainterp, greenkey, start, @@ -437,6 +443,7 @@ #if metainterp_sd.warmrunnerdesc is not None: # for tests # metainterp_sd.warmrunnerdesc.memory_manager.keep_loop_alive( # original_loop_token) + return asminfo # ____________________________________________________________ @@ -742,6 +749,11 @@ def loop_version(self): return True + def clone(self): + cloned = ResumeGuardDescr.clone(self) + cloned.version = self.version + return cloned + class AllVirtuals: llopaque = True cache = None diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -758,38 +758,7 @@ label = operations[idx] self.label_pos = idx self.inputargs = label.getarglist() - - def register_all_guards(self, opt_ops, invariant_arg_count=0): - from rpython.jit.metainterp.compile import CompileLoopVersionDescr - pass_by = 0 - idx = index_of_first(rop.LABEL, opt_ops) - if opt_ops[idx].getdescr() is not opt_ops[-1].getdescr(): - idx = index_of_first(rop.LABEL, opt_ops, pass_by=1) - assert idx >= 0 - version_failargs = opt_ops[idx].getarglist() - if invariant_arg_count > 0: - # constant/variable expansion append arguments to the label - # if they are not removed, the register allocator cannot - # reconstruct the binding if len(inputargs) != len(faillocs) - to = len(version_failargs) - invariant_arg_count - assert to >= 0 - version_failargs = version_failargs[:to] - - for op in opt_ops: - if op.is_guard(): - assert isinstance(op, GuardResOp) - descr = op.getdescr() - if descr.loop_version(): - assert isinstance(descr, CompileLoopVersionDescr) - if descr.version is None: - # currently there is only ONE versioning, - # that is the original loop after unrolling. - # if there are more possibilites, let the descr - # know which loop version he preferes - descr.version = self - self.faildescrs.append(descr) - op.setfailargs(version_failargs) - op.rd_snapshot = None + self.compiled = None def register_guard(self, op): from rpython.jit.metainterp.compile import CompileLoopVersionDescr @@ -798,8 +767,6 @@ assert isinstance(descr, CompileLoopVersionDescr) descr.version = self self.faildescrs.append(descr) - op.setfailargs(self.inputargs) - op.rd_snapshot = None def update_token(self, jitcell_token, all_target_tokens): # this is only invoked for versioned loops! @@ -892,16 +859,22 @@ return self.operations def find_first_index(self, opnum, pass_by=0): - """ return the first operation having the same opnum or -1 """ + """ return the first index of the operation having the same opnum or -1 """ return index_of_first(opnum, self.operations, pass_by) + def find_first(self, opnum, pass_by=0): + index = self.find_first_index(opnum, pass_by) + if index != -1: + return self.operations[index] + return None + def snapshot(self): version = LoopVersion(self.copy_operations()) self.versions.append(version) return version def copy_operations(self): - from rpython.jit.metainterp.compile import ResumeGuardDescr + from rpython.jit.metainterp.compile import ResumeGuardDescr, CompileLoopVersionDescr ignore = (rop.DEBUG_MERGE_POINT,) operations = [] for op in self.operations: @@ -913,6 +886,8 @@ if cloned.is_guard() and descr: assert isinstance(descr, ResumeGuardDescr) cloned.setdescr(descr.clone()) + if isinstance(descr, CompileLoopVersionDescr): + descr.version.register_guard(cloned) return operations def get_display_text(self): # for graphpage.py diff --git a/rpython/jit/metainterp/logger.py b/rpython/jit/metainterp/logger.py --- a/rpython/jit/metainterp/logger.py +++ b/rpython/jit/metainterp/logger.py @@ -102,6 +102,7 @@ return descr.repr_of_descr() def repr_of_arg(self, arg): + return str(arg) # XXX try: mv = self.memo[arg] except KeyError: diff --git a/rpython/jit/metainterp/optimizeopt/guard.py b/rpython/jit/metainterp/optimizeopt/guard.py --- a/rpython/jit/metainterp/optimizeopt/guard.py +++ b/rpython/jit/metainterp/optimizeopt/guard.py @@ -10,7 +10,7 @@ from rpython.jit.metainterp.resoperation import (rop, ResOperation, GuardResOp) from rpython.jit.metainterp.history import (ConstInt, BoxVector, BoxFloat, BoxInt, ConstFloat, Box, Const) -from rpython.jit.metainterp.compile import ResumeGuardDescr +from rpython.jit.metainterp.compile import ResumeGuardDescr, CompileLoopVersionDescr from rpython.rlib.objectmodel import we_are_translated class Guard(object): @@ -70,7 +70,7 @@ return (lc <= 0 and rc >= 0) return False - def transitive_imply(self, other, opt): + def transitive_imply(self, other, opt, loop): if self.op.getopnum() != other.op.getopnum(): # stronger restriction, intermixing e.g. <= and < would be possible return None @@ -91,6 +91,8 @@ assert isinstance(descr, ResumeGuardDescr) guard.setdescr(descr.clone()) guard.setarg(0, box_result) + label = loop.find_first(rop.LABEL) + guard.setfailargs(label.getarglist()) opt.emit_operation(guard) return guard @@ -149,6 +151,10 @@ def set_to_none(self, operations): assert operations[self.index] is self.op operations[self.index] = None + descr = self.op.getdescr() + if isinstance(descr, CompileLoopVersionDescr) and descr.version: + descr.version.faildescrs.remove(descr) + descr.version = None if operations[self.index-1] is self.cmp_op: operations[self.index-1] = None @@ -171,12 +177,14 @@ return Guard(index, guard_op, cmp_op, index_vars) class GuardStrengthenOpt(object): - def __init__(self, index_vars): + """ Note that this optimization is only used in the vector optimizer (yet) """ + def __init__(self, index_vars, has_two_labels): self.index_vars = index_vars self._newoperations = [] self.strength_reduced = 0 # how many guards could be removed? self.strongest_guards = {} self.guards = {} + self.has_two_labels = has_two_labels def collect_guard_information(self, loop): operations = loop.operations @@ -256,8 +264,18 @@ # the guards are ordered. guards[i] is before guards[j] iff i < j self.collect_guard_information(loop) self.eliminate_guards(loop) + # + assert len(loop.versions) == 1, "none or more than one version created" + version = loop.versions[0] - if user_code or True: + for op in loop.operations: + if not op.is_guard(): + continue + descr = op.getdescr() + if isinstance(descr, CompileLoopVersionDescr): + version.register_guard(op) + + if user_code and False: version = loop.snapshot() self.eliminate_array_bound_checks(loop, version) @@ -278,11 +296,16 @@ # iff we add invariant guards one = guards[0] for other in guards[1:]: - transitive_guard = one.transitive_imply(other, self) + transitive_guard = one.transitive_imply(other, self, loop) if transitive_guard: other.set_to_none(loop.operations) version.register_guard(transitive_guard) - loop.operations = self._newoperations + \ - [op for op in loop.operations if op] + if self.has_two_labels: + oplist = [loop.operations[0]] + self._newoperations + \ + [op for op in loop.operations[1:] if op] + loop.operations = oplist + else: + loop.operations = self._newoperations + \ + [op for op in loop.operations if op] diff --git a/rpython/jit/metainterp/optimizeopt/schedule.py b/rpython/jit/metainterp/optimizeopt/schedule.py --- a/rpython/jit/metainterp/optimizeopt/schedule.py +++ b/rpython/jit/metainterp/optimizeopt/schedule.py @@ -856,34 +856,6 @@ assert not isinstance(box, BoxVector) self.box_to_vbox[box] = (off, vector) - def prepend_invariant_operations(self, oplist, orig_label_args): - if len(self.invariant_oplist) > 0: - label = oplist[0] - assert label.getopnum() == rop.LABEL - # - jump = oplist[-1] - assert jump.getopnum() == rop.JUMP - # - label_args = label.getarglist()[:] - jump_args = jump.getarglist() - for var in self.invariant_vector_vars: - label_args.append(var) - jump_args.append(var) - # - # in case of any invariant_vector_vars, the label is restored - # and the invariant operations are added between the original label - # and the new label - descr = label.getdescr() - assert isinstance(descr, TargetToken) - token = TargetToken(descr.targeting_jitcell_token) - oplist[0] = label.copy_and_change(label.getopnum(), args=label_args, descr=token) - oplist[-1] = jump.copy_and_change(jump.getopnum(), args=jump_args, descr=token) - # - return [ResOperation(rop.LABEL, orig_label_args, None, descr)] + \ - self.invariant_oplist + oplist - # - return oplist - class Pack(object): """ A pack is a set of n statements that are: * isomorphic diff --git a/rpython/jit/metainterp/optimizeopt/test/test_guard.py b/rpython/jit/metainterp/optimizeopt/test/test_guard.py --- a/rpython/jit/metainterp/optimizeopt/test/test_guard.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_guard.py @@ -84,7 +84,7 @@ if op.is_guard(): op.setdescr(compile.CompileLoopVersionDescr()) dep = DependencyGraph(loop) - opt = GuardStrengthenOpt(dep.index_vars) + opt = GuardStrengthenOpt(dep.index_vars, False) opt.propagate_all_forward(loop, user_code) return opt diff --git a/rpython/jit/metainterp/optimizeopt/vectorize.py b/rpython/jit/metainterp/optimizeopt/vectorize.py --- a/rpython/jit/metainterp/optimizeopt/vectorize.py +++ b/rpython/jit/metainterp/optimizeopt/vectorize.py @@ -49,10 +49,11 @@ # opt = VectorizingOptimizer(metainterp_sd, jitdriver_sd, loop, 0) opt.propagate_all_forward() - gso = GuardStrengthenOpt(opt.dependency_graph.index_vars) + # + gso = GuardStrengthenOpt(opt.dependency_graph.index_vars, opt.has_two_labels) gso.propagate_all_forward(opt.loop, user_code) # connect all compile loop version fail descriptors to this version - version.register_all_guards(loop.operations, opt.appended_arg_count) + #version.register_all_guards(loop.operations, opt.appended_arg_count) # # end = time.clock() @@ -135,6 +136,7 @@ self.costmodel = X86_CostModel(cost_threshold, self.cpu.vector_register_size) self.appended_arg_count = 0 self.orig_label_args = None + self.has_two_labels = False def propagate_all_forward(self, clear=True): self.clear_newoperations() @@ -503,11 +505,46 @@ accum = arg.getaccum() if accum: accum.save_to_descr(op.getdescr(),i) - self.loop.operations = \ - sched_data.prepend_invariant_operations(self._newoperations, - self.orig_label_args) + self.has_two_labels = len(sched_data.invariant_oplist) > 0 + self.loop.operations = self.prepend_invariant_operations(sched_data) + else: + self.loop.operations = self._newoperations + self.clear_newoperations() + def prepend_invariant_operations(self, sched_data): + """ Add invariant operations to the trace loop. returns the operation list + as first argument and a second a boolean value. it is true if any inva + """ + oplist = self._newoperations + + if len(sched_data.invariant_oplist) > 0: + label = oplist[0] + assert label.getopnum() == rop.LABEL + # + jump = oplist[-1] + assert jump.getopnum() == rop.JUMP + # + label_args = label.getarglist()[:] + jump_args = jump.getarglist() + for var in sched_data.invariant_vector_vars: + label_args.append(var) + jump_args.append(var) + # + # in case of any invariant_vector_vars, the label is restored + # and the invariant operations are added between the original label + # and the new label + descr = label.getdescr() + assert isinstance(descr, TargetToken) + token = TargetToken(descr.targeting_jitcell_token) + oplist[0] = label.copy_and_change(label.getopnum(), args=label_args, descr=token) + oplist[-1] = jump.copy_and_change(jump.getopnum(), args=jump_args, descr=token) + # + return [ResOperation(rop.LABEL, self.orig_label_args, None, descr)] + \ + sched_data.invariant_oplist + oplist + # + return oplist + def analyse_index_calculations(self): ee_pos = self.loop.find_first_index(rop.GUARD_EARLY_EXIT) if len(self.loop.operations) <= 2 or ee_pos == -1: @@ -580,7 +617,6 @@ descr.copy_all_attributes_from(olddescr) # tgt_op.setdescr(descr) - tgt_op.rd_snapshot = op.rd_snapshot tgt_op.setfailargs(op.getfailargs()[:]) diff --git a/rpython/jit/metainterp/test/test_vectorize.py b/rpython/jit/metainterp/test/test_vectorize.py --- a/rpython/jit/metainterp/test/test_vectorize.py +++ b/rpython/jit/metainterp/test/test_vectorize.py @@ -222,17 +222,19 @@ def test_accum(self): myjitdriver = JitDriver(greens = [], reds = 'auto') - T = lltype.Array(rffi.DOUBLE, hints={'nolength': True}) + T = lltype.Array(rffi.DOUBLE) def f(d, value): va = lltype.malloc(T, d, flavor='raw', zero=True) for i in range(d): va[i] = value r = 0 i = 0 + k = d + 2 + # in this case a guard k <= d is inserted which fails right away! while i < d: myjitdriver.jit_merge_point() - if not(i < d): - raise IndexError + #if not(i < k): + # k -= 1 r += va[i] i += 1 lltype.free(va, flavor='raw') _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit