Revert "Revert "[IndVars] Replace PHIs if loop exits on 1st iteration""
authorMax Kazantsev <mkazantsev@azul.com>
Mon, 20 Sep 2021 04:28:56 +0000 (11:28 +0700)
committerMax Kazantsev <mkazantsev@azul.com>
Mon, 20 Sep 2021 05:01:10 +0000 (12:01 +0700)
This reverts commit 6fec6552f54885ae06bf76b35f9f1173a0561a4c.

The patch was reverted on incorrect claim that this patch may break LCSSA form
when the loop is not in a simplify form. All IndVars' transform insure that
the loop is in simplify and LCSSA form, so if it wasn't broken before this
transform, it will also not be broken after it.

llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
llvm/test/Transforms/IndVarSimplify/eliminate-backedge.ll
llvm/test/Transforms/IndVarSimplify/eliminate-exit-no-dl.ll
llvm/test/Transforms/IndVarSimplify/floating-point-iv.ll

index 9b665bb..320e20c 100644 (file)
@@ -1309,6 +1309,17 @@ static void foldExit(const Loop *L, BasicBlock *ExitingBB, bool IsTaken,
   replaceExitCond(BI, NewCond, DeadInsts);
 }
 
+static void replaceLoopPHINodesWithPreheaderValues(
+    Loop *L, SmallVectorImpl<WeakTrackingVH> &DeadInsts) {
+  auto *LoopPreheader = L->getLoopPreheader();
+  auto *LoopHeader = L->getHeader();
+  for (auto &PN : LoopHeader->phis()) {
+    auto *PreheaderIncoming = PN.getIncomingValueForBlock(LoopPreheader);
+    PN.replaceAllUsesWith(PreheaderIncoming);
+    DeadInsts.emplace_back(&PN);
+  }
+}
+
 static void replaceWithInvariantCond(
     const Loop *L, BasicBlock *ExitingBB, ICmpInst::Predicate InvariantPred,
     const SCEV *InvariantLHS, const SCEV *InvariantRHS, SCEVExpander &Rewriter,
@@ -1499,10 +1510,11 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
     // If we know we'd exit on the first iteration, rewrite the exit to
     // reflect this.  This does not imply the loop must exit through this
     // exit; there may be an earlier one taken on the first iteration.
-    // TODO: Given we know the backedge can't be taken, we should go ahead
-    // and break it.  Or at least, kill all the header phis and simplify.
+    // We know that the backedge can't be taken, so we replace all
+    // the header PHIs with values coming from the preheader.
     if (ExitCount->isZero()) {
       foldExit(L, ExitingBB, true, DeadInsts);
+      replaceLoopPHINodesWithPreheaderValues(L, DeadInsts);
       Changed = true;
       continue;
     }
index 34bc4f6..e2ba6e0 100644 (file)
@@ -15,16 +15,13 @@ define i1 @kill_backedge_and_phis(i8* align 1 %lhs, i8* align 1 %rhs, i32 %len)
 ; CHECK:       loop_preheader:
 ; CHECK-NEXT:    br label %loop
 ; CHECK:       loop:
-; CHECK-NEXT:    %iv = phi i32 [ 0, %loop_preheader ], [ %iv.next, %exiting_3 ]
-; CHECK-NEXT:    %iv.wide = phi i64 [ 0, %loop_preheader ], [ %iv.wide.next, %exiting_3 ]
-; CHECK-NEXT:    %iv.next = add nuw nsw i32 %iv, 1
-; CHECK-NEXT:    %iv.wide.next = add nuw nsw i64 %iv.wide, 1
-; CHECK-NEXT:    %left_ptr = getelementptr inbounds i8, i8* %lhs, i32 %iv
-; CHECK-NEXT:    %right_ptr = getelementptr inbounds i8, i8* %rhs, i32 %iv
+; CHECK-NEXT:    %iv.next = add nuw nsw i32 0, 1
+; CHECK-NEXT:    %left_ptr = getelementptr inbounds i8, i8* %lhs, i32 0
+; CHECK-NEXT:    %right_ptr = getelementptr inbounds i8, i8* %rhs, i32 0
 ; CHECK-NEXT:    %result = call i1 @foo(i8* %left_ptr, i8* %right_ptr)
 ; CHECK-NEXT:    br i1 %result, label %exiting_1, label %exit.loopexit
 ; CHECK:       exiting_1:
-; CHECK-NEXT:    %iv.wide.is_not_zero = icmp ne i64 %iv.wide, 0
+; CHECK-NEXT:    %iv.wide.is_not_zero = icmp ne i64 0, 0
 ; CHECK-NEXT:    br i1 false, label %exiting_2, label %exit.loopexit
 ; CHECK:       exiting_2:
 ; CHECK-NEXT:    %bar_ret = call i1 @bar()
index 0abfb06..d8e0484 100644 (file)
@@ -14,10 +14,9 @@ define void @foo() {
 ; CHECK-NEXT:  bb:
 ; CHECK-NEXT:    br label [[BB3:%.*]]
 ; CHECK:       bb3:
-; CHECK-NEXT:    [[TMP:%.*]] = phi i8* [ [[TMP4:%.*]], [[BB7:%.*]] ], [ getelementptr inbounds ([0 x i8], [0 x i8]* @global, i64 0, i64 2), [[BB:%.*]] ]
-; CHECK-NEXT:    [[TMP4]] = getelementptr inbounds i8, i8* [[TMP]], i64 -1
+; CHECK-NEXT:    [[TMP4:%.*]] = getelementptr inbounds i8, i8* getelementptr inbounds ([0 x i8], [0 x i8]* @global, i64 0, i64 2), i64 -1
 ; CHECK-NEXT:    [[TMP6:%.*]] = load i8, i8* [[TMP4]], align 1
-; CHECK-NEXT:    br i1 false, label [[BB7]], label [[BB11:%.*]]
+; CHECK-NEXT:    br i1 false, label [[BB7:%.*]], label [[BB11:%.*]]
 ; CHECK:       bb7:
 ; CHECK-NEXT:    [[TMP8:%.*]] = zext i8 [[TMP6]] to i64
 ; CHECK-NEXT:    br i1 true, label [[BB11]], label [[BB3]]
index f22e606..ca081e8 100644 (file)
@@ -65,9 +65,7 @@ define void @test3() nounwind {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    br label [[BB:%.*]]
 ; CHECK:       bb:
-; CHECK-NEXT:    [[IV:%.*]] = phi double [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[TMP1:%.*]], [[BB]] ]
-; CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @foo(double [[IV]]) #[[ATTR0]]
-; CHECK-NEXT:    [[TMP1]] = fadd double [[IV]], 1.000000e+00
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call i32 @foo(double 0.000000e+00) #[[ATTR0]]
 ; CHECK-NEXT:    br i1 false, label [[BB]], label [[RETURN:%.*]]
 ; CHECK:       return:
 ; CHECK-NEXT:    ret void