<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Oct 3, 2016 at 1:43 PM, David Callahan <span dir="ltr"><<a href="mailto:dcallahan@fb.com" target="_blank">dcallahan@fb.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">david2050 added a comment.<br>
<br>
For illustration, this is what the client code looks like (abstracted a bit) for at least one back edge in a loop.<br></blockquote><div><br></div><div>This seems a lot more complicated than just modifying insert :)</div><div><br></div><div>If you give it a "from" argument, you only need to do the following, i think.</div><div><br></div><div>  std::pair<iterator, bool> insert(BasicBlock *From BasicBlock *BB) {</div><div>   // If insert succeeds, we've never seen this before<br>          if (!Status.insert(BB).second) {</div><div>             // We've seen this before, so this is a back or cross edge. If it's a cross edge, we must have both visited and completed the other block by now,</div><div>             // otherwise, it's somewhere in our ancestors, by definition.</div><div>             if (!Completed.count(From))</div><div>               Backedge.insert(From, BB).</div><div><br>        }<br></div><div>}</div><div>        void completed(BasicBlock *BB) { Completed[BB] = true; }<br></div><div><br></div><div><br></div><div>(IE there are two cases. In the case of the cross-edge, since we know we visited it already, if it's a *cross* edge, it has to have been in some other part of the tree that we finished, and thus completed should be true.</div><div>In the case of the backedge, it's visited but not completed.</div><div><br></div><div>This is a bit easier to see if think of dfsnumin/dfsnumout.</div><div>dfsnumin gets assigned when we visit the first time and call insert.</div><div>dfsnumout gets assigned when completed happens.</div><div>If, on insert, you find it inserted already, and "from" is a thing with dfsnumin valid but dfsnumout not, it's your ancestor</div><div>If they are both valid, it must be a cross-edge (and you can assert that {dfsnumin, dfsnumout} is not contained in {from.dfsnum, from.dfsnumout})</div><div><br></div><div>Staring for a second, this is the method gcc uses (it explicitly tracks the dfsnumin and dfsnumout for each block)</div><div><br></div><div><br></div><div><br></div><div><br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
(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).<br>
<br>
      // This stores state for the depth-first iterator. In addition<br>
      // to recording which nodes have been visited we also record whether<br>
      // a node is currently on the "stack" of active ancestors of the current<br>
      // node.<br>
      class DFState {<br>
        DenseMap<BasicBlock *, bool> Status;<br>
<br>
      public:<br>
        typedef typename DenseMap<BasicBlock *, bool>::iterator iterator;<br>
<br>
        DFState(unsigned N) { Status.reserve(N); }<br>
        std::pair<iterator, bool> insert(BasicBlock *BB) {<br>
          return Status.insert(std::make_pair(<wbr>BB, true));<br>
        }<br>
        unsigned count(BasicBlock *BB) { return Status.count(BB); }<br>
        // Invoked after we have visited all children of a node.<br>
        void completed(BasicBlock *BB) { Status[BB] = false; }<br>
        // Return true if \p BB is currently on the active stack<br>
        // of ancestors.<br>
        bool onStack(BasicBlock *BB) {<br>
          auto Iter = Status.find(BB);<br>
          return Iter != Status.end() && Iter->second;<br>
        }<br>
      } State(F.size());<br>
<br>
      // Iterate over blocks in depth-first pre-order and<br>
      // treat all edges to a block already seen as loop back edges<br>
      // and mark the branch live it if there is a back edge.<br>
      typedef df_iterator<BasicBlock *, DFState, true> Iterator;<br>
      auto Iter = Iterator::begin(&F.<wbr>getEntryBlock(), State);<br>
      auto End = Iterator::end(&F.<wbr>getEntryBlock(), State);<br>
      for (; Iter != End; ++Iter) {<br>
        auto *BB = *Iter;<br>
<br>
        for (auto Succ : successors(BB))<br>
          if (State.onStack(Succ)) {<br>
            // back edge....<br>
          }<br>
      }<br>
  }<br>
<br>
<br>
<a href="https://reviews.llvm.org/D25191" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D25191</a><br>
<br>
<br>
<br>
</blockquote></div><br></div></div>