From: Florian Hahn Date: Tue, 1 Jun 2021 11:20:46 +0000 (+0100) Subject: [LoopDeletion] Consider infinite loops alive, unless mustprogress. X-Git-Tag: llvmorg-14-init~5181 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1b84acb23acac2fbb450312049495164a16ee715;p=platform%2Fupstream%2Fllvm.git [LoopDeletion] Consider infinite loops alive, unless mustprogress. The current loop or any of its sub-loops may be infinite. Unless the function or the loops are marked as mustprogress, this in itself makes the loop *not* dead. This patch moves the logic to check whether the current loop is finite or mustprogress to `isLoopDead` and also extends it to check the sub-loops. This should fix PR50511. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D103382 --- diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp index fd0e983b6..62b145b 100644 --- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp @@ -100,6 +100,30 @@ static bool isLoopDead(Loop *L, ScalarEvolution &SE, return I.mayHaveSideEffects() && !I.isDroppable(); })) return false; + + // The loop or any of its sub-loops looping infinitely is legal. The loop can + // only be considered dead if either + // a. the function is mustprogress. + // b. all (sub-)loops are mustprogress or have a known trip-count. + if (L->getHeader()->getParent()->mustProgress()) + return true; + + SmallVector WorkList; + WorkList.push_back(L); + while (!WorkList.empty()) { + Loop *Current = WorkList.pop_back_val(); + if (hasMustProgress(Current)) + continue; + + const SCEV *S = SE.getConstantMaxBackedgeTakenCount(Current); + if (isa(S)) { + LLVM_DEBUG( + dbgs() << "Could not compute SCEV MaxBackedgeTakenCount and was " + "not required to make progress.\n"); + return false; + } + WorkList.append(Current->begin(), Current->end()); + } return true; } @@ -230,17 +254,6 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, DominatorTree &DT, : LoopDeletionResult::Unmodified; } - // Don't remove loops for which we can't solve the trip count unless the loop - // was required to make progress but has been determined to be dead. - const SCEV *S = SE.getConstantMaxBackedgeTakenCount(L); - if (isa(S) && - !L->getHeader()->getParent()->mustProgress() && !hasMustProgress(L)) { - LLVM_DEBUG(dbgs() << "Could not compute SCEV MaxBackedgeTakenCount and was " - "not required to make progress.\n"); - return Changed ? LoopDeletionResult::Modified - : LoopDeletionResult::Unmodified; - } - LLVM_DEBUG(dbgs() << "Loop is invariant, delete it!"); ORE.emit([&]() { return OptimizationRemark(DEBUG_TYPE, "Invariant", L->getStartLoc(), diff --git a/llvm/test/Transforms/LoopDeletion/noop-loops-with-subloops.ll b/llvm/test/Transforms/LoopDeletion/noop-loops-with-subloops.ll index 23eb324..715915b 100644 --- a/llvm/test/Transforms/LoopDeletion/noop-loops-with-subloops.ll +++ b/llvm/test/Transforms/LoopDeletion/noop-loops-with-subloops.ll @@ -158,7 +158,19 @@ exit: ; function/loop is mustprogress. Test case from PR50511. define void @inner_loop_may_be_infinite(i1 %c1, i1 %c2) { ; CHECK-LABEL: @inner_loop_may_be_infinite( -; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK-NEXT: br label [[LOOP1:%.*]] +; CHECK: loop1: +; CHECK-NEXT: br i1 [[C1:%.*]], label [[LOOP1_LATCH:%.*]], label [[LOOP2_PREHEADER:%.*]] +; CHECK: loop2.preheader: +; CHECK-NEXT: br label [[LOOP2:%.*]] +; CHECK: loop2: +; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP1_LATCH_LOOPEXIT:%.*]], label [[LOOP2]] +; CHECK: loop1.latch.loopexit: +; CHECK-NEXT: br label [[LOOP1_LATCH]] +; 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 ; @@ -256,7 +268,21 @@ exit: ; mustprogress and can be removed. define void @loop2_mustprogress_but_not_sibling_loop(i1 %c1, i1 %c2, i1 %c3) { ; CHECK-LABEL: @loop2_mustprogress_but_not_sibling_loop( -; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK-NEXT: br label [[LOOP1:%.*]] +; CHECK: loop1: +; CHECK-NEXT: br i1 [[C1:%.*]], label [[LOOP1_LATCH:%.*]], label [[LOOP2_PREHEADER:%.*]] +; CHECK: loop2.preheader: +; CHECK-NEXT: br label [[LOOP3_PREHEADER:%.*]] +; CHECK: loop3.preheader: +; CHECK-NEXT: br label [[LOOP3:%.*]] +; CHECK: loop3: +; CHECK-NEXT: br i1 [[C3:%.*]], label [[LOOP1_LATCH_LOOPEXIT:%.*]], label [[LOOP3]] +; CHECK: loop1.latch.loopexit: +; CHECK-NEXT: br label [[LOOP1_LATCH]] +; 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 ; @@ -281,7 +307,27 @@ exit: define void @loop2_finite_but_child_is_not(i1 %c1, i1 %c2, i1 %c3) { ; CHECK-LABEL: @loop2_finite_but_child_is_not( ; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK-NEXT: br label [[LOOP1:%.*]] +; CHECK: loop1: +; CHECK-NEXT: [[IV1:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV1_NEXT:%.*]], [[LOOP1_LATCH:%.*]] ] +; CHECK-NEXT: br i1 [[C1:%.*]], label [[LOOP1_LATCH]], label [[LOOP2_PREHEADER:%.*]] +; CHECK: loop2.preheader: +; CHECK-NEXT: br label [[LOOP2:%.*]] +; CHECK: loop2: +; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP2_LATCH:%.*]] ], [ 0, [[LOOP2_PREHEADER]] ] +; CHECK-NEXT: br label [[LOOP3:%.*]] +; CHECK: loop3: +; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP2_LATCH]], label [[LOOP3]] +; CHECK: loop2.latch: +; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1 +; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[IV]], 200 +; CHECK-NEXT: br i1 [[C]], label [[LOOP1_LATCH_LOOPEXIT:%.*]], label [[LOOP2]] +; CHECK: loop1.latch.loopexit: +; CHECK-NEXT: br label [[LOOP1_LATCH]] +; CHECK: loop1.latch: +; CHECK-NEXT: [[IV1_NEXT]] = add nuw i32 [[IV1]], 1 +; CHECK-NEXT: [[C4:%.*]] = icmp ult i32 [[IV1_NEXT]], 200 +; CHECK-NEXT: br i1 [[C4]], label [[LOOP1]], label [[EXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/LoopDeletion/unreachable-loops.ll b/llvm/test/Transforms/LoopDeletion/unreachable-loops.ll index bd0d53f..6baaab6 100644 --- a/llvm/test/Transforms/LoopDeletion/unreachable-loops.ll +++ b/llvm/test/Transforms/LoopDeletion/unreachable-loops.ll @@ -317,7 +317,21 @@ exit: define void @test9(i64 %n) { ; CHECK-LABEL: @test9( ; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK-NEXT: br label [[L1:%.*]] +; CHECK: L1.loopexit: +; CHECK-NEXT: br label [[L1_LOOPEXIT_SPLIT:%.*]] +; CHECK: L1.loopexit.split: +; CHECK-NEXT: unreachable +; CHECK: L1: +; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[L2_PREHEADER:%.*]] +; CHECK: L2.preheader: +; CHECK-NEXT: br label [[L3_PREHEADER:%.*]] +; CHECK: L3.preheader: +; CHECK-NEXT: [[Y_L2_LCSSA:%.*]] = phi i64 [ undef, [[L2_PREHEADER]] ] +; CHECK-NEXT: br label [[L3:%.*]] +; CHECK: L3: +; CHECK-NEXT: [[COND2:%.*]] = icmp slt i64 [[Y_L2_LCSSA]], [[N:%.*]] +; CHECK-NEXT: br i1 [[COND2]], label [[L3]], label [[L1_LOOPEXIT:%.*]] ; CHECK: exit: ; CHECK-NEXT: ret void ;