aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp1001
1 files changed, 597 insertions, 404 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 2dd671b4ab9e..a13bdade320f 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -15,8 +15,6 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
@@ -34,6 +32,7 @@
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
@@ -73,6 +72,7 @@
#include <algorithm>
#include <cassert>
#include <cstdint>
+#include <optional>
#include <utility>
using namespace llvm;
@@ -83,15 +83,6 @@ using namespace llvm::PatternMatch;
static cl::opt<unsigned> DomConditionsMaxUses("dom-conditions-max-uses",
cl::Hidden, cl::init(20));
-// According to the LangRef, branching on a poison condition is absolutely
-// immediate full UB. However, historically we haven't implemented that
-// consistently as we had an important transformation (non-trivial unswitch)
-// which introduced instances of branch on poison/undef to otherwise well
-// defined programs. This issue has since been fixed, but the flag is
-// temporarily retained to easily diagnose potential regressions.
-static cl::opt<bool> BranchOnPoisonAsUB("branch-on-poison-as-ub",
- cl::Hidden, cl::init(true));
-
/// Returns the bitwidth of the given scalar or pointer type. For vector types,
/// returns the element type's bitwidth.
@@ -166,39 +157,16 @@ static const Instruction *safeCxtI(const Value *V1, const Value *V2, const Instr
static bool getShuffleDemandedElts(const ShuffleVectorInst *Shuf,
const APInt &DemandedElts,
APInt &DemandedLHS, APInt &DemandedRHS) {
- // The length of scalable vectors is unknown at compile time, thus we
- // cannot check their values
- if (isa<ScalableVectorType>(Shuf->getType()))
- return false;
-
- int NumElts =
- cast<FixedVectorType>(Shuf->getOperand(0)->getType())->getNumElements();
- int NumMaskElts = cast<FixedVectorType>(Shuf->getType())->getNumElements();
- DemandedLHS = DemandedRHS = APInt::getZero(NumElts);
- if (DemandedElts.isZero())
- return true;
- // Simple case of a shuffle with zeroinitializer.
- if (all_of(Shuf->getShuffleMask(), [](int Elt) { return Elt == 0; })) {
- DemandedLHS.setBit(0);
+ if (isa<ScalableVectorType>(Shuf->getType())) {
+ assert(DemandedElts == APInt(1,1));
+ DemandedLHS = DemandedRHS = DemandedElts;
return true;
}
- for (int i = 0; i != NumMaskElts; ++i) {
- if (!DemandedElts[i])
- continue;
- int M = Shuf->getMaskValue(i);
- assert(M < (NumElts * 2) && "Invalid shuffle mask constant");
-
- // For undef elements, we don't know anything about the common state of
- // the shuffle result.
- if (M == -1)
- return false;
- if (M < NumElts)
- DemandedLHS.setBit(M % NumElts);
- else
- DemandedRHS.setBit(M % NumElts);
- }
- return true;
+ int NumElts =
+ cast<FixedVectorType>(Shuf->getOperand(0)->getType())->getNumElements();
+ return llvm::getShuffleDemandedElts(NumElts, Shuf->getShuffleMask(),
+ DemandedElts, DemandedLHS, DemandedRHS);
}
static void computeKnownBits(const Value *V, const APInt &DemandedElts,
@@ -206,13 +174,9 @@ static void computeKnownBits(const Value *V, const APInt &DemandedElts,
static void computeKnownBits(const Value *V, KnownBits &Known, unsigned Depth,
const Query &Q) {
- // FIXME: We currently have no way to represent the DemandedElts of a scalable
- // vector
- if (isa<ScalableVectorType>(V->getType())) {
- Known.resetAll();
- return;
- }
-
+ // Since the number of lanes in a scalable vector is unknown at compile time,
+ // we track one bit which is implicitly broadcast to all lanes. This means
+ // that all lanes in a scalable vector are considered demanded.
auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
APInt DemandedElts =
FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
@@ -296,6 +260,15 @@ bool llvm::haveNoCommonBitsSet(const Value *LHS, const Value *RHS,
match(LHS, m_c_Xor(m_c_And(m_Specific(RHS), m_Value(Y)), m_Deferred(Y))))
return true;
+ // Peek through extends to find a 'not' of the other side:
+ // (ext Y) op ext(~Y)
+ // (ext ~Y) op ext(Y)
+ if ((match(LHS, m_ZExtOrSExt(m_Value(Y))) &&
+ match(RHS, m_ZExtOrSExt(m_Not(m_Specific(Y))))) ||
+ (match(RHS, m_ZExtOrSExt(m_Value(Y))) &&
+ match(LHS, m_ZExtOrSExt(m_Not(m_Specific(Y))))))
+ return true;
+
// Look for: (A & B) op ~(A | B)
{
Value *A, *B;
@@ -401,11 +374,6 @@ static unsigned ComputeNumSignBits(const Value *V, const APInt &DemandedElts,
static unsigned ComputeNumSignBits(const Value *V, unsigned Depth,
const Query &Q) {
- // FIXME: We currently have no way to represent the DemandedElts of a scalable
- // vector
- if (isa<ScalableVectorType>(V->getType()))
- return 1;
-
auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
APInt DemandedElts =
FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
@@ -648,7 +616,7 @@ static bool isKnownNonZeroFromAssume(const Value *V, const Query &Q) {
for (auto &AssumeVH : Q.AC->assumptionsFor(V)) {
if (!AssumeVH)
continue;
- CallInst *I = cast<CallInst>(AssumeVH);
+ CondGuardInst *I = cast<CondGuardInst>(AssumeVH);
assert(I->getFunction() == Q.CxtI->getFunction() &&
"Got assumption for the wrong function!");
@@ -656,9 +624,6 @@ static bool isKnownNonZeroFromAssume(const Value *V, const Query &Q) {
// We're running this loop for once for each value queried resulting in a
// runtime of ~O(#assumes * #values).
- assert(I->getCalledFunction()->getIntrinsicID() == Intrinsic::assume &&
- "must be an assume intrinsic");
-
Value *RHS;
CmpInst::Predicate Pred;
auto m_V = m_CombineOr(m_Specific(V), m_PtrToInt(m_Specific(V)));
@@ -696,7 +661,7 @@ static void computeKnownBitsFromAssume(const Value *V, KnownBits &Known,
for (auto &AssumeVH : Q.AC->assumptionsFor(V)) {
if (!AssumeVH)
continue;
- CallInst *I = cast<CallInst>(AssumeVH);
+ CondGuardInst *I = cast<CondGuardInst>(AssumeVH);
assert(I->getParent()->getParent() == Q.CxtI->getParent()->getParent() &&
"Got assumption for the wrong function!");
@@ -704,9 +669,6 @@ static void computeKnownBitsFromAssume(const Value *V, KnownBits &Known,
// We're running this loop for once for each value queried resulting in a
// runtime of ~O(#assumes * #values).
- assert(I->getCalledFunction()->getIntrinsicID() == Intrinsic::assume &&
- "must be an assume intrinsic");
-
Value *Arg = I->getArgOperand(0);
if (Arg == V && isValidAssumeForContext(I, Q.CxtI, Q.DT)) {
@@ -972,6 +934,14 @@ static void computeKnownBitsFromAssume(const Value *V, KnownBits &Known,
Known.Zero.setHighBits(RHSKnown.countMinLeadingZeros());
}
break;
+ case ICmpInst::ICMP_NE: {
+ // assume (v & b != 0) where b is a power of 2
+ const APInt *BPow2;
+ if (match(Cmp, m_ICmp(Pred, m_c_And(m_V, m_Power2(BPow2)), m_Zero())) &&
+ isValidAssumeForContext(I, Q.CxtI, Q.DT)) {
+ Known.One |= BPow2->zextOrTrunc(BitWidth);
+ }
+ } break;
}
}
@@ -1047,7 +1017,7 @@ static void computeKnownBitsFromShiftOperator(
// If we know the shifter operand is nonzero, we can sometimes infer more
// known bits. However this is expensive to compute, so be lazy about it and
// only compute it when absolutely necessary.
- Optional<bool> ShifterOperandIsNonZero;
+ std::optional<bool> ShifterOperandIsNonZero;
// Early exit if we can't constrain any well-defined shift amount.
if (!(ShiftAmtKZ & (PowerOf2Ceil(BitWidth) - 1)) &&
@@ -1200,7 +1170,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
case Instruction::PtrToInt:
case Instruction::IntToPtr:
// Fall through and handle them the same as zext/trunc.
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case Instruction::ZExt:
case Instruction::Trunc: {
Type *SrcTy = I->getOperand(0)->getType();
@@ -1232,7 +1202,8 @@ static void computeKnownBitsFromOperator(const Operator *I,
// Handle cast from vector integer type to scalar or vector integer.
auto *SrcVecTy = dyn_cast<FixedVectorType>(SrcTy);
if (!SrcVecTy || !SrcVecTy->getElementType()->isIntegerTy() ||
- !I->getType()->isIntOrIntVectorTy())
+ !I->getType()->isIntOrIntVectorTy() ||
+ isa<ScalableVectorType>(I->getType()))
break;
// Look through a cast from narrow vector elements to wider type.
@@ -1398,7 +1369,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
KnownBits IndexBits(IndexBitWidth);
computeKnownBits(Index, IndexBits, Depth + 1, Q);
TypeSize IndexTypeSize = Q.DL.getTypeAllocSize(IndexedTy);
- uint64_t TypeSizeInBytes = IndexTypeSize.getKnownMinSize();
+ uint64_t TypeSizeInBytes = IndexTypeSize.getKnownMinValue();
KnownBits ScalingFactor(IndexBitWidth);
// Multiply by current sizeof type.
// &A[i] == A + i * sizeof(*A[i]).
@@ -1575,9 +1546,45 @@ static void computeKnownBitsFromOperator(const Operator *I,
RecQ.CxtI = P->getIncomingBlock(u)->getTerminator();
Known2 = KnownBits(BitWidth);
+
// Recurse, but cap the recursion to one level, because we don't
// want to waste time spinning around in loops.
computeKnownBits(IncValue, Known2, MaxAnalysisRecursionDepth - 1, RecQ);
+
+ // If this failed, see if we can use a conditional branch into the phi
+ // to help us determine the range of the value.
+ if (Known2.isUnknown()) {
+ ICmpInst::Predicate Pred;
+ const APInt *RHSC;
+ BasicBlock *TrueSucc, *FalseSucc;
+ // TODO: Use RHS Value and compute range from its known bits.
+ if (match(RecQ.CxtI,
+ m_Br(m_c_ICmp(Pred, m_Specific(IncValue), m_APInt(RHSC)),
+ m_BasicBlock(TrueSucc), m_BasicBlock(FalseSucc)))) {
+ // Check for cases of duplicate successors.
+ if ((TrueSucc == P->getParent()) != (FalseSucc == P->getParent())) {
+ // If we're using the false successor, invert the predicate.
+ if (FalseSucc == P->getParent())
+ Pred = CmpInst::getInversePredicate(Pred);
+
+ switch (Pred) {
+ case CmpInst::Predicate::ICMP_EQ:
+ Known2 = KnownBits::makeConstant(*RHSC);
+ break;
+ case CmpInst::Predicate::ICMP_ULE:
+ Known2.Zero.setHighBits(RHSC->countLeadingZeros());
+ break;
+ case CmpInst::Predicate::ICMP_ULT:
+ Known2.Zero.setHighBits((*RHSC - 1).countLeadingZeros());
+ break;
+ default:
+ // TODO - add additional integer predicate handling.
+ break;
+ }
+ }
+ }
+ }
+
Known = KnownBits::commonBits(Known, Known2);
// If all bits have been ruled out, there's no need to check
// more operands.
@@ -1626,7 +1633,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
// If this call is poison for 0 input, the result will be less than 2^n.
if (II->getArgOperand(1) == ConstantInt::getTrue(II->getContext()))
PossibleLZ = std::min(PossibleLZ, BitWidth - 1);
- unsigned LowBits = Log2_32(PossibleLZ)+1;
+ unsigned LowBits = llvm::bit_width(PossibleLZ);
Known.Zero.setBitsFrom(LowBits);
break;
}
@@ -1637,7 +1644,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
// If this call is poison for 0 input, the result will be less than 2^n.
if (II->getArgOperand(1) == ConstantInt::getTrue(II->getContext()))
PossibleTZ = std::min(PossibleTZ, BitWidth - 1);
- unsigned LowBits = Log2_32(PossibleTZ)+1;
+ unsigned LowBits = llvm::bit_width(PossibleTZ);
Known.Zero.setBitsFrom(LowBits);
break;
}
@@ -1646,7 +1653,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
// We can bound the space the count needs. Also, bits known to be zero
// can't contribute to the population.
unsigned BitsPossiblySet = Known2.countMaxPopulation();
- unsigned LowBits = Log2_32(BitsPossiblySet)+1;
+ unsigned LowBits = llvm::bit_width(BitsPossiblySet);
Known.Zero.setBitsFrom(LowBits);
// TODO: we could bound KnownOne using the lower bound on the number
// of bits which might be set provided by popcnt KnownOne2.
@@ -1740,7 +1747,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
break;
auto Attr = II->getFunction()->getFnAttribute(Attribute::VScaleRange);
- Optional<unsigned> VScaleMax = Attr.getVScaleRangeMax();
+ std::optional<unsigned> VScaleMax = Attr.getVScaleRangeMax();
if (!VScaleMax)
break;
@@ -1756,7 +1763,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
break;
}
- unsigned FirstZeroHighBit = 32 - countLeadingZeros(*VScaleMax);
+ unsigned FirstZeroHighBit = llvm::bit_width(*VScaleMax);
if (FirstZeroHighBit < BitWidth)
Known.Zero.setBitsFrom(FirstZeroHighBit);
@@ -1796,6 +1803,10 @@ static void computeKnownBitsFromOperator(const Operator *I,
break;
}
case Instruction::InsertElement: {
+ if (isa<ScalableVectorType>(I->getType())) {
+ Known.resetAll();
+ return;
+ }
const Value *Vec = I->getOperand(0);
const Value *Elt = I->getOperand(1);
auto *CIdx = dyn_cast<ConstantInt>(I->getOperand(2));
@@ -1912,9 +1923,8 @@ KnownBits computeKnownBits(const Value *V, unsigned Depth, const Query &Q) {
/// for all of the demanded elements in the vector specified by DemandedElts.
void computeKnownBits(const Value *V, const APInt &DemandedElts,
KnownBits &Known, unsigned Depth, const Query &Q) {
- if (!DemandedElts || isa<ScalableVectorType>(V->getType())) {
- // No demanded elts or V is a scalable vector, better to assume we don't
- // know anything.
+ if (!DemandedElts) {
+ // No demanded elts, better to assume we don't know anything.
Known.resetAll();
return;
}
@@ -1935,7 +1945,7 @@ void computeKnownBits(const Value *V, const APInt &DemandedElts,
"DemandedElt width should equal the fixed vector number of elements");
} else {
assert(DemandedElts == APInt(1, 1) &&
- "DemandedElt width should be 1 for scalars");
+ "DemandedElt width should be 1 for scalars or scalable vectors");
}
Type *ScalarTy = Ty->getScalarType();
@@ -1962,6 +1972,7 @@ void computeKnownBits(const Value *V, const APInt &DemandedElts,
// Handle a constant vector by taking the intersection of the known bits of
// each element.
if (const ConstantDataVector *CDV = dyn_cast<ConstantDataVector>(V)) {
+ assert(!isa<ScalableVectorType>(V->getType()));
// We know that CDV must be a vector of integers. Take the intersection of
// each element.
Known.Zero.setAllBits(); Known.One.setAllBits();
@@ -1976,6 +1987,7 @@ void computeKnownBits(const Value *V, const APInt &DemandedElts,
}
if (const auto *CV = dyn_cast<ConstantVector>(V)) {
+ assert(!isa<ScalableVectorType>(V->getType()));
// We know that CV must be a vector of integers. Take the intersection of
// each element.
Known.Zero.setAllBits(); Known.One.setAllBits();
@@ -2073,7 +2085,7 @@ static bool isPowerOfTwoRecurrence(const PHINode *PN, bool OrZero,
// power of two is not sufficient, and it has to be a constant.
if (!match(Start, m_Power2()) || match(Start, m_SignMask()))
return false;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case Instruction::UDiv:
// Divisor must be a power of two.
// If OrZero is false, cannot guarantee induction variable is non-zero after
@@ -2085,7 +2097,7 @@ static bool isPowerOfTwoRecurrence(const PHINode *PN, bool OrZero,
case Instruction::AShr:
if (!match(Start, m_Power2()) || match(Start, m_SignMask()))
return false;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case Instruction::LShr:
return OrZero || Q.IIQ.isExact(BO);
default:
@@ -2261,7 +2273,7 @@ static bool isGEPKnownNonNull(const GEPOperator *GEP, unsigned Depth,
}
// If we have a zero-sized type, the index doesn't matter. Keep looping.
- if (Q.DL.getTypeAllocSize(GTI.getIndexedType()).getKnownMinSize() == 0)
+ if (Q.DL.getTypeAllocSize(GTI.getIndexedType()).isZero())
continue;
// Fast path the constant operand case both for efficiency and so we don't
@@ -2433,10 +2445,20 @@ static bool isNonZeroRecurrence(const PHINode *PN) {
/// Supports values with integer or pointer type and vectors of integers.
bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
const Query &Q) {
- // FIXME: We currently have no way to represent the DemandedElts of a scalable
- // vector
- if (isa<ScalableVectorType>(V->getType()))
- return false;
+
+#ifndef NDEBUG
+ Type *Ty = V->getType();
+ assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
+
+ if (auto *FVTy = dyn_cast<FixedVectorType>(Ty)) {
+ assert(
+ FVTy->getNumElements() == DemandedElts.getBitWidth() &&
+ "DemandedElt width should equal the fixed vector number of elements");
+ } else {
+ assert(DemandedElts == APInt(1, 1) &&
+ "DemandedElt width should be 1 for scalars");
+ }
+#endif
if (auto *C = dyn_cast<Constant>(V)) {
if (C->isNullValue())
@@ -2445,16 +2467,6 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
// Must be non-zero due to null test above.
return true;
- if (auto *CE = dyn_cast<ConstantExpr>(C)) {
- // See the comment for IntToPtr/PtrToInt instructions below.
- if (CE->getOpcode() == Instruction::IntToPtr ||
- CE->getOpcode() == Instruction::PtrToInt)
- if (Q.DL.getTypeSizeInBits(CE->getOperand(0)->getType())
- .getFixedSize() <=
- Q.DL.getTypeSizeInBits(CE->getType()).getFixedSize())
- return isKnownNonZero(CE->getOperand(0), Depth, Q);
- }
-
// For constant vectors, check that all elements are undefined or known
// non-zero to determine that the whole vector is known non-zero.
if (auto *VecTy = dyn_cast<FixedVectorType>(C->getType())) {
@@ -2477,7 +2489,10 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
if (!GV->isAbsoluteSymbolRef() && !GV->hasExternalWeakLinkage() &&
GV->getType()->getAddressSpace() == 0)
return true;
- } else
+ }
+
+ // For constant expressions, fall through to the Operator code below.
+ if (!isa<ConstantExpr>(V))
return false;
}
@@ -2493,7 +2508,7 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
}
}
- if (isKnownNonZeroFromAssume(V, Q))
+ if (!isa<Constant>(V) && isKnownNonZeroFromAssume(V, Q))
return true;
// Some of the tests below are recursive, so bail out if we hit the limit.
@@ -2529,101 +2544,110 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
}
}
- if (isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
+ if (!isa<Constant>(V) &&
+ isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
return true;
- // Check for recursive pointer simplifications.
- if (V->getType()->isPointerTy()) {
- // Look through bitcast operations, GEPs, and int2ptr instructions as they
- // do not alter the value, or at least not the nullness property of the
- // value, e.g., int2ptr is allowed to zero/sign extend the value.
- //
+ const Operator *I = dyn_cast<Operator>(V);
+ if (!I)
+ return false;
+
+ unsigned BitWidth = getBitWidth(V->getType()->getScalarType(), Q.DL);
+ switch (I->getOpcode()) {
+ case Instruction::GetElementPtr:
+ if (I->getType()->isPointerTy())
+ return isGEPKnownNonNull(cast<GEPOperator>(I), Depth, Q);
+ break;
+ case Instruction::BitCast:
+ if (I->getType()->isPointerTy())
+ return isKnownNonZero(I->getOperand(0), Depth, Q);
+ break;
+ case Instruction::IntToPtr:
// Note that we have to take special care to avoid looking through
// truncating casts, e.g., int2ptr/ptr2int with appropriate sizes, as well
// as casts that can alter the value, e.g., AddrSpaceCasts.
- if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V))
- return isGEPKnownNonNull(GEP, Depth, Q);
-
- if (auto *BCO = dyn_cast<BitCastOperator>(V))
- return isKnownNonZero(BCO->getOperand(0), Depth, Q);
-
- if (auto *I2P = dyn_cast<IntToPtrInst>(V))
- if (Q.DL.getTypeSizeInBits(I2P->getSrcTy()).getFixedSize() <=
- Q.DL.getTypeSizeInBits(I2P->getDestTy()).getFixedSize())
- return isKnownNonZero(I2P->getOperand(0), Depth, Q);
- }
-
- // Similar to int2ptr above, we can look through ptr2int here if the cast
- // is a no-op or an extend and not a truncate.
- if (auto *P2I = dyn_cast<PtrToIntInst>(V))
- if (Q.DL.getTypeSizeInBits(P2I->getSrcTy()).getFixedSize() <=
- Q.DL.getTypeSizeInBits(P2I->getDestTy()).getFixedSize())
- return isKnownNonZero(P2I->getOperand(0), Depth, Q);
-
- unsigned BitWidth = getBitWidth(V->getType()->getScalarType(), Q.DL);
-
- // X | Y != 0 if X != 0 or Y != 0.
- Value *X = nullptr, *Y = nullptr;
- if (match(V, m_Or(m_Value(X), m_Value(Y))))
- return isKnownNonZero(X, DemandedElts, Depth, Q) ||
- isKnownNonZero(Y, DemandedElts, Depth, Q);
-
- // ext X != 0 if X != 0.
- if (isa<SExtInst>(V) || isa<ZExtInst>(V))
- return isKnownNonZero(cast<Instruction>(V)->getOperand(0), Depth, Q);
+ if (!isa<ScalableVectorType>(I->getType()) &&
+ Q.DL.getTypeSizeInBits(I->getOperand(0)->getType()).getFixedValue() <=
+ Q.DL.getTypeSizeInBits(I->getType()).getFixedValue())
+ return isKnownNonZero(I->getOperand(0), Depth, Q);
+ break;
+ case Instruction::PtrToInt:
+ // Similar to int2ptr above, we can look through ptr2int here if the cast
+ // is a no-op or an extend and not a truncate.
+ if (!isa<ScalableVectorType>(I->getType()) &&
+ Q.DL.getTypeSizeInBits(I->getOperand(0)->getType()).getFixedValue() <=
+ Q.DL.getTypeSizeInBits(I->getType()).getFixedValue())
+ return isKnownNonZero(I->getOperand(0), Depth, Q);
+ break;
+ case Instruction::Or:
+ // X | Y != 0 if X != 0 or Y != 0.
+ return isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q) ||
+ isKnownNonZero(I->getOperand(1), DemandedElts, Depth, Q);
+ case Instruction::SExt:
+ case Instruction::ZExt:
+ // ext X != 0 if X != 0.
+ return isKnownNonZero(I->getOperand(0), Depth, Q);
- // shl X, Y != 0 if X is odd. Note that the value of the shift is undefined
- // if the lowest bit is shifted off the end.
- if (match(V, m_Shl(m_Value(X), m_Value(Y)))) {
+ case Instruction::Shl: {
// shl nuw can't remove any non-zero bits.
const OverflowingBinaryOperator *BO = cast<OverflowingBinaryOperator>(V);
if (Q.IIQ.hasNoUnsignedWrap(BO))
- return isKnownNonZero(X, Depth, Q);
+ return isKnownNonZero(I->getOperand(0), Depth, Q);
+ // shl X, Y != 0 if X is odd. Note that the value of the shift is undefined
+ // if the lowest bit is shifted off the end.
KnownBits Known(BitWidth);
- computeKnownBits(X, DemandedElts, Known, Depth, Q);
+ computeKnownBits(I->getOperand(0), DemandedElts, Known, Depth, Q);
if (Known.One[0])
return true;
+ break;
}
- // shr X, Y != 0 if X is negative. Note that the value of the shift is not
- // defined if the sign bit is shifted off the end.
- else if (match(V, m_Shr(m_Value(X), m_Value(Y)))) {
+ case Instruction::LShr:
+ case Instruction::AShr: {
// shr exact can only shift out zero bits.
const PossiblyExactOperator *BO = cast<PossiblyExactOperator>(V);
if (BO->isExact())
- return isKnownNonZero(X, Depth, Q);
+ return isKnownNonZero(I->getOperand(0), Depth, Q);
- KnownBits Known = computeKnownBits(X, DemandedElts, Depth, Q);
+ // shr X, Y != 0 if X is negative. Note that the value of the shift is not
+ // defined if the sign bit is shifted off the end.
+ KnownBits Known =
+ computeKnownBits(I->getOperand(0), DemandedElts, Depth, Q);
if (Known.isNegative())
return true;
// If the shifter operand is a constant, and all of the bits shifted
// out are known to be zero, and X is known non-zero then at least one
// non-zero bit must remain.
- if (ConstantInt *Shift = dyn_cast<ConstantInt>(Y)) {
+ if (ConstantInt *Shift = dyn_cast<ConstantInt>(I->getOperand(1))) {
auto ShiftVal = Shift->getLimitedValue(BitWidth - 1);
// Is there a known one in the portion not shifted out?
if (Known.countMaxLeadingZeros() < BitWidth - ShiftVal)
return true;
// Are all the bits to be shifted out known zero?
if (Known.countMinTrailingZeros() >= ShiftVal)
- return isKnownNonZero(X, DemandedElts, Depth, Q);
+ return isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q);
}
+ break;
}
- // div exact can only produce a zero if the dividend is zero.
- else if (match(V, m_Exact(m_IDiv(m_Value(X), m_Value())))) {
- return isKnownNonZero(X, DemandedElts, Depth, Q);
- }
- // X + Y.
- else if (match(V, m_Add(m_Value(X), m_Value(Y)))) {
- KnownBits XKnown = computeKnownBits(X, DemandedElts, Depth, Q);
- KnownBits YKnown = computeKnownBits(Y, DemandedElts, Depth, Q);
+ case Instruction::UDiv:
+ case Instruction::SDiv:
+ // div exact can only produce a zero if the dividend is zero.
+ if (cast<PossiblyExactOperator>(I)->isExact())
+ return isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q);
+ break;
+ case Instruction::Add: {
+ // X + Y.
+ KnownBits XKnown =
+ computeKnownBits(I->getOperand(0), DemandedElts, Depth, Q);
+ KnownBits YKnown =
+ computeKnownBits(I->getOperand(1), DemandedElts, Depth, Q);
// If X and Y are both non-negative (as signed values) then their sum is not
// zero unless both X and Y are zero.
if (XKnown.isNonNegative() && YKnown.isNonNegative())
- if (isKnownNonZero(X, DemandedElts, Depth, Q) ||
- isKnownNonZero(Y, DemandedElts, Depth, Q))
+ if (isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q) ||
+ isKnownNonZero(I->getOperand(1), DemandedElts, Depth, Q))
return true;
// If X and Y are both negative (as signed values) then their sum is not
@@ -2642,30 +2666,31 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
// The sum of a non-negative number and a power of two is not zero.
if (XKnown.isNonNegative() &&
- isKnownToBeAPowerOfTwo(Y, /*OrZero*/ false, Depth, Q))
+ isKnownToBeAPowerOfTwo(I->getOperand(1), /*OrZero*/ false, Depth, Q))
return true;
if (YKnown.isNonNegative() &&
- isKnownToBeAPowerOfTwo(X, /*OrZero*/ false, Depth, Q))
+ isKnownToBeAPowerOfTwo(I->getOperand(0), /*OrZero*/ false, Depth, Q))
return true;
+ break;
}
- // X * Y.
- else if (match(V, m_Mul(m_Value(X), m_Value(Y)))) {
- const OverflowingBinaryOperator *BO = cast<OverflowingBinaryOperator>(V);
+ case Instruction::Mul: {
// If X and Y are non-zero then so is X * Y as long as the multiplication
// does not overflow.
+ const OverflowingBinaryOperator *BO = cast<OverflowingBinaryOperator>(V);
if ((Q.IIQ.hasNoSignedWrap(BO) || Q.IIQ.hasNoUnsignedWrap(BO)) &&
- isKnownNonZero(X, DemandedElts, Depth, Q) &&
- isKnownNonZero(Y, DemandedElts, Depth, Q))
+ isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q) &&
+ isKnownNonZero(I->getOperand(1), DemandedElts, Depth, Q))
return true;
+ break;
}
- // (C ? X : Y) != 0 if X != 0 and Y != 0.
- else if (const SelectInst *SI = dyn_cast<SelectInst>(V)) {
- if (isKnownNonZero(SI->getTrueValue(), DemandedElts, Depth, Q) &&
- isKnownNonZero(SI->getFalseValue(), DemandedElts, Depth, Q))
+ case Instruction::Select:
+ // (C ? X : Y) != 0 if X != 0 and Y != 0.
+ if (isKnownNonZero(I->getOperand(1), DemandedElts, Depth, Q) &&
+ isKnownNonZero(I->getOperand(2), DemandedElts, Depth, Q))
return true;
- }
- // PHI
- else if (const PHINode *PN = dyn_cast<PHINode>(V)) {
+ break;
+ case Instruction::PHI: {
+ auto *PN = cast<PHINode>(I);
if (Q.IIQ.UseInstrInfo && isNonZeroRecurrence(PN))
return true;
@@ -2679,28 +2704,28 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
return isKnownNonZero(U.get(), DemandedElts, NewDepth, RecQ);
});
}
- // ExtractElement
- else if (const auto *EEI = dyn_cast<ExtractElementInst>(V)) {
- const Value *Vec = EEI->getVectorOperand();
- const Value *Idx = EEI->getIndexOperand();
- auto *CIdx = dyn_cast<ConstantInt>(Idx);
- if (auto *VecTy = dyn_cast<FixedVectorType>(Vec->getType())) {
- unsigned NumElts = VecTy->getNumElements();
- APInt DemandedVecElts = APInt::getAllOnes(NumElts);
- if (CIdx && CIdx->getValue().ult(NumElts))
- DemandedVecElts = APInt::getOneBitSet(NumElts, CIdx->getZExtValue());
- return isKnownNonZero(Vec, DemandedVecElts, Depth, Q);
- }
- }
- // Freeze
- else if (const FreezeInst *FI = dyn_cast<FreezeInst>(V)) {
- auto *Op = FI->getOperand(0);
- if (isKnownNonZero(Op, Depth, Q) &&
- isGuaranteedNotToBePoison(Op, Q.AC, Q.CxtI, Q.DT, Depth))
- return true;
- } else if (const auto *II = dyn_cast<IntrinsicInst>(V)) {
- if (II->getIntrinsicID() == Intrinsic::vscale)
+ case Instruction::ExtractElement:
+ if (const auto *EEI = dyn_cast<ExtractElementInst>(V)) {
+ const Value *Vec = EEI->getVectorOperand();
+ const Value *Idx = EEI->getIndexOperand();
+ auto *CIdx = dyn_cast<ConstantInt>(Idx);
+ if (auto *VecTy = dyn_cast<FixedVectorType>(Vec->getType())) {
+ unsigned NumElts = VecTy->getNumElements();
+ APInt DemandedVecElts = APInt::getAllOnes(NumElts);
+ if (CIdx && CIdx->getValue().ult(NumElts))
+ DemandedVecElts = APInt::getOneBitSet(NumElts, CIdx->getZExtValue());
+ return isKnownNonZero(Vec, DemandedVecElts, Depth, Q);
+ }
+ }
+ break;
+ case Instruction::Freeze:
+ return isKnownNonZero(I->getOperand(0), Depth, Q) &&
+ isGuaranteedNotToBePoison(I->getOperand(0), Q.AC, Q.CxtI, Q.DT,
+ Depth);
+ case Instruction::Call:
+ if (cast<CallInst>(I)->getIntrinsicID() == Intrinsic::vscale)
return true;
+ break;
}
KnownBits Known(BitWidth);
@@ -2709,11 +2734,6 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
}
bool isKnownNonZero(const Value* V, unsigned Depth, const Query& Q) {
- // FIXME: We currently have no way to represent the DemandedElts of a scalable
- // vector
- if (isa<ScalableVectorType>(V->getType()))
- return false;
-
auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
APInt DemandedElts =
FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
@@ -2722,15 +2742,15 @@ bool isKnownNonZero(const Value* V, unsigned Depth, const Query& Q) {
/// If the pair of operators are the same invertible function, return the
/// the operands of the function corresponding to each input. Otherwise,
-/// return None. An invertible function is one that is 1-to-1 and maps
+/// return std::nullopt. An invertible function is one that is 1-to-1 and maps
/// every input value to exactly one output value. This is equivalent to
/// saying that Op1 and Op2 are equal exactly when the specified pair of
/// operands are equal, (except that Op1 and Op2 may be poison more often.)
-static Optional<std::pair<Value*, Value*>>
+static std::optional<std::pair<Value*, Value*>>
getInvertibleOperands(const Operator *Op1,
const Operator *Op2) {
if (Op1->getOpcode() != Op2->getOpcode())
- return None;
+ return std::nullopt;
auto getOperands = [&](unsigned OpNum) -> auto {
return std::make_pair(Op1->getOperand(OpNum), Op2->getOperand(OpNum));
@@ -2824,7 +2844,7 @@ getInvertibleOperands(const Operator *Op1,
return std::make_pair(Start1, Start2);
}
}
- return None;
+ return std::nullopt;
}
/// Return true if V2 == V1 + X, where X is known non-zero.
@@ -3065,12 +3085,6 @@ static unsigned ComputeNumSignBitsImpl(const Value *V,
const APInt &DemandedElts,
unsigned Depth, const Query &Q) {
Type *Ty = V->getType();
-
- // FIXME: We currently have no way to represent the DemandedElts of a scalable
- // vector
- if (isa<ScalableVectorType>(Ty))
- return 1;
-
#ifndef NDEBUG
assert(Depth <= MaxAnalysisRecursionDepth && "Limit Search Depth");
@@ -3300,10 +3314,17 @@ static unsigned ComputeNumSignBitsImpl(const Value *V,
return Tmp;
}
- case Instruction::Trunc:
- // FIXME: it's tricky to do anything useful for this, but it is an
- // important case for targets like X86.
- break;
+ case Instruction::Trunc: {
+ // If the input contained enough sign bits that some remain after the
+ // truncation, then we can make use of that. Otherwise we don't know
+ // anything.
+ Tmp = ComputeNumSignBits(U->getOperand(0), Depth + 1, Q);
+ unsigned OperandTyBits = U->getOperand(0)->getType()->getScalarSizeInBits();
+ if (Tmp > (OperandTyBits - TyBits))
+ return Tmp - (OperandTyBits - TyBits);
+
+ return 1;
+ }
case Instruction::ExtractElement:
// Look through extract element. At the moment we keep this simple and
@@ -3593,15 +3614,24 @@ static bool cannotBeOrderedLessThanZeroImpl(const Value *V,
// Unsigned integers are always nonnegative.
case Instruction::UIToFP:
return true;
- case Instruction::FMul:
case Instruction::FDiv:
- // X * X is always non-negative or a NaN.
// X / X is always exactly 1.0 or a NaN.
if (I->getOperand(0) == I->getOperand(1) &&
(!SignBitOnly || cast<FPMathOperator>(I)->hasNoNaNs()))
return true;
- LLVM_FALLTHROUGH;
+ // Set SignBitOnly for RHS, because X / -0.0 is -Inf (or NaN).
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
+ Depth + 1) &&
+ cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI,
+ /*SignBitOnly*/ true, Depth + 1);
+ case Instruction::FMul:
+ // X * X is always non-negative or a NaN.
+ if (I->getOperand(0) == I->getOperand(1) &&
+ (!SignBitOnly || cast<FPMathOperator>(I)->hasNoNaNs()))
+ return true;
+
+ [[fallthrough]];
case Instruction::FAdd:
case Instruction::FRem:
return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly,
@@ -3630,6 +3660,17 @@ static bool cannotBeOrderedLessThanZeroImpl(const Value *V,
switch (IID) {
default:
break;
+ case Intrinsic::canonicalize:
+ case Intrinsic::arithmetic_fence:
+ case Intrinsic::floor:
+ case Intrinsic::ceil:
+ case Intrinsic::trunc:
+ case Intrinsic::rint:
+ case Intrinsic::nearbyint:
+ case Intrinsic::round:
+ case Intrinsic::roundeven:
+ case Intrinsic::fptrunc_round:
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(0), TLI, SignBitOnly, Depth + 1);
case Intrinsic::maxnum: {
Value *V0 = I->getOperand(0), *V1 = I->getOperand(1);
auto isPositiveNum = [&](Value *V) {
@@ -3668,7 +3709,10 @@ static bool cannotBeOrderedLessThanZeroImpl(const Value *V,
case Intrinsic::exp2:
case Intrinsic::fabs:
return true;
-
+ case Intrinsic::copysign:
+ // Only the sign operand matters.
+ return cannotBeOrderedLessThanZeroImpl(I->getOperand(1), TLI, true,
+ Depth + 1);
case Intrinsic::sqrt:
// sqrt(x) is always >= -0 or NaN. Moreover, sqrt(x) == -0 iff x == -0.
if (!SignBitOnly)
@@ -3756,9 +3800,73 @@ bool llvm::isKnownNeverInfinity(const Value *V, const TargetLibraryInfo *TLI,
Type *FPTy = Inst->getType()->getScalarType();
return ilogb(APFloat::getLargest(FPTy->getFltSemantics())) >= IntSize;
}
+ case Instruction::FNeg:
+ case Instruction::FPExt: {
+ // Peek through to source op. If it is not infinity, this is not infinity.
+ return isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1);
+ }
+ case Instruction::FPTrunc: {
+ // Need a range check.
+ return false;
+ }
default:
break;
}
+
+ if (const auto *II = dyn_cast<IntrinsicInst>(V)) {
+ switch (II->getIntrinsicID()) {
+ case Intrinsic::sin:
+ case Intrinsic::cos:
+ // Return NaN on infinite inputs.
+ return true;
+ case Intrinsic::fabs:
+ case Intrinsic::sqrt:
+ case Intrinsic::canonicalize:
+ case Intrinsic::copysign:
+ case Intrinsic::arithmetic_fence:
+ case Intrinsic::trunc:
+ return isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1);
+ case Intrinsic::floor:
+ case Intrinsic::ceil:
+ case Intrinsic::rint:
+ case Intrinsic::nearbyint:
+ case Intrinsic::round:
+ case Intrinsic::roundeven:
+ // PPC_FP128 is a special case.
+ if (V->getType()->isMultiUnitFPType())
+ return false;
+ return isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1);
+ case Intrinsic::fptrunc_round:
+ // Requires knowing the value range.
+ return false;
+ case Intrinsic::minnum:
+ case Intrinsic::maxnum:
+ case Intrinsic::minimum:
+ case Intrinsic::maximum:
+ return isKnownNeverInfinity(Inst->getOperand(0), TLI, Depth + 1) &&
+ isKnownNeverInfinity(Inst->getOperand(1), TLI, Depth + 1);
+ case Intrinsic::log:
+ case Intrinsic::log10:
+ case Intrinsic::log2:
+ // log(+inf) -> +inf
+ // log([+-]0.0) -> -inf
+ // log(-inf) -> nan
+ // log(-x) -> nan
+ // TODO: We lack API to check the == 0 case.
+ return false;
+ case Intrinsic::exp:
+ case Intrinsic::exp2:
+ case Intrinsic::pow:
+ case Intrinsic::powi:
+ case Intrinsic::fma:
+ case Intrinsic::fmuladd:
+ // These can return infinities on overflow cases, so it's hard to prove
+ // anything about it.
+ return false;
+ default:
+ break;
+ }
+ }
}
// try to handle fixed width vector constants
@@ -3832,6 +3940,7 @@ bool llvm::isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI,
return true;
case Instruction::FPTrunc:
case Instruction::FPExt:
+ case Instruction::FNeg:
return isKnownNeverNaN(Inst->getOperand(0), TLI, Depth + 1);
default:
break;
@@ -3852,6 +3961,7 @@ bool llvm::isKnownNeverNaN(const Value *V, const TargetLibraryInfo *TLI,
case Intrinsic::nearbyint:
case Intrinsic::round:
case Intrinsic::roundeven:
+ case Intrinsic::arithmetic_fence:
return isKnownNeverNaN(II->getArgOperand(0), TLI, Depth + 1);
case Intrinsic::sqrt:
return isKnownNeverNaN(II->getArgOperand(0), TLI, Depth + 1) &&
@@ -4039,8 +4149,8 @@ static Value *BuildSubAggregate(Value *From, Value* To, Type *IndexedType,
return nullptr;
// Insert the value in the new (sub) aggregate
- return InsertValueInst::Create(To, V, makeArrayRef(Idxs).slice(IdxSkip),
- "tmp", InsertBefore);
+ return InsertValueInst::Create(To, V, ArrayRef(Idxs).slice(IdxSkip), "tmp",
+ InsertBefore);
}
// This helper takes a nested struct and extracts a part of it (which is again a
@@ -4060,7 +4170,7 @@ static Value *BuildSubAggregate(Value *From, ArrayRef<unsigned> idx_range,
assert(InsertBefore && "Must have someplace to insert!");
Type *IndexedType = ExtractValueInst::getIndexedType(From->getType(),
idx_range);
- Value *To = UndefValue::get(IndexedType);
+ Value *To = PoisonValue::get(IndexedType);
SmallVector<unsigned, 10> Idxs(idx_range.begin(), idx_range.end());
unsigned IdxSkip = Idxs.size();
@@ -4112,7 +4222,7 @@ Value *llvm::FindInsertedValue(Value *V, ArrayRef<unsigned> idx_range,
// %C = insertvalue {i32, i32 } %A, i32 11, 1
// which allows the unused 0,0 element from the nested struct to be
// removed.
- return BuildSubAggregate(V, makeArrayRef(idx_range.begin(), req_idx),
+ return BuildSubAggregate(V, ArrayRef(idx_range.begin(), req_idx),
InsertBefore);
}
@@ -4127,8 +4237,7 @@ Value *llvm::FindInsertedValue(Value *V, ArrayRef<unsigned> idx_range,
// requested (though possibly only partially). Now we recursively look at
// the inserted value, passing any remaining indices.
return FindInsertedValue(I->getInsertedValueOperand(),
- makeArrayRef(req_idx, idx_range.end()),
- InsertBefore);
+ ArrayRef(req_idx, idx_range.end()), InsertBefore);
}
if (ExtractValueInst *I = dyn_cast<ExtractValueInst>(V)) {
@@ -4182,10 +4291,14 @@ bool llvm::isGEPBasedOnPointerToString(const GEPOperator *GEP,
// its initializer if the size of its elements equals ElementSize, or,
// for ElementSize == 8, to its representation as an array of unsiged
// char. Return true on success.
+// Offset is in the unit "nr of ElementSize sized elements".
bool llvm::getConstantDataArrayInfo(const Value *V,
ConstantDataArraySlice &Slice,
unsigned ElementSize, uint64_t Offset) {
- assert(V);
+ assert(V && "V should not be null.");
+ assert((ElementSize % 8) == 0 &&
+ "ElementSize expected to be a multiple of the size of a byte.");
+ unsigned ElementSizeInBytes = ElementSize / 8;
// Drill down into the pointer expression V, ignoring any intervening
// casts, and determine the identity of the object it references along
@@ -4209,15 +4322,19 @@ bool llvm::getConstantDataArrayInfo(const Value *V,
// Fail if the constant offset is excessive.
return false;
- Offset += StartIdx;
+ // Off/StartIdx is in the unit of bytes. So we need to convert to number of
+ // elements. Simply bail out if that isn't possible.
+ if ((StartIdx % ElementSizeInBytes) != 0)
+ return false;
+ Offset += StartIdx / ElementSizeInBytes;
ConstantDataArray *Array = nullptr;
ArrayType *ArrayTy = nullptr;
if (GV->getInitializer()->isNullValue()) {
Type *GVTy = GV->getValueType();
- uint64_t SizeInBytes = DL.getTypeStoreSize(GVTy).getFixedSize();
- uint64_t Length = SizeInBytes / (ElementSize / 8);
+ uint64_t SizeInBytes = DL.getTypeStoreSize(GVTy).getFixedValue();
+ uint64_t Length = SizeInBytes / ElementSizeInBytes;
Slice.Array = nullptr;
Slice.Offset = 0;
@@ -4271,9 +4388,9 @@ bool llvm::getConstantDataArrayInfo(const Value *V,
/// return true. When TrimAtNul is set, Str will contain only the bytes up
/// to but not including the first nul. Return false on failure.
bool llvm::getConstantStringInfo(const Value *V, StringRef &Str,
- uint64_t Offset, bool TrimAtNul) {
+ bool TrimAtNul) {
ConstantDataArraySlice Slice;
- if (!getConstantDataArrayInfo(V, Slice, 8, Offset))
+ if (!getConstantDataArrayInfo(V, Slice, 8))
return false;
if (Slice.Array == nullptr) {
@@ -4682,15 +4799,17 @@ bool llvm::mustSuppressSpeculation(const LoadInst &LI) {
bool llvm::isSafeToSpeculativelyExecute(const Instruction *Inst,
const Instruction *CtxI,
+ AssumptionCache *AC,
const DominatorTree *DT,
const TargetLibraryInfo *TLI) {
return isSafeToSpeculativelyExecuteWithOpcode(Inst->getOpcode(), Inst, CtxI,
- DT, TLI);
+ AC, DT, TLI);
}
bool llvm::isSafeToSpeculativelyExecuteWithOpcode(
unsigned Opcode, const Instruction *Inst, const Instruction *CtxI,
- const DominatorTree *DT, const TargetLibraryInfo *TLI) {
+ AssumptionCache *AC, const DominatorTree *DT,
+ const TargetLibraryInfo *TLI) {
#ifndef NDEBUG
if (Inst->getOpcode() != Opcode) {
// Check that the operands are actually compatible with the Opcode override.
@@ -4748,9 +4867,9 @@ bool llvm::isSafeToSpeculativelyExecuteWithOpcode(
if (mustSuppressSpeculation(*LI))
return false;
const DataLayout &DL = LI->getModule()->getDataLayout();
- return isDereferenceableAndAlignedPointer(
- LI->getPointerOperand(), LI->getType(), LI->getAlign(), DL, CtxI, DT,
- TLI);
+ return isDereferenceableAndAlignedPointer(LI->getPointerOperand(),
+ LI->getType(), LI->getAlign(), DL,
+ CtxI, AC, DT, TLI);
}
case Instruction::Call: {
auto *CI = dyn_cast<const CallInst>(Inst);
@@ -5085,10 +5204,35 @@ bool llvm::isOverflowIntrinsicNoWrap(const WithOverflowInst *WO,
return llvm::any_of(GuardingBranches, AllUsesGuardedByBranch);
}
+/// Shifts return poison if shiftwidth is larger than the bitwidth.
+static bool shiftAmountKnownInRange(const Value *ShiftAmount) {
+ auto *C = dyn_cast<Constant>(ShiftAmount);
+ if (!C)
+ return false;
+
+ // Shifts return poison if shiftwidth is larger than the bitwidth.
+ SmallVector<const Constant *, 4> ShiftAmounts;
+ if (auto *FVTy = dyn_cast<FixedVectorType>(C->getType())) {
+ unsigned NumElts = FVTy->getNumElements();
+ for (unsigned i = 0; i < NumElts; ++i)
+ ShiftAmounts.push_back(C->getAggregateElement(i));
+ } else if (isa<ScalableVectorType>(C->getType()))
+ return false; // Can't tell, just return false to be safe
+ else
+ ShiftAmounts.push_back(C);
+
+ bool Safe = llvm::all_of(ShiftAmounts, [](const Constant *C) {
+ auto *CI = dyn_cast_or_null<ConstantInt>(C);
+ return CI && CI->getValue().ult(C->getType()->getIntegerBitWidth());
+ });
+
+ return Safe;
+}
+
static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
- bool ConsiderFlags) {
+ bool ConsiderFlagsAndMetadata) {
- if (ConsiderFlags && Op->hasPoisonGeneratingFlags())
+ if (ConsiderFlagsAndMetadata && Op->hasPoisonGeneratingFlagsOrMetadata())
return true;
unsigned Opcode = Op->getOpcode();
@@ -5097,27 +5241,8 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
switch (Opcode) {
case Instruction::Shl:
case Instruction::AShr:
- case Instruction::LShr: {
- // Shifts return poison if shiftwidth is larger than the bitwidth.
- if (auto *C = dyn_cast<Constant>(Op->getOperand(1))) {
- SmallVector<Constant *, 4> ShiftAmounts;
- if (auto *FVTy = dyn_cast<FixedVectorType>(C->getType())) {
- unsigned NumElts = FVTy->getNumElements();
- for (unsigned i = 0; i < NumElts; ++i)
- ShiftAmounts.push_back(C->getAggregateElement(i));
- } else if (isa<ScalableVectorType>(C->getType()))
- return true; // Can't tell, just return true to be safe
- else
- ShiftAmounts.push_back(C);
-
- bool Safe = llvm::all_of(ShiftAmounts, [](Constant *C) {
- auto *CI = dyn_cast_or_null<ConstantInt>(C);
- return CI && CI->getValue().ult(C->getType()->getIntegerBitWidth());
- });
- return !Safe;
- }
- return true;
- }
+ case Instruction::LShr:
+ return !shiftAmountKnownInRange(Op->getOperand(1));
case Instruction::FPToSI:
case Instruction::FPToUI:
// fptosi/ui yields poison if the resulting value does not fit in the
@@ -5127,17 +5252,78 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
if (auto *II = dyn_cast<IntrinsicInst>(Op)) {
switch (II->getIntrinsicID()) {
// TODO: Add more intrinsics.
+ case Intrinsic::ctlz:
+ case Intrinsic::cttz:
+ case Intrinsic::abs:
+ if (cast<ConstantInt>(II->getArgOperand(1))->isNullValue())
+ return false;
+ break;
case Intrinsic::ctpop:
+ case Intrinsic::bswap:
+ case Intrinsic::bitreverse:
+ case Intrinsic::fshl:
+ case Intrinsic::fshr:
+ case Intrinsic::smax:
+ case Intrinsic::smin:
+ case Intrinsic::umax:
+ case Intrinsic::umin:
+ case Intrinsic::ptrmask:
+ case Intrinsic::fptoui_sat:
+ case Intrinsic::fptosi_sat:
case Intrinsic::sadd_with_overflow:
case Intrinsic::ssub_with_overflow:
case Intrinsic::smul_with_overflow:
case Intrinsic::uadd_with_overflow:
case Intrinsic::usub_with_overflow:
case Intrinsic::umul_with_overflow:
+ case Intrinsic::sadd_sat:
+ case Intrinsic::uadd_sat:
+ case Intrinsic::ssub_sat:
+ case Intrinsic::usub_sat:
+ return false;
+ case Intrinsic::sshl_sat:
+ case Intrinsic::ushl_sat:
+ return !shiftAmountKnownInRange(II->getArgOperand(1));
+ case Intrinsic::fma:
+ case Intrinsic::fmuladd:
+ case Intrinsic::sqrt:
+ case Intrinsic::powi:
+ case Intrinsic::sin:
+ case Intrinsic::cos:
+ case Intrinsic::pow:
+ case Intrinsic::log:
+ case Intrinsic::log10:
+ case Intrinsic::log2:
+ case Intrinsic::exp:
+ case Intrinsic::exp2:
+ case Intrinsic::fabs:
+ case Intrinsic::copysign:
+ case Intrinsic::floor:
+ case Intrinsic::ceil:
+ case Intrinsic::trunc:
+ case Intrinsic::rint:
+ case Intrinsic::nearbyint:
+ case Intrinsic::round:
+ case Intrinsic::roundeven:
+ case Intrinsic::fptrunc_round:
+ case Intrinsic::canonicalize:
+ case Intrinsic::arithmetic_fence:
+ case Intrinsic::minnum:
+ case Intrinsic::maxnum:
+ case Intrinsic::minimum:
+ case Intrinsic::maximum:
+ case Intrinsic::is_fpclass:
+ return false;
+ case Intrinsic::lround:
+ case Intrinsic::llround:
+ case Intrinsic::lrint:
+ case Intrinsic::llrint:
+ // If the value doesn't fit an unspecified value is returned (but this
+ // is not poison).
return false;
}
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case Instruction::CallBr:
case Instruction::Invoke: {
const auto *CB = cast<CallBase>(Op);
@@ -5172,6 +5358,11 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
case Instruction::Freeze:
case Instruction::ICmp:
case Instruction::FCmp:
+ case Instruction::FAdd:
+ case Instruction::FSub:
+ case Instruction::FMul:
+ case Instruction::FDiv:
+ case Instruction::FRem:
return false;
case Instruction::GetElementPtr:
// inbounds is handled above
@@ -5189,12 +5380,15 @@ static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly,
}
}
-bool llvm::canCreateUndefOrPoison(const Operator *Op, bool ConsiderFlags) {
- return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/false, ConsiderFlags);
+bool llvm::canCreateUndefOrPoison(const Operator *Op,
+ bool ConsiderFlagsAndMetadata) {
+ return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/false,
+ ConsiderFlagsAndMetadata);
}
-bool llvm::canCreatePoison(const Operator *Op, bool ConsiderFlags) {
- return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/true, ConsiderFlags);
+bool llvm::canCreatePoison(const Operator *Op, bool ConsiderFlagsAndMetadata) {
+ return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/true,
+ ConsiderFlagsAndMetadata);
}
static bool directlyImpliesPoison(const Value *ValAssumedPoison,
@@ -5207,15 +5401,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)
@@ -5373,7 +5564,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;
}
}
@@ -5495,13 +5687,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()) {
@@ -5535,49 +5729,58 @@ bool llvm::propagatesPoison(const Operator *I) {
}
void llvm::getGuaranteedWellDefinedOps(
- const Instruction *I, SmallPtrSetImpl<const Value *> &Operands) {
+ const Instruction *I, SmallVectorImpl<const Value *> &Operands) {
switch (I->getOpcode()) {
case Instruction::Store:
- Operands.insert(cast<StoreInst>(I)->getPointerOperand());
+ Operands.push_back(cast<StoreInst>(I)->getPointerOperand());
break;
case Instruction::Load:
- Operands.insert(cast<LoadInst>(I)->getPointerOperand());
+ Operands.push_back(cast<LoadInst>(I)->getPointerOperand());
break;
// Since dereferenceable attribute imply noundef, atomic operations
// also implicitly have noundef pointers too
case Instruction::AtomicCmpXchg:
- Operands.insert(cast<AtomicCmpXchgInst>(I)->getPointerOperand());
+ Operands.push_back(cast<AtomicCmpXchgInst>(I)->getPointerOperand());
break;
case Instruction::AtomicRMW:
- Operands.insert(cast<AtomicRMWInst>(I)->getPointerOperand());
+ Operands.push_back(cast<AtomicRMWInst>(I)->getPointerOperand());
break;
case Instruction::Call:
case Instruction::Invoke: {
const CallBase *CB = cast<CallBase>(I);
if (CB->isIndirectCall())
- Operands.insert(CB->getCalledOperand());
+ Operands.push_back(CB->getCalledOperand());
for (unsigned i = 0; i < CB->arg_size(); ++i) {
if (CB->paramHasAttr(i, Attribute::NoUndef) ||
CB->paramHasAttr(i, Attribute::Dereferenceable))
- Operands.insert(CB->getArgOperand(i));
+ Operands.push_back(CB->getArgOperand(i));
}
break;
}
case Instruction::Ret:
if (I->getFunction()->hasRetAttribute(Attribute::NoUndef))
- Operands.insert(I->getOperand(0));
+ Operands.push_back(I->getOperand(0));
break;
+ case Instruction::Switch:
+ Operands.push_back(cast<SwitchInst>(I)->getCondition());
+ break;
+ case Instruction::Br: {
+ auto *BR = cast<BranchInst>(I);
+ if (BR->isConditional())
+ Operands.push_back(BR->getCondition());
+ break;
+ }
default:
break;
}
}
void llvm::getGuaranteedNonPoisonOps(const Instruction *I,
- SmallPtrSetImpl<const Value *> &Operands) {
+ SmallVectorImpl<const Value *> &Operands) {
getGuaranteedWellDefinedOps(I, Operands);
switch (I->getOpcode()) {
// Divisors of these operations are allowed to be partially undef.
@@ -5585,18 +5788,8 @@ void llvm::getGuaranteedNonPoisonOps(const Instruction *I,
case Instruction::SDiv:
case Instruction::URem:
case Instruction::SRem:
- Operands.insert(I->getOperand(1));
+ Operands.push_back(I->getOperand(1));
break;
- case Instruction::Switch:
- if (BranchOnPoisonAsUB)
- Operands.insert(cast<SwitchInst>(I)->getCondition());
- break;
- case Instruction::Br: {
- auto *BR = cast<BranchInst>(I);
- if (BranchOnPoisonAsUB && BR->isConditional())
- Operands.insert(BR->getCondition());
- break;
- }
default:
break;
}
@@ -5604,7 +5797,7 @@ void llvm::getGuaranteedNonPoisonOps(const Instruction *I,
bool llvm::mustTriggerUB(const Instruction *I,
const SmallSet<const Value *, 16>& KnownPoison) {
- SmallPtrSet<const Value *, 4> NonPoisonOps;
+ SmallVector<const Value *, 4> NonPoisonOps;
getGuaranteedNonPoisonOps(I, NonPoisonOps);
for (const auto *V : NonPoisonOps)
@@ -5652,9 +5845,9 @@ static bool programUndefinedIfUndefOrPoison(const Value *V,
if (--ScanLimit == 0)
break;
- SmallPtrSet<const Value *, 4> WellDefinedOps;
+ SmallVector<const Value *, 4> WellDefinedOps;
getGuaranteedWellDefinedOps(&I, WellDefinedOps);
- if (WellDefinedOps.contains(V))
+ if (is_contained(WellDefinedOps, V))
return true;
if (!isGuaranteedToTransferExecutionToSuccessor(&I))
@@ -5669,11 +5862,6 @@ static bool programUndefinedIfUndefOrPoison(const Value *V,
SmallSet<const BasicBlock *, 4> Visited;
YieldsPoison.insert(V);
- auto Propagate = [&](const User *User) {
- if (propagatesPoison(cast<Operator>(User)))
- YieldsPoison.insert(User);
- };
- for_each(V->users(), Propagate);
Visited.insert(BB);
while (true) {
@@ -5687,9 +5875,13 @@ static bool programUndefinedIfUndefOrPoison(const Value *V,
if (!isGuaranteedToTransferExecutionToSuccessor(&I))
return false;
- // Mark poison that propagates from I through uses of I.
- if (YieldsPoison.count(&I))
- for_each(I.users(), Propagate);
+ // 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;
+ }
+ }
}
BB = BB->getSingleSuccessor();
@@ -6049,6 +6241,7 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
Value *TrueVal, Value *FalseVal,
Value *&LHS, Value *&RHS,
unsigned Depth) {
+ bool HasMismatchedZeros = false;
if (CmpInst::isFPPredicate(Pred)) {
// IEEE-754 ignores the sign of 0.0 in comparisons. So if the select has one
// 0.0 operand, set the compare's 0.0 operands to that same value for the
@@ -6063,10 +6256,14 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
OutputZeroVal = FalseVal;
if (OutputZeroVal) {
- if (match(CmpLHS, m_AnyZeroFP()))
+ if (match(CmpLHS, m_AnyZeroFP()) && CmpLHS != OutputZeroVal) {
+ HasMismatchedZeros = true;
CmpLHS = OutputZeroVal;
- if (match(CmpRHS, m_AnyZeroFP()))
+ }
+ if (match(CmpRHS, m_AnyZeroFP()) && CmpRHS != OutputZeroVal) {
+ HasMismatchedZeros = true;
CmpRHS = OutputZeroVal;
+ }
}
}
@@ -6080,7 +6277,11 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred,
// operands is known to not be zero or if we don't care about signed zero.
switch (Pred) {
default: break;
- // FIXME: Include OGT/OLT/UGT/ULT.
+ case CmpInst::FCMP_OGT: case CmpInst::FCMP_OLT:
+ case CmpInst::FCMP_UGT: case CmpInst::FCMP_ULT:
+ if (!HasMismatchedZeros)
+ break;
+ [[fallthrough]];
case CmpInst::FCMP_OGE: case CmpInst::FCMP_OLE:
case CmpInst::FCMP_UGE: case CmpInst::FCMP_ULE:
if (!FMF.noSignedZeros() && !isKnownNonZero(CmpLHS) &&
@@ -6421,10 +6622,6 @@ Intrinsic::ID llvm::getInverseMinMaxIntrinsic(Intrinsic::ID MinMaxID) {
}
}
-CmpInst::Predicate llvm::getInverseMinMaxPred(SelectPatternFlavor SPF) {
- return getMinMaxPred(getInverseMinMaxFlavor(SPF));
-}
-
APInt llvm::getMinMaxLimit(SelectPatternFlavor SPF, unsigned BitWidth) {
switch (SPF) {
case SPF_SMAX: return APInt::getSignedMaxValue(BitWidth);
@@ -6502,7 +6699,8 @@ bool llvm::matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO,
case Instruction::Sub:
case Instruction::And:
case Instruction::Or:
- case Instruction::Mul: {
+ case Instruction::Mul:
+ case Instruction::FMul: {
Value *LL = LU->getOperand(0);
Value *LR = LU->getOperand(1);
// Find a recurrence.
@@ -6599,119 +6797,114 @@ static bool isTruePredicate(CmpInst::Predicate Pred, const Value *LHS,
}
/// Return true if "icmp Pred BLHS BRHS" is true whenever "icmp Pred
-/// ALHS ARHS" is true. Otherwise, return None.
-static Optional<bool>
+/// ALHS ARHS" is true. Otherwise, return std::nullopt.
+static std::optional<bool>
isImpliedCondOperands(CmpInst::Predicate Pred, const Value *ALHS,
const Value *ARHS, const Value *BLHS, const Value *BRHS,
const DataLayout &DL, unsigned Depth) {
switch (Pred) {
default:
- return None;
+ return std::nullopt;
case CmpInst::ICMP_SLT:
case CmpInst::ICMP_SLE:
if (isTruePredicate(CmpInst::ICMP_SLE, BLHS, ALHS, DL, Depth) &&
isTruePredicate(CmpInst::ICMP_SLE, ARHS, BRHS, DL, Depth))
return true;
- return None;
+ return std::nullopt;
case CmpInst::ICMP_ULT:
case CmpInst::ICMP_ULE:
if (isTruePredicate(CmpInst::ICMP_ULE, BLHS, ALHS, DL, Depth) &&
isTruePredicate(CmpInst::ICMP_ULE, ARHS, BRHS, DL, Depth))
return true;
- return None;
+ return std::nullopt;
}
}
-/// Return true if the operands of the two compares match. IsSwappedOps is true
-/// when the operands match, but are swapped.
-static bool isMatchingOps(const Value *ALHS, const Value *ARHS,
- const Value *BLHS, const Value *BRHS,
- bool &IsSwappedOps) {
-
- bool IsMatchingOps = (ALHS == BLHS && ARHS == BRHS);
- IsSwappedOps = (ALHS == BRHS && ARHS == BLHS);
- return IsMatchingOps || IsSwappedOps;
+/// Return true if the operands of two compares (expanded as "L0 pred L1" and
+/// "R0 pred R1") match. IsSwappedOps is true when the operands match, but are
+/// swapped.
+static bool areMatchingOperands(const Value *L0, const Value *L1, const Value *R0,
+ const Value *R1, bool &AreSwappedOps) {
+ bool AreMatchingOps = (L0 == R0 && L1 == R1);
+ AreSwappedOps = (L0 == R1 && L1 == R0);
+ return AreMatchingOps || AreSwappedOps;
}
-/// Return true if "icmp1 APred X, Y" implies "icmp2 BPred X, Y" is true.
-/// Return false if "icmp1 APred X, Y" implies "icmp2 BPred X, Y" is false.
-/// Otherwise, return None if we can't infer anything.
-static Optional<bool> isImpliedCondMatchingOperands(CmpInst::Predicate APred,
- CmpInst::Predicate BPred,
- bool AreSwappedOps) {
+/// Return true if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is true.
+/// Return false if "icmp1 LPred X, Y" implies "icmp2 RPred X, Y" is false.
+/// Otherwise, return std::nullopt if we can't infer anything.
+static std::optional<bool>
+isImpliedCondMatchingOperands(CmpInst::Predicate LPred,
+ CmpInst::Predicate RPred, bool AreSwappedOps) {
// Canonicalize the predicate as if the operands were not commuted.
if (AreSwappedOps)
- BPred = ICmpInst::getSwappedPredicate(BPred);
+ RPred = ICmpInst::getSwappedPredicate(RPred);
- if (CmpInst::isImpliedTrueByMatchingCmp(APred, BPred))
+ if (CmpInst::isImpliedTrueByMatchingCmp(LPred, RPred))
return true;
- if (CmpInst::isImpliedFalseByMatchingCmp(APred, BPred))
+ if (CmpInst::isImpliedFalseByMatchingCmp(LPred, RPred))
return false;
- return None;
+ return std::nullopt;
}
-/// Return true if "icmp APred X, C1" implies "icmp BPred X, C2" is true.
-/// Return false if "icmp APred X, C1" implies "icmp BPred X, C2" is false.
-/// Otherwise, return None if we can't infer anything.
-static Optional<bool> isImpliedCondMatchingImmOperands(CmpInst::Predicate APred,
- const APInt &C1,
- CmpInst::Predicate BPred,
- const APInt &C2) {
- ConstantRange DomCR = ConstantRange::makeExactICmpRegion(APred, C1);
- ConstantRange CR = ConstantRange::makeExactICmpRegion(BPred, C2);
+/// Return true if "icmp LPred X, LC" implies "icmp RPred X, RC" is true.
+/// Return false if "icmp LPred X, LC" implies "icmp RPred X, RC" is false.
+/// Otherwise, return std::nullopt if we can't infer anything.
+static std::optional<bool> isImpliedCondCommonOperandWithConstants(
+ CmpInst::Predicate LPred, const APInt &LC, CmpInst::Predicate RPred,
+ const APInt &RC) {
+ ConstantRange DomCR = ConstantRange::makeExactICmpRegion(LPred, LC);
+ ConstantRange CR = ConstantRange::makeExactICmpRegion(RPred, RC);
ConstantRange Intersection = DomCR.intersectWith(CR);
ConstantRange Difference = DomCR.difference(CR);
if (Intersection.isEmptySet())
return false;
if (Difference.isEmptySet())
return true;
- return None;
+ return std::nullopt;
}
-/// Return true if LHS implies RHS is true. Return false if LHS implies RHS is
-/// false. Otherwise, return None if we can't infer anything.
-static Optional<bool> isImpliedCondICmps(const ICmpInst *LHS,
- CmpInst::Predicate BPred,
- const Value *BLHS, const Value *BRHS,
- const DataLayout &DL, bool LHSIsTrue,
- unsigned Depth) {
- Value *ALHS = LHS->getOperand(0);
- Value *ARHS = LHS->getOperand(1);
+/// Return true if LHS implies RHS (expanded to its components as "R0 RPred R1")
+/// is true. Return false if LHS implies RHS is false. Otherwise, return
+/// std::nullopt if we can't infer anything.
+static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS,
+ CmpInst::Predicate RPred,
+ const Value *R0, const Value *R1,
+ const DataLayout &DL,
+ bool LHSIsTrue, unsigned Depth) {
+ Value *L0 = LHS->getOperand(0);
+ Value *L1 = LHS->getOperand(1);
// The rest of the logic assumes the LHS condition is true. If that's not the
// case, invert the predicate to make it so.
- CmpInst::Predicate APred =
+ CmpInst::Predicate LPred =
LHSIsTrue ? LHS->getPredicate() : LHS->getInversePredicate();
// Can we infer anything when the two compares have matching operands?
bool AreSwappedOps;
- if (isMatchingOps(ALHS, ARHS, BLHS, BRHS, AreSwappedOps)) {
- if (Optional<bool> Implication = isImpliedCondMatchingOperands(
- APred, BPred, AreSwappedOps))
- return Implication;
- // No amount of additional analysis will infer the second condition, so
- // early exit.
- return None;
- }
+ if (areMatchingOperands(L0, L1, R0, R1, AreSwappedOps))
+ return isImpliedCondMatchingOperands(LPred, RPred, AreSwappedOps);
- // Can we infer anything when the LHS operands match and the RHS operands are
+ // Can we infer anything when the 0-operands match and the 1-operands are
// constants (not necessarily matching)?
- const APInt *AC, *BC;
- if (ALHS == BLHS && match(ARHS, m_APInt(AC)) && match(BRHS, m_APInt(BC)))
- return isImpliedCondMatchingImmOperands(APred, *AC, BPred, *BC);
+ const APInt *LC, *RC;
+ if (L0 == R0 && match(L1, m_APInt(LC)) && match(R1, m_APInt(RC)))
+ return isImpliedCondCommonOperandWithConstants(LPred, *LC, RPred, *RC);
+
+ if (LPred == RPred)
+ return isImpliedCondOperands(LPred, L0, L1, R0, R1, DL, Depth);
- if (APred == BPred)
- return isImpliedCondOperands(APred, ALHS, ARHS, BLHS, BRHS, DL, Depth);
- return None;
+ return std::nullopt;
}
/// Return true if LHS implies RHS is true. Return false if LHS implies RHS is
-/// false. Otherwise, return None if we can't infer anything. We expect the
-/// RHS to be an icmp and the LHS to be an 'and', 'or', or a 'select' instruction.
-static Optional<bool>
+/// false. Otherwise, return std::nullopt if we can't infer anything. We
+/// expect the RHS to be an icmp and the LHS to be an 'and', 'or', or a 'select'
+/// instruction.
+static std::optional<bool>
isImpliedCondAndOr(const Instruction *LHS, CmpInst::Predicate RHSPred,
const Value *RHSOp0, const Value *RHSOp1,
const DataLayout &DL, bool LHSIsTrue, unsigned Depth) {
@@ -6730,29 +6923,29 @@ isImpliedCondAndOr(const Instruction *LHS, CmpInst::Predicate RHSPred,
if ((!LHSIsTrue && match(LHS, m_LogicalOr(m_Value(ALHS), m_Value(ARHS)))) ||
(LHSIsTrue && match(LHS, m_LogicalAnd(m_Value(ALHS), m_Value(ARHS))))) {
// FIXME: Make this non-recursion.
- if (Optional<bool> Implication = isImpliedCondition(
+ if (std::optional<bool> Implication = isImpliedCondition(
ALHS, RHSPred, RHSOp0, RHSOp1, DL, LHSIsTrue, Depth + 1))
return Implication;
- if (Optional<bool> Implication = isImpliedCondition(
+ if (std::optional<bool> Implication = isImpliedCondition(
ARHS, RHSPred, RHSOp0, RHSOp1, DL, LHSIsTrue, Depth + 1))
return Implication;
- return None;
+ return std::nullopt;
}
- return None;
+ return std::nullopt;
}
-Optional<bool>
+std::optional<bool>
llvm::isImpliedCondition(const Value *LHS, CmpInst::Predicate RHSPred,
const Value *RHSOp0, const Value *RHSOp1,
const DataLayout &DL, bool LHSIsTrue, unsigned Depth) {
// Bail out when we hit the limit.
if (Depth == MaxAnalysisRecursionDepth)
- return None;
+ return std::nullopt;
// A mismatch occurs when we compare a scalar cmp to a vector cmp, for
// example.
if (RHSOp0->getType()->isVectorTy() != LHS->getType()->isVectorTy())
- return None;
+ return std::nullopt;
assert(LHS->getType()->isIntOrIntVectorTy(1) &&
"Expected integer type only!");
@@ -6773,12 +6966,12 @@ llvm::isImpliedCondition(const Value *LHS, CmpInst::Predicate RHSPred,
return isImpliedCondAndOr(LHSI, RHSPred, RHSOp0, RHSOp1, DL, LHSIsTrue,
Depth);
}
- return None;
+ return std::nullopt;
}
-Optional<bool> llvm::isImpliedCondition(const Value *LHS, const Value *RHS,
- const DataLayout &DL, bool LHSIsTrue,
- unsigned Depth) {
+std::optional<bool> llvm::isImpliedCondition(const Value *LHS, const Value *RHS,
+ const DataLayout &DL,
+ bool LHSIsTrue, unsigned Depth) {
// LHS ==> RHS by definition
if (LHS == RHS)
return LHSIsTrue;
@@ -6789,33 +6982,33 @@ Optional<bool> llvm::isImpliedCondition(const Value *LHS, const Value *RHS,
LHSIsTrue, Depth);
if (Depth == MaxAnalysisRecursionDepth)
- return None;
+ return std::nullopt;
// LHS ==> (RHS1 || RHS2) if LHS ==> RHS1 or LHS ==> RHS2
// LHS ==> !(RHS1 && RHS2) if LHS ==> !RHS1 or LHS ==> !RHS2
const Value *RHS1, *RHS2;
if (match(RHS, m_LogicalOr(m_Value(RHS1), m_Value(RHS2)))) {
- if (Optional<bool> Imp =
+ if (std::optional<bool> Imp =
isImpliedCondition(LHS, RHS1, DL, LHSIsTrue, Depth + 1))
if (*Imp == true)
return true;
- if (Optional<bool> Imp =
+ if (std::optional<bool> Imp =
isImpliedCondition(LHS, RHS2, DL, LHSIsTrue, Depth + 1))
if (*Imp == true)
return true;
}
if (match(RHS, m_LogicalAnd(m_Value(RHS1), m_Value(RHS2)))) {
- if (Optional<bool> Imp =
+ if (std::optional<bool> Imp =
isImpliedCondition(LHS, RHS1, DL, LHSIsTrue, Depth + 1))
if (*Imp == false)
return false;
- if (Optional<bool> Imp =
+ if (std::optional<bool> Imp =
isImpliedCondition(LHS, RHS2, DL, LHSIsTrue, Depth + 1))
if (*Imp == false)
return false;
}
- return None;
+ return std::nullopt;
}
// Returns a pair (Condition, ConditionIsTrue), where Condition is a branch
@@ -6849,25 +7042,26 @@ getDomPredecessorCondition(const Instruction *ContextI) {
return {PredCond, TrueBB == ContextBB};
}
-Optional<bool> llvm::isImpliedByDomCondition(const Value *Cond,
- const Instruction *ContextI,
- const DataLayout &DL) {
+std::optional<bool> llvm::isImpliedByDomCondition(const Value *Cond,
+ const Instruction *ContextI,
+ const DataLayout &DL) {
assert(Cond->getType()->isIntOrIntVectorTy(1) && "Condition must be bool");
auto PredCond = getDomPredecessorCondition(ContextI);
if (PredCond.first)
return isImpliedCondition(PredCond.first, Cond, DL, PredCond.second);
- return None;
+ return std::nullopt;
}
-Optional<bool> llvm::isImpliedByDomCondition(CmpInst::Predicate Pred,
- const Value *LHS, const Value *RHS,
- const Instruction *ContextI,
- const DataLayout &DL) {
+std::optional<bool> llvm::isImpliedByDomCondition(CmpInst::Predicate Pred,
+ const Value *LHS,
+ const Value *RHS,
+ const Instruction *ContextI,
+ const DataLayout &DL) {
auto PredCond = getDomPredecessorCondition(ContextI);
if (PredCond.first)
return isImpliedCondition(PredCond.first, Pred, LHS, RHS, DL,
PredCond.second);
- return None;
+ return std::nullopt;
}
static void setLimitsForBinOp(const BinaryOperator &BO, APInt &Lower,
@@ -7246,11 +7440,9 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool ForSigned,
for (auto &AssumeVH : AC->assumptionsFor(V)) {
if (!AssumeVH)
continue;
- CallInst *I = cast<CallInst>(AssumeVH);
+ IntrinsicInst *I = cast<IntrinsicInst>(AssumeVH);
assert(I->getParent()->getParent() == CtxI->getParent()->getParent() &&
"Got assumption for the wrong function!");
- assert(I->getCalledFunction()->getIntrinsicID() == Intrinsic::assume &&
- "must be an assume intrinsic");
if (!isValidAssumeForContext(I, CtxI, DT))
continue;
@@ -7271,7 +7463,7 @@ ConstantRange llvm::computeConstantRange(const Value *V, bool ForSigned,
return CR;
}
-static Optional<int64_t>
+static std::optional<int64_t>
getOffsetFromIndex(const GEPOperator *GEP, unsigned Idx, const DataLayout &DL) {
// Skip over the first indices.
gep_type_iterator GTI = gep_type_begin(GEP);
@@ -7283,7 +7475,7 @@ getOffsetFromIndex(const GEPOperator *GEP, unsigned Idx, const DataLayout &DL) {
for (unsigned i = Idx, e = GEP->getNumOperands(); i != e; ++i, ++GTI) {
ConstantInt *OpC = dyn_cast<ConstantInt>(GEP->getOperand(i));
if (!OpC)
- return None;
+ return std::nullopt;
if (OpC->isZero())
continue; // No offset.
@@ -7297,15 +7489,16 @@ getOffsetFromIndex(const GEPOperator *GEP, unsigned Idx, const DataLayout &DL) {
// vector. Multiply the index by the ElementSize.
TypeSize Size = DL.getTypeAllocSize(GTI.getIndexedType());
if (Size.isScalable())
- return None;
- Offset += Size.getFixedSize() * OpC->getSExtValue();
+ return std::nullopt;
+ Offset += Size.getFixedValue() * OpC->getSExtValue();
}
return Offset;
}
-Optional<int64_t> llvm::isPointerOffset(const Value *Ptr1, const Value *Ptr2,
- const DataLayout &DL) {
+std::optional<int64_t> llvm::isPointerOffset(const Value *Ptr1,
+ const Value *Ptr2,
+ const DataLayout &DL) {
APInt Offset1(DL.getIndexTypeSizeInBits(Ptr1->getType()), 0);
APInt Offset2(DL.getIndexTypeSizeInBits(Ptr2->getType()), 0);
Ptr1 = Ptr1->stripAndAccumulateConstantOffsets(DL, Offset1, true);
@@ -7325,7 +7518,7 @@ Optional<int64_t> llvm::isPointerOffset(const Value *Ptr1, const Value *Ptr2,
// handle no other case.
if (!GEP1 || !GEP2 || GEP1->getOperand(0) != GEP2->getOperand(0) ||
GEP1->getSourceElementType() != GEP2->getSourceElementType())
- return None;
+ return std::nullopt;
// Skip any common indices and track the GEP types.
unsigned Idx = 1;
@@ -7336,7 +7529,7 @@ Optional<int64_t> llvm::isPointerOffset(const Value *Ptr1, const Value *Ptr2,
auto IOffset1 = getOffsetFromIndex(GEP1, Idx, DL);
auto IOffset2 = getOffsetFromIndex(GEP2, Idx, DL);
if (!IOffset1 || !IOffset2)
- return None;
+ return std::nullopt;
return *IOffset2 - *IOffset1 + Offset2.getSExtValue() -
Offset1.getSExtValue();
}