diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -6173,7 +6173,18 @@ } } - return LatchControlDependentOnPoison && loopHasNoAbnormalExits(L); + if (LatchControlDependentOnPoison) { + if (LatchBB == I->getParent()) + // If I is in the latch and all instructions between I and the end of the + // block are guaranteed to execute, I cannot be poison. + return all_of(make_range(I->getIterator(), I->getParent()->end()), + [](const Instruction &I) { + return isGuaranteedToTransferExecutionToSuccessor(&I); + }); + return loopHasNoAbnormalExits(L); + } + + return false; } ScalarEvolution::LoopProperties diff --git a/llvm/test/Transforms/LoopStrengthReduce/X86/2008-08-14-ShadowIV.ll b/llvm/test/Transforms/LoopStrengthReduce/X86/2008-08-14-ShadowIV.ll --- a/llvm/test/Transforms/LoopStrengthReduce/X86/2008-08-14-ShadowIV.ll +++ b/llvm/test/Transforms/LoopStrengthReduce/X86/2008-08-14-ShadowIV.ll @@ -86,12 +86,13 @@ ret void } -; Unable to eliminate cast due to overflow. +; We can eliminate the cast, as all instructions between %indvar.next and the +; branch are guaranteed to execute and branching on poison is undef. Hence +; %indvar.next cannot overflow and neither can %i.03. define void @foobar4() nounwind { ; CHECK-LABEL: foobar4( -; CHECK-NOT: phi double -; CHECK-NOT: phi float +; CHECK: phi double entry: br label %bb.nph