Exemplo n.º 1
0
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
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    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)