[Loops] Restructure the LoopInfo verify function so that it more

directly walks the current loop structure verifying that a matching
structure can be found in a freshly computed version.

Also pull things out of containers when necessary once an issue is found
and print them directly.

This makes it substantially easier to debug verification failures as
the process stops at the exact point in the loop nest where they diverge
and has in easily accessed local variables (or printed to stderr
already) the loops and other information needed to analyze the failure.

Differential Revision: https://reviews.llvm.org/D29142

llvm-svn: 293133
This commit is contained in:
Chandler Carruth 2017-01-26 02:07:20 +00:00
parent 6201d78653
commit 647d34fe61

View File

@ -586,6 +586,40 @@ addInnerLoopsToHeadersMap(DenseMap<BlockT *, const LoopT *> &LoopHeaders,
addInnerLoopsToHeadersMap(LoopHeaders, LI, *SL);
}
#ifndef NDEBUG
template <class BlockT, class LoopT>
static void compareLoops(const LoopT *L, const LoopT *OtherL,
DenseMap<BlockT *, const LoopT *> &OtherLoopHeaders) {
BlockT *H = L->getHeader();
BlockT *OtherH = OtherL->getHeader();
assert(H == OtherH &&
"Mismatched headers even though found in the same map entry!");
assert(L->getLoopDepth() == OtherL->getLoopDepth() &&
"Mismatched loop depth!");
const LoopT *ParentL = L, *OtherParentL = OtherL;
do {
assert(ParentL->getHeader() == OtherParentL->getHeader() &&
"Mismatched parent loop headers!");
ParentL = ParentL->getParentLoop();
OtherParentL = OtherParentL->getParentLoop();
} while (ParentL);
for (const LoopT *SubL : *L) {
BlockT *SubH = SubL->getHeader();
const LoopT *OtherSubL = OtherLoopHeaders.lookup(SubH);
assert(OtherSubL && "Inner loop is missing in computed loop info!");
OtherLoopHeaders.erase(SubH);
compareLoops(SubL, OtherSubL, OtherLoopHeaders);
}
std::vector<BlockT *> BBs = L->getBlocks();
std::vector<BlockT *> OtherBBs = OtherL->getBlocks();
assert(compareVectors(BBs, OtherBBs) &&
"Mismatched basic blocks in the loops!");
}
#endif
template <class BlockT, class LoopT>
void LoopInfoBase<BlockT, LoopT>::verify(
const DominatorTreeBase<BlockT> &DomTree) const {
@ -608,42 +642,32 @@ void LoopInfoBase<BlockT, LoopT>::verify(
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);
// Build a map we can use to move from our LI to the computed one. This
// allows us to ignore the particular order in any layer of the loop forest
// while still comparing the structure.
DenseMap<BlockT *, const LoopT *> OtherLoopHeaders;
for (LoopT *L : OtherLI)
addInnerLoopsToHeadersMap(LoopHeaders2, OtherLI, *L);
assert(LoopHeaders1.size() == LoopHeaders2.size() &&
"LoopInfo is incorrect.");
addInnerLoopsToHeadersMap(OtherLoopHeaders, OtherLI, *L);
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;
// Walk the top level loops and ensure there is a corresponding top-level
// loop in the computed version and then recursively compare those loop
// nests.
for (LoopT *L : *this) {
BlockT *Header = L->getHeader();
const LoopT *OtherL = OtherLoopHeaders.lookup(Header);
assert(OtherL && "Top level loop is missing in computed loop info!");
// Now that we've matched this loop, erase its header from the map.
OtherLoopHeaders.erase(Header);
// And recursively compare these loops.
compareLoops(L, OtherL, OtherLoopHeaders);
}
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.");
// Any remaining entries in the map are loops which were found when computing
// a fresh LoopInfo but not present in the current one.
if (!OtherLoopHeaders.empty()) {
for (const auto &HeaderAndLoop : OtherLoopHeaders)
dbgs() << "Found new loop: " << *HeaderAndLoop.second << "\n";
llvm_unreachable("Found new loops when recomputing LoopInfo!");
}
#endif
}