diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp --- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp @@ -16,11 +16,14 @@ #include "llvm/Transforms/Scalar/LoopDeletion.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/CFG.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/MemorySSA.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/IR/Dominators.h" +#include "llvm/Analysis/LoopIterator.h" + #include "llvm/IR/PatternMatch.h" #include "llvm/InitializePasses.h" #include "llvm/Transforms/Scalar.h" @@ -54,7 +57,7 @@ static bool isLoopDead(Loop *L, ScalarEvolution &SE, SmallVectorImpl &ExitingBlocks, BasicBlock *ExitBlock, bool &Changed, - BasicBlock *Preheader) { + BasicBlock *Preheader, LoopInfo &LI) { // Make sure that all PHI entries coming from the loop are loop invariant. // Because the code is in LCSSA form, any values used outside of the loop // must pass through a PHI in the exit block, meaning that this check is @@ -108,6 +111,12 @@ if (L->getHeader()->getParent()->mustProgress()) return true; + LoopBlocksRPO RPOT(L); + RPOT.perform(&LI); + // If the loop contains an irreducible cycle, it may loop infinitely. + if (containsIrreducibleCFG(RPOT, LI)) + return false; + SmallVector WorkList; WorkList.push_back(L); while (!WorkList.empty()) { @@ -248,7 +257,7 @@ } // Finally, we have to check that the loop really is dead. bool Changed = false; - if (!isLoopDead(L, SE, ExitingBlocks, ExitBlock, Changed, Preheader)) { + if (!isLoopDead(L, SE, ExitingBlocks, ExitBlock, Changed, Preheader, LI)) { LLVM_DEBUG(dbgs() << "Loop is not invariant, cannot delete.\n"); return Changed ? LoopDeletionResult::Modified : LoopDeletionResult::Unmodified; diff --git a/llvm/test/Transforms/LoopDeletion/loops-with-irreducible-subloops.ll b/llvm/test/Transforms/LoopDeletion/loops-with-irreducible-subloops.ll --- a/llvm/test/Transforms/LoopDeletion/loops-with-irreducible-subloops.ll +++ b/llvm/test/Transforms/LoopDeletion/loops-with-irreducible-subloops.ll @@ -3,12 +3,28 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64" +; loop1 contains an irreducible cycle, which may loop infinitely. Do not remove +; the loop. define void @irreducible_subloop_no_mustprogress(i1 %c1, i1 %c2, i1 %c3) { ; CHECK-LABEL: @irreducible_subloop_no_mustprogress( -; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LOOP1:%.*]] +; CHECK: loop1: +; CHECK-NEXT: br i1 [[C1:%.*]], label [[LOOP1_BB1:%.*]], label [[IRR_BB1:%.*]] +; CHECK: loop1.bb1: +; CHECK-NEXT: br label [[IRR_BB2:%.*]] +; CHECK: irr.bb1: +; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP1_LATCH:%.*]], label [[IRR_BB2]] +; CHECK: irr.bb2: +; CHECK-NEXT: br i1 [[C3:%.*]], label [[LOOP1_LATCH]], label [[IRR_BB1]] +; CHECK: loop1.latch: +; CHECK-NEXT: br i1 false, label [[LOOP1_LATCH_LOOP1_CRIT_EDGE:%.*]], label [[EXIT:%.*]] +; CHECK: loop1.latch.loop1_crit_edge: +; CHECK-NEXT: unreachable ; CHECK: exit: ; CHECK-NEXT: ret void ; +entry: br label %loop1 loop1: