Skip to content

Commit 6f01cb9

Browse files
committed
Handle select in programUndefinedIfPoison.
If both the true and false operands of a `select` are poison, then the `select` is poison. Differential Revision: https://reviews.llvm.org/D149427
1 parent 8df5913 commit 6f01cb9

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6707,7 +6707,7 @@ bool llvm::isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC,
67076707
return ::isGuaranteedNotToBeUndefOrPoison(V, AC, CtxI, DT, Depth, true);
67086708
}
67096709

6710-
/// Return true if undefined behavior would provable be executed on the path to
6710+
/// Return true if undefined behavior would provably be executed on the path to
67116711
/// OnPathTo if Root produced a posion result. Note that this doesn't say
67126712
/// anything about whether OnPathTo is actually executed or whether Root is
67136713
/// actually poison. This can be used to assess whether a new use of Root can
@@ -7041,6 +7041,15 @@ static bool programUndefinedIfUndefOrPoison(const Value *V,
70417041
break;
70427042
}
70437043
}
7044+
7045+
// Special handling for select, which returns poison if its operand 0 is
7046+
// poison (handled in the loop above) *or* if both its true/false operands
7047+
// are poison (handled here).
7048+
if (I.getOpcode() == Instruction::Select &&
7049+
YieldsPoison.count(I.getOperand(1)) &&
7050+
YieldsPoison.count(I.getOperand(2))) {
7051+
YieldsPoison.insert(&I);
7052+
}
70447053
}
70457054

70467055
BB = BB->getSingleSuccessor();

llvm/unittests/Analysis/ValueTrackingTest.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,20 @@ TEST_F(ValueTrackingTest, programUndefinedIfPoison) {
982982
EXPECT_EQ(programUndefinedIfPoison(A), true);
983983
}
984984

985+
TEST_F(ValueTrackingTest, programUndefinedIfPoisonSelect) {
986+
parseAssembly("declare i32 @any_num()"
987+
"define void @test(i1 %Cond) {\n"
988+
" %A = call i32 @any_num()\n"
989+
" %B = add i32 %A, 1\n"
990+
" %C = select i1 %Cond, i32 %A, i32 %B\n"
991+
" udiv i32 1, %C"
992+
" ret void\n"
993+
"}\n");
994+
// If A is poison, B is also poison, and therefore C is poison regardless of
995+
// the value of %Cond.
996+
EXPECT_EQ(programUndefinedIfPoison(A), true);
997+
}
998+
985999
TEST_F(ValueTrackingTest, programUndefinedIfUndefOrPoison) {
9861000
parseAssembly("declare i32 @any_num()"
9871001
"define void @test(i32 %mask) {\n"

0 commit comments

Comments
 (0)