def optimize_vector(trace, metainterp_sd, jitdriver_sd, warmstate, loop_info, loop_ops, jitcell_token=None): """ Enter the world of SIMD. Bails if it cannot transform the trace. """ user_code = not jitdriver_sd.vec and warmstate.vec_all e = len(loop_ops)-1 assert e > 0 assert rop.is_final(loop_ops[e].getopnum()) loop = VectorLoop(loop_info.label_op, loop_ops[:e], loop_ops[-1]) if user_code and user_loop_bail_fast_path(loop, warmstate): return loop_info, loop_ops # the original loop (output of optimize_unroll) info = LoopVersionInfo(loop_info) version = info.snapshot(loop) loop.setup_vectorization() try: debug_start("vec-opt-loop") metainterp_sd.logger_noopt.log_loop([], loop.finaloplist(label=True), -2, None, None, "pre vectorize") metainterp_sd.profiler.count(Counters.OPT_VECTORIZE_TRY) # start = time.clock() opt = VectorizingOptimizer(metainterp_sd, jitdriver_sd, warmstate.vec_cost) index_vars = opt.run_optimization(info, loop) gso = GuardStrengthenOpt(index_vars) gso.propagate_all_forward(info, loop, user_code) end = time.clock() # metainterp_sd.profiler.count(Counters.OPT_VECTORIZED) metainterp_sd.logger_noopt.log_loop([], loop.finaloplist(label=True), -2, None, None, "post vectorize") nano = int((end-start)*10.0**9) debug_print("# vecopt factor: %d opcount: (%d -> %d) took %dns" % \ (opt.unroll_count+1, len(version.loop.operations), len(loop.operations), nano)) debug_stop("vec-opt-loop") # info.label_op = loop.label return info, loop.finaloplist(jitcell_token=jitcell_token, reset_label_token=False) except NotAVectorizeableLoop: debug_stop("vec-opt-loop") # vectorization is not possible return loop_info, version.loop.finaloplist() except NotAProfitableLoop: debug_stop("vec-opt-loop") # cost model says to skip this loop return loop_info, version.loop.finaloplist() except Exception as e: debug_stop("vec-opt-loop") debug_print("failed to vectorize loop. THIS IS A FATAL ERROR!") if we_are_translated(): from rpython.rtyper.lltypesystem import lltype from rpython.rtyper.lltypesystem.lloperation import llop llop.debug_print_traceback(lltype.Void) else: raise finally: loop.teardown_vectorization() return loop_info, loop_ops
def build_dependencies(self): """ This is basically building the definition-use chain and saving this information in a graph structure. This is the same as calculating the reaching definitions and the 'looking back' whenever it is used. Write After Read, Write After Write dependencies are not possible, the operations are in SSA form """ tracker = DefTracker(self) # label_pos = 0 jump_pos = len(self.nodes)-1 intformod = IntegralForwardModification(self.memory_refs, self.index_vars, self.comparison_vars, self.invariant_vars) # pass 1 for i,node in enumerate(self.nodes): op = node.op if rop.is_always_pure(op.opnum): node.setpriority(1) if rop.is_guard(op.opnum): node.setpriority(2) # the label operation defines all operations at the # beginning of the loop intformod.inspect_operation(op,node) # definition of a new variable if op.type != 'v': # In SSA form. Modifications get a new variable tracker.define(op, node) # usage of defined variables if rop.is_always_pure(op.opnum) or rop.is_final(op.opnum): # normal case every arguments definition is set for arg in op.getarglist(): tracker.depends_on_arg(arg, node) elif rop.is_guard(op.opnum): if node.exits_early(): pass else: # consider cross iterations? if len(self.guards) > 0: last_guard = self.guards[-1] last_guard.edge_to(node, failarg=True, label="guardorder") for nonpure in tracker.non_pure: nonpure.edge_to(node, failarg=True, label="nonpure") tracker.non_pure = [] self.guards.append(node) self.build_guard_dependencies(node, tracker) else: self.build_non_pure_dependencies(node, tracker)