[ValueTracking] Fix analyses to update CxtI to be phi's incoming edges' terminators

It was mentioned that D88276 that when a phi node is visited, terminators at their incoming edges should be used for CtxI.
This is a patch that makes two functions (ComputeNumSignBitsImpl, isGuaranteedNotToBeUndefOrPoison) to do so.

Reviewed By: nikic

Differential Revision: https://reviews.llvm.org/D88360
This commit is contained in:
Juneyoung Lee 2020-09-26 23:56:30 +09:00
parent c372809f5a
commit ba8911d560
2 changed files with 43 additions and 4 deletions

View File

@ -2967,11 +2967,13 @@ static unsigned ComputeNumSignBitsImpl(const Value *V,
// 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);
for (unsigned i = 1, e = NumIncomingValues; i != e; ++i) {
Query RecQ = Q;
Tmp = TyBits;
for (unsigned i = 0, 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;
}
@ -4939,7 +4941,20 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
return true;
}
if (!canCreateUndefOrPoison(Opr) && all_of(Opr->operands(), OpCheck))
if (const auto *PN = dyn_cast<PHINode>(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;
}

View File

@ -768,6 +768,30 @@ TEST_F(ValueTrackingTest, isGuaranteedNotToBePoison_exploitBranchCond) {
}
}
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, %NEXT]\n"
" %A.next = call i32 @any_i32(i32 %A)\n"
" %cond = icmp eq i32 %A.next, 0\n"
" br i1 %cond, label %NEXT, label %EXIT\n"
"NEXT:\n"
" br label %LOOP\n"
"EXIT:\n"
" ret void\n"
"}\n");
DominatorTree DT(*F);
for (auto &BB : *F) {
if (BB.getName() == "LOOP") {
EXPECT_EQ(isGuaranteedNotToBePoison(A, A, &DT), true)
<< "isGuaranteedNotToBePoison does not hold";
}
}
}
TEST_F(ValueTrackingTest, isGuaranteedNotToBeUndefOrPoison) {
parseAssembly("declare void @f(i32 noundef)"
"define void @test(i32 %x) {\n"