[llvm] r316976 - [IndVarSimplify] Simplify code using preheader assumption

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 30 22:16:46 PDT 2017


Author: reames
Date: Mon Oct 30 22:16:46 2017
New Revision: 316976

URL: http://llvm.org/viewvc/llvm-project?rev=316976&view=rev
Log:
[IndVarSimplify] Simplify code using preheader assumption

As noted in the nice block comment, the previous code didn't actually handle multi-entry loops correctly, it just assumed SCEV didn't analyze such loops.  Given SCEV has comments to the contrary, that seems a bit suspect.  More importantly, the pass actually requires loopsimplify form which ensures a loop-preheader is available.  Remove the excessive generaility and shorten the code greatly.

Note that we do successfully analyze many multi-entry loops, but we do so by converting them to single entry loops.  See the added test case.


Modified:
    llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    llvm/trunk/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll

Modified: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp?rev=316976&r1=316975&r2=316976&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Mon Oct 30 22:16:46 2017
@@ -182,7 +182,8 @@ bool SimplifyIndvar::makeIVComparisonInv
   ICmpInst::Predicate InvariantPredicate;
   const SCEV *InvariantLHS, *InvariantRHS;
 
-  if (!isa<PHINode>(IVOperand))
+  auto *PN = dyn_cast<PHINode>(IVOperand);
+  if (!PN)
     return false;
   if (!SE->isLoopInvariantPredicate(Pred, S, X, L, InvariantPredicate,
                                     InvariantLHS, InvariantRHS))
@@ -202,49 +203,10 @@ bool SimplifyIndvar::makeIVComparisonInv
     NewRHS =
       ICmp->getOperand(S == InvariantRHS ? IVOperIdx : (1 - IVOperIdx));
 
-  auto *PN = cast<PHINode>(IVOperand);
-  for (unsigned i = 0, e = PN->getNumIncomingValues();
-       i != e && (!NewLHS || !NewRHS);
-       ++i) {
-
-    // If this is a value incoming from the backedge, then it cannot be a loop
-    // invariant value (since we know that IVOperand is an induction variable).
-    if (L->contains(PN->getIncomingBlock(i)))
-      continue;
-
-    // NB! This following assert does not fundamentally have to be true, but
-    // it is true today given how SCEV analyzes induction variables.
-    // Specifically, today SCEV will *not* recognize %iv as an induction
-    // variable in the following case:
-    //
-    // define void @f(i32 %k) {
-    // entry:
-    //   br i1 undef, label %r, label %l
-    //
-    // l:
-    //   %k.inc.l = add i32 %k, 1
-    //   br label %loop
-    //
-    // r:
-    //   %k.inc.r = add i32 %k, 1
-    //   br label %loop
-    //
-    // loop:
-    //   %iv = phi i32 [ %k.inc.l, %l ], [ %k.inc.r, %r ], [ %iv.inc, %loop ]
-    //   %iv.inc = add i32 %iv, 1
-    //   br label %loop
-    // }
-    //
-    // but if it starts to, at some point, then the assertion below will have
-    // to be changed to a runtime check.
-
-    Value *Incoming = PN->getIncomingValue(i);
-
-#ifndef NDEBUG
-    if (auto *I = dyn_cast<Instruction>(Incoming))
-      assert(DT->dominates(I, ICmp) && "Should be a unique loop dominating value!");
-#endif
-
+  // TODO: Support multiple entry loops?  (We currently bail out of these in
+  // the IndVarSimplify pass)
+  if (auto *BB = L->getLoopPredecessor()) {
+    Value *Incoming = PN->getIncomingValue(PN->getBasicBlockIndex(BB));
     const SCEV *IncomingS = SE->getSCEV(Incoming);
 
     if (!NewLHS && IncomingS == InvariantLHS)

Modified: llvm/trunk/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll?rev=316976&r1=316975&r2=316976&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll (original)
+++ llvm/trunk/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll Mon Oct 30 22:16:46 2017
@@ -273,6 +273,28 @@ for.end:
   ret void
 }
 
+; check to handle loops without preheaders, but invariant operands
+; (we handle this today by inserting a preheader)
+define void @test9(i1 %cnd, i64 %start) {
+; CHECK-LABEL: @test9
+; CHECK-LABEL: loop.preheader:
+entry:
+  br i1 %cnd, label %entry1, label %entry2
+entry1:
+  br label %loop
+entry2:
+  br label %loop
+loop:
+  %indvars.iv = phi i64 [ %start, %entry1 ],[ %start, %entry2 ], [ %indvars.iv.next, %loop ]
+  %indvars.iv.next = add nsw i64 %indvars.iv, 1
+; CHECK: %cmp1 = icmp slt i64 %start, -1
+  %cmp1 = icmp slt i64 %indvars.iv, -1
+  br i1 %cmp1, label %for.end, label %loop
+
+for.end:                                          ; preds = %if.end, %entry
+  ret void
+}
+
 !1 = !{i64 -1, i64 100}
 
 




More information about the llvm-commits mailing list