示例#1
0
文件: loopsplit.cpp 项目: wh5a/xgill
// get the result of transitively following skip edges from point
PPoint FollowSkipEdges(BlockCFG *cfg, PPoint point)
{
    PPoint cur = point;
    bool changed = true;

    while (changed) {
        changed = false;

        const Vector<PEdge*> &outgoing = cfg->GetOutgoingEdges(cur);
        if (outgoing.Size() == 1) {
            PEdge *edge = outgoing[0];
            if (edge->IsSkip()) {
                PPoint next = edge->GetTarget();

                // watch out for skip edges aborting the function.
                if (next) {
                    cur = next;
                    changed = true;
                }
            }
        }
    }

    return cur;
}
示例#2
0
文件: loopsplit.cpp 项目: wh5a/xgill
// compute the points in the CFG reachable from the entry point.
void GetEntryReachable(BlockCFG *cfg)
{
    // worklist items are reachable points whose outgoing edges have
    // not been examined
    Vector<PPoint> worklist;

    PPoint entry = cfg->GetEntryPoint();
    entry_reach_table->Insert(entry);
    worklist.PushBack(entry);

    while (!worklist.Empty()) {
        PPoint back = worklist.Back();
        worklist.PopBack();

        const Vector<PEdge*>& outgoing = cfg->GetOutgoingEdges(back);
        for (size_t oind = 0; oind < outgoing.Size(); oind++) {
            PEdge *edge = outgoing[oind];
            PPoint next = edge->GetTarget();

            // already did this target
            if (entry_reach_table->Lookup(next))
                continue;

            entry_reach_table->Insert(next);
            worklist.PushBack(next);
        }
    }
}
示例#3
0
文件: loopsplit.cpp 项目: wh5a/xgill
// marks the points in cfg which are isomorphic to points in the loop_cfg
// invoked by cfg at the specified edge. code in a syntactic loop body
// will be reflected in CFGs for both the loop and its parent if it may
// reach both the recursive loop edge and a loop exit point. this common
// code will be isomorphic between the two CFGs.
void GetLoopIsomorphicPoints(BlockCFG *cfg, PEdge *loop_edge,
                             BlockCFG *loop_cfg)
{
    // mapping from points in cfg to isomorphic points in loop_cfg.
    PPointListHash remapping;

    // worklist items are isomorphic points whose outgoing edges have not
    // been examined.
    Vector<PPoint> worklist;

    PPoint target = loop_edge->GetTarget();
    remapping.Insert(target, loop_cfg->GetEntryPoint());
    cfg->AddLoopIsomorphic(target);
    worklist.PushBack(target);

    while (!worklist.Empty()) {
        PPoint cfg_point = worklist.Back();
        worklist.PopBack();

        PPoint loop_point = remapping.LookupSingle(cfg_point);

        const Vector<PEdge*> &cfg_outgoing =
            cfg->GetOutgoingEdges(cfg_point);
        const Vector<PEdge*> &loop_outgoing =
            loop_cfg->GetOutgoingEdges(loop_point);

        for (size_t eind = 0; eind < cfg_outgoing.Size(); eind++) {
            PEdge *edge = cfg_outgoing[eind];
            PPoint target = edge->GetTarget();

            // check for an existing remapping entry. some isomorphic points have
            // multiple incoming edges. we don't need to check all such incoming
            // edges; if any edge is isomorphic, they all will be.
            if (remapping.Lookup(target, false))
                continue;

            // look for an equivalent outgoing edge from the loop.
            PPoint loop_target = 0;

            for (size_t lind = 0; lind < loop_outgoing.Size(); lind++) {
                PEdge *loop_edge = loop_outgoing[lind];

                if (PEdge::CompareInner(edge, loop_edge) == 0) {
                    loop_target = loop_edge->GetTarget();
                    break;
                }
            }

            if (!loop_target) {
                Assert(edge->IsAssume());
                continue;
            }

            remapping.Insert(target, loop_target);
            cfg->AddLoopIsomorphic(target);
            worklist.PushBack(target);
        }
    }
}
示例#4
0
文件: loopsplit.cpp 项目: wh5a/xgill
// get the set of points reachable from loophead over paths
// that do not go through a backedge. if loophead itself is
// reachable, it is irreducible and those new edges to it are added
// as backedges. return value is true iff the loop is irreducible.
bool GetLoopReachable(BlockCFG *cfg, PPoint loophead)
{
    // worklist items are points in reach_table whose outgoing edges
    // have not been examined
    Vector<PPoint> worklist;

    if (!entry_reach_table->Lookup(loophead))
        return false;

    reach_table->Insert(PPointPair(loophead, loophead));
    worklist.PushBack(loophead);

    bool found_irreducible = false;

    while (!worklist.Empty()) {
        PPoint back = worklist.Back();
        worklist.PopBack();

        const Vector<PEdge*>& outgoing = cfg->GetOutgoingEdges(back);
        for (size_t oind = 0; oind < outgoing.Size(); oind++) {
            PEdge *edge = outgoing[oind];
            PPoint next = edge->GetTarget();

            if (backedge_table->Lookup(edge))
                continue;

            if (next == loophead) {
                // we're in an irreducible loop. add the new edge to backedge_table.
                backedge_table->Insert(edge);
                found_irreducible = true;
                continue;
            }

            if (!reach_table->Insert(PPointPair(loophead, next)))
                worklist.PushBack(next);
        }
    }

    return found_irreducible;
}
示例#5
0
文件: loopsplit.cpp 项目: wh5a/xgill
void TopoSortCFG(BlockCFG *cfg)
{
    // can't topo sort a CFG that might have loops.
    Assert(cfg->GetLoopHeadCount() == 0);

    // map from old CFG points to the new points in the topo order. we can only
    // add a new point once we've added all its predecessors.
    PPointListHash remapping;

    // points in the remappping, in the order to add them to the CFG.
    Vector<Location*> new_points;

    // map from new points back to original CFG points.
    Vector<PPoint> old_points;

    // worklist items are the points where the sources of incoming edges have
    // already been added to the remapping, the point itself has not.
    Vector<PPoint> worklist;

    PPoint entry_point = cfg->GetEntryPoint();
    PPoint exit_point = cfg->GetExitPoint();

    // seed the worklist.
    worklist.PushBack(entry_point);

    while (!worklist.Empty()) {
        // pick the point from the worklist with the minimum line number.
        // if there is code like:
        //   if (x)
        //     a;
        //   else
        //     b;
        // we could add either a or b to the remapping first, but we want to add
        // a first. the ordering of points is used for naming loops, and we want
        // this ordering to be deterministic and map back to the code predictably.

        size_t best_index = 0;
        size_t best_line = cfg->GetPointLocation(worklist[0])->Line();

        for (size_t ind = 1; ind < worklist.Size(); ind++) {
            size_t new_line = cfg->GetPointLocation(worklist[ind])->Line();
            if (new_line < best_line) {
                best_index = ind;
                best_line = new_line;
            }
        }

        PPoint point = worklist[best_index];
        worklist[best_index] = worklist.Back();
        worklist.PopBack();

        Assert(!remapping.Lookup(point, false));

        Location *loc = cfg->GetPointLocation(point);
        loc->IncRef();
        new_points.PushBack(loc);
        old_points.PushBack(point);

        remapping.Insert(point, new_points.Size());

        const Vector<PEdge*> &outgoing = cfg->GetOutgoingEdges(point);
        for (size_t oind = 0; oind < outgoing.Size(); oind++) {
            PEdge *edge = outgoing[oind];
            PPoint target = edge->GetTarget();

            // this can happen if there are multiple edges from the worklist point
            // to the target, e.g. 'if (x) {}'. not going to happen much.
            if (worklist.Contains(target))
                continue;

            Assert(!remapping.Lookup(target, false));

            // we can add the target to the worklist if it has no incoming edges
            // from points not in the remapping.
            bool missing_incoming = false;

            const Vector<PEdge*> &incoming = cfg->GetIncomingEdges(target);
            for (size_t iind = 0; iind < incoming.Size(); iind++) {
                PEdge *edge = incoming[iind];
                PPoint source = edge->GetSource();
                if (!remapping.Lookup(source, false)) {
                    missing_incoming = true;
                    break;
                }
            }

            if (!missing_incoming)
                worklist.PushBack(target);
        }
    }

    // this assert will fail if either the CFG contains cycles, or if there are
    // nodes unreachable from the start. neither of these cases should be
    // possible here.
    Assert(new_points.Size() == cfg->GetPointCount());
    Assert(old_points.Size() == cfg->GetPointCount());

    // remap all the edges. this is also done so that the edges will be
    // in topological order according to their source points.
    Vector<PEdge*> new_edges;

    for (size_t pind = 0; pind < old_points.Size(); pind++) {
        const Vector<PEdge*> &edges = cfg->GetOutgoingEdges(old_points[pind]);

        for (size_t eind = 0; eind < edges.Size(); eind++) {
            PEdge *edge = edges[eind];

            PPoint new_source = remapping.LookupSingle(edge->GetSource());
            PPoint new_target = remapping.LookupSingle(edge->GetTarget());

            PEdge *new_edge = PEdge::ChangeEdge(edge, new_source, new_target);
            new_edges.PushBack(new_edge);
        }
    }

    // clear out the initial CFG.
    cfg->ClearBody();

    // add the new points, edges, annotations.
    for (size_t pind = 0; pind < new_points.Size(); pind++)
        cfg->AddPoint(new_points[pind]);
    for (size_t eind = 0; eind < new_edges.Size(); eind++)
        cfg->AddEdge(new_edges[eind]);

    // set the new entry point. this had better be the first point in the order.
    PPoint new_entry_point = remapping.LookupSingle(entry_point);
    Assert(new_entry_point == 1);
    cfg->SetEntryPoint(new_entry_point);

    if (exit_point) {
        // set the new exit point. this had better be the last point in the order.
        PPoint new_exit_point = remapping.LookupSingle(exit_point);
        Assert(new_exit_point == new_points.Size());
        cfg->SetExitPoint(new_exit_point);
    }
}
示例#6
0
文件: loopsplit.cpp 项目: wh5a/xgill
void TrimUnreachable(BlockCFG *cfg, bool flatten_skips)
{
    // can't flatten skips if there might be loops in the CFG.
    Assert(!flatten_skips || cfg->GetLoopHeadCount() == 0);

    // receives the locations of the new points and edges of the CFG. we will
    // fill these in, then replace wholesale the old points/edges on the CFG.
    Vector<Location*> new_points;
    Vector<PEdge*> new_edges;
    Vector<LoopHead> new_loop_heads;

    Vector<PPoint> worklist;

    // get the set of points reachable from CFG entry.
    // worklist items are points in entry_reachable whose outgoing edges
    // have not been examined.
    PPointHash entry_reachable;

    PPoint entry = cfg->GetEntryPoint();
    entry_reachable.Insert(entry);
    worklist.PushBack(entry);

    while (!worklist.Empty()) {
        PPoint back = worklist.Back();
        worklist.PopBack();

        const Vector<PEdge*> &outgoing = cfg->GetOutgoingEdges(back);
        for (size_t oind = 0; oind < outgoing.Size(); oind++) {
            PEdge *edge = outgoing[oind];
            PPoint next = edge->GetTarget();

            if (!entry_reachable.Lookup(next)) {
                entry_reachable.Insert(next);
                worklist.PushBack(next);
            }
        }
    }

    // get the set of points which reach the CFG exit.
    // worklist items are points in exit_reaches whose incoming edges
    // have not been examined.
    PPointHash exit_reaches;

    PPoint exit = cfg->GetExitPoint();
    exit_reaches.Insert(exit);
    worklist.PushBack(exit);

    while (!worklist.Empty()) {
        PPoint back = worklist.Back();
        worklist.PopBack();

        const Vector<PEdge*> &incoming = cfg->GetIncomingEdges(back);
        for (size_t iind = 0; iind < incoming.Size(); iind++) {
            PEdge *edge = incoming[iind];
            PPoint prev = edge->GetSource();

            if (!exit_reaches.Lookup(prev)) {
                exit_reaches.Insert(prev);
                worklist.PushBack(prev);
            }
        }
    }

    // make sure we include the entry regardless of whether the function
    // has a path from entry to exit.
    exit_reaches.Insert(entry);
    if (flatten_skips)
        exit_reaches.Insert(FollowSkipEdges(cfg, entry));

    // map from old points to corresponding new points. only defined for
    // points that are in both entry_reachable and exit_reaches,
    // and that do not have outgoing skip edges (if flatten_skips is set).
    PPointListHash remapping;

    // map from some old p0 to another old p1 where p0 connects to p1 by
    // skip edges and p1 has no outgoing skips. empty if flatten_skips is
    // not set. only defined if remapping is defined for p1.
    PPointListHash skip_remapping;

    for (PPoint point = 1; point <= cfg->GetPointCount(); point++) {
        if (entry_reachable.Lookup(point) && exit_reaches.Lookup(point)) {

            // if this is just the source of some skip edges flatten them out.
            // the target of the skips will be defined by remapping since
            // there can be only one outgoing skip edge from a point and
            // thus all paths from point pass through target_point; if point
            // reaches the exit then so does target_point.
            if (flatten_skips) {
                PPoint target_point = FollowSkipEdges(cfg, point);
                if (target_point != point) {
                    skip_remapping.Insert(point, target_point);

                    // don't add anything to remapping for point
                    continue;
                }
            }

            Location *loc = cfg->GetPointLocation(point);
            loc->IncRef();
            new_points.PushBack(loc);
            PPoint new_point = new_points.Size();

            remapping.Insert(point, new_point);
        }
    }

    for (size_t eind = 0; eind < cfg->GetEdgeCount(); eind++) {
        PEdge *edge = cfg->GetEdge(eind);

        PPoint source = edge->GetSource();
        PPoint target = edge->GetTarget();

        if (skip_remapping.Lookup(source, false))
            continue;

        // flatten any skips after the target point
        Vector<PPoint> *skip_target_list = skip_remapping.Lookup(target, false);
        if (skip_target_list) {
            Assert(skip_target_list->Size() == 1);
            target = skip_target_list->At(0);
        }

        Vector<PPoint> *new_source_list = remapping.Lookup(source, false);
        Vector<PPoint> *new_target_list = remapping.Lookup(target, false);

        if (new_source_list && new_target_list) {
            Assert(new_source_list->Size() == 1);
            Assert(new_target_list->Size() == 1);

            PPoint new_source = new_source_list->At(0);
            PPoint new_target = new_target_list->At(0);

            PEdge *new_edge = PEdge::ChangeEdge(edge, new_source, new_target);
            new_edges.PushBack(new_edge);
        }
    }

    for (size_t lind = 0; lind < cfg->GetLoopHeadCount(); lind++) {
        const LoopHead &head = cfg->GetLoopHead(lind);

        // don't check skip_remapping because we don't allow skip flattening
        // when the CFG still has loops in it

        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();

            new_loop_heads.PushBack(new_head);
        }
    }

    // clear out the initial CFG.
    cfg->ClearBody();

    // add the new points, edges, loop heads.
    for (size_t pind = 0; pind < new_points.Size(); pind++)
        cfg->AddPoint(new_points[pind]);
    for (size_t eind = 0; eind < new_edges.Size(); eind++)
        cfg->AddEdge(new_edges[eind]);
    for (size_t lind = 0; lind < new_loop_heads.Size(); lind++)
        cfg->AddLoopHead(new_loop_heads[lind].point,
                         new_loop_heads[lind].end_location);

    // set the new entry and exit points of the CFG.

    // the entry may be connected to skip edges
    Vector<PPoint> *skip_entry_list = skip_remapping.Lookup(entry, false);
    if (skip_entry_list) {
        Assert(skip_entry_list->Size() == 1);
        entry = skip_entry_list->At(0);
    }

    PPoint new_entry = remapping.LookupSingle(entry);
    PPoint new_exit = 0;

    Vector<PPoint> *new_exit_list = remapping.Lookup(exit, false);
    if (new_exit_list) {
        Assert(new_exit_list->Size() == 1);
        new_exit = new_exit_list->At(0);
    }

    cfg->SetEntryPoint(new_entry);
    cfg->SetExitPoint(new_exit);
}
示例#7
0
文件: loopsplit.cpp 项目: wh5a/xgill
// clone a loop body, mapping each point in the body of loophead
// to a new point in receive_cfg. receive_cfg will receive new points
// for the cloned body, and new edges for any non-backedge whose source
// and target are both in loophead's body. for other edges involving loophead,
// old_entry/exit/backedge_indexes will be filled in with indexes into
// the edges list of base_cfg. it may be that base_cfg == receive_cfg.
void CloneLoopBody(BlockCFG *base_cfg, PPoint loophead,
                   PPointListHash *remapping,
                   BlockCFG *receive_cfg,
                   Vector<size_t> *old_entry_indexes,
                   Vector<size_t> *old_exit_indexes,
                   Vector<size_t> *old_back_indexes)
{
    Assert(remapping->IsEmpty());

    Vector<PPoint> *body_list = body_list_table->Lookup(loophead, true);
    Assert(!body_list->Empty());

    // allow for base_cfg == receive_cfg, so keep track of how many points and
    // edges were originally in base_cfg before modifying receive_cfg.
    size_t init_points_size = base_cfg->GetPointCount();
    size_t init_edges_size = base_cfg->GetEdgeCount();

    // copy all points in the loop body to the new CFG.
    for (size_t bind = 0; bind < body_list->Size(); bind++) {
        PPoint body_point = body_list->At(bind);
        Assert(remapping->Lookup(body_point, false) == NULL);

        Assert(0 < body_point && body_point <= init_points_size);
        Location *loc = base_cfg->GetPointLocation(body_point);

        loc->IncRef();
        PPoint new_point = receive_cfg->AddPoint(loc);
        remapping->Insert(body_point, new_point);
    }

    // copy all edges between points in the body to the new CFG.
    for (size_t eind = 0; eind < init_edges_size; eind++) {
        PEdge *edge = base_cfg->GetEdge(eind);
        PPoint source = edge->GetSource();
        PPoint target = edge->GetTarget();

        if (!entry_reach_table->Lookup(source))
            continue;

        PPoint new_source = 0;
        if (body_table->Lookup(PPointPair(loophead, source)))
            new_source = remapping->LookupSingle(source);

        PPoint new_target = 0;
        if (body_table->Lookup(PPointPair(loophead, target)))
            new_target = remapping->LookupSingle(target);

        if (!new_source && !new_target) {
            // edge is not involved with this loop. leave it alone
        }
        else if (!new_source && new_target) {
            // entry edge. leave it alone
            old_entry_indexes->PushBack(eind);
        }
        else if (new_source && !new_target) {
            // exit edge. leave it alone
            old_exit_indexes->PushBack(eind);
        }
        else {
            Assert(new_source && new_target);

            if (target == loophead) {
                // back edge. leave it alone
                Assert(backedge_table->Lookup(edge));
                old_back_indexes->PushBack(eind);
            }
            else {
                // inner edge. clone the edge for the new source and target
                PEdge *new_edge = PEdge::ChangeEdge(edge, new_source, new_target);
                receive_cfg->AddEdge(new_edge);
            }
        }
    }
}
示例#8
0
文件: loopsplit.cpp 项目: wh5a/xgill
// determine whether loophead is a reducible loop with backedges in cfg.
// fill in dominate_table with the points dominated by loophead,
// and add as backedges any edge going to loophead which is itself
// dominated by loophead. return true if any backedges were found.
bool GetLoopBackedges(BlockCFG *cfg, PPoint loophead)
{
    // compute the nodes reachable from the entry point other than
    // through start. the dominated points are the dual of this set.

    // points reachable from the start according to the above criteria
    PPointHash reachable;

    // worklist items are points in reachable whose outgoing edges have
    // not been examined
    Vector<PPoint> worklist;

    if (!entry_reach_table->Lookup(loophead))
        return false;

    PPoint entry = cfg->GetEntryPoint();
    reachable.Insert(entry);
    worklist.PushBack(entry);

    while (!worklist.Empty()) {
        PPoint back = worklist.Back();
        worklist.PopBack();

        const Vector<PEdge*>& outgoing = cfg->GetOutgoingEdges(back);
        for (size_t oind = 0; oind < outgoing.Size(); oind++) {
            PEdge *edge = outgoing[oind];
            PPoint next = edge->GetTarget();

            if (next == loophead)
                continue;

            // already did this target
            if (reachable.Lookup(next))
                continue;

            reachable.Insert(next);
            worklist.PushBack(next);
        }
    }

    // compute the set of dominated points. this is the difference
    // between the points reachable from the CFG entry, and the points
    // in the reach table we just computed.
    for (PPoint point = 1; point <= cfg->GetPointCount(); point++) {
        if (!reachable.Lookup(point) && entry_reach_table->Lookup(point))
            dominate_table->Insert(PPointPair(loophead, point));
    }

    // backedges on the loophead are incoming edges whose source is
    // dominated by the loophead
    bool found_backedge = false;
    const Vector<PEdge*> &incoming = cfg->GetIncomingEdges(loophead);
    for (size_t eind = 0; eind < incoming.Size(); eind++) {
        PEdge *edge = incoming[eind];
        if (dominate_table->Lookup(PPointPair(loophead, edge->GetSource()))) {
            backedge_table->Insert(edge);
            found_backedge = true;
        }
    }

    return found_backedge;
}