Index: include/llvm/Analysis/LoopInfo.h =================================================================== --- include/llvm/Analysis/LoopInfo.h +++ include/llvm/Analysis/LoopInfo.h @@ -178,6 +178,12 @@ return DenseBlockSet; } + /// Return a direct, immutable handle to the blocks set. + const SmallPtrSetImpl &getBlocksSet() const { + assert(!isInvalid() && "Loop not in a valid state!"); + return DenseBlockSet; + } + /// Return true if this loop is no longer valid. The only valid use of this /// helper is "assert(L.isInvalid())" or equivalent, since IsInvalid is set to /// true by the destructor. In other words, if this accessor returns true, Index: include/llvm/Analysis/LoopInfoImpl.h =================================================================== --- include/llvm/Analysis/LoopInfoImpl.h +++ include/llvm/Analysis/LoopInfoImpl.h @@ -617,6 +617,15 @@ std::vector OtherBBs = OtherL->getBlocks(); assert(compareVectors(BBs, OtherBBs) && "Mismatched basic blocks in the loops!"); + + const SmallPtrSetImpl &BlocksSet = L->getBlocksSet(); + const SmallPtrSetImpl &OtherBlocksSet = L->getBlocksSet(); + assert(BlocksSet.size() == OtherBlocksSet.size() && + std::all_of(BlocksSet.begin(), BlocksSet.end(), + [&OtherBlocksSet](const BlockT *BB) { + return OtherBlocksSet.count(BB); + }) && + "Mismatched basic blocks in BlocksSets!"); } #endif @@ -636,6 +645,9 @@ LoopT *L = Entry.second; assert(Loops.count(L) && "orphaned loop"); assert(L->contains(BB) && "orphaned block"); + for (LoopT *ChildLoop : *L) + assert(!ChildLoop->contains(BB) && + "BBMap should point to the innermost loop containing BB"); } // Recompute LoopInfo to verify loops structure.