[llvm] r360694 - [IndVars] Extend reasoning about loop invariant exits to non-header blocks

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Tue May 14 10:20:10 PDT 2019


Author: reames
Date: Tue May 14 10:20:10 2019
New Revision: 360694

URL: http://llvm.org/viewvc/llvm-project?rev=360694&view=rev
Log:
[IndVars] Extend reasoning about loop invariant exits to non-header blocks

Noticed while glancing through the code for other reasons.  The extension is trivial enough, decided to just do it.


Modified:
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll
    llvm/trunk/test/Transforms/LoopUnroll/scevunroll.ll

Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=360694&r1=360693&r2=360694&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Tue May 14 10:20:10 2019
@@ -728,11 +728,13 @@ bool IndVarSimplify::rewriteFirstIterati
            IncomingValIdx != E; ++IncomingValIdx) {
         auto *IncomingBB = PN.getIncomingBlock(IncomingValIdx);
 
-        // We currently only support loop exits from loop header. If the
-        // incoming block is not loop header, we need to recursively check
-        // all conditions starting from loop header are loop invariants.
-        // Additional support might be added in the future.
-        if (IncomingBB != LoopHeader)
+        // Can we prove that the exit must run on the first iteration if it
+        // runs at all?  (i.e. early exits are fine for our purposes, but
+        // traces which lead to this exit being taken on the 2nd iteration
+        // aren't.)  Note that this is about whether the exit branch is
+        // executed, not about whether it is taken.
+        if (!L->getLoopLatch() ||
+            !DT->dominates(IncomingBB, L->getLoopLatch()))
           continue;
 
         // Get condition that leads to the exit path.
@@ -753,8 +755,8 @@ bool IndVarSimplify::rewriteFirstIterati
 
         auto *ExitVal = dyn_cast<PHINode>(PN.getIncomingValue(IncomingValIdx));
 
-        // Only deal with PHIs.
-        if (!ExitVal)
+        // Only deal with PHIs in the loop header.
+        if (!ExitVal || ExitVal->getParent() != L->getHeader())
           continue;
 
         // If ExitVal is a PHI on the loop header, then we know its

Modified: llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll?rev=360694&r1=360693&r2=360694&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll Tue May 14 10:20:10 2019
@@ -94,3 +94,68 @@ exit:
   ret i32 %phi_indvar
 }
 
+
+; Multiple exits dominating latch
+define i32 @test4(i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: @test4(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[HEADER:%.*]]
+; CHECK:       header:
+; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[LOOP:%.*]], label [[EXIT:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[HEADER]], label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  br label %header
+
+header:
+  %phi_indvar = phi i32 [0, %entry], [%indvar, %loop]
+  br i1 %cond1, label %loop, label %exit
+
+loop:
+  %indvar = add i32 %phi_indvar, 1
+  br i1 %cond2, label %header, label %exit
+
+exit:
+  ret i32 %phi_indvar
+}
+
+; A conditionally executed exit.
+define i32 @test5(i1* %addr, i1 %cond2) {
+; CHECK-LABEL: @test5(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br label [[HEADER:%.*]]
+; CHECK:       header:
+; CHECK-NEXT:    [[PHI_INDVAR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INDVAR:%.*]], [[LOOP:%.*]] ]
+; CHECK-NEXT:    [[COND1:%.*]] = load volatile i1, i1* [[ADDR:%.*]], align 1
+; CHECK-NEXT:    br i1 [[COND1]], label [[LOOP]], label [[MAYBE:%.*]]
+; CHECK:       maybe:
+; CHECK-NEXT:    br i1 [[COND2:%.*]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[INDVAR]] = add i32 [[PHI_INDVAR]], 1
+; CHECK-NEXT:    br label [[HEADER]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i32 [[PHI_INDVAR]]
+;
+entry:
+  br label %header
+
+header:
+  %phi_indvar = phi i32 [0, %entry], [%indvar, %loop]
+  %cond1 = load volatile i1, i1* %addr
+  br i1 %cond1, label %loop, label %maybe
+
+maybe:
+  br i1 %cond2, label %loop, label %exit
+
+loop:
+  %indvar = add i32 %phi_indvar, 1
+  br label %header
+
+exit:
+  ret i32 %phi_indvar
+}
+
+

Modified: llvm/trunk/test/Transforms/LoopUnroll/scevunroll.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/scevunroll.ll?rev=360694&r1=360693&r2=360694&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LoopUnroll/scevunroll.ll (original)
+++ llvm/trunk/test/Transforms/LoopUnroll/scevunroll.ll Tue May 14 10:20:10 2019
@@ -184,7 +184,7 @@ for.body87:
 ; CHECK: for.body:
 ; CHECK: %b.03 = phi i32 [ 0, %entry ], [ %add, %for.cond ]
 ; CHECK: return:
-; CHECK: %b.03.lcssa = phi i32 [ %b.03, %for.body ], [ %b.03, %for.cond ]
+; CHECK: %b.03.lcssa = phi i32 [ %b.03, %for.body ], [ 0, %for.cond ]
 define void @nsw_latch(i32* %a) nounwind {
 entry:
   br label %for.body




More information about the llvm-commits mailing list