<p dir="ltr">Looks like this broke some bots <a href="http://lab.llvm.org:8011/builders/clang-cmake-mips/builds/10258/steps/ninja%20check%201/logs/stdio">http://lab.llvm.org:8011/builders/clang-cmake-mips/builds/10258/steps/ninja%20check%201/logs/stdio</a></p>
<p dir="ltr">Sent from a mobile device, please excuse typos.</p>
<div class="gmail_quote">On Oct 27, 2015 21:47, "Chen Li via llvm-commits" <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: chenli<br>
Date: Tue Oct 27 23:45:47 2015<br>
New Revision: 251492<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=251492&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=251492&view=rev</a><br>
Log:<br>
[IndVarSimplify] Rewrite loop exit values with their initial values from loop preheader<br>
<br>
Summary:<br>
This patch adds support to check if a loop has loop invariant conditions which lead to loop exits. If so, we know that if the exit path is taken, it is at the first loop iteration. If there is an induction variable used in that exit path whose value has not been updated, it will keep its initial value passing from loop preheader. We can therefore rewrite the exit value with<br>
its initial value. This will help remove phis created by LCSSA and enable other optimizations like loop unswitch.<br>
<br>
<br>
Reviewers: sanjoy<br>
<br>
Subscribers: llvm-commits<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D13974" rel="noreferrer" target="_blank">http://reviews.llvm.org/D13974</a><br>
<br>
Added:<br>
    llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll<br>
Modified:<br>
    llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp<br>
    llvm/trunk/test/Transforms/LoopUnroll/scevunroll.ll<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=251492&r1=251491&r2=251492&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=251492&r1=251491&r2=251492&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Tue Oct 27 23:45:47 2015<br>
@@ -132,6 +132,7 @@ private:<br>
<br>
   bool canLoopBeDeleted(Loop *L, SmallVector<RewritePhi, 8> &RewritePhiSet);<br>
   void rewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter);<br>
+  void rewriteFirstIterationLoopExitValues(Loop *L);<br>
<br>
   Value *linearFunctionTestReplace(Loop *L, const SCEV *BackedgeTakenCount,<br>
                                    PHINode *IndVar, SCEVExpander &Rewriter);<br>
@@ -700,6 +701,71 @@ void IndVarSimplify::rewriteLoopExitValu<br>
   Rewriter.clearInsertPoint();<br>
 }<br>
<br>
+//===---------------------------------------------------------------------===//<br>
+// rewriteFirstIterationLoopExitValues: Rewrite loop exit values if we know<br>
+// they will exit at the first iteration.<br>
+//===---------------------------------------------------------------------===//<br>
+<br>
+/// Check to see if this loop has loop invariant conditions which lead to loop<br>
+/// exits. If so, we know that if the exit path is taken, it is at the first<br>
+/// loop iteration. This lets us predict exit values of PHI nodes that live in<br>
+/// loop header.<br>
+void IndVarSimplify::rewriteFirstIterationLoopExitValues(Loop *L) {<br>
+  // Verify the input to the pass is already in LCSSA form.<br>
+  assert(L->isLCSSAForm(*DT));<br>
+<br>
+  SmallVector<BasicBlock *, 8> ExitBlocks;<br>
+  L->getUniqueExitBlocks(ExitBlocks);<br>
+<br>
+  for (auto *ExitBB : ExitBlocks) {<br>
+    BasicBlock::iterator begin = ExitBB->begin();<br>
+    // If there are no more PHI nodes in this exit block, then no more<br>
+    // values defined inside the loop are used on this path.<br>
+    while (auto *PN = dyn_cast<PHINode>(begin++)) {<br>
+      for (unsigned IncomingValIdx = 0, e = PN->getNumIncomingValues();<br>
+          IncomingValIdx != e; ++IncomingValIdx) {<br>
+        auto *IncomingBB = PN->getIncomingBlock(IncomingValIdx);<br>
+        if (!L->contains(IncomingBB))<br>
+          continue;<br>
+<br>
+        // Get condition that leads to the exit path.<br>
+        auto *TermInst = IncomingBB->getTerminator();<br>
+<br>
+        Value *Cond = nullptr;<br>
+        if (auto *BI = dyn_cast<BranchInst>(TermInst)) {<br>
+          // Must be a conditional branch, otherwise the block<br>
+          // should not be in the loop.<br>
+          Cond = BI->getCondition();<br>
+        } else if (auto *SI = dyn_cast<SwitchInst>(TermInst))<br>
+          Cond = SI->getCondition();<br>
+<br>
+        // All non-instructions are loop-invariant.<br>
+        if (isa<Instruction>(Cond) && !L->isLoopInvariant(Cond))<br>
+            continue;<br>
+<br>
+        auto *ExitVal =<br>
+            dyn_cast<PHINode>(PN->getIncomingValue(IncomingValIdx));<br>
+<br>
+        // Only deal with PHIs.<br>
+        if (!ExitVal)<br>
+          continue;<br>
+<br>
+        // If ExitVal is a PHI on the loop header, then we know its<br>
+        // value along this exit because the exit can only be taken<br>
+        // on the first iteration.<br>
+        auto *LoopPreheader = L->getLoopPreheader();<br>
+        assert(LoopPreheader && "Invalid loop");<br>
+        if (ExitVal->getBasicBlockIndex(LoopPreheader) != -1) {<br>
+          assert(ExitVal->getParent() == L->getHeader() &&<br>
+              "ExitVal must be in loop header");<br>
+          PN->setIncomingValue(IncomingValIdx,<br>
+              ExitVal->getIncomingValueForBlock(LoopPreheader));<br>
+        }<br>
+      }<br>
+    }<br>
+  }<br>
+}<br>
+<br>
 /// Check whether it is possible to delete the loop after rewriting exit<br>
 /// value. If it is possible, ignore ReplaceExitValue and do rewriting<br>
 /// aggressively.<br>
