Commit d9ca4448 authored by Max Kazantsev's avatar Max Kazantsev
Browse files

[IndVars] Break backedge and replace PHIs if loop exits on 1st iteration

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
parent 5a6dfb27
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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;
    }

+2 −5
Original line number Diff line number Diff line
@@ -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