diff options
Diffstat (limited to 'include/llvm/Analysis/LoopInfoImpl.h')
-rw-r--r-- | include/llvm/Analysis/LoopInfoImpl.h | 150 |
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 } |