@@ -2173,6 +2239,11 @@ bool IndVarSimplify::runOnLoop(Loop *L,<br>
   // loop may be sunk below the loop to reduce register pressure.<br>
   sinkUnusedInvariants(L);<br>
<br>
+  // rewriteFirstIterationLoopExitValues does not rely on the computation of<br>
+  // trip count and therefore can further simplify exit values in addition to<br>
+  // rewriteLoopExitValues.<br>
+  rewriteFirstIterationLoopExitValues(L);<br>
+<br>
   // Clean up dead instructions.<br>
   Changed |= DeleteDeadPHIs(L->getHeader(), TLI);<br>
   // Check a post-condition.<br>
<br>
Added: llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll?rev=251492&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll?rev=251492&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll (added)<br>
+++ llvm/trunk/test/Transforms/IndVarSimplify/rewrite-loop-exit-value.ll Tue Oct 27 23:45:47 2015<br>
@@ -0,0 +1,75 @@<br>
+; RUN: opt -indvars -instcombine -S < %s | FileCheck %s<br>
+<br>
+;; Test that loop's exit value is rewritten to its initial<br>
+;; value from loop preheader<br>
+define i32 @test1(i32* %var) {<br>
+; CHECK-LABEL: @test1<br>
+entry:<br>
+ %cond = icmp eq i32* %var, null<br>
+ br label %header<br>
+<br>
+header:<br>
+ %phi_indvar = phi i32 [0, %entry], [%indvar, %loop]<br>
+ br i1 %cond, label %loop, label %exit<br>
+<br>
+loop:<br>
+ %indvar = add i32 %phi_indvar, 1<br>
+ br label %header<br>
+<br>
+exit:<br>
+; CHECK: ret i32 0<br>
+ ret i32 %phi_indvar<br>
+}<br>
+<br>
+<br>
+;; Test that inner loop's exit value is first rewritten to outer<br>
+;; loop's induction variable, and then further rewritten to a<br>
+;; constant when process outer loop.<br>
+define i32 @test2(i32* %var1, i32* %var2) {<br>
+; CHECK-LABEL: @test2<br>
+entry:<br>
+ %cond1 = icmp eq i32* %var1, null<br>
+ %cond2 = icmp eq i32* %var2, null<br>
+ br label %outer_header<br>
+<br>
+outer_header:<br>
+ %phi_outer = phi i32 [0, %entry], [%indvar_outer, %inner_exit]<br>
+ br label %inner_header<br>
+<br>
+inner_header:<br>
+ %phi_inner = phi i32 [%phi_outer, %outer_header], [%indvar_inner, %loop]<br>
+ br i1 %cond1, label %loop, label %exit<br>
+<br>
+loop:<br>
+ %indvar_inner = add i32 %phi_inner, 1<br>
+ br i1 %cond2, label %inner_header, label %inner_exit<br>
+<br>
+inner_exit:<br>
+ %indvar_outer = add i32 %phi_outer, 1<br>
+ br label %outer_header<br>
+<br>
+exit:<br>
+;; %phi_inner is first rewritten to %phi_outer<br>
+;; and then %phi_outer is rewritten to 0<br>
+ %ret_val = add i32 %phi_inner, %phi_outer<br>
+; CHECK: ret i32 0<br>
+ ret i32 %ret_val<br>
+}<br>
+<br>
+;; Test that we can not rewrite loop exit value if it's not<br>
+;; a phi node (%indvar is an add instruction in this test).<br>
+define i32 @test3(i32* %var) {<br>
+; CHECK-LABEL: @test3<br>
+entry:<br>
+ %cond = icmp eq i32* %var, null<br>
+ br label %header<br>
+<br>
+header:<br>
+ %phi_indvar = phi i32 [0, %entry], [%indvar, %header]<br>
+ %indvar = add i32 %phi_indvar, 1<br>
+ br i1 %cond, label %header, label %exit<br>
+<br>
+exit:<br>
+; CHECK: ret i32 %indvar<br>
+ ret i32 %indvar<br>
+}<br>
\ No newline at end of file<br>
<br>
Modified: llvm/trunk/test/Transforms/LoopUnroll/scevunroll.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/scevunroll.ll?rev=251492&r1=251491&r2=251492&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/scevunroll.ll?rev=251492&r1=251491&r2=251492&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/LoopUnroll/scevunroll.ll (original)<br>
+++ llvm/trunk/test/Transforms/LoopUnroll/scevunroll.ll Tue Oct 27 23:45:47 2015<br>
@@ -184,7 +184,7 @@ for.body87:<br>
 ; CHECK: for.body:<br>
 ; CHECK: %b.03 = phi i32 [ 0, %entry ], [ %add, %for.cond ]<br>
 ; CHECK: return:<br>
-; CHECK: %b.03.lcssa = phi i32 [ %b.03, %for.body ], [ %b.03, %for.cond ]<br>
+; CHECK: %b.03.lcssa = phi i32 [ %b.03, %for.body ], [ 0, %for.cond ]<br>
 define void @nsw_latch(i32* %a) nounwind {<br>
 entry:<br>
   br label %for.body<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>