]> granicus.if.org Git - llvm/commitdiff
[IndVars] Fix a bug introduced in r317012
authorPhilip Reames <listmail@philipreames.com>
Fri, 1 Dec 2017 20:57:19 +0000 (20:57 +0000)
committerPhilip Reames <listmail@philipreames.com>
Fri, 1 Dec 2017 20:57:19 +0000 (20:57 +0000)
Turns out we can have comparisons which are indirect users of the induction variable that we can make invariant.  In this case, there is no loop invariant value contributing and we'd fail an assert.

The test case was found by a java fuzzer and reduced.  It's a real cornercase.  You have to have a static loop which we've already proven only executes once, but haven't broken the backedge on, and an inner phi whose result can be constant folded by SCEV using exit count reasoning but not proven by isKnownPredicate.  To my knowledge, only the fuzzer has hit this case.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319583 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Utils/SimplifyIndVar.cpp
test/Transforms/IndVarSimplify/loop-invariant-conditions.ll

index fce7f8b81bac7c0c9cd867566586bccf26ca772b..96b51396c9b639a5c27441bee903d686337a572a 100644 (file)
@@ -200,13 +200,23 @@ bool SimplifyIndvar::makeIVComparisonInvariant(ICmpInst *ICmp,
   // TODO: Support multiple entry loops?  (We currently bail out of these in
   // the IndVarSimplify pass)
   if (auto *BB = L->getLoopPredecessor()) {
-    Value *Incoming = PN->getIncomingValueForBlock(BB);
-    const SCEV *IncomingS = SE->getSCEV(Incoming);
-    CheapExpansions[IncomingS] = Incoming;
+    const int Idx = PN->getBasicBlockIndex(BB);
+    if (Idx >= 0) {
+      Value *Incoming = PN->getIncomingValue(Idx);
+      const SCEV *IncomingS = SE->getSCEV(Incoming);
+      CheapExpansions[IncomingS] = Incoming;
+    }
   }
   Value *NewLHS = CheapExpansions[InvariantLHS];
   Value *NewRHS = CheapExpansions[InvariantRHS];
 
+  if (!NewLHS)
+    if (auto *ConstLHS = dyn_cast<SCEVConstant>(InvariantLHS))
+      NewLHS = ConstLHS->getValue();
+  if (!NewRHS)
+    if (auto *ConstRHS = dyn_cast<SCEVConstant>(InvariantRHS))
+      NewRHS = ConstRHS->getValue();
+
   if (!NewLHS || !NewRHS)
     // We could not find an existing value to replace either LHS or RHS.
     // Generating new instructions has subtler tradeoffs, so avoid doing that
index 1c8eb93869ada9441e7dba0e21da42d4cde89c71..70cf714ba9f2a8a1cea23cdbcd51d9bdf9e683a4 100644 (file)
@@ -295,6 +295,36 @@ for.end:                                          ; preds = %if.end, %entry
   ret void
 }
 
+; check that we handle conditions with loop invariant operands which
+; *aren't* in the header - this is a very rare and fragile case where
+; we have a "loop" which is known to run exactly one iteration but
+; haven't yet simplified the uses of the IV
+define void @test10() {
+; CHECK-LABEL: @test10
+entry:
+  br label %loop
+
+loop:
+  %phi1 = phi i32 [ %phi2, %latch ], [ 0, %entry ]
+  %dec = add i32 %phi1, -1
+  br i1 false, label %left, label %right
+
+left:
+  br label %latch
+
+right:
+  br label %latch
+
+latch:
+  %phi2 = phi i32 [ %phi1, %left ], [ %dec, %right ]
+  ; CHECK: %cmp = icmp slt i32 -1, undef
+  %cmp = icmp slt i32 %phi2, undef
+  br i1 true, label %exit, label %loop
+
+exit:
+  ret void
+}
+
 !1 = !{i64 -1, i64 100}