Index: include/llvm/Analysis/LoopInfo.h =================================================================== --- include/llvm/Analysis/LoopInfo.h +++ include/llvm/Analysis/LoopInfo.h @@ -277,11 +277,22 @@ /// Otherwise return null. BlockT *getUniqueExitBlock() const; - /// Edge type. - typedef std::pair Edge; - /// Return all pairs of (_inside_block_,_outside_block_). - void getExitEdges(SmallVectorImpl &ExitEdges) const; + template + void getExitEdges(SmallVectorImpl > & + ExitEdges) const { + // Assert that ParamBlockT and BlockT are the same +/- const qualifier. + static_assert( + std::is_same::type, + typename std::remove_const::type>::value, + "not same!"); + assert(!isInvalid() && "Loop not in a valid state!"); + for (const auto BB : blocks()) + for (const auto &Succ : children(BB)) + if (!contains(Succ)) + // Not in current loop? It must be an exit block. + ExitEdges.emplace_back(BB, Succ); + } /// If there is a preheader for this loop, return it. A loop has a preheader /// if there is only one edge to the header of the loop from outside of the Index: include/llvm/Analysis/LoopInfoImpl.h =================================================================== --- include/llvm/Analysis/LoopInfoImpl.h +++ include/llvm/Analysis/LoopInfoImpl.h @@ -149,18 +149,6 @@ return nullptr; } -/// getExitEdges - Return all pairs of (_inside_block_,_outside_block_). -template -void LoopBase::getExitEdges( - SmallVectorImpl &ExitEdges) const { - assert(!isInvalid() && "Loop not in a valid state!"); - for (const auto BB : blocks()) - for (const auto &Succ : children(BB)) - if (!contains(Succ)) - // Not in current loop? It must be an exit block. - ExitEdges.emplace_back(BB, Succ); -} - /// getLoopPreheader - If there is a preheader for this loop, return it. A /// loop has a preheader if there is only one edge to the header of the loop /// from outside of the loop and it is legal to hoist instructions into the Index: unittests/Analysis/LoopInfoTest.cpp =================================================================== --- unittests/Analysis/LoopInfoTest.cpp +++ unittests/Analysis/LoopInfoTest.cpp @@ -1110,3 +1110,45 @@ L->isAuxiliaryInductionVariable(Instruction_mulopcode, SE)); }); } + +// Check that getExitEdges works for both const and non const ExitEdges param. +TEST(LoopInfoTest, LoopGetExitEdges) { + const char *ModuleStr = + "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n" + "define void @foo(i32 %n) {\n" + "entry:\n" + " br i1 undef, label %for.cond, label %for.end\n" + "for.cond:\n" + " %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]\n" + " %cmp = icmp slt i32 %i.0, %n\n" + " br i1 %cmp, label %for.inc, label %for.end\n" + "for.inc:\n" + " %inc = add nsw i32 %i.0, 1\n" + " br label %for.cond\n" + "for.end:\n" + " ret void\n" + "}\n"; + + // Parse the module. + LLVMContext Context; + std::unique_ptr M = makeLLVMModule(Context, ModuleStr); + + runWithLoopInfo(*M, "foo", [&](Function &F, LoopInfo &LI) { + Function::iterator FI = F.begin(); + // First basic block is entry - skip it. + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.cond"); + Loop *L = LI.getLoopFor(Header); + + SmallVector, 1> NonConstExitEdges; + SmallVector, 1> + ConstExitEdges; + // Get Loop Edges. + L->getExitEdges(NonConstExitEdges); + L->getExitEdges(ConstExitEdges); + + // Check result. + EXPECT_TRUE(NonConstExitEdges.size() == 1); + EXPECT_TRUE(ConstExitEdges.size() == 1); + }); +}