aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r--llvm/lib/Analysis/BasicAliasAnalysis.cpp3
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp48
-rw-r--r--llvm/lib/Analysis/LazyValueInfo.cpp5
-rw-r--r--llvm/lib/Analysis/Lint.cpp5
-rw-r--r--llvm/lib/Analysis/Loads.cpp4
-rw-r--r--llvm/lib/Analysis/ModuleSummaryAnalysis.cpp37
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp2
-rw-r--r--llvm/lib/Analysis/TypeMetadataUtils.cpp47
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp125
9 files changed, 168 insertions, 108 deletions
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index b082dfe..16ee2ca 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -1283,8 +1283,7 @@ AliasResult BasicAAResult::aliasGEP(
// VarIndex = Scale*V.
const VariableGEPIndex &Var = DecompGEP1.VarIndices[0];
if (Var.Val.TruncBits == 0 &&
- isKnownNonZero(Var.Val.V, /*Depth=*/0,
- SimplifyQuery(DL, DT, &AC, Var.CxtI))) {
+ isKnownNonZero(Var.Val.V, SimplifyQuery(DL, DT, &AC, Var.CxtI))) {
// Check if abs(V*Scale) >= abs(Scale) holds in the presence of
// potentially wrapping math.
auto MultiplyByScaleNoWrap = [](const VariableGEPIndex &Var) {
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 4e6e666..06ba5ca 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1513,7 +1513,7 @@ static Value *simplifyAShrInst(Value *Op0, Value *Op1, bool IsExact,
// -1 >>a X --> -1
// (-1 << X) a>> X --> -1
- // Do not return Op0 because it may contain undef elements if it's a vector.
+ // We could return the original -1 constant to preserve poison elements.
if (match(Op0, m_AllOnes()) ||
match(Op0, m_Shl(m_AllOnes(), m_Specific(Op1))))
return Constant::getAllOnesValue(Op0->getType());
@@ -1586,10 +1586,10 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
if (match(UnsignedICmp,
m_c_ICmp(UnsignedPred, m_Specific(Y), m_Specific(A)))) {
if (UnsignedPred == ICmpInst::ICMP_UGE && IsAnd &&
- EqPred == ICmpInst::ICMP_NE && isKnownNonZero(B, /*Depth=*/0, Q))
+ EqPred == ICmpInst::ICMP_NE && isKnownNonZero(B, Q))
return UnsignedICmp;
if (UnsignedPred == ICmpInst::ICMP_ULT && !IsAnd &&
- EqPred == ICmpInst::ICMP_EQ && isKnownNonZero(B, /*Depth=*/0, Q))
+ EqPred == ICmpInst::ICMP_EQ && isKnownNonZero(B, Q))
return UnsignedICmp;
}
}
@@ -1607,13 +1607,13 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
// X > Y && Y == 0 --> Y == 0 iff X != 0
// X > Y || Y == 0 --> X > Y iff X != 0
if (UnsignedPred == ICmpInst::ICMP_UGT && EqPred == ICmpInst::ICMP_EQ &&
- isKnownNonZero(X, /*Depth=*/0, Q))
+ isKnownNonZero(X, Q))
return IsAnd ? ZeroICmp : UnsignedICmp;
// X <= Y && Y != 0 --> X <= Y iff X != 0
// X <= Y || Y != 0 --> Y != 0 iff X != 0
if (UnsignedPred == ICmpInst::ICMP_ULE && EqPred == ICmpInst::ICMP_NE &&
- isKnownNonZero(X, /*Depth=*/0, Q))
+ isKnownNonZero(X, Q))
return IsAnd ? UnsignedICmp : ZeroICmp;
// The transforms below here are expected to be handled more generally with
@@ -2281,7 +2281,7 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
// (B ^ ~A) | (A & B) --> B ^ ~A
// (~A ^ B) | (B & A) --> ~A ^ B
// (B ^ ~A) | (B & A) --> B ^ ~A
- if (match(X, m_c_Xor(m_NotForbidUndef(m_Value(A)), m_Value(B))) &&
+ if (match(X, m_c_Xor(m_Not(m_Value(A)), m_Value(B))) &&
match(Y, m_c_And(m_Specific(A), m_Specific(B))))
return X;
@@ -2298,31 +2298,29 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
// (B & ~A) | ~(A | B) --> ~A
// (B & ~A) | ~(B | A) --> ~A
Value *NotA;
- if (match(X,
- m_c_And(m_CombineAnd(m_Value(NotA), m_NotForbidUndef(m_Value(A))),
- m_Value(B))) &&
+ if (match(X, m_c_And(m_CombineAnd(m_Value(NotA), m_Not(m_Value(A))),
+ m_Value(B))) &&
match(Y, m_Not(m_c_Or(m_Specific(A), m_Specific(B)))))
return NotA;
// The same is true of Logical And
// TODO: This could share the logic of the version above if there was a
// version of LogicalAnd that allowed more than just i1 types.
- if (match(X, m_c_LogicalAnd(
- m_CombineAnd(m_Value(NotA), m_NotForbidUndef(m_Value(A))),
- m_Value(B))) &&
+ if (match(X, m_c_LogicalAnd(m_CombineAnd(m_Value(NotA), m_Not(m_Value(A))),
+ m_Value(B))) &&
match(Y, m_Not(m_c_LogicalOr(m_Specific(A), m_Specific(B)))))
return NotA;
// ~(A ^ B) | (A & B) --> ~(A ^ B)
// ~(A ^ B) | (B & A) --> ~(A ^ B)
Value *NotAB;
- if (match(X, m_CombineAnd(m_NotForbidUndef(m_Xor(m_Value(A), m_Value(B))),
+ if (match(X, m_CombineAnd(m_Not(m_Xor(m_Value(A), m_Value(B))),
m_Value(NotAB))) &&
match(Y, m_c_And(m_Specific(A), m_Specific(B))))
return NotAB;
// ~(A & B) | (A ^ B) --> ~(A & B)
// ~(A & B) | (B ^ A) --> ~(A & B)
- if (match(X, m_CombineAnd(m_NotForbidUndef(m_And(m_Value(A), m_Value(B))),
+ if (match(X, m_CombineAnd(m_Not(m_And(m_Value(A), m_Value(B))),
m_Value(NotAB))) &&
match(Y, m_c_Xor(m_Specific(A), m_Specific(B))))
return NotAB;
@@ -2552,9 +2550,8 @@ static Value *simplifyXorInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
// The 'not' op must contain a complete -1 operand (no undef elements for
// vector) for the transform to be safe.
Value *NotA;
- if (match(X,
- m_c_Or(m_CombineAnd(m_NotForbidUndef(m_Value(A)), m_Value(NotA)),
- m_Value(B))) &&
+ if (match(X, m_c_Or(m_CombineAnd(m_Not(m_Value(A)), m_Value(NotA)),
+ m_Value(B))) &&
match(Y, m_c_And(m_Specific(A), m_Specific(B))))
return NotA;
@@ -2817,10 +2814,9 @@ static Constant *computePointerICmp(CmpInst::Predicate Pred, Value *LHS,
// the other operand can not be based on the alloc - if it were, then
// the cmp itself would be a capture.
Value *MI = nullptr;
- if (isAllocLikeFn(LHS, TLI) && llvm::isKnownNonZero(RHS, /*Depth=*/0, Q))
+ if (isAllocLikeFn(LHS, TLI) && llvm::isKnownNonZero(RHS, Q))
MI = LHS;
- else if (isAllocLikeFn(RHS, TLI) &&
- llvm::isKnownNonZero(LHS, /*Depth=*/0, Q))
+ else if (isAllocLikeFn(RHS, TLI) && llvm::isKnownNonZero(LHS, Q))
MI = RHS;
if (MI) {
// FIXME: This is incorrect, see PR54002. While we can assume that the
@@ -2976,12 +2972,12 @@ static Value *simplifyICmpWithZero(CmpInst::Predicate Pred, Value *LHS,
return getTrue(ITy);
case ICmpInst::ICMP_EQ:
case ICmpInst::ICMP_ULE:
- if (isKnownNonZero(LHS, /*Depth=*/0, Q))
+ if (isKnownNonZero(LHS, Q))
return getFalse(ITy);
break;
case ICmpInst::ICMP_NE:
case ICmpInst::ICMP_UGT:
- if (isKnownNonZero(LHS, /*Depth=*/0, Q))
+ if (isKnownNonZero(LHS, Q))
return getTrue(ITy);
break;
case ICmpInst::ICMP_SLT: {
@@ -2996,7 +2992,7 @@ static Value *simplifyICmpWithZero(CmpInst::Predicate Pred, Value *LHS,
KnownBits LHSKnown = computeKnownBits(LHS, /* Depth */ 0, Q);
if (LHSKnown.isNegative())
return getTrue(ITy);
- if (LHSKnown.isNonNegative() && isKnownNonZero(LHS, /*Depth=*/0, Q))
+ if (LHSKnown.isNonNegative() && isKnownNonZero(LHS, Q))
return getFalse(ITy);
break;
}
@@ -3012,7 +3008,7 @@ static Value *simplifyICmpWithZero(CmpInst::Predicate Pred, Value *LHS,
KnownBits LHSKnown = computeKnownBits(LHS, /* Depth */ 0, Q);
if (LHSKnown.isNegative())
return getFalse(ITy);
- if (LHSKnown.isNonNegative() && isKnownNonZero(LHS, /*Depth=*/0, Q))
+ if (LHSKnown.isNonNegative() && isKnownNonZero(LHS, Q))
return getTrue(ITy);
break;
}
@@ -3165,7 +3161,7 @@ static Value *simplifyICmpWithBinOpOnLHS(CmpInst::Predicate Pred,
const APInt *C;
if ((match(LBO, m_LShr(m_Specific(RHS), m_APInt(C))) && *C != 0) ||
(match(LBO, m_UDiv(m_Specific(RHS), m_APInt(C))) && *C != 1)) {
- if (isKnownNonZero(RHS, /*Depth=*/0, Q)) {
+ if (isKnownNonZero(RHS, Q)) {
switch (Pred) {
default:
break;
@@ -3398,7 +3394,7 @@ static Value *simplifyICmpWithBinOp(CmpInst::Predicate Pred, Value *LHS,
bool NUW = Q.IIQ.hasNoUnsignedWrap(LBO) && Q.IIQ.hasNoUnsignedWrap(RBO);
bool NSW = Q.IIQ.hasNoSignedWrap(LBO) && Q.IIQ.hasNoSignedWrap(RBO);
if (!NUW || (ICmpInst::isSigned(Pred) && !NSW) ||
- !isKnownNonZero(LBO->getOperand(0), /*Depth=*/0, Q))
+ !isKnownNonZero(LBO->getOperand(0), Q))
break;
if (Value *V = simplifyICmpInst(Pred, LBO->getOperand(1),
RBO->getOperand(1), Q, MaxRecurse - 1))
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp
index 3223b05..6cded82 100644
--- a/llvm/lib/Analysis/LazyValueInfo.cpp
+++ b/llvm/lib/Analysis/LazyValueInfo.cpp
@@ -645,7 +645,7 @@ LazyValueInfoImpl::solveBlockValueImpl(Value *Val, BasicBlock *BB) {
// instruction is placed, even if it could legally be hoisted much higher.
// That is unfortunate.
PointerType *PT = dyn_cast<PointerType>(BBI->getType());
- if (PT && isKnownNonZero(BBI, /*Depth=*/0, DL))
+ if (PT && isKnownNonZero(BBI, DL))
return ValueLatticeElement::getNot(ConstantPointerNull::get(PT));
if (BBI->getType()->isIntegerTy()) {
@@ -1863,8 +1863,7 @@ LazyValueInfo::getPredicateAt(unsigned Pred, Value *V, Constant *C,
Module *M = CxtI->getModule();
const DataLayout &DL = M->getDataLayout();
if (V->getType()->isPointerTy() && C->isNullValue() &&
- isKnownNonZero(V->stripPointerCastsSameRepresentation(), /*Depth=*/0,
- DL)) {
+ isKnownNonZero(V->stripPointerCastsSameRepresentation(), DL)) {
if (Pred == ICmpInst::ICMP_EQ)
return LazyValueInfo::False;
else if (Pred == ICmpInst::ICMP_NE)
diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp
index 0694c29..1ab856a 100644
--- a/llvm/lib/Analysis/Lint.cpp
+++ b/llvm/lib/Analysis/Lint.cpp
@@ -350,10 +350,7 @@ void Lint::visitCallBase(CallBase &I) {
}
case Intrinsic::vastart:
- Check(I.getParent()->getParent()->isVarArg(),
- "Undefined behavior: va_start called in a non-varargs function",
- &I);
-
+ // vastart in non-varargs function is rejected by the verifier
visitMemoryReference(I, MemoryLocation::getForArgument(&I, 0, TLI),
std::nullopt, nullptr, MemRef::Read | MemRef::Write);
break;
diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp
index b540340..ac508e1 100644
--- a/llvm/lib/Analysis/Loads.cpp
+++ b/llvm/lib/Analysis/Loads.cpp
@@ -100,7 +100,7 @@ static bool isDereferenceableAndAlignedPointer(
if (KnownDerefBytes.getBoolValue() && KnownDerefBytes.uge(Size) &&
!CheckForFreed)
if (!CheckForNonNull ||
- isKnownNonZero(V, /*Depth=*/0, SimplifyQuery(DL, DT, AC, CtxI))) {
+ isKnownNonZero(V, SimplifyQuery(DL, DT, AC, CtxI))) {
// As we recursed through GEPs to get here, we've incrementally checked
// that each step advanced by a multiple of the alignment. If our base is
// properly aligned, then the original offset accessed must also be.
@@ -134,7 +134,7 @@ static bool isDereferenceableAndAlignedPointer(
if (getObjectSize(V, ObjSize, DL, TLI, Opts)) {
APInt KnownDerefBytes(Size.getBitWidth(), ObjSize);
if (KnownDerefBytes.getBoolValue() && KnownDerefBytes.uge(Size) &&
- isKnownNonZero(V, /*Depth=*/0, SimplifyQuery(DL, DT, AC, CtxI)) &&
+ isKnownNonZero(V, SimplifyQuery(DL, DT, AC, CtxI)) &&
!V->canBeFreed()) {
// As we recursed through GEPs to get here, we've incrementally
// checked that each step advanced by a multiple of the alignment. If
diff --git a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
index deda1ee..c3d15af 100644
--- a/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
+++ b/llvm/lib/Analysis/ModuleSummaryAnalysis.cpp
@@ -22,6 +22,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
+#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemoryProfileInfo.h"
@@ -668,7 +669,8 @@ static void computeFunctionSummary(
/// within the initializer.
static void findFuncPointers(const Constant *I, uint64_t StartingOffset,
const Module &M, ModuleSummaryIndex &Index,
- VTableFuncList &VTableFuncs) {
+ VTableFuncList &VTableFuncs,
+ const GlobalVariable &OrigGV) {
// First check if this is a function pointer.
if (I->getType()->isPointerTy()) {
auto C = I->stripPointerCasts();
@@ -696,7 +698,7 @@ static void findFuncPointers(const Constant *I, uint64_t StartingOffset,
auto Offset = SL->getElementOffset(EI.index());
unsigned Op = SL->getElementContainingOffset(Offset);
findFuncPointers(cast<Constant>(I->getOperand(Op)),
- StartingOffset + Offset, M, Index, VTableFuncs);
+ StartingOffset + Offset, M, Index, VTableFuncs, OrigGV);
}
} else if (auto *C = dyn_cast<ConstantArray>(I)) {
ArrayType *ATy = C->getType();
@@ -704,7 +706,34 @@ static void findFuncPointers(const Constant *I, uint64_t StartingOffset,
uint64_t EltSize = DL.getTypeAllocSize(EltTy);
for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {
findFuncPointers(cast<Constant>(I->getOperand(i)),
- StartingOffset + i * EltSize, M, Index, VTableFuncs);
+ StartingOffset + i * EltSize, M, Index, VTableFuncs,
+ OrigGV);
+ }
+ } else if (const auto *CE = dyn_cast<ConstantExpr>(I)) {
+ // For relative vtables, the next sub-component should be a trunc.
+ if (CE->getOpcode() != Instruction::Trunc ||
+ !(CE = dyn_cast<ConstantExpr>(CE->getOperand(0))))
+ return;
+
+ // If this constant can be reduced to the offset between a function and a
+ // global, then we know this is a valid virtual function if the RHS is the
+ // original vtable we're scanning through.
+ if (CE->getOpcode() == Instruction::Sub) {
+ GlobalValue *LHS, *RHS;
+ APSInt LHSOffset, RHSOffset;
+ if (IsConstantOffsetFromGlobal(CE->getOperand(0), LHS, LHSOffset, DL) &&
+ IsConstantOffsetFromGlobal(CE->getOperand(1), RHS, RHSOffset, DL) &&
+ RHS == &OrigGV &&
+
+ // For relative vtables, this component should point to the callable
+ // function without any offsets.
+ LHSOffset == 0 &&
+
+ // Also, the RHS should always point to somewhere within the vtable.
+ RHSOffset <=
+ static_cast<uint64_t>(DL.getTypeAllocSize(OrigGV.getInitializer()->getType()))) {
+ findFuncPointers(LHS, StartingOffset, M, Index, VTableFuncs, OrigGV);
+ }
}
}
}
@@ -717,7 +746,7 @@ static void computeVTableFuncs(ModuleSummaryIndex &Index,
return;
findFuncPointers(V.getInitializer(), /*StartingOffset=*/0, M, Index,
- VTableFuncs);
+ VTableFuncs, V);
#ifndef NDEBUG
// Validate that the VTableFuncs list is ordered by offset.
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 1c98b02..95440dd 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -6900,7 +6900,7 @@ const ConstantRange &ScalarEvolution::getRangeRef(
uint64_t Rem = MaxVal.urem(Align);
MaxVal -= APInt(BitWidth, Rem);
APInt MinVal = APInt::getZero(BitWidth);
- if (llvm::isKnownNonZero(V, /*Depth=*/0, DL))
+ if (llvm::isKnownNonZero(V, DL))
MinVal = Align;
ConservativeResult = ConservativeResult.intersectWith(
ConstantRange::getNonEmpty(MinVal, MaxVal + 1), RangeType);
diff --git a/llvm/lib/Analysis/TypeMetadataUtils.cpp b/llvm/lib/Analysis/TypeMetadataUtils.cpp
index b8dcc39..67ce154 100644
--- a/llvm/lib/Analysis/TypeMetadataUtils.cpp
+++ b/llvm/lib/Analysis/TypeMetadataUtils.cpp
@@ -67,6 +67,14 @@ static void findLoadCallsAtConstantOffset(
findLoadCallsAtConstantOffset(M, DevirtCalls, User, Offset + GEPOffset,
CI, DT);
}
+ } else if (auto *Call = dyn_cast<CallInst>(User)) {
+ if (Call->getIntrinsicID() == llvm::Intrinsic::load_relative) {
+ if (auto *LoadOffset = dyn_cast<ConstantInt>(Call->getOperand(1))) {
+ findCallsAtConstantOffset(DevirtCalls, nullptr, User,
+ Offset + LoadOffset->getSExtValue(), CI,
+ DT);
+ }
+ }
}
}
}
@@ -131,6 +139,12 @@ void llvm::findDevirtualizableCallsForTypeCheckedLoad(
Constant *llvm::getPointerAtOffset(Constant *I, uint64_t Offset, Module &M,
Constant *TopLevelGlobal) {
+ // TODO: Ideally it would be the caller who knows if it's appropriate to strip
+ // the DSOLocalEquicalent. More generally, it would feel more appropriate to
+ // have two functions that handle absolute and relative pointers separately.
+ if (auto *Equiv = dyn_cast<DSOLocalEquivalent>(I))
+ I = Equiv->getGlobalValue();
+
if (I->getType()->isPointerTy()) {
if (Offset == 0)
return I;
@@ -161,7 +175,7 @@ Constant *llvm::getPointerAtOffset(Constant *I, uint64_t Offset, Module &M,
Offset % ElemSize, M, TopLevelGlobal);
}
- // (Swift-specific) relative-pointer support starts here.
+ // Relative-pointer support starts here.
if (auto *CI = dyn_cast<ConstantInt>(I)) {
if (Offset == 0 && CI->isZero()) {
return I;
@@ -221,19 +235,26 @@ llvm::getFunctionAtVTableOffset(GlobalVariable *GV, uint64_t Offset,
return std::pair<Function *, Constant *>(Fn, C);
}
-void llvm::replaceRelativePointerUsersWithZero(Function *F) {
- for (auto *U : F->users()) {
- auto *PtrExpr = dyn_cast<ConstantExpr>(U);
- if (!PtrExpr || PtrExpr->getOpcode() != Instruction::PtrToInt)
- continue;
+static void replaceRelativePointerUserWithZero(User *U) {
+ auto *PtrExpr = dyn_cast<ConstantExpr>(U);
+ if (!PtrExpr || PtrExpr->getOpcode() != Instruction::PtrToInt)
+ return;
- for (auto *PtrToIntUser : PtrExpr->users()) {
- auto *SubExpr = dyn_cast<ConstantExpr>(PtrToIntUser);
- if (!SubExpr || SubExpr->getOpcode() != Instruction::Sub)
- continue;
+ for (auto *PtrToIntUser : PtrExpr->users()) {
+ auto *SubExpr = dyn_cast<ConstantExpr>(PtrToIntUser);
+ if (!SubExpr || SubExpr->getOpcode() != Instruction::Sub)
+ return;
- SubExpr->replaceNonMetadataUsesWith(
- ConstantInt::get(SubExpr->getType(), 0));
- }
+ SubExpr->replaceNonMetadataUsesWith(
+ ConstantInt::get(SubExpr->getType(), 0));
+ }
+}
+
+void llvm::replaceRelativePointerUsersWithZero(Constant *C) {
+ for (auto *U : C->users()) {
+ if (auto *Equiv = dyn_cast<DSOLocalEquivalent>(U))
+ replaceRelativePointerUsersWithZero(Equiv);
+ else
+ replaceRelativePointerUserWithZero(U);
}
}
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 5beea61..ab2f43e 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -272,7 +272,7 @@ bool llvm::isKnownToBeAPowerOfTwo(const Value *V, const DataLayout &DL,
}
static bool isKnownNonZero(const Value *V, const APInt &DemandedElts,
- unsigned Depth, const SimplifyQuery &Q);
+ const SimplifyQuery &Q, unsigned Depth);
bool llvm::isKnownNonNegative(const Value *V, const SimplifyQuery &SQ,
unsigned Depth) {
@@ -288,7 +288,7 @@ bool llvm::isKnownPositive(const Value *V, const SimplifyQuery &SQ,
// this updated.
KnownBits Known = computeKnownBits(V, Depth, SQ);
return Known.isNonNegative() &&
- (Known.isNonZero() || isKnownNonZero(V, Depth, SQ));
+ (Known.isNonZero() || isKnownNonZero(V, SQ, Depth));
}
bool llvm::isKnownNegative(const Value *V, const SimplifyQuery &SQ,
@@ -868,7 +868,7 @@ static void computeKnownBitsFromShiftOperator(
bool ShAmtNonZero =
Known.isNonZero() ||
(Known.getMaxValue().ult(Known.getBitWidth()) &&
- isKnownNonZero(I->getOperand(1), DemandedElts, Depth + 1, Q));
+ isKnownNonZero(I->getOperand(1), DemandedElts, Q, Depth + 1));
Known = KF(Known2, Known, ShAmtNonZero);
}
@@ -2124,7 +2124,7 @@ bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero, unsigned Depth,
case Instruction::Mul:
return isKnownToBeAPowerOfTwo(I->getOperand(1), OrZero, Depth, Q) &&
isKnownToBeAPowerOfTwo(I->getOperand(0), OrZero, Depth, Q) &&
- (OrZero || isKnownNonZero(I, Depth, Q));
+ (OrZero || isKnownNonZero(I, Q, Depth));
case Instruction::And:
// A power of two and'd with anything is a power of two or zero.
if (OrZero &&
@@ -2134,7 +2134,7 @@ bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero, unsigned Depth,
// X & (-X) is always a power of two or zero.
if (match(I->getOperand(0), m_Neg(m_Specific(I->getOperand(1)))) ||
match(I->getOperand(1), m_Neg(m_Specific(I->getOperand(0)))))
- return OrZero || isKnownNonZero(I->getOperand(0), Depth, Q);
+ return OrZero || isKnownNonZero(I->getOperand(0), Q, Depth);
return false;
case Instruction::Add: {
// Adding a power-of-two or zero to the same power-of-two or zero yields
@@ -2249,7 +2249,7 @@ static bool isGEPKnownNonNull(const GEPOperator *GEP, unsigned Depth,
// If the base pointer is non-null, we cannot walk to a null address with an
// inbounds GEP in address space zero.
- if (isKnownNonZero(GEP->getPointerOperand(), Depth, Q))
+ if (isKnownNonZero(GEP->getPointerOperand(), Q, Depth))
return true;
// Walk the GEP operands and see if any operand introduces a non-zero offset.
@@ -2288,7 +2288,7 @@ static bool isGEPKnownNonNull(const GEPOperator *GEP, unsigned Depth,
if (Depth++ >= MaxAnalysisRecursionDepth)
continue;
- if (isKnownNonZero(GTI.getOperand(), Depth, Q))
+ if (isKnownNonZero(GTI.getOperand(), Q, Depth))
return true;
}
@@ -2441,8 +2441,8 @@ static bool isNonZeroAdd(const APInt &DemandedElts, unsigned Depth,
const SimplifyQuery &Q, unsigned BitWidth, Value *X,
Value *Y, bool NSW, bool NUW) {
if (NUW)
- return isKnownNonZero(Y, DemandedElts, Depth, Q) ||
- isKnownNonZero(X, DemandedElts, Depth, Q);
+ return isKnownNonZero(Y, DemandedElts, Q, Depth) ||
+ isKnownNonZero(X, DemandedElts, Q, Depth);
KnownBits XKnown = computeKnownBits(X, DemandedElts, Depth, Q);
KnownBits YKnown = computeKnownBits(Y, DemandedElts, Depth, Q);
@@ -2450,8 +2450,8 @@ static bool isNonZeroAdd(const APInt &DemandedElts, unsigned Depth,
// 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(Y, DemandedElts, Depth, Q) ||
- isKnownNonZero(X, DemandedElts, Depth, Q))
+ if (isKnownNonZero(Y, DemandedElts, Q, Depth) ||
+ isKnownNonZero(X, DemandedElts, Q, Depth))
return true;
// If X and Y are both negative (as signed values) then their sum is not
@@ -2485,7 +2485,7 @@ static bool isNonZeroSub(const APInt &DemandedElts, unsigned Depth,
Value *Y) {
// TODO: Move this case into isKnownNonEqual().
if (auto *C = dyn_cast<Constant>(X))
- if (C->isNullValue() && isKnownNonZero(Y, DemandedElts, Depth, Q))
+ if (C->isNullValue() && isKnownNonZero(Y, DemandedElts, Q, Depth))
return true;
return ::isKnownNonEqual(X, Y, Depth, Q);
@@ -2497,18 +2497,18 @@ static bool isNonZeroMul(const APInt &DemandedElts, unsigned Depth,
// If X and Y are non-zero then so is X * Y as long as the multiplication
// does not overflow.
if (NSW || NUW)
- return isKnownNonZero(X, DemandedElts, Depth, Q) &&
- isKnownNonZero(Y, DemandedElts, Depth, Q);
+ return isKnownNonZero(X, DemandedElts, Q, Depth) &&
+ isKnownNonZero(Y, DemandedElts, Q, Depth);
// If either X or Y is odd, then if the other is non-zero the result can't
// be zero.
KnownBits XKnown = computeKnownBits(X, DemandedElts, Depth, Q);
if (XKnown.One[0])
- return isKnownNonZero(Y, DemandedElts, Depth, Q);
+ return isKnownNonZero(Y, DemandedElts, Q, Depth);
KnownBits YKnown = computeKnownBits(Y, DemandedElts, Depth, Q);
if (YKnown.One[0])
- return XKnown.isNonZero() || isKnownNonZero(X, DemandedElts, Depth, Q);
+ return XKnown.isNonZero() || isKnownNonZero(X, DemandedElts, Q, Depth);
// If there exists any subset of X (sX) and subset of Y (sY) s.t sX * sY is
// non-zero, then X * Y is non-zero. We can find sX and sY by just taking
@@ -2564,7 +2564,7 @@ static bool isNonZeroShift(const Operator *I, const APInt &DemandedElts,
// non-zero then at least one non-zero bit must remain.
if (InvShiftOp(KnownVal.Zero, NumBits - MaxShift)
.eq(InvShiftOp(APInt::getAllOnes(NumBits), NumBits - MaxShift)) &&
- isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q))
+ isKnownNonZero(I->getOperand(0), DemandedElts, Q, Depth))
return true;
return false;
@@ -2613,7 +2613,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
Type *FromTy = I->getOperand(0)->getType();
if ((FromTy->isIntOrIntVectorTy() || FromTy->isPtrOrPtrVectorTy()) &&
(BitWidth % getBitWidth(FromTy->getScalarType(), Q.DL)) == 0)
- return isKnownNonZero(I->getOperand(0), Depth, Q);
+ return isKnownNonZero(I->getOperand(0), Q, Depth);
} break;
case Instruction::IntToPtr:
// Note that we have to take special care to avoid looking through
@@ -2622,7 +2622,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
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);
+ return isKnownNonZero(I->getOperand(0), Q, Depth);
break;
case Instruction::PtrToInt:
// Similar to int2ptr above, we can look through ptr2int here if the cast
@@ -2630,25 +2630,25 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
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);
+ return isKnownNonZero(I->getOperand(0), Q, Depth);
break;
case Instruction::Sub:
return isNonZeroSub(DemandedElts, Depth, Q, BitWidth, I->getOperand(0),
I->getOperand(1));
case Instruction::Or:
// X | Y != 0 if X != 0 or Y != 0.
- return isKnownNonZero(I->getOperand(1), DemandedElts, Depth, Q) ||
- isKnownNonZero(I->getOperand(0), DemandedElts, Depth, Q);
+ return isKnownNonZero(I->getOperand(1), DemandedElts, Q, Depth) ||
+ isKnownNonZero(I->getOperand(0), DemandedElts, Q, Depth);
case Instruction::SExt:
case Instruction::ZExt:
// ext X != 0 if X != 0.
- return isKnownNonZero(I->getOperand(0), Depth, Q);
+ return isKnownNonZero(I->getOperand(0), Q, Depth);
case Instruction::Shl: {
// shl nsw/nuw can't remove any non-zero bits.
const OverflowingBinaryOperator *BO = cast<OverflowingBinaryOperator>(I);
if (Q.IIQ.hasNoUnsignedWrap(BO) || Q.IIQ.hasNoSignedWrap(BO))
- return isKnownNonZero(I->getOperand(0), Depth, Q);
+ return isKnownNonZero(I->getOperand(0), Q, Depth);
// 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.
@@ -2664,7 +2664,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
// shr exact can only shift out zero bits.
const PossiblyExactOperator *BO = cast<PossiblyExactOperator>(I);
if (BO->isExact())
- return isKnownNonZero(I->getOperand(0), Depth, Q);
+ return isKnownNonZero(I->getOperand(0), Q, Depth);
// 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.
@@ -2680,7 +2680,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
// X / Y
// 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);
+ return isKnownNonZero(I->getOperand(0), DemandedElts, Q, Depth);
std::optional<bool> XUgeY;
KnownBits XKnown =
@@ -2730,7 +2730,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
Value *Op;
Op = IsTrueArm ? I->getOperand(1) : I->getOperand(2);
// Op is trivially non-zero.
- if (isKnownNonZero(Op, DemandedElts, Depth, Q))
+ if (isKnownNonZero(Op, DemandedElts, Q, Depth))
return true;
// The condition of the select dominates the true/false arm. Check if the
@@ -2780,7 +2780,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
}
}
// Finally recurse on the edge and check it directly.
- return isKnownNonZero(U.get(), DemandedElts, NewDepth, RecQ);
+ return isKnownNonZero(U.get(), DemandedElts, RecQ, NewDepth);
});
}
case Instruction::InsertElement: {
@@ -2802,9 +2802,9 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
// Result is zero if Elt is non-zero and rest of the demanded elts in Vec
// are non-zero.
- return (SkipElt || isKnownNonZero(Elt, Depth, Q)) &&
+ return (SkipElt || isKnownNonZero(Elt, Q, Depth)) &&
(DemandedVecElts.isZero() ||
- isKnownNonZero(Vec, DemandedVecElts, Depth, Q));
+ isKnownNonZero(Vec, DemandedVecElts, Q, Depth));
}
case Instruction::ExtractElement:
if (const auto *EEI = dyn_cast<ExtractElementInst>(I)) {
@@ -2816,7 +2816,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
APInt DemandedVecElts = APInt::getAllOnes(NumElts);
if (CIdx && CIdx->getValue().ult(NumElts))
DemandedVecElts = APInt::getOneBitSet(NumElts, CIdx->getZExtValue());
- return isKnownNonZero(Vec, DemandedVecElts, Depth, Q);
+ return isKnownNonZero(Vec, DemandedVecElts, Q, Depth);
}
}
break;
@@ -2831,12 +2831,12 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
break;
// If demanded elements for both vecs are non-zero, the shuffle is non-zero.
return (DemandedRHS.isZero() ||
- isKnownNonZero(Shuf->getOperand(1), DemandedRHS, Depth, Q)) &&
+ isKnownNonZero(Shuf->getOperand(1), DemandedRHS, Q, Depth)) &&
(DemandedLHS.isZero() ||
- isKnownNonZero(Shuf->getOperand(0), DemandedLHS, Depth, Q));
+ isKnownNonZero(Shuf->getOperand(0), DemandedLHS, Q, Depth));
}
case Instruction::Freeze:
- return isKnownNonZero(I->getOperand(0), Depth, Q) &&
+ return isKnownNonZero(I->getOperand(0), Q, Depth) &&
isGuaranteedNotToBePoison(I->getOperand(0), Q.AC, Q.CxtI, Q.DT,
Depth);
case Instruction::Load: {
@@ -2886,7 +2886,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
if (Call->isReturnNonNull())
return true;
if (const auto *RP = getArgumentAliasingToReturnedPointer(Call, true))
- return isKnownNonZero(RP, Depth, Q);
+ return isKnownNonZero(RP, Q, Depth);
} else {
if (MDNode *Ranges = Q.IIQ.getMetadata(Call, LLVMContext::MD_range))
return rangeMetadataExcludesValue(Ranges, APInt::getZero(BitWidth));
@@ -2896,7 +2896,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
return true;
}
if (const Value *RV = Call->getReturnedArgOperand())
- if (RV->getType() == I->getType() && isKnownNonZero(RV, Depth, Q))
+ if (RV->getType() == I->getType() && isKnownNonZero(RV, Q, Depth))
return true;
}
@@ -2908,7 +2908,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
case Intrinsic::bitreverse:
case Intrinsic::bswap:
case Intrinsic::ctpop:
- return isKnownNonZero(II->getArgOperand(0), DemandedElts, Depth, Q);
+ return isKnownNonZero(II->getArgOperand(0), DemandedElts, Q, Depth);
// NB: We don't do usub_sat here as in any case we can prove its
// non-zero, we will fold it to `sub nuw` in InstCombine.
case Intrinsic::ssub_sat:
@@ -2924,11 +2924,11 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
case Intrinsic::vector_reduce_umin:
case Intrinsic::vector_reduce_smax:
case Intrinsic::vector_reduce_smin:
- return isKnownNonZero(II->getArgOperand(0), Depth, Q);
+ return isKnownNonZero(II->getArgOperand(0), Q, Depth);
case Intrinsic::umax:
case Intrinsic::uadd_sat:
- return isKnownNonZero(II->getArgOperand(1), DemandedElts, Depth, Q) ||
- isKnownNonZero(II->getArgOperand(0), DemandedElts, Depth, Q);
+ return isKnownNonZero(II->getArgOperand(1), DemandedElts, Q, Depth) ||
+ isKnownNonZero(II->getArgOperand(0), DemandedElts, Q, Depth);
case Intrinsic::smax: {
// If either arg is strictly positive the result is non-zero. Otherwise
// the result is non-zero if both ops are non-zero.
@@ -2936,7 +2936,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
const KnownBits &OpKnown) {
if (!OpNonZero.has_value())
OpNonZero = OpKnown.isNonZero() ||
- isKnownNonZero(Op, DemandedElts, Depth, Q);
+ isKnownNonZero(Op, DemandedElts, Q, Depth);
return *OpNonZero;
};
// Avoid re-computing isKnownNonZero.
@@ -2971,8 +2971,8 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
}
[[fallthrough]];
case Intrinsic::umin:
- return isKnownNonZero(II->getArgOperand(0), DemandedElts, Depth, Q) &&
- isKnownNonZero(II->getArgOperand(1), DemandedElts, Depth, Q);
+ return isKnownNonZero(II->getArgOperand(0), DemandedElts, Q, Depth) &&
+ isKnownNonZero(II->getArgOperand(1), DemandedElts, Q, Depth);
case Intrinsic::cttz:
return computeKnownBits(II->getArgOperand(0), DemandedElts, Depth, Q)
.Zero[0];
@@ -2983,12 +2983,12 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
case Intrinsic::fshl:
// If Op0 == Op1, this is a rotate. rotate(x, y) != 0 iff x != 0.
if (II->getArgOperand(0) == II->getArgOperand(1))
- return isKnownNonZero(II->getArgOperand(0), DemandedElts, Depth, Q);
+ return isKnownNonZero(II->getArgOperand(0), DemandedElts, Q, Depth);
break;
case Intrinsic::vscale:
return true;
case Intrinsic::experimental_get_vector_length:
- return isKnownNonZero(I->getOperand(0), Depth, Q);
+ return isKnownNonZero(I->getOperand(0), Q, Depth);
default:
break;
}
@@ -3010,8 +3010,8 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
/// specified, perform context-sensitive analysis and return true if the
/// pointer couldn't possibly be null at the specified instruction.
/// Supports values with integer or pointer type and vectors of integers.
-bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
- const SimplifyQuery &Q) {
+bool isKnownNonZero(const Value *V, const APInt &DemandedElts,
+ const SimplifyQuery &Q, unsigned Depth) {
Type *Ty = V->getType();
#ifndef NDEBUG
@@ -3101,12 +3101,12 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts, unsigned Depth,
return false;
}
-bool llvm::isKnownNonZero(const Value *V, unsigned Depth,
- const SimplifyQuery &Q) {
+bool llvm::isKnownNonZero(const Value *V, const SimplifyQuery &Q,
+ unsigned Depth) {
auto *FVTy = dyn_cast<FixedVectorType>(V->getType());
APInt DemandedElts =
FVTy ? APInt::getAllOnes(FVTy->getNumElements()) : APInt(1, 1);
- return ::isKnownNonZero(V, DemandedElts, Depth, Q);
+ return ::isKnownNonZero(V, DemandedElts, Q, Depth);
}
/// If the pair of operators are the same invertible function, return the
@@ -3253,7 +3253,7 @@ static bool isModifyingBinopOfNonZero(const Value *V1, const Value *V2,
Op = BO->getOperand(0);
else
return false;
- return isKnownNonZero(Op, Depth + 1, Q);
+ return isKnownNonZero(Op, Q, Depth + 1);
}
return false;
}
@@ -3266,7 +3266,7 @@ static bool isNonEqualMul(const Value *V1, const Value *V2, unsigned Depth,
const APInt *C;
return match(OBO, m_Mul(m_Specific(V1), m_APInt(C))) &&
(OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap()) &&
- !C->isZero() && !C->isOne() && isKnownNonZero(V1, Depth + 1, Q);
+ !C->isZero() && !C->isOne() && isKnownNonZero(V1, Q, Depth + 1);
}
return false;
}
@@ -3279,7 +3279,7 @@ static bool isNonEqualShl(const Value *V1, const Value *V2, unsigned Depth,
const APInt *C;
return match(OBO, m_Shl(m_Specific(V1), m_APInt(C))) &&
(OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap()) &&
- !C->isZero() && isKnownNonZero(V1, Depth + 1, Q);
+ !C->isZero() && isKnownNonZero(V1, Q, Depth + 1);
}
return false;
}
@@ -4664,6 +4664,12 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
return;
}
+ if (isa<PoisonValue>(V)) {
+ Known.KnownFPClasses = fcNone;
+ Known.SignBit = false;
+ return;
+ }
+
// Try to handle fixed width vector constants
auto *VFVTy = dyn_cast<FixedVectorType>(V->getType());
const Constant *CV = dyn_cast<Constant>(V);
@@ -5026,6 +5032,19 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
break;
}
+ case Intrinsic::vector_reduce_fmax:
+ case Intrinsic::vector_reduce_fmin:
+ case Intrinsic::vector_reduce_fmaximum:
+ case Intrinsic::vector_reduce_fminimum: {
+ // reduce min/max will choose an element from one of the vector elements,
+ // so we can infer and class information that is common to all elements.
+ Known = computeKnownFPClass(II->getArgOperand(0), II->getFastMathFlags(),
+ InterestedClasses, Depth + 1, Q);
+ // Can only propagate sign if output is never NaN.
+ if (!Known.isKnownNeverNaN())
+ Known.SignBit.reset();
+ break;
+ }
case Intrinsic::trunc:
case Intrinsic::floor:
case Intrinsic::ceil: