Skip to content

Commit 425cbbc

Browse files
committed
[Operator] Add hasPoisonGeneratingFlags [mostly NFC]
This method parallels the dropPoisonGeneratingFlags on Instruction, but is hoisted to operator to handle constant expressions as well. This is mostly code movement, but I did go ahead and add the inrange constexpr gep case. This had been discussed previously, but apparently never followed up o.
1 parent f06e332 commit 425cbbc

File tree

4 files changed

+35
-13
lines changed

4 files changed

+35
-13
lines changed

llvm/include/llvm/IR/Operator.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ class Operator : public User {
5959
static bool classof(const Value *V) {
6060
return isa<Instruction>(V) || isa<ConstantExpr>(V);
6161
}
62+
63+
/// Return true if this operator has flags which may cause this operator
64+
/// to evaluate to poison despite having non-poison inputs.
65+
bool hasPoisonGeneratingFlags() const;
6266
};
6367

6468
/// Utility class for integer operators which may exhibit overflow - Add, Sub,

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4963,19 +4963,9 @@ bool llvm::isOverflowIntrinsicNoWrap(const WithOverflowInst *WO,
49634963

49644964
static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
49654965
bool ConsiderFlags) {
4966-
if (ConsiderFlags) {
4967-
// See whether I has flags that may create poison
4968-
if (const auto *OvOp = dyn_cast<OverflowingBinaryOperator>(Op)) {
4969-
if (OvOp->hasNoSignedWrap() || OvOp->hasNoUnsignedWrap())
4970-
return true;
4971-
}
4972-
if (const auto *ExactOp = dyn_cast<PossiblyExactOperator>(Op))
4973-
if (ExactOp->isExact())
4974-
return true;
4975-
if (const auto *GEP = dyn_cast<GEPOperator>(Op))
4976-
if (GEP->isInBounds())
4977-
return true;
4978-
}
4966+
4967+
if (ConsiderFlags && Op->hasPoisonGeneratingFlags())
4968+
return true;
49794969

49804970
// TODO: this should really be under the ConsiderFlags block, but currently
49814971
// these are not dropped by dropPoisonGeneratingFlags

llvm/lib/IR/Instruction.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ void Instruction::dropPoisonGeneratingFlags() {
163163
break;
164164
}
165165
// TODO: FastMathFlags!
166+
167+
assert(!cast<Operator>(this)->hasPoisonGeneratingFlags() &&
168+
"must be kept in sync");
166169
}
167170

168171
void Instruction::dropUndefImplyingAttrsAndUnknownMetadata(

llvm/lib/IR/Operator.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,31 @@
1919
#include "ConstantsContext.h"
2020

2121
namespace llvm {
22+
bool Operator::hasPoisonGeneratingFlags() const {
23+
switch (getOpcode()) {
24+
case Instruction::Add:
25+
case Instruction::Sub:
26+
case Instruction::Mul:
27+
case Instruction::Shl: {
28+
auto *OBO = cast<OverflowingBinaryOperator>(this);
29+
return OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap();
30+
}
31+
case Instruction::UDiv:
32+
case Instruction::SDiv:
33+
case Instruction::AShr:
34+
case Instruction::LShr:
35+
return cast<PossiblyExactOperator>(this)->isExact();
36+
case Instruction::GetElementPtr: {
37+
auto *GEP = cast<GEPOperator>(this);
38+
// Note: inrange exists on constexpr only
39+
return GEP->isInBounds() || GEP->getInRangeIndex() != None;
40+
}
41+
default:
42+
return false;
43+
}
44+
// TODO: FastMathFlags! (On instructions, but not constexpr)
45+
}
46+
2247
Type *GEPOperator::getSourceElementType() const {
2348
if (auto *I = dyn_cast<GetElementPtrInst>(this))
2449
return I->getSourceElementType();

0 commit comments

Comments
 (0)