diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp index fce7f8b81bac7c0c9cd867566586bccf26ca772b..96b51396c9b639a5c27441bee903d686337a572a 100644 --- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp @@ -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 diff --git a/llvm/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll b/llvm/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll index 1c8eb93869ada9441e7dba0e21da42d4cde89c71..70cf714ba9f2a8a1cea23cdbcd51d9bdf9e683a4 100644 --- a/llvm/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll +++ b/llvm/test/Transforms/IndVarSimplify/loop-invariant-conditions.ll @@ -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}