aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Analysis/LoopInfoImpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Analysis/LoopInfoImpl.h')
-rw-r--r--include/llvm/Analysis/LoopInfoImpl.h150
1 files changed, 111 insertions, 39 deletions
diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h
index 833a2202a568..761f8721b54f 100644
--- a/include/llvm/Analysis/LoopInfoImpl.h
+++ b/include/llvm/Analysis/LoopInfoImpl.h
@@ -507,6 +507,55 @@ analyze(const DominatorTreeBase<BlockT> &DomTree) {
DFS.traverse(DomRoot->getBlock());
}
+template <class BlockT, class LoopT>
+SmallVector<LoopT *, 4> LoopInfoBase<BlockT, LoopT>::getLoopsInPreorder() {
+ SmallVector<LoopT *, 4> PreOrderLoops, PreOrderWorklist;
+ // The outer-most loop actually goes into the result in the same relative
+ // order as we walk it. But LoopInfo stores the top level loops in reverse
+ // program order so for here we reverse it to get forward program order.
+ // FIXME: If we change the order of LoopInfo we will want to remove the
+ // reverse here.
+ for (LoopT *RootL : reverse(*this)) {
+ assert(PreOrderWorklist.empty() &&
+ "Must start with an empty preorder walk worklist.");
+ PreOrderWorklist.push_back(RootL);
+ do {
+ LoopT *L = PreOrderWorklist.pop_back_val();
+ // Sub-loops are stored in forward program order, but will process the
+ // worklist backwards so append them in reverse order.
+ PreOrderWorklist.append(L->rbegin(), L->rend());
+ PreOrderLoops.push_back(L);
+ } while (!PreOrderWorklist.empty());
+ }
+
+ return PreOrderLoops;
+}
+
+template <class BlockT, class LoopT>
+SmallVector<LoopT *, 4>
+LoopInfoBase<BlockT, LoopT>::getLoopsInReverseSiblingPreorder() {
+ SmallVector<LoopT *, 4> PreOrderLoops, PreOrderWorklist;
+ // The outer-most loop actually goes into the result in the same relative
+ // order as we walk it. LoopInfo stores the top level loops in reverse
+ // program order so we walk in order here.
+ // FIXME: If we change the order of LoopInfo we will want to add a reverse
+ // here.
+ for (LoopT *RootL : *this) {
+ assert(PreOrderWorklist.empty() &&
+ "Must start with an empty preorder walk worklist.");
+ PreOrderWorklist.push_back(RootL);
+ do {
+ LoopT *L = PreOrderWorklist.pop_back_val();
+ // Sub-loops are stored in forward program order, but will process the
+ // worklist backwards so we can just append them in order.
+ PreOrderWorklist.append(L->begin(), L->end());
+ PreOrderLoops.push_back(L);
+ } while (!PreOrderWorklist.empty());
+ }
+
+ return PreOrderLoops;
+}
+
// Debugging
template<class BlockT, class LoopT>
void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const {
@@ -528,15 +577,48 @@ bool compareVectors(std::vector<T> &BB1, std::vector<T> &BB2) {
}
template <class BlockT, class LoopT>
-static void
-addInnerLoopsToHeadersMap(DenseMap<BlockT *, const LoopT *> &LoopHeaders,
- const LoopInfoBase<BlockT, LoopT> &LI,
- const LoopT &L) {
+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);
}
+#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 {
@@ -559,42 +641,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.");
-
- 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.");
+ addInnerLoopsToHeadersMap(OtherLoopHeaders, OtherLI, *L);
+
+ // 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);
+ }
+
+ // 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
}