diff options
author | Florian Hahn <flo@fhahn.com> | 2022-12-19 11:47:51 +0000 |
---|---|---|
committer | Florian Hahn <flo@fhahn.com> | 2022-12-19 11:47:51 +0000 |
commit | 8a3efcd40b48543d5b77ff9d6e0d1950847e824e (patch) | |
tree | a98a70d166d481156cc1d0b55fe228b02af2d405 /llvm/lib/Analysis/ValueTracking.cpp | |
parent | 60228733726e25d011b1f9221e005732191cc077 (diff) | |
download | llvm-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.cpp | 35 |
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; } } } |