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 @@ -156,13 +156,6 @@ << "Deletion requires Loop with preheader and dedicated exits.\n"); return LoopDeletionResult::Unmodified; } - // We can't remove loops that contain subloops. If the subloops were dead, - // they would already have been removed in earlier executions of this pass. - if (L->begin() != L->end()) { - LLVM_DEBUG(dbgs() << "Loop contains subloops.\n"); - return LoopDeletionResult::Unmodified; - } - BasicBlock *ExitBlock = L->getUniqueExitBlock(); diff --git a/llvm/test/Transforms/LoopDeletion/noop-loops-with-subloops.ll b/llvm/test/Transforms/LoopDeletion/noop-loops-with-subloops.ll --- a/llvm/test/Transforms/LoopDeletion/noop-loops-with-subloops.ll +++ b/llvm/test/Transforms/LoopDeletion/noop-loops-with-subloops.ll @@ -10,24 +10,7 @@ define void @test1(i64 %N, i64 %M, %pair_t* %ptr) willreturn { ; CHECK-LABEL: @test1( ; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] -; CHECK: outer.header: -; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ] -; CHECK-NEXT: br label [[INNER:%.*]] -; CHECK: inner: -; CHECK-NEXT: [[INNER_IV:%.*]] = phi i64 [ 0, [[OUTER_HEADER]] ], [ [[INNER_IV_NEXT:%.*]], [[INNER]] ] -; CHECK-NEXT: [[GEP:%.*]] = getelementptr [[PAIR_T:%.*]], %pair_t* [[PTR:%.*]], i64 [[INNER_IV]] -; CHECK-NEXT: [[P:%.*]] = load [[PAIR_T]], %pair_t* [[GEP]], align 4 -; CHECK-NEXT: [[V_0:%.*]] = extractvalue [[PAIR_T]] [[P]], 0 -; CHECK-NEXT: [[V_1:%.*]] = extractvalue [[PAIR_T]] [[P]], 1 -; CHECK-NEXT: [[INNER_EC:%.*]] = icmp ult i64 [[V_0]], [[V_1]] -; CHECK-NEXT: [[INNER_IV_NEXT]] = add i64 [[INNER_IV]], 1 -; CHECK-NEXT: br i1 [[INNER_EC]], label [[OUTER_LATCH]], label [[INNER]] -; CHECK: outer.latch: -; CHECK-NEXT: [[LCSSA:%.*]] = phi i64 [ [[V_1]], [[INNER]] ] -; CHECK-NEXT: [[OUTER_EC:%.*]] = icmp ult i64 [[OUTER_IV]], [[LCSSA]] -; CHECK-NEXT: [[OUTER_IV_NEXT]] = add i64 [[OUTER_IV]], 1 -; CHECK-NEXT: br i1 [[OUTER_EC]], label [[EXIT:%.*]], label [[OUTER_HEADER]] +; CHECK-NEXT: br 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 --- a/llvm/test/Transforms/LoopDeletion/unreachable-loops.ll +++ b/llvm/test/Transforms/LoopDeletion/unreachable-loops.ll @@ -244,22 +244,15 @@ ; Delete a loop (L2) which has subloop (L3). ; Here we delete loop L2, but leave L3 as is. -; FIXME: Can delete L3 as well, by iteratively going backward through the single -; predecessor of L3 until we reach L1's block that guarantees L3 is never -; executed. define void @test9(i64 %n) { ; CHECK-LABEL: test9 -; CHECK-LABEL: L2.preheader: -; CHECK-NEXT: br label %L3.preheader -; CHECK-NOT: L2: -; CHECK-LABEL: L3.preheader: -; CHECK-NEXT: %y.L2.lcssa = phi i64 [ undef, %L2.preheader ] -; CHECK-NEXT: br label %L3 -; CHECK-LABEL: L3: -; CHECK: br i1 %cond2, label %L3, label %L1.loopexit +; CHECK-LABEL: entry: +; CHECK-NEXT: br label %exit +; CHECK-LABEL: exit: +; CHECK-NEXT: ret void ; REMARKS-LABEL: Function: test9 ; REMARKS: Loop deleted because it never executes -entry: +entry: br label %L1 L1: @@ -283,12 +276,12 @@ ; We cannot delete L3 because of call within it. ; Since L3 is not deleted, and entirely contained within L2, L2 is also not ; deleted. -; FIXME: We can delete unexecutable loops having -; subloops contained entirely within them. define void @test10(i64 %n) { ; CHECK-LABEL: test10 -; CHECK: L2: -; CHECK: L3: +; CHECK-LABEL: entry: +; CHECK-NEXT: br label %exit +; CHECK-LABEL: exit: +; CHECK-NEXT: ret void entry: br label %L1 diff --git a/llvm/test/Transforms/LoopDeletion/update-scev.ll b/llvm/test/Transforms/LoopDeletion/update-scev.ll --- a/llvm/test/Transforms/LoopDeletion/update-scev.ll +++ b/llvm/test/Transforms/LoopDeletion/update-scev.ll @@ -48,6 +48,7 @@ for.inc11: ; preds = %for.body6 %and.lcssa = phi i32 [ %and, %for.body6 ] + call void @sideeffect(i32 %and.lcssa) %inc12 = add nsw i32 %val, 1 %tobool = icmp eq i32 %inc12, 0 br i1 %tobool, label %for.cond14, label %for.body @@ -56,6 +57,8 @@ br i1 undef, label %for.cond, label %for.cond14 } +declare void @sideeffect(i32) + ; LoopDeletion removes the loop %for.body7.1. Make sure %inc.lcssa.1 in the loop ; exit block is correctly invalidated.