File indexing completed on 2026-05-10 08:44:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_SUPPORT_GENERICLOOPINFOIMPL_H
0015 #define LLVM_SUPPORT_GENERICLOOPINFOIMPL_H
0016
0017 #include "llvm/ADT/DepthFirstIterator.h"
0018 #include "llvm/ADT/PostOrderIterator.h"
0019 #include "llvm/ADT/STLExtras.h"
0020 #include "llvm/ADT/SetOperations.h"
0021 #include "llvm/Support/GenericLoopInfo.h"
0022
0023 namespace llvm {
0024
0025
0026
0027
0028
0029
0030
0031
0032 template <class BlockT, class LoopT>
0033 void LoopBase<BlockT, LoopT>::getExitingBlocks(
0034 SmallVectorImpl<BlockT *> &ExitingBlocks) const {
0035 assert(!isInvalid() && "Loop not in a valid state!");
0036 for (const auto BB : blocks())
0037 for (auto *Succ : children<BlockT *>(BB))
0038 if (!contains(Succ)) {
0039
0040 ExitingBlocks.push_back(BB);
0041 break;
0042 }
0043 }
0044
0045
0046
0047 template <class BlockT, class LoopT>
0048 BlockT *LoopBase<BlockT, LoopT>::getExitingBlock() const {
0049 assert(!isInvalid() && "Loop not in a valid state!");
0050 auto notInLoop = [&](BlockT *BB) { return !contains(BB); };
0051 auto isExitBlock = [&](BlockT *BB, bool AllowRepeats) -> BlockT * {
0052 assert(!AllowRepeats && "Unexpected parameter value.");
0053
0054 return any_of(children<BlockT *>(BB), notInLoop) ? BB : nullptr;
0055 };
0056
0057 return find_singleton<BlockT>(blocks(), isExitBlock);
0058 }
0059
0060
0061
0062
0063 template <class BlockT, class LoopT>
0064 void LoopBase<BlockT, LoopT>::getExitBlocks(
0065 SmallVectorImpl<BlockT *> &ExitBlocks) const {
0066 assert(!isInvalid() && "Loop not in a valid state!");
0067 for (const auto BB : blocks())
0068 for (auto *Succ : children<BlockT *>(BB))
0069 if (!contains(Succ))
0070
0071 ExitBlocks.push_back(Succ);
0072 }
0073
0074
0075
0076 template <class BlockT, class LoopT>
0077 std::pair<BlockT *, bool> getExitBlockHelper(const LoopBase<BlockT, LoopT> *L,
0078 bool Unique) {
0079 assert(!L->isInvalid() && "Loop not in a valid state!");
0080 auto notInLoop = [&](BlockT *BB,
0081 bool AllowRepeats) -> std::pair<BlockT *, bool> {
0082 assert(AllowRepeats == Unique && "Unexpected parameter value.");
0083 return {!L->contains(BB) ? BB : nullptr, false};
0084 };
0085 auto singleExitBlock = [&](BlockT *BB,
0086 bool AllowRepeats) -> std::pair<BlockT *, bool> {
0087 assert(AllowRepeats == Unique && "Unexpected parameter value.");
0088 return find_singleton_nested<BlockT>(children<BlockT *>(BB), notInLoop,
0089 AllowRepeats);
0090 };
0091 return find_singleton_nested<BlockT>(L->blocks(), singleExitBlock, Unique);
0092 }
0093
0094 template <class BlockT, class LoopT>
0095 bool LoopBase<BlockT, LoopT>::hasNoExitBlocks() const {
0096 auto RC = getExitBlockHelper(this, false);
0097 if (RC.second)
0098
0099 return false;
0100
0101 return !RC.first;
0102 }
0103
0104
0105
0106 template <class BlockT, class LoopT>
0107 BlockT *LoopBase<BlockT, LoopT>::getExitBlock() const {
0108 return getExitBlockHelper(this, false).first;
0109 }
0110
0111 template <class BlockT, class LoopT>
0112 bool LoopBase<BlockT, LoopT>::hasDedicatedExits() const {
0113
0114
0115 SmallVector<BlockT *, 4> UniqueExitBlocks;
0116 getUniqueExitBlocks(UniqueExitBlocks);
0117 for (BlockT *EB : UniqueExitBlocks)
0118 for (BlockT *Predecessor : inverse_children<BlockT *>(EB))
0119 if (!contains(Predecessor))
0120 return false;
0121
0122 return true;
0123 }
0124
0125
0126
0127 template <class BlockT, class LoopT, typename PredicateT>
0128 void getUniqueExitBlocksHelper(const LoopT *L,
0129 SmallVectorImpl<BlockT *> &ExitBlocks,
0130 PredicateT Pred) {
0131 assert(!L->isInvalid() && "Loop not in a valid state!");
0132 SmallPtrSet<BlockT *, 32> Visited;
0133 auto Filtered = make_filter_range(L->blocks(), Pred);
0134 for (BlockT *BB : Filtered)
0135 for (BlockT *Successor : children<BlockT *>(BB))
0136 if (!L->contains(Successor))
0137 if (Visited.insert(Successor).second)
0138 ExitBlocks.push_back(Successor);
0139 }
0140
0141 template <class BlockT, class LoopT>
0142 void LoopBase<BlockT, LoopT>::getUniqueExitBlocks(
0143 SmallVectorImpl<BlockT *> &ExitBlocks) const {
0144 getUniqueExitBlocksHelper(this, ExitBlocks,
0145 [](const BlockT *BB) { return true; });
0146 }
0147
0148 template <class BlockT, class LoopT>
0149 void LoopBase<BlockT, LoopT>::getUniqueNonLatchExitBlocks(
0150 SmallVectorImpl<BlockT *> &ExitBlocks) const {
0151 const BlockT *Latch = getLoopLatch();
0152 assert(Latch && "Latch block must exists");
0153 getUniqueExitBlocksHelper(this, ExitBlocks,
0154 [Latch](const BlockT *BB) { return BB != Latch; });
0155 }
0156
0157 template <class BlockT, class LoopT>
0158 BlockT *LoopBase<BlockT, LoopT>::getUniqueExitBlock() const {
0159 return getExitBlockHelper(this, true).first;
0160 }
0161
0162 template <class BlockT, class LoopT>
0163 BlockT *LoopBase<BlockT, LoopT>::getUniqueLatchExitBlock() const {
0164 BlockT *Latch = getLoopLatch();
0165 assert(Latch && "Latch block must exists");
0166 auto IsExitBlock = [this](BlockT *BB, bool AllowRepeats) -> BlockT * {
0167 assert(!AllowRepeats && "Unexpected parameter value.");
0168 return !contains(BB) ? BB : nullptr;
0169 };
0170 return find_singleton<BlockT>(children<BlockT *>(Latch), IsExitBlock);
0171 }
0172
0173
0174 template <class BlockT, class LoopT>
0175 void LoopBase<BlockT, LoopT>::getExitEdges(
0176 SmallVectorImpl<Edge> &ExitEdges) const {
0177 assert(!isInvalid() && "Loop not in a valid state!");
0178 for (const auto BB : blocks())
0179 for (auto *Succ : children<BlockT *>(BB))
0180 if (!contains(Succ))
0181
0182 ExitEdges.emplace_back(BB, Succ);
0183 }
0184
0185 namespace detail {
0186 template <class BlockT>
0187 using has_hoist_check = decltype(&BlockT::isLegalToHoistInto);
0188
0189 template <class BlockT>
0190 using detect_has_hoist_check = llvm::is_detected<has_hoist_check, BlockT>;
0191
0192
0193
0194 template <class BlockT> bool isLegalToHoistInto(BlockT *Block) {
0195 if constexpr (detect_has_hoist_check<BlockT>::value)
0196 return Block->isLegalToHoistInto();
0197 return false;
0198 }
0199 }
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209 template <class BlockT, class LoopT>
0210 BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const {
0211 assert(!isInvalid() && "Loop not in a valid state!");
0212
0213 BlockT *Out = getLoopPredecessor();
0214 if (!Out)
0215 return nullptr;
0216
0217
0218 if (!detail::isLegalToHoistInto(Out))
0219 return nullptr;
0220
0221
0222 if (!llvm::hasSingleElement(llvm::children<BlockT *>(Out)))
0223 return nullptr;
0224
0225
0226 return Out;
0227 }
0228
0229
0230
0231
0232
0233
0234 template <class BlockT, class LoopT>
0235 BlockT *LoopBase<BlockT, LoopT>::getLoopPredecessor() const {
0236 assert(!isInvalid() && "Loop not in a valid state!");
0237
0238 BlockT *Out = nullptr;
0239
0240
0241 BlockT *Header = getHeader();
0242 for (const auto Pred : inverse_children<BlockT *>(Header)) {
0243 if (!contains(Pred)) {
0244 if (Out && Out != Pred)
0245 return nullptr;
0246 Out = Pred;
0247 }
0248 }
0249
0250 return Out;
0251 }
0252
0253
0254
0255 template <class BlockT, class LoopT>
0256 BlockT *LoopBase<BlockT, LoopT>::getLoopLatch() const {
0257 assert(!isInvalid() && "Loop not in a valid state!");
0258 BlockT *Header = getHeader();
0259 BlockT *Latch = nullptr;
0260 for (const auto Pred : inverse_children<BlockT *>(Header)) {
0261 if (contains(Pred)) {
0262 if (Latch)
0263 return nullptr;
0264 Latch = Pred;
0265 }
0266 }
0267
0268 return Latch;
0269 }
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281 template <class BlockT, class LoopT>
0282 void LoopBase<BlockT, LoopT>::addBasicBlockToLoop(
0283 BlockT *NewBB, LoopInfoBase<BlockT, LoopT> &LIB) {
0284 assert(!isInvalid() && "Loop not in a valid state!");
0285 #ifndef NDEBUG
0286 if (!Blocks.empty()) {
0287 auto SameHeader = LIB[getHeader()];
0288 assert(contains(SameHeader) && getHeader() == SameHeader->getHeader() &&
0289 "Incorrect LI specified for this loop!");
0290 }
0291 #endif
0292 assert(NewBB && "Cannot add a null basic block to the loop!");
0293 assert(!LIB[NewBB] && "BasicBlock already in the loop!");
0294
0295 LoopT *L = static_cast<LoopT *>(this);
0296
0297
0298 LIB.BBMap[NewBB] = L;
0299
0300
0301 while (L) {
0302 L->addBlockEntry(NewBB);
0303 L = L->getParentLoop();
0304 }
0305 }
0306
0307
0308
0309
0310
0311 template <class BlockT, class LoopT>
0312 void LoopBase<BlockT, LoopT>::replaceChildLoopWith(LoopT *OldChild,
0313 LoopT *NewChild) {
0314 assert(!isInvalid() && "Loop not in a valid state!");
0315 assert(OldChild->ParentLoop == this && "This loop is already broken!");
0316 assert(!NewChild->ParentLoop && "NewChild already has a parent!");
0317 typename std::vector<LoopT *>::iterator I = find(SubLoops, OldChild);
0318 assert(I != SubLoops.end() && "OldChild not in loop!");
0319 *I = NewChild;
0320 OldChild->ParentLoop = nullptr;
0321 NewChild->ParentLoop = static_cast<LoopT *>(this);
0322 }
0323
0324
0325 template <class BlockT, class LoopT>
0326 void LoopBase<BlockT, LoopT>::verifyLoop() const {
0327 assert(!isInvalid() && "Loop not in a valid state!");
0328 #ifndef NDEBUG
0329 assert(!Blocks.empty() && "Loop header is missing");
0330
0331
0332 SmallVector<BlockT *, 8> ExitBBs;
0333 getExitBlocks(ExitBBs);
0334 df_iterator_default_set<BlockT *> VisitSet;
0335 VisitSet.insert(ExitBBs.begin(), ExitBBs.end());
0336
0337
0338 SmallPtrSet<BlockT *, 8> VisitedBBs;
0339
0340
0341 for (BlockT *BB : depth_first_ext(getHeader(), VisitSet)) {
0342 assert(llvm::any_of(children<BlockT *>(BB),
0343 [&](BlockT *B) { return contains(B); }) &&
0344 "Loop block has no in-loop successors!");
0345
0346 assert(llvm::any_of(inverse_children<BlockT *>(BB),
0347 [&](BlockT *B) { return contains(B); }) &&
0348 "Loop block has no in-loop predecessors!");
0349
0350 SmallVector<BlockT *, 2> OutsideLoopPreds;
0351 for (BlockT *B : inverse_children<BlockT *>(BB))
0352 if (!contains(B))
0353 OutsideLoopPreds.push_back(B);
0354
0355 if (BB == getHeader()) {
0356 assert(!OutsideLoopPreds.empty() && "Loop is unreachable!");
0357 } else if (!OutsideLoopPreds.empty()) {
0358
0359
0360
0361 BlockT *EntryBB = &BB->getParent()->front();
0362 for (BlockT *CB : depth_first(EntryBB))
0363 for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i)
0364 assert(CB != OutsideLoopPreds[i] &&
0365 "Loop has multiple entry points!");
0366 }
0367 assert(BB != &getHeader()->getParent()->front() &&
0368 "Loop contains function entry block!");
0369
0370 VisitedBBs.insert(BB);
0371 }
0372
0373 if (VisitedBBs.size() != getNumBlocks()) {
0374 dbgs() << "The following blocks are unreachable in the loop: ";
0375 for (auto *BB : Blocks) {
0376 if (!VisitedBBs.count(BB)) {
0377 dbgs() << *BB << "\n";
0378 }
0379 }
0380 assert(false && "Unreachable block in loop");
0381 }
0382
0383
0384 for (iterator I = begin(), E = end(); I != E; ++I)
0385
0386 for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end();
0387 BI != BE; ++BI) {
0388 assert(contains(*BI) &&
0389 "Loop does not contain all the blocks of a subloop!");
0390 }
0391
0392
0393 if (ParentLoop) {
0394 assert(is_contained(ParentLoop->getSubLoops(), this) &&
0395 "Loop is not a subloop of its parent!");
0396 }
0397 #endif
0398 }
0399
0400
0401 template <class BlockT, class LoopT>
0402 void LoopBase<BlockT, LoopT>::verifyLoopNest(
0403 DenseSet<const LoopT *> *Loops) const {
0404 assert(!isInvalid() && "Loop not in a valid state!");
0405 Loops->insert(static_cast<const LoopT *>(this));
0406
0407 verifyLoop();
0408
0409 for (iterator I = begin(), E = end(); I != E; ++I)
0410 (*I)->verifyLoopNest(Loops);
0411 }
0412
0413 template <class BlockT, class LoopT>
0414 void LoopBase<BlockT, LoopT>::print(raw_ostream &OS, bool Verbose,
0415 bool PrintNested, unsigned Depth) const {
0416 OS.indent(Depth * 2);
0417 if (static_cast<const LoopT *>(this)->isAnnotatedParallel())
0418 OS << "Parallel ";
0419 OS << "Loop at depth " << getLoopDepth() << " containing: ";
0420
0421 BlockT *H = getHeader();
0422 for (unsigned i = 0; i < getBlocks().size(); ++i) {
0423 BlockT *BB = getBlocks()[i];
0424 if (!Verbose) {
0425 if (i)
0426 OS << ",";
0427 BB->printAsOperand(OS, false);
0428 } else
0429 OS << "\n";
0430
0431 if (BB == H)
0432 OS << "<header>";
0433 if (isLoopLatch(BB))
0434 OS << "<latch>";
0435 if (isLoopExiting(BB))
0436 OS << "<exiting>";
0437 if (Verbose)
0438 BB->print(OS);
0439 }
0440
0441 if (PrintNested) {
0442 OS << "\n";
0443
0444 for (iterator I = begin(), E = end(); I != E; ++I)
0445 (*I)->print(OS, false, PrintNested, Depth + 2);
0446 }
0447 }
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457 template <class BlockT, class LoopT>
0458 static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT *> Backedges,
0459 LoopInfoBase<BlockT, LoopT> *LI,
0460 const DomTreeBase<BlockT> &DomTree) {
0461 typedef GraphTraits<Inverse<BlockT *>> InvBlockTraits;
0462
0463 unsigned NumBlocks = 0;
0464 unsigned NumSubloops = 0;
0465
0466
0467 std::vector<BlockT *> ReverseCFGWorklist(Backedges.begin(), Backedges.end());
0468 while (!ReverseCFGWorklist.empty()) {
0469 BlockT *PredBB = ReverseCFGWorklist.back();
0470 ReverseCFGWorklist.pop_back();
0471
0472 LoopT *Subloop = LI->getLoopFor(PredBB);
0473 if (!Subloop) {
0474 if (!DomTree.isReachableFromEntry(PredBB))
0475 continue;
0476
0477
0478 LI->changeLoopFor(PredBB, L);
0479 ++NumBlocks;
0480 if (PredBB == L->getHeader())
0481 continue;
0482
0483 ReverseCFGWorklist.insert(ReverseCFGWorklist.end(),
0484 InvBlockTraits::child_begin(PredBB),
0485 InvBlockTraits::child_end(PredBB));
0486 } else {
0487
0488 Subloop = Subloop->getOutermostLoop();
0489
0490
0491 if (Subloop == L)
0492 continue;
0493
0494
0495 Subloop->setParentLoop(L);
0496 ++NumSubloops;
0497 NumBlocks += Subloop->getBlocksVector().capacity();
0498 PredBB = Subloop->getHeader();
0499
0500
0501
0502
0503 for (const auto Pred : inverse_children<BlockT *>(PredBB)) {
0504 if (LI->getLoopFor(Pred) != Subloop)
0505 ReverseCFGWorklist.push_back(Pred);
0506 }
0507 }
0508 }
0509 L->getSubLoopsVector().reserve(NumSubloops);
0510 L->reserveBlocks(NumBlocks);
0511 }
0512
0513
0514 template <class BlockT, class LoopT> class PopulateLoopsDFS {
0515 typedef GraphTraits<BlockT *> BlockTraits;
0516 typedef typename BlockTraits::ChildIteratorType SuccIterTy;
0517
0518 LoopInfoBase<BlockT, LoopT> *LI;
0519
0520 public:
0521 PopulateLoopsDFS(LoopInfoBase<BlockT, LoopT> *li) : LI(li) {}
0522
0523 void traverse(BlockT *EntryBlock);
0524
0525 protected:
0526 void insertIntoLoop(BlockT *Block);
0527 };
0528
0529
0530 template <class BlockT, class LoopT>
0531 void PopulateLoopsDFS<BlockT, LoopT>::traverse(BlockT *EntryBlock) {
0532 for (BlockT *BB : post_order(EntryBlock))
0533 insertIntoLoop(BB);
0534 }
0535
0536
0537
0538
0539 template <class BlockT, class LoopT>
0540 void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) {
0541 LoopT *Subloop = LI->getLoopFor(Block);
0542 if (Subloop && Block == Subloop->getHeader()) {
0543
0544
0545 if (!Subloop->isOutermost())
0546 Subloop->getParentLoop()->getSubLoopsVector().push_back(Subloop);
0547 else
0548 LI->addTopLevelLoop(Subloop);
0549
0550
0551
0552 Subloop->reverseBlock(1);
0553 std::reverse(Subloop->getSubLoopsVector().begin(),
0554 Subloop->getSubLoopsVector().end());
0555
0556 Subloop = Subloop->getParentLoop();
0557 }
0558 for (; Subloop; Subloop = Subloop->getParentLoop())
0559 Subloop->addBlockEntry(Block);
0560 }
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576 template <class BlockT, class LoopT>
0577 void LoopInfoBase<BlockT, LoopT>::analyze(const DomTreeBase<BlockT> &DomTree) {
0578
0579 const DomTreeNodeBase<BlockT> *DomRoot = DomTree.getRootNode();
0580 for (auto DomNode : post_order(DomRoot)) {
0581
0582 BlockT *Header = DomNode->getBlock();
0583 SmallVector<BlockT *, 4> Backedges;
0584
0585
0586 for (const auto Backedge : inverse_children<BlockT *>(Header)) {
0587
0588 const DomTreeNodeBase<BlockT> *BackedgeNode = DomTree.getNode(Backedge);
0589 if (BackedgeNode && DomTree.dominates(DomNode, BackedgeNode))
0590 Backedges.push_back(Backedge);
0591 }
0592
0593 if (!Backedges.empty()) {
0594 LoopT *L = AllocateLoop(Header);
0595 discoverAndMapSubloop(L, ArrayRef<BlockT *>(Backedges), this, DomTree);
0596 }
0597 }
0598
0599
0600 PopulateLoopsDFS<BlockT, LoopT> DFS(this);
0601 DFS.traverse(DomRoot->getBlock());
0602 }
0603
0604 template <class BlockT, class LoopT>
0605 SmallVector<LoopT *, 4>
0606 LoopInfoBase<BlockT, LoopT>::getLoopsInPreorder() const {
0607 SmallVector<LoopT *, 4> PreOrderLoops, PreOrderWorklist;
0608
0609
0610
0611
0612
0613 for (LoopT *RootL : reverse(*this)) {
0614 auto PreOrderLoopsInRootL = RootL->getLoopsInPreorder();
0615 PreOrderLoops.append(PreOrderLoopsInRootL.begin(),
0616 PreOrderLoopsInRootL.end());
0617 }
0618
0619 return PreOrderLoops;
0620 }
0621
0622 template <class BlockT, class LoopT>
0623 SmallVector<LoopT *, 4>
0624 LoopInfoBase<BlockT, LoopT>::getLoopsInReverseSiblingPreorder() const {
0625 SmallVector<LoopT *, 4> PreOrderLoops, PreOrderWorklist;
0626
0627
0628
0629
0630
0631 for (LoopT *RootL : *this) {
0632 assert(PreOrderWorklist.empty() &&
0633 "Must start with an empty preorder walk worklist.");
0634 PreOrderWorklist.push_back(RootL);
0635 do {
0636 LoopT *L = PreOrderWorklist.pop_back_val();
0637
0638
0639 PreOrderWorklist.append(L->begin(), L->end());
0640 PreOrderLoops.push_back(L);
0641 } while (!PreOrderWorklist.empty());
0642 }
0643
0644 return PreOrderLoops;
0645 }
0646
0647
0648 template <class BlockT, class LoopT>
0649 void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const {
0650 for (unsigned i = 0; i < TopLevelLoops.size(); ++i)
0651 TopLevelLoops[i]->print(OS);
0652 #if 0
0653 for (DenseMap<BasicBlock*, LoopT*>::const_iterator I = BBMap.begin(),
0654 E = BBMap.end(); I != E; ++I)
0655 OS << "BB '" << I->first->getName() << "' level = "
0656 << I->second->getLoopDepth() << "\n";
0657 #endif
0658 }
0659
0660 template <typename T>
0661 bool compareVectors(std::vector<T> &BB1, std::vector<T> &BB2) {
0662 llvm::sort(BB1);
0663 llvm::sort(BB2);
0664 return BB1 == BB2;
0665 }
0666
0667 template <class BlockT, class LoopT>
0668 void addInnerLoopsToHeadersMap(DenseMap<BlockT *, const LoopT *> &LoopHeaders,
0669 const LoopInfoBase<BlockT, LoopT> &LI,
0670 const LoopT &L) {
0671 LoopHeaders[L.getHeader()] = &L;
0672 for (LoopT *SL : L)
0673 addInnerLoopsToHeadersMap(LoopHeaders, LI, *SL);
0674 }
0675
0676 #ifndef NDEBUG
0677 template <class BlockT, class LoopT>
0678 static void compareLoops(const LoopT *L, const LoopT *OtherL,
0679 DenseMap<BlockT *, const LoopT *> &OtherLoopHeaders) {
0680 BlockT *H = L->getHeader();
0681 BlockT *OtherH = OtherL->getHeader();
0682 assert(H == OtherH &&
0683 "Mismatched headers even though found in the same map entry!");
0684
0685 assert(L->getLoopDepth() == OtherL->getLoopDepth() &&
0686 "Mismatched loop depth!");
0687 const LoopT *ParentL = L, *OtherParentL = OtherL;
0688 do {
0689 assert(ParentL->getHeader() == OtherParentL->getHeader() &&
0690 "Mismatched parent loop headers!");
0691 ParentL = ParentL->getParentLoop();
0692 OtherParentL = OtherParentL->getParentLoop();
0693 } while (ParentL);
0694
0695 for (const LoopT *SubL : *L) {
0696 BlockT *SubH = SubL->getHeader();
0697 const LoopT *OtherSubL = OtherLoopHeaders.lookup(SubH);
0698 assert(OtherSubL && "Inner loop is missing in computed loop info!");
0699 OtherLoopHeaders.erase(SubH);
0700 compareLoops(SubL, OtherSubL, OtherLoopHeaders);
0701 }
0702
0703 std::vector<BlockT *> BBs = L->getBlocks();
0704 std::vector<BlockT *> OtherBBs = OtherL->getBlocks();
0705 assert(compareVectors(BBs, OtherBBs) &&
0706 "Mismatched basic blocks in the loops!");
0707
0708 const SmallPtrSetImpl<const BlockT *> &BlocksSet = L->getBlocksSet();
0709 const SmallPtrSetImpl<const BlockT *> &OtherBlocksSet =
0710 OtherL->getBlocksSet();
0711 assert(BlocksSet.size() == OtherBlocksSet.size() &&
0712 llvm::set_is_subset(BlocksSet, OtherBlocksSet) &&
0713 "Mismatched basic blocks in BlocksSets!");
0714 }
0715 #endif
0716
0717 template <class BlockT, class LoopT>
0718 void LoopInfoBase<BlockT, LoopT>::verify(
0719 const DomTreeBase<BlockT> &DomTree) const {
0720 DenseSet<const LoopT *> Loops;
0721 for (iterator I = begin(), E = end(); I != E; ++I) {
0722 assert((*I)->isOutermost() && "Top-level loop has a parent!");
0723 (*I)->verifyLoopNest(&Loops);
0724 }
0725
0726
0727 #ifndef NDEBUG
0728 for (auto &Entry : BBMap) {
0729 const BlockT *BB = Entry.first;
0730 LoopT *L = Entry.second;
0731 assert(Loops.count(L) && "orphaned loop");
0732 assert(L->contains(BB) && "orphaned block");
0733 for (LoopT *ChildLoop : *L)
0734 assert(!ChildLoop->contains(BB) &&
0735 "BBMap should point to the innermost loop containing BB");
0736 }
0737
0738
0739 LoopInfoBase<BlockT, LoopT> OtherLI;
0740 OtherLI.analyze(DomTree);
0741
0742
0743
0744
0745 DenseMap<BlockT *, const LoopT *> OtherLoopHeaders;
0746 for (LoopT *L : OtherLI)
0747 addInnerLoopsToHeadersMap(OtherLoopHeaders, OtherLI, *L);
0748
0749
0750
0751
0752 for (LoopT *L : *this) {
0753 BlockT *Header = L->getHeader();
0754 const LoopT *OtherL = OtherLoopHeaders.lookup(Header);
0755 assert(OtherL && "Top level loop is missing in computed loop info!");
0756
0757 OtherLoopHeaders.erase(Header);
0758
0759 compareLoops(L, OtherL, OtherLoopHeaders);
0760 }
0761
0762
0763
0764 if (!OtherLoopHeaders.empty()) {
0765 for (const auto &HeaderAndLoop : OtherLoopHeaders)
0766 dbgs() << "Found new loop: " << *HeaderAndLoop.second << "\n";
0767 llvm_unreachable("Found new loops when recomputing LoopInfo!");
0768 }
0769 #endif
0770 }
0771
0772 }
0773
0774 #endif