Index: include/llvm/Analysis/LoopInfo.h =================================================================== --- include/llvm/Analysis/LoopInfo.h +++ include/llvm/Analysis/LoopInfo.h @@ -636,6 +636,7 @@ void print(raw_ostream &OS) const; void verify() const; + void verifyByRecomputation(const DominatorTreeBase &DomTree) const; }; // Implementation in LoopInfoImpl.h Index: include/llvm/Analysis/LoopInfoImpl.h =================================================================== --- include/llvm/Analysis/LoopInfoImpl.h +++ 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" @@ -535,6 +536,76 @@ #endif } +template +bool compareVectors(std::vector &BB1, std::vector &BB2) { + if (BB1.size() != BB2.size()) + return false; + + SmallSetVector BBSet1; + for (T BB : BB1) + BBSet1.insert(BB); + for (T BB : BB2) + if (BBSet1.count(BB) != 1) + return false; + + return true; +} + +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 +static bool 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; +} + +template +void LoopInfoBase::verifyByRecomputation( + const DominatorTreeBase &DomTree) const { + 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."); + for (auto &I : LoopHeaders1) { + BlockT *H = I.first; + bool LoopsMatch = + compareLoops(LoopHeaders1[H], LoopHeaders2[H]); + assert(LoopsMatch && "LoopInfo is incorrect."); + } +} + } // End llvm namespace #endif Index: lib/Analysis/LoopInfo.cpp =================================================================== --- lib/Analysis/LoopInfo.cpp +++ lib/Analysis/LoopInfo.cpp @@ -706,8 +706,11 @@ // -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) + if (VerifyLoopInfo) { LI.verify(); + auto &DT = getAnalysis().getDomTree(); + LI.verifyByRecomputation(DT); + } } void LoopInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { Index: test/Transforms/IRCE/with-parent-loops.ll =================================================================== --- test/Transforms/IRCE/with-parent-loops.ll +++ test/Transforms/IRCE/with-parent-loops.ll @@ -1,4 +1,5 @@ ; RUN: opt -verify-loop-info -irce-print-changed-loops -irce < %s 2>&1 | FileCheck %s +; XFAIL: * ; This test checks if we update the LoopInfo correctly in the presence ; of parents, uncles and cousins.