diff options
author | Michael Zolotukhin <mzolotukhin@apple.com> | 2016-08-31 19:26:19 +0000 |
---|---|---|
committer | Michael Zolotukhin <mzolotukhin@apple.com> | 2016-08-31 19:26:19 +0000 |
commit | e0b2d97b520b381f4002f1028f580defe1a31d9d (patch) | |
tree | ed81bc1bd60b8f571b53dd7c802949b624410b45 | |
parent | 8d84605f25d91c63c2c9e2c8f42575da520f17a3 (diff) | |
download | bcm5719-llvm-e0b2d97b520b381f4002f1028f580defe1a31d9d.tar.gz bcm5719-llvm-e0b2d97b520b381f4002f1028f580defe1a31d9d.zip |
[LoopInfo] Add verification by recomputation.
Summary:
Current implementation of LI verifier isn't ideal and fails to detect
some cases when LI is incorrect. For instance, it checks that all
recorded loops are in a correct form, but it has no way to check if
there are no more other (unrecorded in LI) loops in the function. This
patch adds a way to detect such bugs.
Reviewers: chandlerc, sanjoy, hfinkel
Subscribers: llvm-commits, silvas, mzolotukhin
Differential Revision: https://reviews.llvm.org/D23437
llvm-svn: 280280
-rw-r--r-- | llvm/include/llvm/Analysis/LoopInfo.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/Analysis/LoopInfoImpl.h | 65 | ||||
-rw-r--r-- | llvm/lib/Analysis/LoopInfo.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/LoopDistribute.cpp | 2 |
4 files changed, 71 insertions, 7 deletions
diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h index 651a749a6d6..85c06826dae 100644 --- a/llvm/include/llvm/Analysis/LoopInfo.h +++ b/llvm/include/llvm/Analysis/LoopInfo.h @@ -635,7 +635,7 @@ public: // Debugging void print(raw_ostream &OS) const; - void verify() const; + void verify(const DominatorTreeBase<BlockT> &DomTree) const; }; // Implementation in LoopInfoImpl.h diff --git a/llvm/include/llvm/Analysis/LoopInfoImpl.h b/llvm/include/llvm/Analysis/LoopInfoImpl.h index 72a09cdd055..6635860139b 100644 --- a/llvm/include/llvm/Analysis/LoopInfoImpl.h +++ b/llvm/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 @@ void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const { #endif } -template<class BlockT, class LoopT> -void LoopInfoBase<BlockT, LoopT>::verify() const { +template <typename T> +bool compareVectors(std::vector<T> &BB1, std::vector<T> &BB2) { + std::sort(BB1.begin(), BB1.end()); + std::sort(BB2.begin(), BB2.end()); + return BB1 == BB2; +} + +template <class BlockT, class LoopT> +static void +addInnerLoopsToHeadersMap(DenseMap<BlockT *, const LoopT *> &LoopHeaders, + const LoopInfoBase<BlockT, LoopT> &LI, + const LoopT &L) { + LoopHeaders[L.getHeader()] = &L; + for (LoopT *SL : L) + addInnerLoopsToHeadersMap(LoopHeaders, LI, *SL); +} + +template <class BlockT, class LoopT> +void LoopInfoBase<BlockT, LoopT>::verify( + const DominatorTreeBase<BlockT> &DomTree) const { DenseSet<const LoopT*> Loops; for (iterator I = begin(), E = end(); I != E; ++I) { assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); @@ -530,6 +549,48 @@ void LoopInfoBase<BlockT, LoopT>::verify() const { assert(Loops.count(L) && "orphaned loop"); assert(L->contains(BB) && "orphaned block"); } + + // Recompute LoopInfo to verify loops structure. + LoopInfoBase<BlockT, LoopT> OtherLI; + OtherLI.analyze(DomTree); + + DenseMap<BlockT *, const LoopT *> LoopHeaders1; + DenseMap<BlockT *, const LoopT *> 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<BlockT *> BB1 = L1->getBlocks(); + std::vector<BlockT *> BB2 = L2->getBlocks(); + if (!compareVectors(BB1, BB2)) + return false; + + std::vector<BlockT *> SubLoopHeaders1; + std::vector<BlockT *> 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 } diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp index 9d2e38e19da..a5f816dd5ad 100644 --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -703,8 +703,10 @@ void LoopInfoWrapperPass::verifyAnalysis() const { // -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<DominatorTreeWrapperPass>().getDomTree(); + LI.verify(DT); + } } void LoopInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { @@ -719,7 +721,8 @@ void LoopInfoWrapperPass::print(raw_ostream &OS, const Module *) const { PreservedAnalyses LoopVerifierPass::run(Function &F, FunctionAnalysisManager &AM) { LoopInfo &LI = AM.getResult<LoopAnalysis>(F); - LI.verify(); + auto &DT = AM.getResult<DominatorTreeAnalysis>(F); + LI.verify(DT); return PreservedAnalyses::all(); } diff --git a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp index 74cfdbfa84e..ad973cf31de 100644 --- a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp @@ -742,7 +742,7 @@ public: DEBUG(Partitions.printBlocks()); if (LDistVerify) { - LI->verify(); + LI->verify(*DT); DT->verifyDomTree(); } |