diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -2967,11 +2967,14 @@ // Take the minimum of all incoming values. This can't infinitely loop // because of our depth threshold. - Tmp = ComputeNumSignBits(PN->getIncomingValue(0), Depth + 1, Q); + Query RecQ = Q; + RecQ.CxtI = PN->getIncomingBlock(0)->getTerminator(); + Tmp = ComputeNumSignBits(PN->getIncomingValue(0), Depth + 1, RecQ); for (unsigned i = 1, e = NumIncomingValues; i != e; ++i) { if (Tmp == 1) return Tmp; + RecQ.CxtI = PN->getIncomingBlock(i)->getTerminator(); Tmp = std::min( - Tmp, ComputeNumSignBits(PN->getIncomingValue(i), Depth + 1, Q)); + Tmp, ComputeNumSignBits(PN->getIncomingValue(i), Depth + 1, RecQ)); } return Tmp; } @@ -4930,7 +4933,20 @@ return true; } - if (!canCreateUndefOrPoison(Opr) && all_of(Opr->operands(), OpCheck)) + if (auto *PN = dyn_cast(V)) { + unsigned Num = PN->getNumIncomingValues(); + bool IsWellDefined = true; + for (unsigned i = 0; i < Num; ++i) { + auto *TI = PN->getIncomingBlock(i)->getTerminator(); + if (!isGuaranteedNotToBeUndefOrPoison(PN->getIncomingValue(i), TI, DT, + Depth + 1, PoisonOnly)) { + IsWellDefined = false; + break; + } + } + if (IsWellDefined) + return true; + } else if (!canCreateUndefOrPoison(Opr) && all_of(Opr->operands(), OpCheck)) return true; } diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -768,6 +768,29 @@ } } +TEST_F(ValueTrackingTest, isGuaranteedNotToBePoison_phi) { + parseAssembly("declare i32 @any_i32(i32)" + "define void @test() {\n" + "ENTRY:\n" + " br label %LOOP\n" + "LOOP:\n" + " %A = phi i32 [0, %ENTRY], [%A.next, %LOOP]\n" + " %A.next = call i32 @any_i32(i32 %A)\n" + " udiv i32 1, %A.next\n" + " %cond = icmp eq i32 %A.next, 0\n" + " br i1 %cond, label %LOOP, label %EXIT\n" + "EXIT:\n" + " ret void\n" + "}\n"); + for (auto &BB : *F) { + if (BB.getName() == "LOOP") { + auto *TI = BB.getTerminator(); + EXPECT_EQ(isGuaranteedNotToBePoison(A), true) + << "isGuaranteedNotToBePoison does not hold at " << *TI; + } + } +} + TEST_F(ValueTrackingTest, isGuaranteedNotToBeUndefOrPoison) { parseAssembly("declare void @f(i32 noundef)" "define void @test(i32 %x) {\n"