aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
authorFlorian Hahn <flo@fhahn.com>2022-12-19 11:47:51 +0000
committerFlorian Hahn <flo@fhahn.com>2022-12-19 11:47:51 +0000
commit8a3efcd40b48543d5b77ff9d6e0d1950847e824e (patch)
treea98a70d166d481156cc1d0b55fe228b02af2d405 /llvm/lib/Analysis/ValueTracking.cpp
parent60228733726e25d011b1f9221e005732191cc077 (diff)
downloadllvm-8a3efcd40b48543d5b77ff9d6e0d1950847e824e.zip
llvm-8a3efcd40b48543d5b77ff9d6e0d1950847e824e.tar.gz
llvm-8a3efcd40b48543d5b77ff9d6e0d1950847e824e.tar.bz2
[ValueTracking] Consider single poison operands in propgatesPoison.
This patch updates propgatesPoison to take a Use as argument and propagatesPoison now returns true if the passed in operand causes the user to yield poison if the operand is poison This allows propagating poison if the condition of a select is poison. This helps improve results for programUndefinedIfUndefOrPoison. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D111643
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp35
1 files changed, 16 insertions, 19 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index dbd5d3c..36fcec9 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -5330,15 +5330,12 @@ static bool directlyImpliesPoison(const Value *ValAssumedPoison,
return false;
if (const auto *I = dyn_cast<Instruction>(V)) {
- if (propagatesPoison(cast<Operator>(I)))
- return any_of(I->operands(), [=](const Value *Op) {
- return directlyImpliesPoison(ValAssumedPoison, Op, Depth + 1);
- });
+ if (any_of(I->operands(), [=](const Use &Op) {
+ return propagatesPoison(Op) &&
+ directlyImpliesPoison(ValAssumedPoison, Op, Depth + 1);
+ }))
+ return true;
- // 'select ValAssumedPoison, _, _' is poison.
- if (const auto *SI = dyn_cast<SelectInst>(I))
- return directlyImpliesPoison(ValAssumedPoison, SI->getCondition(),
- Depth + 1);
// V = extractvalue V0, idx
// V2 = extractvalue V0, idx2
// V0's elements are all poison or not. (e.g., add_with_overflow)
@@ -5496,7 +5493,8 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
else if (PoisonOnly && isa<Operator>(Cond)) {
// For poison, we can analyze further
auto *Opr = cast<Operator>(Cond);
- if (propagatesPoison(Opr) && is_contained(Opr->operand_values(), V))
+ if (any_of(Opr->operands(),
+ [V](const Use &U) { return V == U && propagatesPoison(U); }))
return true;
}
}
@@ -5618,13 +5616,15 @@ bool llvm::isGuaranteedToExecuteForEveryIteration(const Instruction *I,
llvm_unreachable("Instruction not contained in its own parent basic block.");
}
-bool llvm::propagatesPoison(const Operator *I) {
+bool llvm::propagatesPoison(const Use &PoisonOp) {
+ const Operator *I = cast<Operator>(PoisonOp.getUser());
switch (I->getOpcode()) {
case Instruction::Freeze:
- case Instruction::Select:
case Instruction::PHI:
case Instruction::Invoke:
return false;
+ case Instruction::Select:
+ return PoisonOp.getOperandNo() == 0;
case Instruction::Call:
if (auto *II = dyn_cast<IntrinsicInst>(I)) {
switch (II->getIntrinsicID()) {
@@ -5805,14 +5805,11 @@ static bool programUndefinedIfUndefOrPoison(const Value *V,
if (!isGuaranteedToTransferExecutionToSuccessor(&I))
return false;
- // If this instruction propagates poison, mark it as poison if any of
- // its operands are poison
- if (propagatesPoison(cast<Operator>(&I))) {
- for (const Value *Op : I.operands()) {
- if (YieldsPoison.count(Op)) {
- YieldsPoison.insert(&I);
- break;
- }
+ // If an operand is poison and propagates it, mark I as yielding poison.
+ for (const Use &Op : I.operands()) {
+ if (YieldsPoison.count(Op) && propagatesPoison(Op)) {
+ YieldsPoison.insert(&I);
+ break;
}
}
}