Index: llvm/trunk/include/llvm/Analysis/LoopInfo.h =================================================================== --- llvm/trunk/include/llvm/Analysis/LoopInfo.h +++ llvm/trunk/include/llvm/Analysis/LoopInfo.h @@ -635,7 +635,7 @@ // Debugging void print(raw_ostream &OS) const; - void verify() const; + void verify(const DominatorTreeBase &DomTree) const; }; // Implementation in LoopInfoImpl.h Index: llvm/trunk/include/llvm/Analysis/LoopInfoImpl.h =================================================================== --- llvm/trunk/include/llvm/Analysis/LoopInfoImpl.h +++ llvm/trunk/include/llvm/Analysis/LoopInfoImpl.h @@ -17,6 +17,7 @@ #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/IR/Dominators.h" @@ -514,8 +515,26 @@ #endif } -template -void LoopInfoBase::verify() const { +template +bool compareVectors(std::vector &BB1, std::vector &BB2) { + std::sort(BB1.begin(), BB1.end()); + std::sort(BB2.begin(), BB2.end()); + return BB1 == BB2; +} + +template +static void +addInnerLoopsToHeadersMap(DenseMap &LoopHeaders, + const LoopInfoBase &LI, + const LoopT &L) { + LoopHeaders[L.getHeader()] = &L; + for (LoopT *SL : L) + addInnerLoopsToHeadersMap(LoopHeaders, LI, *SL); +} + +template +void LoopInfoBase::verify( + const DominatorTreeBase &DomTree) const { DenseSet Loops; for (iterator I = begin(), E = end(); I != E; ++I) { assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); @@ -530,6 +549,48 @@ assert(Loops.count(L) && "orphaned loop"); assert(L->contains(BB) && "orphaned block"); } + + // Recompute LoopInfo to verify loops structure. + LoopInfoBase OtherLI; + OtherLI.analyze(DomTree); + + DenseMap LoopHeaders1; + DenseMap LoopHeaders2; + + for (LoopT *L : *this) + addInnerLoopsToHeadersMap(LoopHeaders1, *this, *L); + for (LoopT *L : OtherLI) + addInnerLoopsToHeadersMap(LoopHeaders2, OtherLI, *L); + assert(LoopHeaders1.size() == LoopHeaders2.size() && + "LoopInfo is incorrect."); + + auto compareLoops = [&](const LoopT *L1, const LoopT *L2) { + BlockT *H1 = L1->getHeader(); + BlockT *H2 = L2->getHeader(); + if (H1 != H2) + return false; + std::vector BB1 = L1->getBlocks(); + std::vector BB2 = L2->getBlocks(); + if (!compareVectors(BB1, BB2)) + return false; + + std::vector SubLoopHeaders1; + std::vector SubLoopHeaders2; + for (LoopT *L : *L1) + SubLoopHeaders1.push_back(L->getHeader()); + for (LoopT *L : *L2) + SubLoopHeaders2.push_back(L->getHeader()); + + if (!compareVectors(SubLoopHeaders1, SubLoopHeaders2)) + return false; + return true; + }; + + for (auto &I : LoopHeaders1) { + BlockT *H = I.first; + bool LoopsMatch = compareLoops(LoopHeaders1[H], LoopHeaders2[H]); + assert(LoopsMatch && "LoopInfo is incorrect."); + } #endif } Index: llvm/trunk/lib/Analysis/LoopInfo.cpp =================================================================== --- llvm/trunk/lib/Analysis/LoopInfo.cpp +++ llvm/trunk/lib/Analysis/LoopInfo.cpp @@ -703,8 +703,10 @@ // -verify-loop-info option can enable this. In order to perform some // checking by default, LoopPass has been taught to call verifyLoop manually // during loop pass sequences. - if (VerifyLoopInfo) - LI.verify(); + if (VerifyLoopInfo) { + auto &DT = getAnalysis().getDomTree(); + LI.verify(DT); + } } void LoopInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { @@ -719,7 +721,8 @@ PreservedAnalyses LoopVerifierPass::run(Function &F, FunctionAnalysisManager &AM) { LoopInfo &LI = AM.getResult(F); - LI.verify(); + auto &DT = AM.getResult(F); + LI.verify(DT); return PreservedAnalyses::all(); } Index: llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp +++ llvm/trunk/lib/Transforms/Scalar/LoopDistribute.cpp @@ -742,7 +742,7 @@ DEBUG(Partitions.printBlocks()); if (LDistVerify) { - LI->verify(); + LI->verify(*DT); DT->verifyDomTree(); }