Index: llvm/include/llvm/ADT/SCCIterator.h =================================================================== --- llvm/include/llvm/ADT/SCCIterator.h +++ llvm/include/llvm/ADT/SCCIterator.h @@ -130,6 +130,9 @@ /// still contain a loop if the node has an edge back to itself. bool hasLoop() const; + /// Test if the current SCC is a natural loop. + bool isNaturalLoop() const; + /// This informs the \c scc_iterator that the specified \c Old node /// has been deleted, and \c New is to be used in its place. void ReplaceNode(NodeRef Old, NodeRef New) { @@ -224,6 +227,37 @@ return false; } +template +bool scc_iterator::isNaturalLoop() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + + // TODO: Somehow get LoopInfo analysis for this graph into a variable LI. + + if (!hasLoop()) + return false; + Loop *L = LI->getLoopFor(CurrentSCC.front()); + // If any random block in this SCC does not belong to a loop, + // then this SCC is definitely not a loop. + if (!L) + return false; + // L is the _innermost_ loop that has a common block with the SCC. + // Since a loop is always an SCC, if their number of blocks + // are equal, the SCC is a loop - specifically, L. Otherwise, there are 2 cases: + // - If the SCC has less blocks, then it is definitely not a loop. + // - If it has more, then we can't decide since the SCC can be a parent loop of L. + // So, we perform the same test for the parent of L. + do { + if (L->getNumBlocks() == CurrentSCC.size()) + return true; + if (CurrentSCC.size() < L->getNumBlocks()) + return false; + L = L->getParentLoop(); + } while (L); + // L is nullptr, so we found no loop that matches exactly + // the number of blocks of the SCC and so the SCC is not a loop. + return false; +} + /// Construct the begin iterator for a deduced graph type T. template scc_iterator scc_begin(const T &G) { return scc_iterator::begin(G);