aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Analysis/ValueTracking.cpp126
1 files changed, 74 insertions, 52 deletions
diff --git a/contrib/llvm-project/llvm/lib/Analysis/ValueTracking.cpp b/contrib/llvm-project/llvm/lib/Analysis/ValueTracking.cpp
index 9ae05a4b5ccc..cac2602d455f 100644
--- a/contrib/llvm-project/llvm/lib/Analysis/ValueTracking.cpp
+++ b/contrib/llvm-project/llvm/lib/Analysis/ValueTracking.cpp
@@ -1826,6 +1826,8 @@ void computeKnownBits(const Value *V, const APInt &DemandedElts,
Known.Zero &= ~Elt;
Known.One &= Elt;
}
+ if (Known.hasConflict())
+ Known.resetAll();
return;
}
@@ -1849,6 +1851,8 @@ void computeKnownBits(const Value *V, const APInt &DemandedElts,
Known.Zero &= ~Elt;
Known.One &= Elt;
}
+ if (Known.hasConflict())
+ Known.resetAll();
return;
}
@@ -2368,19 +2372,12 @@ static bool isNonZeroAdd(const APInt &DemandedElts, unsigned Depth,
static bool isNonZeroSub(const APInt &DemandedElts, unsigned Depth,
const SimplifyQuery &Q, unsigned BitWidth, Value *X,
Value *Y) {
+ // TODO: Move this case into isKnownNonEqual().
if (auto *C = dyn_cast<Constant>(X))
if (C->isNullValue() && isKnownNonZero(Y, DemandedElts, Depth, Q))
return true;
- KnownBits XKnown = computeKnownBits(X, DemandedElts, Depth, Q);
- if (XKnown.isUnknown())
- return false;
- KnownBits YKnown = computeKnownBits(Y, DemandedElts, Depth, Q);
- // If X != Y then X - Y is non zero.
- std::optional<bool> ne = KnownBits::ne(XKnown, YKnown);
- // If we are unable to compute if X != Y, we won't be able to do anything
- // computing the knownbits of the sub expression so just return here.
- return ne && *ne;
+ return ::isKnownNonEqual(X, Y, Depth, Q);
}
static bool isNonZeroShift(const Operator *I, const APInt &DemandedElts,
@@ -3191,11 +3188,12 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
// Are any known bits in V1 contradictory to known bits in V2? If V1
// has a known zero where V2 has a known one, they must not be equal.
KnownBits Known1 = computeKnownBits(V1, Depth, Q);
- KnownBits Known2 = computeKnownBits(V2, Depth, Q);
-
- if (Known1.Zero.intersects(Known2.One) ||
- Known2.Zero.intersects(Known1.One))
- return true;
+ if (!Known1.isUnknown()) {
+ KnownBits Known2 = computeKnownBits(V2, Depth, Q);
+ if (Known1.Zero.intersects(Known2.One) ||
+ Known2.Zero.intersects(Known1.One))
+ return true;
+ }
}
if (isNonEqualSelect(V1, V2, Depth, Q) || isNonEqualSelect(V2, V1, Depth, Q))
@@ -3205,6 +3203,13 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
isNonEqualPointersWithRecursiveGEP(V2, V1, Q))
return true;
+ Value *A, *B;
+ // PtrToInts are NonEqual if their Ptrs are NonEqual.
+ // Check PtrToInt type matches the pointer size.
+ if (match(V1, m_PtrToIntSameSize(Q.DL, m_Value(A))) &&
+ match(V2, m_PtrToIntSameSize(Q.DL, m_Value(B))))
+ return isKnownNonEqual(A, B, Depth + 1, Q);
+
return false;
}
@@ -6284,10 +6289,10 @@ static OverflowResult mapOverflowResult(ConstantRange::OverflowResult OR) {
}
/// Combine constant ranges from computeConstantRange() and computeKnownBits().
-static ConstantRange
-computeConstantRangeIncludingKnownBits(const WithCache<const Value *> &V,
- bool ForSigned,
- const SimplifyQuery &SQ) {
+ConstantRange
+llvm::computeConstantRangeIncludingKnownBits(const WithCache<const Value *> &V,
+ bool ForSigned,
+ const SimplifyQuery &SQ) {
ConstantRange CR1 =
ConstantRange::fromKnownBits(V.getKnownBits(SQ), ForSigned);
ConstantRange CR2 = computeConstantRange(V, ForSigned, SQ.IIQ.UseInstrInfo);
@@ -6555,10 +6560,25 @@ static bool shiftAmountKnownInRange(const Value *ShiftAmount) {
return Safe;
}
-static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
+enum class UndefPoisonKind {
+ PoisonOnly = (1 << 0),
+ UndefOnly = (1 << 1),
+ UndefOrPoison = PoisonOnly | UndefOnly,
+};
+
+static bool includesPoison(UndefPoisonKind Kind) {
+ return (unsigned(Kind) & unsigned(UndefPoisonKind::PoisonOnly)) != 0;
+}
+
+static bool includesUndef(UndefPoisonKind Kind) {
+ return (unsigned(Kind) & unsigned(UndefPoisonKind::UndefOnly)) != 0;
+}
+
+static bool canCreateUndefOrPoison(const Operator *Op, UndefPoisonKind Kind,
bool ConsiderFlagsAndMetadata) {
- if (ConsiderFlagsAndMetadata && Op->hasPoisonGeneratingFlagsOrMetadata())
+ if (ConsiderFlagsAndMetadata && includesPoison(Kind) &&
+ Op->hasPoisonGeneratingFlagsOrMetadata())
return true;
unsigned Opcode = Op->getOpcode();
@@ -6568,7 +6588,7 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
case Instruction::Shl:
case Instruction::AShr:
case Instruction::LShr:
- return !shiftAmountKnownInRange(Op->getOperand(1));
+ return includesPoison(Kind) && !shiftAmountKnownInRange(Op->getOperand(1));
case Instruction::FPToSI:
case Instruction::FPToUI:
// fptosi/ui yields poison if the resulting value does not fit in the
@@ -6609,7 +6629,8 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
return false;
case Intrinsic::sshl_sat:
case Intrinsic::ushl_sat:
- return !shiftAmountKnownInRange(II->getArgOperand(1));
+ return includesPoison(Kind) &&
+ !shiftAmountKnownInRange(II->getArgOperand(1));
case Intrinsic::fma:
case Intrinsic::fmuladd:
case Intrinsic::sqrt:
@@ -6664,18 +6685,16 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
auto *VTy = cast<VectorType>(Op->getOperand(0)->getType());
unsigned IdxOp = Op->getOpcode() == Instruction::InsertElement ? 2 : 1;
auto *Idx = dyn_cast<ConstantInt>(Op->getOperand(IdxOp));
- if (!Idx || Idx->getValue().uge(VTy->getElementCount().getKnownMinValue()))
- return true;
+ if (includesPoison(Kind))
+ return !Idx ||
+ Idx->getValue().uge(VTy->getElementCount().getKnownMinValue());
return false;
}
case Instruction::ShuffleVector: {
- // shufflevector may return undef.
- if (PoisonOnly)
- return false;
ArrayRef<int> Mask = isa<ConstantExpr>(Op)
? cast<ConstantExpr>(Op)->getShuffleMask()
: cast<ShuffleVectorInst>(Op)->getShuffleMask();
- return is_contained(Mask, PoisonMaskElem);
+ return includesPoison(Kind) && is_contained(Mask, PoisonMaskElem);
}
case Instruction::FNeg:
case Instruction::PHI:
@@ -6711,17 +6730,17 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
bool llvm::canCreateUndefOrPoison(const Operator *Op,
bool ConsiderFlagsAndMetadata) {
- return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/false,
+ return ::canCreateUndefOrPoison(Op, UndefPoisonKind::UndefOrPoison,
ConsiderFlagsAndMetadata);
}
bool llvm::canCreatePoison(const Operator *Op, bool ConsiderFlagsAndMetadata) {
- return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/true,
+ return ::canCreateUndefOrPoison(Op, UndefPoisonKind::PoisonOnly,
ConsiderFlagsAndMetadata);
}
-static bool directlyImpliesPoison(const Value *ValAssumedPoison,
- const Value *V, unsigned Depth) {
+static bool directlyImpliesPoison(const Value *ValAssumedPoison, const Value *V,
+ unsigned Depth) {
if (ValAssumedPoison == V)
return true;
@@ -6773,14 +6792,11 @@ bool llvm::impliesPoison(const Value *ValAssumedPoison, const Value *V) {
return ::impliesPoison(ValAssumedPoison, V, /* Depth */ 0);
}
-static bool programUndefinedIfUndefOrPoison(const Value *V,
- bool PoisonOnly);
+static bool programUndefinedIfUndefOrPoison(const Value *V, bool PoisonOnly);
-static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
- AssumptionCache *AC,
- const Instruction *CtxI,
- const DominatorTree *DT,
- unsigned Depth, bool PoisonOnly) {
+static bool isGuaranteedNotToBeUndefOrPoison(
+ const Value *V, AssumptionCache *AC, const Instruction *CtxI,
+ const DominatorTree *DT, unsigned Depth, UndefPoisonKind Kind) {
if (Depth >= MaxAnalysisRecursionDepth)
return false;
@@ -6795,16 +6811,19 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
}
if (auto *C = dyn_cast<Constant>(V)) {
+ if (isa<PoisonValue>(C))
+ return !includesPoison(Kind);
+
if (isa<UndefValue>(C))
- return PoisonOnly && !isa<PoisonValue>(C);
+ return !includesUndef(Kind);
if (isa<ConstantInt>(C) || isa<GlobalVariable>(C) || isa<ConstantFP>(V) ||
isa<ConstantPointerNull>(C) || isa<Function>(C))
return true;
if (C->getType()->isVectorTy() && !isa<ConstantExpr>(C))
- return (PoisonOnly ? !C->containsPoisonElement()
- : !C->containsUndefOrPoisonElement()) &&
+ return (!includesUndef(Kind) ? !C->containsPoisonElement()
+ : !C->containsUndefOrPoisonElement()) &&
!C->containsConstantExpression();
}
@@ -6822,8 +6841,7 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
return true;
auto OpCheck = [&](const Value *V) {
- return isGuaranteedNotToBeUndefOrPoison(V, AC, CtxI, DT, Depth + 1,
- PoisonOnly);
+ return isGuaranteedNotToBeUndefOrPoison(V, AC, CtxI, DT, Depth + 1, Kind);
};
if (auto *Opr = dyn_cast<Operator>(V)) {
@@ -6845,14 +6863,16 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
for (unsigned i = 0; i < Num; ++i) {
auto *TI = PN->getIncomingBlock(i)->getTerminator();
if (!isGuaranteedNotToBeUndefOrPoison(PN->getIncomingValue(i), AC, TI,
- DT, Depth + 1, PoisonOnly)) {
+ DT, Depth + 1, Kind)) {
IsWellDefined = false;
break;
}
}
if (IsWellDefined)
return true;
- } else if (!canCreateUndefOrPoison(Opr) && all_of(Opr->operands(), OpCheck))
+ } else if (!::canCreateUndefOrPoison(Opr, Kind,
+ /*ConsiderFlagsAndMetadata*/ true) &&
+ all_of(Opr->operands(), OpCheck))
return true;
}
@@ -6862,7 +6882,7 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
I->hasMetadata(LLVMContext::MD_dereferenceable_or_null))
return true;
- if (programUndefinedIfUndefOrPoison(V, PoisonOnly))
+ if (programUndefinedIfUndefOrPoison(V, !includesUndef(Kind)))
return true;
// CxtI may be null or a cloned instruction.
@@ -6894,7 +6914,7 @@ static bool isGuaranteedNotToBeUndefOrPoison(const Value *V,
if (Cond) {
if (Cond == V)
return true;
- else if (PoisonOnly && isa<Operator>(Cond)) {
+ else if (!includesUndef(Kind) && isa<Operator>(Cond)) {
// For poison, we can analyze further
auto *Opr = cast<Operator>(Cond);
if (any_of(Opr->operands(),
@@ -6916,20 +6936,22 @@ bool llvm::isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC,
const Instruction *CtxI,
const DominatorTree *DT,
unsigned Depth) {
- return ::isGuaranteedNotToBeUndefOrPoison(V, AC, CtxI, DT, Depth, false);
+ return ::isGuaranteedNotToBeUndefOrPoison(V, AC, CtxI, DT, Depth,
+ UndefPoisonKind::UndefOrPoison);
}
bool llvm::isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC,
const Instruction *CtxI,
const DominatorTree *DT, unsigned Depth) {
- return ::isGuaranteedNotToBeUndefOrPoison(V, AC, CtxI, DT, Depth, true);
+ return ::isGuaranteedNotToBeUndefOrPoison(V, AC, CtxI, DT, Depth,
+ UndefPoisonKind::PoisonOnly);
}
bool llvm::isGuaranteedNotToBeUndef(const Value *V, AssumptionCache *AC,
const Instruction *CtxI,
const DominatorTree *DT, unsigned Depth) {
- // TODO: This is currently equivalent to isGuaranteedNotToBeUndefOrPoison().
- return ::isGuaranteedNotToBeUndefOrPoison(V, AC, CtxI, DT, Depth, false);
+ return ::isGuaranteedNotToBeUndefOrPoison(V, AC, CtxI, DT, Depth,
+ UndefPoisonKind::UndefOnly);
}
/// Return true if undefined behavior would provably be executed on the path to