This is an archive of the discontinued LLVM Phabricator instance.

Modify df_iterator to support post-order actions
ClosedPublic

Authored by david2050 on Oct 3 2016, 9:05 AM.

Details

Summary

This makes a change to the state used to maintain visited information for depth first iterator. We know assume a method "completed(...)" which is called after all children of a node have been visited. In all existing cases, this method does nothing so this patch has no functional changes. It will however allow a client to distinguish back from cross edges in a DFS tree.

Diff Detail

Repository
rL LLVM

Event Timeline

david2050 updated this revision to Diff 73286.Oct 3 2016, 9:05 AM
david2050 retitled this revision from to Modify df_iterator to support post-order actions.
david2050 updated this object.
david2050 added subscribers: llvm-commits, freik, twoh.
mehdi_amini edited edge metadata.Oct 3 2016, 11:23 AM

This looks fine to me as well.
(I don't know how you'll figure back-edge with it, but I'll see in the next patch)

For illustration, this is what the client code looks like (abstracted a bit) for at least one back edge in a loop.
(Note this code is still order dependent in that the specific edges selected as back edges is order dependent for irreducible loops but is well defined otherwise).

    // This stores state for the depth-first iterator. In addition
    // to recording which nodes have been visited we also record whether
    // a node is currently on the "stack" of active ancestors of the current
    // node.
    class DFState {
      DenseMap<BasicBlock *, bool> Status;

    public:
      typedef typename DenseMap<BasicBlock *, bool>::iterator iterator;

      DFState(unsigned N) { Status.reserve(N); }
      std::pair<iterator, bool> insert(BasicBlock *BB) {
        return Status.insert(std::make_pair(BB, true));
      }
      unsigned count(BasicBlock *BB) { return Status.count(BB); }
      // Invoked after we have visited all children of a node.
      void completed(BasicBlock *BB) { Status[BB] = false; }
      // Return true if \p BB is currently on the active stack
      // of ancestors.
      bool onStack(BasicBlock *BB) {
        auto Iter = Status.find(BB);
        return Iter != Status.end() && Iter->second;
      }
    } State(F.size());

    // Iterate over blocks in depth-first pre-order and
    // treat all edges to a block already seen as loop back edges
    // and mark the branch live it if there is a back edge.
    typedef df_iterator<BasicBlock *, DFState, true> Iterator;
    auto Iter = Iterator::begin(&F.getEntryBlock(), State);
    auto End = Iterator::end(&F.getEntryBlock(), State);
    for (; Iter != End; ++Iter) {
      auto *BB = *Iter;

      for (auto Succ : successors(BB))
        if (State.onStack(Succ)) {
          // back edge....
        }
    }
}

Any additional suggestions for this diff?

dberlin accepted this revision.Oct 5 2016, 2:31 PM
dberlin edited edge metadata.
This revision is now accepted and ready to land.Oct 5 2016, 2:31 PM
This revision was automatically updated to reflect the committed changes.