forked from OSchip/llvm-project
[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
This commit is contained in:
parent
8d84605f25
commit
e0b2d97b52
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -742,7 +742,7 @@ public:
|
|||
DEBUG(Partitions.printBlocks());
|
||||
|
||||
if (LDistVerify) {
|
||||
LI->verify();
|
||||
LI->verify(*DT);
|
||||
DT->verifyDomTree();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue