[IndVars] Break backedge and replace PHIs if loop exits on 1st iteration
authorMax Kazantsev <mkazantsev@azul.com>
Mon, 13 Sep 2021 04:29:33 +0000 (11:29 +0700)
committerMax Kazantsev <mkazantsev@azul.com>
Mon, 13 Sep 2021 04:30:55 +0000 (11:30 +0700)
Implement TODO in optimizeLoopExits. Now if we have proved that some loop exit
is taken on 1st iteration, we make all branches in the following exiting blocks
always branch out of the loop and their conditions simplified away.

Patch by Dmitry Makogon!

Differential Revision: https://reviews.llvm.org/D108910
Reviewed By: lebedev.ri

llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
llvm/test/Transforms/IndVarSimplify/eliminate-backedge.ll

index 320e20c..f6a6ea1 100644 (file)
@@ -1465,8 +1465,15 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
 
   bool Changed = false;
   bool SkipLastIter = false;
+  bool ExitsOnFirstIter = false;
   SmallSet<const SCEV*, 8> DominatingExitCounts;
   for (BasicBlock *ExitingBB : ExitingBlocks) {
+    if (ExitsOnFirstIter) {
+      // If proved that some earlier exit is taken
+      // on 1st iteration, then fold this one.
+      foldExit(L, ExitingBB, true, DeadInsts);
+      continue;
+    }
     const SCEV *ExitCount = SE->getExitCount(L, ExitingBB);
     if (isa<SCEVCouldNotCompute>(ExitCount)) {
       // Okay, we do not know the exit count here. Can we at least prove that it
@@ -1516,6 +1523,7 @@ bool IndVarSimplify::optimizeLoopExits(Loop *L, SCEVExpander &Rewriter) {
       foldExit(L, ExitingBB, true, DeadInsts);
       replaceLoopPHINodesWithPreheaderValues(L, DeadInsts);
       Changed = true;
+      ExitsOnFirstIter = true;
       continue;
     }
 
index e2ba6e0..6070178 100644 (file)
@@ -15,7 +15,6 @@ 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.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)
@@ -25,12 +24,10 @@ define i1 @kill_backedge_and_phis(i8* align 1 %lhs, i8* align 1 %rhs, i32 %len)
 ; CHECK-NEXT:    br i1 false, label %exiting_2, label %exit.loopexit
 ; CHECK:       exiting_2:
 ; CHECK-NEXT:    %bar_ret = call i1 @bar()
-; CHECK-NEXT:    br i1 %bar_ret, label %exit.loopexit, label %exiting_3
+; CHECK-NEXT:    br i1 true, label %exit.loopexit, label %exiting_3
 ; CHECK:       exiting_3:
 ; CHECK-NEXT:    %baz_ret = call i1 @baz()
-; CHECK-NEXT:    %continue = icmp ne i32 %iv.next, %len
-; CHECK-NEXT:    %or.cond = select i1 %baz_ret, i1 %continue, i1 false
-; CHECK-NEXT:    br i1 %or.cond, label %loop, label %exit.loopexit
+; CHECK-NEXT:    br i1 false, label %loop, label %exit.loopexit
 ; CHECK:       exit.loopexit:
 ; CHECK-NEXT:    %val.ph = phi i1 [ %baz_ret, %exiting_3 ], [ %bar_ret, %exiting_2 ], [ %iv.wide.is_not_zero, %exiting_1 ], [ %result, %loop ]
 ; CHECK-NEXT:    br label %exit