Exemplo n.º 1
0
void
TclOptimizeBytecode(
    void *envPtr)
{
    ConvertZeroEffectToNOP(envPtr);
    AdvanceJumps(envPtr);
    TrimUnreachable(envPtr);
}
Exemplo n.º 2
0
// split a single loop from the existing body. this creates a new CFG
// with cloned points and edges for the loop's execution, and fixes up
// the points and edges in base_cfg to add a Loop() summary edge and remove
// the CFG cycle.
BlockCFG* SplitSingleLoop(PPoint loophead, const Vector<PPoint> &all_loops,
                          BlockCFG *base_cfg)
{
    // make a temporary name for the loop.
    char loop_name[100];
    snprintf(loop_name, sizeof(loop_name), "scratch#%d", loophead);

    Variable *function_info = base_cfg->GetId()->BaseVar();

    // make an ID for the split loop.
    function_info->IncRef();
    String *loop_info = String::Make(loop_name);
    BlockId *loop_id = BlockId::Make(B_Loop, function_info, loop_info);

    // make a CFG for the split loop.
    BlockCFG *loop_cfg = BlockCFG::Make(loop_id);
    CopyCFGLocationsVariables(base_cfg, loop_cfg);

    PPointListHash remapping;
    Vector<size_t> old_entry_indexes;
    Vector<size_t> old_exit_indexes;
    Vector<size_t> old_back_indexes;

    CloneLoopBody(base_cfg, loophead, &remapping, loop_cfg,
                  &old_entry_indexes, &old_exit_indexes, &old_back_indexes);

    // fixup the old CFG first. we need to perform the following steps:
    // - create a new point with a Loop() edge going to the head.
    // - add the new point to the body of any loop also containing the head.
    // - change all loop entry edges to go to the new point instead of the head.
    // - delete all backedges on the loop by pointing them to point 0.

    Location *loop_head_loc = base_cfg->GetPointLocation(loophead);

    loop_head_loc->IncRef();
    PPoint summary_point = base_cfg->AddPoint(loop_head_loc);

    loop_id->IncRef();
    PEdge *summary_edge = PEdge::MakeLoop(summary_point, loophead, loop_id);
    base_cfg->AddEdge(summary_edge);

    // mark the new summary point as being reachable from the entry point.
    entry_reach_table->Insert(summary_point);

    // add the new summary point to the body of any other loop which
    // already contains the head of this loop in its body.
    for (size_t lind = 0; lind < all_loops.Size(); lind++) {
        if (body_table->Lookup(PPointPair(all_loops[lind], loophead))) {
            body_table->Insert(PPointPair(all_loops[lind], summary_point));
            body_list_table->Insert(all_loops[lind], summary_point);
        }
    }

    for (size_t oind = 0; oind < old_entry_indexes.Size(); oind++) {
        size_t entry_index = old_entry_indexes[oind];
        PEdge *old_edge = base_cfg->GetEdge(entry_index);

        PPoint source = old_edge->GetSource();
        Assert(old_edge->GetTarget() == loophead);

        PEdge *new_edge = PEdge::ChangeEdge(old_edge, source, summary_point);
        base_cfg->SetEdge(entry_index, new_edge);
    }

    for (size_t oind = 0; oind < old_back_indexes.Size(); oind++) {
        size_t back_index = old_back_indexes[oind];
        PEdge *old_edge = base_cfg->GetEdge(back_index);

        PPoint source = old_edge->GetSource();
        Assert(old_edge->GetTarget() == loophead);

        PEdge *new_edge = PEdge::ChangeEdge(old_edge, source, 0);
        base_cfg->SetEdge(back_index, new_edge);
    }

    // fixup the new CFG second. we need to perform the following steps:
    // - mark the cloned head as the entry point.
    // - create a new point as the exit point.
    // - for each backedge in the original loop, redirect to the exit point.

    PPoint split_entry = remapping.LookupSingle(loophead);

    // find the exit location associated with this loop head, if there is one.
    size_t headind = 0;
    for (; headind < base_cfg->GetLoopHeadCount(); headind++) {
        if (base_cfg->GetLoopHead(headind).point == loophead)
            break;
    }
    Assert(headind < base_cfg->GetLoopHeadCount());
    Location *end_location = base_cfg->GetLoopHead(headind).end_location;

    // if there isn't an end location (goto loop in the original source),
    // just use the location of the loop head itself.
    if (!end_location)
        end_location = loop_head_loc;

    end_location->IncRef();
    PPoint split_exit = loop_cfg->AddPoint(end_location);

    for (size_t oind = 0; oind < old_back_indexes.Size(); oind++) {
        size_t back_index = old_back_indexes[oind];
        PEdge *old_edge = base_cfg->GetEdge(back_index);

        PPoint source = old_edge->GetSource();

        // we should have already dropped the target of this edge.
        Assert(old_edge->GetTarget() == 0);

        PPoint new_source = remapping.LookupSingle(source);
        PEdge *new_edge = PEdge::ChangeEdge(old_edge, new_source, split_exit);
        loop_cfg->AddEdge(new_edge);
    }

    // set the entry/exit points of the loop CFG.
    loop_cfg->SetEntryPoint(split_entry);
    loop_cfg->SetExitPoint(split_exit);

    // trim any unreachable portions of the loop CFG, collapse skips
    // and sort the points.
    TrimUnreachable(loop_cfg, true);
    TopoSortCFG(loop_cfg);

    // set the end location of the loop to the point in the body with the
    // highest line number. the GCC frontend does not have information
    // about the end location of loop bodies.
    Location *highest = end_location;
    for (PPoint point = 1; point <= loop_cfg->GetPointCount(); point++) {
        Location *loc = loop_cfg->GetPointLocation(point);
        if (loc->FileName() == highest->FileName() && loc->Line() > highest->Line())
            highest = loc;
    }
    highest->IncRef();
    loop_cfg->SetPointLocation(loop_cfg->GetExitPoint(), highest);

    return loop_cfg;
}
Exemplo n.º 3
0
// remove the irreducible entry edges on loophead by cloning the body
// of loophead, redirecting the irreducible edges to that cloned body,
// and directing the back edges of the cloned loop back to the entry
// of the real loop. destructively modifies cfg.
void ReduceLoop(BlockCFG *cfg, PPoint loophead,
                const Vector<PEdge*> &irreducible_edges)
{
    PPointListHash remapping;

    Vector<size_t> old_entry_indexes;
    Vector<size_t> old_exit_indexes;
    Vector<size_t> old_back_indexes;

    CloneLoopBody(cfg, loophead, &remapping, cfg,
                  &old_entry_indexes, &old_exit_indexes, &old_back_indexes);

    // replace the irreducible entry edges with edges into the
    // corresponding point in the new loop.
    for (size_t iind = 0; iind < irreducible_edges.Size(); iind++) {
        PEdge *irr_edge = irreducible_edges[iind];
        bool found_index = false;

        for (size_t oind = 0; oind < old_entry_indexes.Size(); oind++) {
            size_t entry_index = old_entry_indexes[oind];
            PEdge *old_edge = cfg->GetEdge(entry_index);

            if (old_edge == irr_edge) {
                Assert(!found_index);
                found_index = true;

                PPoint source = old_edge->GetSource();
                PPoint target = old_edge->GetTarget();
                PPoint new_target = remapping.LookupSingle(target);

                PEdge *new_edge = PEdge::ChangeEdge(old_edge, source, new_target);
                cfg->SetEdge(entry_index, new_edge);
            }
        }

        Assert(found_index);
    }

    // add the old exit edges for the new loop.
    for (size_t oind = 0; oind < old_exit_indexes.Size(); oind++) {
        PEdge *old_edge = cfg->GetEdge(old_exit_indexes[oind]);

        PPoint source = old_edge->GetSource();
        PPoint target = old_edge->GetTarget();
        PPoint new_source = remapping.LookupSingle(source);

        PEdge *new_edge = PEdge::ChangeEdge(old_edge, new_source, target);
        cfg->AddEdge(new_edge);
    }

    // add the old back edges as edges to the entry point of the old loop.
    for (size_t oind = 0; oind < old_back_indexes.Size(); oind++) {
        PEdge *old_edge = cfg->GetEdge(old_back_indexes[oind]);

        PPoint source = old_edge->GetSource();
        PPoint target = old_edge->GetTarget();
        PPoint new_source = remapping.LookupSingle(source);

        Assert(target == loophead);

        PEdge *new_edge = PEdge::ChangeEdge(old_edge, new_source, target);
        cfg->AddEdge(new_edge);
    }

    // add any loopheads that may have been duplicated within the cloned loop.
    // note that the new loophead does not have any incoming edges and will
    // get trimmed by TrimUnreachable().
    for (size_t lind = 0; lind < cfg->GetLoopHeadCount(); lind++) {
        const LoopHead &head = cfg->GetLoopHead(lind);

        Vector<PPoint> *new_point_list = remapping.Lookup(head.point, false);
        if (new_point_list) {
            Assert(new_point_list->Size() == 1);
            LoopHead new_head(new_point_list->At(0), head.end_location);

            if (head.end_location)
                head.end_location->IncRef();

            cfg->AddLoopHead(new_head.point, new_head.end_location);
        }
    }

    // trim unreachable portions of the cfg, but do not collapse skip edges.
    TrimUnreachable(cfg, false);
}
Exemplo n.º 4
0
void SplitLoops(BlockCFG *base_cfg, Vector<BlockCFG*> *result_cfg_list)
{
    // get the CFG which will eventually become the loop-free outer function CFG.
    BlockCFG *func_cfg;
    if (base_cfg->GetId()->Kind() == B_FunctionWhole) {
        // make an ID for the outer function body.
        Variable *function_info = base_cfg->GetId()->BaseVar();
        function_info->IncRef();
        BlockId *outer_id = BlockId::Make(B_Function, function_info);

        // make the function CFG by cloning the base CFG with the new ID.
        func_cfg = BlockCFG::Make(outer_id);
        CopyCFGLocationsVariables(base_cfg, func_cfg);
        CopyCFGPointsEdges(base_cfg, func_cfg);
    }
    else if (base_cfg->GetId()->Kind() == B_Function) {
        // this call came from a recursive invocation of SplitLoops after we
        // removed an irreducible loop from the function.
        func_cfg = base_cfg;
    }
    else {
        // just destructively update the original CFG.
        base_cfg->IncRef();
        func_cfg = base_cfg;
    }

    // add a new entry point with a skip edge to the original entry point.
    // loop splitting breaks if the entry point is marked as a loop head.

    PPoint entry = func_cfg->GetEntryPoint();
    Location *loc = func_cfg->GetPointLocation(entry);
    loc->IncRef();
    PPoint new_entry = func_cfg->AddPoint(loc);

    PEdge *skip_edge = PEdge::MakeSkip(new_entry, entry);
    func_cfg->AddEdge(skip_edge);
    func_cfg->SetEntryPoint(new_entry);

    // setup the tables we need to do loop splitting.
    SetupTables();

    // compute the points reachable from the entry point.
    GetEntryReachable(func_cfg);

    // the real loops in the program with back edges.
    Vector<PPoint> loops;

    for (size_t lind = 0; lind < func_cfg->GetLoopHeadCount(); lind++) {
        PPoint head = func_cfg->GetLoopHead(lind).point;
        if (GetLoopBackedges(func_cfg, head))
            loops.PushBack(head);
    }

    // compute reachability and check for irreducible loops.
    for (size_t lind = 0; lind < func_cfg->GetLoopHeadCount(); lind++) {
        const LoopHead &head = func_cfg->GetLoopHead(lind);

        if (GetLoopReachable(func_cfg, head.point)) {
            // loop is irreducible.

            // get the loop's irreducible edges.
            Vector<PEdge*> irreducible_edges;
            GetLoopBody(func_cfg, head.point, &irreducible_edges);
            Assert(!irreducible_edges.Empty());

            // clone the loop's body and remove the irreducible edges.
            ReduceLoop(func_cfg, head.point, irreducible_edges);

            // try again on the modified CFG.
            CleanupTables();
            SplitLoops(func_cfg, result_cfg_list);
            return;
        }
    }

    // there are no irreducible loops at this point so this should
    // never have any entries added.
    Vector<PEdge*> irreducible_edges;

    // compute loop bodies.
    for (size_t lind = 0; lind < loops.Size(); lind++) {
        PPoint head = loops[lind];
        GetLoopBody(func_cfg, head, &irreducible_edges);
        Assert(irreducible_edges.Empty());
    }

    // construct a tree of all the loops. loop A contains loop B
    // if A != B and the head of B is in the body of A.
    PPointListHash loop_tree;

    // split off all the loops in the CFG. make sure we split inner loops
    // before outer, so that the Loop edges on inner loops will appear in
    // the split body for outer loops.
    while (!loops.Empty()) {

        // find a candidate loop to split. this is one whose loop children
        // have already been split off and are no longer in the loops list.
        PPoint loophead = 0;
        for (size_t lind = 0; lind < loops.Size(); lind++) {

            bool is_viable = true;
            for (size_t xlind = 0; xlind < loops.Size(); xlind++) {
                if (xlind == lind)
                    continue;
                Assert(loops[lind] != loops[xlind]);

                if (body_table->Lookup(PPointPair(loops[lind], loops[xlind]))) {
                    is_viable = false;
                    break;
                }
            }

            if (is_viable) {
                loophead = loops[lind];
                loops[lind] = loops.Back();
                loops.PopBack();
                break;
            }
        }

        Assert(loophead);
        BlockCFG *loop_cfg = SplitSingleLoop(loophead, loops, func_cfg);
        result_cfg_list->PushBack(loop_cfg);
    }

    // clear out the loopheads, we don't want them around anymore.
    func_cfg->ClearLoopHeads();

    // trim unreachable points in the function CFG (i.e. bodies of loops that
    // now redirect to point zero), collapse skips and topo sort.
    TrimUnreachable(func_cfg, true);
    TopoSortCFG(func_cfg);

    result_cfg_list->PushBack(func_cfg);
    CleanupTables();

    // fill in any loop parents for the inner loop CFGs, and make sure the
    // result CFGs are ordered correctly, with inner loops before outer loops
    // and the outer function.
    for (size_t cind = 0; cind < result_cfg_list->Size(); cind++) {
        BlockCFG *cfg = result_cfg_list->At(cind);

        for (size_t eind = 0; eind < cfg->GetEdgeCount(); eind++) {
            if (PEdgeLoop *edge = cfg->GetEdge(eind)->IfLoop()) {
                BlockId *target_id = edge->GetLoopId();

                bool found_target = false;
                for (size_t xcind = 0; xcind < cind; xcind++) {
                    BlockCFG *xcfg = result_cfg_list->At(xcind);
                    if (xcfg->GetId() == target_id) {
                        found_target = true;

                        cfg->GetId()->IncRef();
                        BlockPPoint where(cfg->GetId(), edge->GetSource());
                        xcfg->AddLoopParent(where);

                        // mark the isomorphic points in the parent CFG.
                        GetLoopIsomorphicPoints(cfg, edge, xcfg);

                        break;
                    }
                }

                Assert(found_target);
            }
        }
    }

    // assign the final names to the various loop CFGs.
    FillLoopNames(func_cfg, "loop", *result_cfg_list);
}