summaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/InstructionSimplify.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/Analysis/InstructionSimplify.cpp
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
Notes
Diffstat (limited to 'llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r--llvm/lib/Analysis/InstructionSimplify.cpp401
1 files changed, 288 insertions, 113 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index d7510c8991013..0975a65d183e4 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -222,7 +222,7 @@ static bool valueDominatesPHI(Value *V, PHINode *P, const DominatorTree *DT) {
// Otherwise, if the instruction is in the entry block and is not an invoke,
// then it obviously dominates all phi nodes.
if (I->getParent() == &I->getFunction()->getEntryBlock() &&
- !isa<InvokeInst>(I))
+ !isa<InvokeInst>(I) && !isa<CallBrInst>(I))
return true;
return false;
@@ -707,9 +707,8 @@ static Constant *stripAndComputeConstantOffsets(const DataLayout &DL, Value *&V,
Offset = Offset.sextOrTrunc(IntIdxTy->getIntegerBitWidth());
Constant *OffsetIntPtr = ConstantInt::get(IntIdxTy, Offset);
- if (V->getType()->isVectorTy())
- return ConstantVector::getSplat(V->getType()->getVectorNumElements(),
- OffsetIntPtr);
+ if (VectorType *VecTy = dyn_cast<VectorType>(V->getType()))
+ return ConstantVector::getSplat(VecTy->getElementCount(), OffsetIntPtr);
return OffsetIntPtr;
}
@@ -943,11 +942,12 @@ static Value *simplifyDivRem(Value *Op0, Value *Op1, bool IsDiv) {
if (match(Op1, m_Zero()))
return UndefValue::get(Ty);
- // If any element of a constant divisor vector is zero or undef, the whole op
- // is undef.
+ // If any element of a constant divisor fixed width vector is zero or undef,
+ // the whole op is undef.
auto *Op1C = dyn_cast<Constant>(Op1);
- if (Op1C && Ty->isVectorTy()) {
- unsigned NumElts = Ty->getVectorNumElements();
+ auto *VTy = dyn_cast<FixedVectorType>(Ty);
+ if (Op1C && VTy) {
+ unsigned NumElts = VTy->getNumElements();
for (unsigned i = 0; i != NumElts; ++i) {
Constant *Elt = Op1C->getAggregateElement(i);
if (Elt && (Elt->isNullValue() || isa<UndefValue>(Elt)))
@@ -1222,7 +1222,8 @@ static bool isUndefShift(Value *Amount) {
// If all lanes of a vector shift are undefined the whole shift is.
if (isa<ConstantVector>(C) || isa<ConstantDataVector>(C)) {
- for (unsigned I = 0, E = C->getType()->getVectorNumElements(); I != E; ++I)
+ for (unsigned I = 0, E = cast<VectorType>(C->getType())->getNumElements();
+ I != E; ++I)
if (!isUndefShift(C->getAggregateElement(I)))
return false;
return true;
@@ -1429,9 +1430,6 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
if (match(UnsignedICmp,
m_c_ICmp(UnsignedPred, m_Specific(A), m_Specific(B))) &&
ICmpInst::isUnsigned(UnsignedPred)) {
- if (UnsignedICmp->getOperand(0) != A)
- UnsignedPred = ICmpInst::getSwappedPredicate(UnsignedPred);
-
// A >=/<= B || (A - B) != 0 <--> true
if ((UnsignedPred == ICmpInst::ICMP_UGE ||
UnsignedPred == ICmpInst::ICMP_ULE) &&
@@ -1461,9 +1459,6 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
// Y < A || Y == 0 --> Y < A iff B != 0
if (match(UnsignedICmp,
m_c_ICmp(UnsignedPred, m_Specific(Y), m_Specific(A)))) {
- if (UnsignedICmp->getOperand(0) != Y)
- UnsignedPred = ICmpInst::getSwappedPredicate(UnsignedPred);
-
if (UnsignedPred == ICmpInst::ICMP_UGE && IsAnd &&
EqPred == ICmpInst::ICMP_NE &&
isKnownNonZero(B, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT))
@@ -1485,10 +1480,11 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
else
return nullptr;
- // X < Y && Y != 0 --> X < Y
- // X < Y || Y != 0 --> Y != 0
- if (UnsignedPred == ICmpInst::ICMP_ULT && EqPred == ICmpInst::ICMP_NE)
- return IsAnd ? UnsignedICmp : 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, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT))
+ return IsAnd ? ZeroICmp : UnsignedICmp;
// X <= Y && Y != 0 --> X <= Y iff X != 0
// X <= Y || Y != 0 --> Y != 0 iff X != 0
@@ -1496,17 +1492,21 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
isKnownNonZero(X, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT))
return IsAnd ? UnsignedICmp : ZeroICmp;
+ // The transforms below here are expected to be handled more generally with
+ // simplifyAndOrOfICmpsWithLimitConst() or in InstCombine's
+ // foldAndOrOfICmpsWithConstEq(). If we are looking to trim optimizer overlap,
+ // these are candidates for removal.
+
+ // X < Y && Y != 0 --> X < Y
+ // X < Y || Y != 0 --> Y != 0
+ if (UnsignedPred == ICmpInst::ICMP_ULT && EqPred == ICmpInst::ICMP_NE)
+ return IsAnd ? UnsignedICmp : ZeroICmp;
+
// X >= Y && Y == 0 --> Y == 0
// X >= Y || Y == 0 --> X >= Y
if (UnsignedPred == ICmpInst::ICMP_UGE && EqPred == ICmpInst::ICMP_EQ)
return IsAnd ? ZeroICmp : UnsignedICmp;
- // 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, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT))
- return IsAnd ? ZeroICmp : UnsignedICmp;
-
// X < Y && Y == 0 --> false
if (UnsignedPred == ICmpInst::ICMP_ULT && EqPred == ICmpInst::ICMP_EQ &&
IsAnd)
@@ -1695,6 +1695,64 @@ static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
return nullptr;
}
+/// Try to eliminate compares with signed or unsigned min/max constants.
+static Value *simplifyAndOrOfICmpsWithLimitConst(ICmpInst *Cmp0, ICmpInst *Cmp1,
+ bool IsAnd) {
+ // Canonicalize an equality compare as Cmp0.
+ if (Cmp1->isEquality())
+ std::swap(Cmp0, Cmp1);
+ if (!Cmp0->isEquality())
+ return nullptr;
+
+ // The equality compare must be against a constant. Convert the 'null' pointer
+ // constant to an integer zero value.
+ APInt MinMaxC;
+ const APInt *C;
+ if (match(Cmp0->getOperand(1), m_APInt(C)))
+ MinMaxC = *C;
+ else if (isa<ConstantPointerNull>(Cmp0->getOperand(1)))
+ MinMaxC = APInt::getNullValue(8);
+ else
+ return nullptr;
+
+ // The non-equality compare must include a common operand (X). Canonicalize
+ // the common operand as operand 0 (the predicate is swapped if the common
+ // operand was operand 1).
+ ICmpInst::Predicate Pred0 = Cmp0->getPredicate();
+ Value *X = Cmp0->getOperand(0);
+ ICmpInst::Predicate Pred1;
+ if (!match(Cmp1, m_c_ICmp(Pred1, m_Specific(X), m_Value())) ||
+ ICmpInst::isEquality(Pred1))
+ return nullptr;
+
+ // DeMorganize if this is 'or': P0 || P1 --> !P0 && !P1.
+ if (!IsAnd) {
+ Pred0 = ICmpInst::getInversePredicate(Pred0);
+ Pred1 = ICmpInst::getInversePredicate(Pred1);
+ }
+
+ // Normalize to unsigned compare and unsigned min/max value.
+ // Example for 8-bit: -128 + 128 -> 0; 127 + 128 -> 255
+ if (ICmpInst::isSigned(Pred1)) {
+ Pred1 = ICmpInst::getUnsignedPredicate(Pred1);
+ MinMaxC += APInt::getSignedMinValue(MinMaxC.getBitWidth());
+ }
+
+ // (X != MAX) && (X < Y) --> X < Y
+ // (X == MAX) || (X >= Y) --> X >= Y
+ if (MinMaxC.isMaxValue())
+ if (Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_ULT)
+ return Cmp1;
+
+ // (X != MIN) && (X > Y) --> X > Y
+ // (X == MIN) || (X <= Y) --> X <= Y
+ if (MinMaxC.isMinValue())
+ if (Pred0 == ICmpInst::ICMP_NE && Pred1 == ICmpInst::ICMP_UGT)
+ return Cmp1;
+
+ return nullptr;
+}
+
static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1,
const SimplifyQuery &Q) {
if (Value *X = simplifyUnsignedRangeCheck(Op0, Op1, /*IsAnd=*/true, Q))
@@ -1710,6 +1768,9 @@ static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1,
if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, true))
return X;
+ if (Value *X = simplifyAndOrOfICmpsWithLimitConst(Op0, Op1, true))
+ return X;
+
if (Value *X = simplifyAndOrOfICmpsWithZero(Op0, Op1, true))
return X;
@@ -1783,6 +1844,9 @@ static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1,
if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, false))
return X;
+ if (Value *X = simplifyAndOrOfICmpsWithLimitConst(Op0, Op1, false))
+ return X;
+
if (Value *X = simplifyAndOrOfICmpsWithZero(Op0, Op1, false))
return X;
@@ -2131,7 +2195,7 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
return Constant::getAllOnesValue(Op1->getType());
// A | ~(A & ?) = -1
- if (match(Op1, m_Not(m_c_And(m_Specific(Op1), m_Value()))))
+ if (match(Op1, m_Not(m_c_And(m_Specific(Op0), m_Value()))))
return Constant::getAllOnesValue(Op0->getType());
Value *A, *B;
@@ -2347,10 +2411,9 @@ computePointerICmp(const DataLayout &DL, const TargetLibraryInfo *TLI,
RHS = RHS->stripPointerCasts();
// A non-null pointer is not equal to a null pointer.
- if (llvm::isKnownNonZero(LHS, DL, 0, nullptr, nullptr, nullptr,
- IIQ.UseInstrInfo) &&
- isa<ConstantPointerNull>(RHS) &&
- (Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE))
+ if (isa<ConstantPointerNull>(RHS) && ICmpInst::isEquality(Pred) &&
+ llvm::isKnownNonZero(LHS, DL, 0, nullptr, nullptr, nullptr,
+ IIQ.UseInstrInfo))
return ConstantInt::get(GetCompareTy(LHS),
!CmpInst::isTrueWhenEqual(Pred));
@@ -3218,6 +3281,30 @@ static Value *simplifyICmpWithMinMax(CmpInst::Predicate Pred, Value *LHS,
return nullptr;
}
+static Value *simplifyICmpWithDominatingAssume(CmpInst::Predicate Predicate,
+ Value *LHS, Value *RHS,
+ const SimplifyQuery &Q) {
+ // Gracefully handle instructions that have not been inserted yet.
+ if (!Q.AC || !Q.CxtI || !Q.CxtI->getParent())
+ return nullptr;
+
+ for (Value *AssumeBaseOp : {LHS, RHS}) {
+ for (auto &AssumeVH : Q.AC->assumptionsFor(AssumeBaseOp)) {
+ if (!AssumeVH)
+ continue;
+
+ CallInst *Assume = cast<CallInst>(AssumeVH);
+ if (Optional<bool> Imp =
+ isImpliedCondition(Assume->getArgOperand(0), Predicate, LHS, RHS,
+ Q.DL))
+ if (isValidAssumeForContext(Assume, Q.CxtI, Q.DT))
+ return ConstantInt::get(GetCompareTy(LHS), *Imp);
+ }
+ }
+
+ return nullptr;
+}
+
/// Given operands for an ICmpInst, see if we can fold the result.
/// If not, this returns null.
static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
@@ -3318,6 +3405,15 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
MaxRecurse-1))
return V;
}
+ // Fold (zext X) ule (sext X), (zext X) sge (sext X) to true.
+ else if (SExtInst *RI = dyn_cast<SExtInst>(RHS)) {
+ if (SrcOp == RI->getOperand(0)) {
+ if (Pred == ICmpInst::ICMP_ULE || Pred == ICmpInst::ICMP_SGE)
+ return ConstantInt::getTrue(ITy);
+ if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_SLT)
+ return ConstantInt::getFalse(ITy);
+ }
+ }
// Turn icmp (zext X), Cst into a compare of X and Cst if Cst is extended
// too. If not, then try to deduce the result of the comparison.
else if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
@@ -3377,6 +3473,15 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
Q, MaxRecurse-1))
return V;
}
+ // Fold (sext X) uge (zext X), (sext X) sle (zext X) to true.
+ else if (ZExtInst *RI = dyn_cast<ZExtInst>(RHS)) {
+ if (SrcOp == RI->getOperand(0)) {
+ if (Pred == ICmpInst::ICMP_UGE || Pred == ICmpInst::ICMP_SLE)
+ return ConstantInt::getTrue(ITy);
+ if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_SGT)
+ return ConstantInt::getFalse(ITy);
+ }
+ }
// Turn icmp (sext X), Cst into a compare of X and Cst if Cst is extended
// too. If not, then try to deduce the result of the comparison.
else if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
@@ -3452,6 +3557,9 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
if (Value *V = simplifyICmpWithMinMax(Pred, LHS, RHS, Q, MaxRecurse))
return V;
+ if (Value *V = simplifyICmpWithDominatingAssume(Pred, LHS, RHS, Q))
+ return V;
+
// Simplify comparisons of related pointers using a powerful, recursive
// GEP-walk when we have target data available..
if (LHS->getType()->isPointerTy())
@@ -3487,7 +3595,8 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
SmallVector<Value *, 4> IndicesRHS(GRHS->idx_begin(), GRHS->idx_end());
Constant *NewRHS = ConstantExpr::getGetElementPtr(
GLHS->getSourceElementType(), Null, IndicesRHS);
- return ConstantExpr::getICmp(Pred, NewLHS, NewRHS);
+ Constant *NewICmp = ConstantExpr::getICmp(Pred, NewLHS, NewRHS);
+ return ConstantFoldConstant(NewICmp, Q.DL);
}
}
}
@@ -3622,9 +3731,9 @@ static Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
// Check comparison of [minnum/maxnum with constant] with other constant.
const APFloat *C2;
if ((match(LHS, m_Intrinsic<Intrinsic::minnum>(m_Value(), m_APFloat(C2))) &&
- C2->compare(*C) == APFloat::cmpLessThan) ||
+ *C2 < *C) ||
(match(LHS, m_Intrinsic<Intrinsic::maxnum>(m_Value(), m_APFloat(C2))) &&
- C2->compare(*C) == APFloat::cmpGreaterThan)) {
+ *C2 > *C)) {
bool IsMaxNum =
cast<IntrinsicInst>(LHS)->getIntrinsicID() == Intrinsic::maxnum;
// The ordered relationship and minnum/maxnum guarantee that we do not
@@ -4009,11 +4118,47 @@ static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
if (TrueVal == FalseVal)
return TrueVal;
- if (isa<UndefValue>(TrueVal)) // select ?, undef, X -> X
+ // If the true or false value is undef, we can fold to the other value as
+ // long as the other value isn't poison.
+ // select ?, undef, X -> X
+ if (isa<UndefValue>(TrueVal) &&
+ isGuaranteedNotToBeUndefOrPoison(FalseVal, Q.CxtI, Q.DT))
return FalseVal;
- if (isa<UndefValue>(FalseVal)) // select ?, X, undef -> X
+ // select ?, X, undef -> X
+ if (isa<UndefValue>(FalseVal) &&
+ isGuaranteedNotToBeUndefOrPoison(TrueVal, Q.CxtI, Q.DT))
return TrueVal;
+ // Deal with partial undef vector constants: select ?, VecC, VecC' --> VecC''
+ Constant *TrueC, *FalseC;
+ if (TrueVal->getType()->isVectorTy() && match(TrueVal, m_Constant(TrueC)) &&
+ match(FalseVal, m_Constant(FalseC))) {
+ unsigned NumElts = cast<VectorType>(TrueC->getType())->getNumElements();
+ SmallVector<Constant *, 16> NewC;
+ for (unsigned i = 0; i != NumElts; ++i) {
+ // Bail out on incomplete vector constants.
+ Constant *TEltC = TrueC->getAggregateElement(i);
+ Constant *FEltC = FalseC->getAggregateElement(i);
+ if (!TEltC || !FEltC)
+ break;
+
+ // If the elements match (undef or not), that value is the result. If only
+ // one element is undef, choose the defined element as the safe result.
+ if (TEltC == FEltC)
+ NewC.push_back(TEltC);
+ else if (isa<UndefValue>(TEltC) &&
+ isGuaranteedNotToBeUndefOrPoison(FEltC))
+ NewC.push_back(FEltC);
+ else if (isa<UndefValue>(FEltC) &&
+ isGuaranteedNotToBeUndefOrPoison(TEltC))
+ NewC.push_back(TEltC);
+ else
+ break;
+ }
+ if (NewC.size() == NumElts)
+ return ConstantVector::get(NewC);
+ }
+
if (Value *V =
simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse))
return V;
@@ -4052,20 +4197,22 @@ static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
Type *LastType = GetElementPtrInst::getIndexedType(SrcTy, Ops.slice(1));
Type *GEPTy = PointerType::get(LastType, AS);
if (VectorType *VT = dyn_cast<VectorType>(Ops[0]->getType()))
- GEPTy = VectorType::get(GEPTy, VT->getNumElements());
+ GEPTy = VectorType::get(GEPTy, VT->getElementCount());
else if (VectorType *VT = dyn_cast<VectorType>(Ops[1]->getType()))
- GEPTy = VectorType::get(GEPTy, VT->getNumElements());
+ GEPTy = VectorType::get(GEPTy, VT->getElementCount());
if (isa<UndefValue>(Ops[0]))
return UndefValue::get(GEPTy);
+ bool IsScalableVec = isa<ScalableVectorType>(SrcTy);
+
if (Ops.size() == 2) {
// getelementptr P, 0 -> P.
if (match(Ops[1], m_Zero()) && Ops[0]->getType() == GEPTy)
return Ops[0];
Type *Ty = SrcTy;
- if (Ty->isSized()) {
+ if (!IsScalableVec && Ty->isSized()) {
Value *P;
uint64_t C;
uint64_t TyAllocSize = Q.DL.getTypeAllocSize(Ty);
@@ -4113,7 +4260,7 @@ static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
}
}
- if (Q.DL.getTypeAllocSize(LastType) == 1 &&
+ if (!IsScalableVec && Q.DL.getTypeAllocSize(LastType) == 1 &&
all_of(Ops.slice(1).drop_back(1),
[](Value *Idx) { return match(Idx, m_Zero()); })) {
unsigned IdxWidth =
@@ -4145,9 +4292,7 @@ static Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
auto *CE = ConstantExpr::getGetElementPtr(SrcTy, cast<Constant>(Ops[0]),
Ops.slice(1));
- if (auto *CEFolded = ConstantFoldConstant(CE, Q.DL))
- return CEFolded;
- return CE;
+ return ConstantFoldConstant(CE, Q.DL);
}
Value *llvm::SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
@@ -4199,10 +4344,10 @@ Value *llvm::SimplifyInsertElementInst(Value *Vec, Value *Val, Value *Idx,
if (VecC && ValC && IdxC)
return ConstantFoldInsertElementInstruction(VecC, ValC, IdxC);
- // Fold into undef if index is out of bounds.
+ // For fixed-length vector, fold into undef if index is out of bounds.
if (auto *CI = dyn_cast<ConstantInt>(Idx)) {
- uint64_t NumElements = cast<VectorType>(Vec->getType())->getNumElements();
- if (CI->uge(NumElements))
+ if (isa<FixedVectorType>(Vec->getType()) &&
+ CI->uge(cast<FixedVectorType>(Vec->getType())->getNumElements()))
return UndefValue::get(Vec->getType());
}
@@ -4210,15 +4355,15 @@ Value *llvm::SimplifyInsertElementInst(Value *Vec, Value *Val, Value *Idx,
if (isa<UndefValue>(Idx))
return UndefValue::get(Vec->getType());
- // Inserting an undef scalar? Assume it is the same value as the existing
- // vector element.
- if (isa<UndefValue>(Val))
+ // If the scalar is undef, and there is no risk of propagating poison from the
+ // vector value, simplify to the vector value.
+ if (isa<UndefValue>(Val) && isGuaranteedNotToBeUndefOrPoison(Vec))
return Vec;
// If we are extracting a value from a vector, then inserting it into the same
// place, that's the input vector:
// insertelt Vec, (extractelt Vec, Idx), Idx --> Vec
- if (match(Val, m_ExtractElement(m_Specific(Vec), m_Specific(Idx))))
+ if (match(Val, m_ExtractElt(m_Specific(Vec), m_Specific(Idx))))
return Vec;
return nullptr;
@@ -4258,6 +4403,7 @@ Value *llvm::SimplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs,
/// If not, this returns null.
static Value *SimplifyExtractElementInst(Value *Vec, Value *Idx, const SimplifyQuery &,
unsigned) {
+ auto *VecVTy = cast<VectorType>(Vec->getType());
if (auto *CVec = dyn_cast<Constant>(Vec)) {
if (auto *CIdx = dyn_cast<Constant>(Idx))
return ConstantFoldExtractElementInstruction(CVec, CIdx);
@@ -4267,15 +4413,16 @@ static Value *SimplifyExtractElementInst(Value *Vec, Value *Idx, const SimplifyQ
return Splat;
if (isa<UndefValue>(Vec))
- return UndefValue::get(Vec->getType()->getVectorElementType());
+ return UndefValue::get(VecVTy->getElementType());
}
// If extracting a specified index from the vector, see if we can recursively
// find a previously computed scalar that was inserted into the vector.
if (auto *IdxC = dyn_cast<ConstantInt>(Idx)) {
- if (IdxC->getValue().uge(Vec->getType()->getVectorNumElements()))
- // definitely out of bounds, thus undefined result
- return UndefValue::get(Vec->getType()->getVectorElementType());
+ // For fixed-length vector, fold into undef if index is out of bounds.
+ if (isa<FixedVectorType>(VecVTy) &&
+ IdxC->getValue().uge(VecVTy->getNumElements()))
+ return UndefValue::get(VecVTy->getElementType());
if (Value *Elt = findScalarElement(Vec, IdxC->getZExtValue()))
return Elt;
}
@@ -4283,7 +4430,7 @@ static Value *SimplifyExtractElementInst(Value *Vec, Value *Idx, const SimplifyQ
// An undef extract index can be arbitrarily chosen to be an out-of-range
// index value, which would result in the instruction being undef.
if (isa<UndefValue>(Idx))
- return UndefValue::get(Vec->getType()->getVectorElementType());
+ return UndefValue::get(VecVTy->getElementType());
return nullptr;
}
@@ -4380,7 +4527,7 @@ static Value *foldIdentityShuffles(int DestElt, Value *Op0, Value *Op1,
return nullptr;
// The mask value chooses which source operand we need to look at next.
- int InVecNumElts = Op0->getType()->getVectorNumElements();
+ int InVecNumElts = cast<VectorType>(Op0->getType())->getNumElements();
int RootElt = MaskVal;
Value *SourceOp = Op0;
if (MaskVal >= InVecNumElts) {
@@ -4416,59 +4563,68 @@ static Value *foldIdentityShuffles(int DestElt, Value *Op0, Value *Op1,
return RootVec;
}
-static Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
- Type *RetTy, const SimplifyQuery &Q,
+static Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1,
+ ArrayRef<int> Mask, Type *RetTy,
+ const SimplifyQuery &Q,
unsigned MaxRecurse) {
- if (isa<UndefValue>(Mask))
+ if (all_of(Mask, [](int Elem) { return Elem == UndefMaskElem; }))
return UndefValue::get(RetTy);
- Type *InVecTy = Op0->getType();
- unsigned MaskNumElts = Mask->getType()->getVectorNumElements();
- unsigned InVecNumElts = InVecTy->getVectorNumElements();
+ auto *InVecTy = cast<VectorType>(Op0->getType());
+ unsigned MaskNumElts = Mask.size();
+ ElementCount InVecEltCount = InVecTy->getElementCount();
+
+ bool Scalable = InVecEltCount.Scalable;
SmallVector<int, 32> Indices;
- ShuffleVectorInst::getShuffleMask(Mask, Indices);
- assert(MaskNumElts == Indices.size() &&
- "Size of Indices not same as number of mask elements?");
+ Indices.assign(Mask.begin(), Mask.end());
// Canonicalization: If mask does not select elements from an input vector,
// replace that input vector with undef.
- bool MaskSelects0 = false, MaskSelects1 = false;
- for (unsigned i = 0; i != MaskNumElts; ++i) {
- if (Indices[i] == -1)
- continue;
- if ((unsigned)Indices[i] < InVecNumElts)
- MaskSelects0 = true;
- else
- MaskSelects1 = true;
+ if (!Scalable) {
+ bool MaskSelects0 = false, MaskSelects1 = false;
+ unsigned InVecNumElts = InVecEltCount.Min;
+ for (unsigned i = 0; i != MaskNumElts; ++i) {
+ if (Indices[i] == -1)
+ continue;
+ if ((unsigned)Indices[i] < InVecNumElts)
+ MaskSelects0 = true;
+ else
+ MaskSelects1 = true;
+ }
+ if (!MaskSelects0)
+ Op0 = UndefValue::get(InVecTy);
+ if (!MaskSelects1)
+ Op1 = UndefValue::get(InVecTy);
}
- if (!MaskSelects0)
- Op0 = UndefValue::get(InVecTy);
- if (!MaskSelects1)
- Op1 = UndefValue::get(InVecTy);
auto *Op0Const = dyn_cast<Constant>(Op0);
auto *Op1Const = dyn_cast<Constant>(Op1);
- // If all operands are constant, constant fold the shuffle.
- if (Op0Const && Op1Const)
+ // If all operands are constant, constant fold the shuffle. This
+ // transformation depends on the value of the mask which is not known at
+ // compile time for scalable vectors
+ if (!Scalable && Op0Const && Op1Const)
return ConstantFoldShuffleVectorInstruction(Op0Const, Op1Const, Mask);
// Canonicalization: if only one input vector is constant, it shall be the
- // second one.
- if (Op0Const && !Op1Const) {
+ // second one. This transformation depends on the value of the mask which
+ // is not known at compile time for scalable vectors
+ if (!Scalable && Op0Const && !Op1Const) {
std::swap(Op0, Op1);
- ShuffleVectorInst::commuteShuffleMask(Indices, InVecNumElts);
+ ShuffleVectorInst::commuteShuffleMask(Indices, InVecEltCount.Min);
}
// A splat of an inserted scalar constant becomes a vector constant:
// shuf (inselt ?, C, IndexC), undef, <IndexC, IndexC...> --> <C, C...>
// NOTE: We may have commuted above, so analyze the updated Indices, not the
// original mask constant.
+ // NOTE: This transformation depends on the value of the mask which is not
+ // known at compile time for scalable vectors
Constant *C;
ConstantInt *IndexC;
- if (match(Op0, m_InsertElement(m_Value(), m_Constant(C),
- m_ConstantInt(IndexC)))) {
+ if (!Scalable && match(Op0, m_InsertElt(m_Value(), m_Constant(C),
+ m_ConstantInt(IndexC)))) {
// Match a splat shuffle mask of the insert index allowing undef elements.
int InsertIndex = IndexC->getZExtValue();
if (all_of(Indices, [InsertIndex](int MaskElt) {
@@ -4489,9 +4645,14 @@ static Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
// value type is same as the input vectors' type.
if (auto *OpShuf = dyn_cast<ShuffleVectorInst>(Op0))
if (isa<UndefValue>(Op1) && RetTy == InVecTy &&
- OpShuf->getMask()->getSplatValue())
+ is_splat(OpShuf->getShuffleMask()))
return Op0;
+ // All remaining transformation depend on the value of the mask, which is
+ // not known at compile time for scalable vectors.
+ if (Scalable)
+ return nullptr;
+
// Don't fold a shuffle with undef mask elements. This may get folded in a
// better way using demanded bits or other analysis.
// TODO: Should we allow this?
@@ -4517,8 +4678,9 @@ static Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
}
/// Given operands for a ShuffleVectorInst, fold the result or return null.
-Value *llvm::SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
- Type *RetTy, const SimplifyQuery &Q) {
+Value *llvm::SimplifyShuffleVectorInst(Value *Op0, Value *Op1,
+ ArrayRef<int> Mask, Type *RetTy,
+ const SimplifyQuery &Q) {
return ::SimplifyShuffleVectorInst(Op0, Op1, Mask, RetTy, Q, RecursionLimit);
}
@@ -4562,14 +4724,24 @@ static Constant *propagateNaN(Constant *In) {
/// Perform folds that are common to any floating-point operation. This implies
/// transforms based on undef/NaN because the operation itself makes no
/// difference to the result.
-static Constant *simplifyFPOp(ArrayRef<Value *> Ops) {
- if (any_of(Ops, [](Value *V) { return isa<UndefValue>(V); }))
- return ConstantFP::getNaN(Ops[0]->getType());
-
- for (Value *V : Ops)
- if (match(V, m_NaN()))
+static Constant *simplifyFPOp(ArrayRef<Value *> Ops,
+ FastMathFlags FMF = FastMathFlags()) {
+ for (Value *V : Ops) {
+ bool IsNan = match(V, m_NaN());
+ bool IsInf = match(V, m_Inf());
+ bool IsUndef = match(V, m_Undef());
+
+ // If this operation has 'nnan' or 'ninf' and at least 1 disallowed operand
+ // (an undef operand can be chosen to be Nan/Inf), then the result of
+ // this operation is poison. That result can be relaxed to undef.
+ if (FMF.noNaNs() && (IsNan || IsUndef))
+ return UndefValue::get(V->getType());
+ if (FMF.noInfs() && (IsInf || IsUndef))
+ return UndefValue::get(V->getType());
+
+ if (IsUndef || IsNan)
return propagateNaN(cast<Constant>(V));
-
+ }
return nullptr;
}
@@ -4580,7 +4752,7 @@ static Value *SimplifyFAddInst(Value *Op0, Value *Op1, FastMathFlags FMF,
if (Constant *C = foldOrCommuteConstant(Instruction::FAdd, Op0, Op1, Q))
return C;
- if (Constant *C = simplifyFPOp({Op0, Op1}))
+ if (Constant *C = simplifyFPOp({Op0, Op1}, FMF))
return C;
// fadd X, -0 ==> X
@@ -4627,7 +4799,7 @@ static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
if (Constant *C = foldOrCommuteConstant(Instruction::FSub, Op0, Op1, Q))
return C;
- if (Constant *C = simplifyFPOp({Op0, Op1}))
+ if (Constant *C = simplifyFPOp({Op0, Op1}, FMF))
return C;
// fsub X, +0 ==> X
@@ -4669,7 +4841,7 @@ static Value *SimplifyFSubInst(Value *Op0, Value *Op1, FastMathFlags FMF,
static Value *SimplifyFMAFMul(Value *Op0, Value *Op1, FastMathFlags FMF,
const SimplifyQuery &Q, unsigned MaxRecurse) {
- if (Constant *C = simplifyFPOp({Op0, Op1}))
+ if (Constant *C = simplifyFPOp({Op0, Op1}, FMF))
return C;
// fmul X, 1.0 ==> X
@@ -4736,7 +4908,7 @@ static Value *SimplifyFDivInst(Value *Op0, Value *Op1, FastMathFlags FMF,
if (Constant *C = foldOrCommuteConstant(Instruction::FDiv, Op0, Op1, Q))
return C;
- if (Constant *C = simplifyFPOp({Op0, Op1}))
+ if (Constant *C = simplifyFPOp({Op0, Op1}, FMF))
return C;
// X / 1.0 -> X
@@ -4781,7 +4953,7 @@ static Value *SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF,
if (Constant *C = foldOrCommuteConstant(Instruction::FRem, Op0, Op1, Q))
return C;
- if (Constant *C = simplifyFPOp({Op0, Op1}))
+ if (Constant *C = simplifyFPOp({Op0, Op1}, FMF))
return C;
// Unlike fdiv, the result of frem always matches the sign of the dividend.
@@ -4942,6 +5114,7 @@ static bool IsIdempotent(Intrinsic::ID ID) {
case Intrinsic::rint:
case Intrinsic::nearbyint:
case Intrinsic::round:
+ case Intrinsic::roundeven:
case Intrinsic::canonicalize:
return true;
}
@@ -5057,6 +5230,7 @@ static Value *simplifyUnaryIntrinsic(Function *F, Value *Op0,
case Intrinsic::trunc:
case Intrinsic::ceil:
case Intrinsic::round:
+ case Intrinsic::roundeven:
case Intrinsic::nearbyint:
case Intrinsic::rint: {
// floor (sitofp x) -> sitofp x
@@ -5288,7 +5462,12 @@ static Value *simplifyIntrinsic(CallBase *Call, const SimplifyQuery &Q) {
}
Value *llvm::SimplifyCall(CallBase *Call, const SimplifyQuery &Q) {
- Value *Callee = Call->getCalledValue();
+ Value *Callee = Call->getCalledOperand();
+
+ // musttail calls can only be simplified if they are also DCEd.
+ // As we can't guarantee this here, don't simplify them.
+ if (Call->isMustTailCall())
+ return nullptr;
// call undef -> undef
// call null -> undef
@@ -5311,8 +5490,11 @@ Value *llvm::SimplifyCall(CallBase *Call, const SimplifyQuery &Q) {
ConstantArgs.reserve(NumArgs);
for (auto &Arg : Call->args()) {
Constant *C = dyn_cast<Constant>(&Arg);
- if (!C)
+ if (!C) {
+ if (isa<MetadataAsValue>(Arg.get()))
+ continue;
return nullptr;
+ }
ConstantArgs.push_back(C);
}
@@ -5320,16 +5502,16 @@ Value *llvm::SimplifyCall(CallBase *Call, const SimplifyQuery &Q) {
}
/// Given operands for a Freeze, see if we can fold the result.
-static Value *SimplifyFreezeInst(Value *Op0) {
+static Value *SimplifyFreezeInst(Value *Op0, const SimplifyQuery &Q) {
// Use a utility function defined in ValueTracking.
- if (llvm::isGuaranteedNotToBeUndefOrPoison(Op0))
+ if (llvm::isGuaranteedNotToBeUndefOrPoison(Op0, Q.CxtI, Q.DT))
return Op0;
// We have room for improvement.
return nullptr;
}
Value *llvm::SimplifyFreezeInst(Value *Op0, const SimplifyQuery &Q) {
- return ::SimplifyFreezeInst(Op0);
+ return ::SimplifyFreezeInst(Op0, Q);
}
/// See if we can compute a simplified version of this instruction.
@@ -5463,8 +5645,9 @@ Value *llvm::SimplifyInstruction(Instruction *I, const SimplifyQuery &SQ,
}
case Instruction::ShuffleVector: {
auto *SVI = cast<ShuffleVectorInst>(I);
- Result = SimplifyShuffleVectorInst(SVI->getOperand(0), SVI->getOperand(1),
- SVI->getMask(), SVI->getType(), Q);
+ Result =
+ SimplifyShuffleVectorInst(SVI->getOperand(0), SVI->getOperand(1),
+ SVI->getShuffleMask(), SVI->getType(), Q);
break;
}
case Instruction::PHI:
@@ -5489,14 +5672,6 @@ Value *llvm::SimplifyInstruction(Instruction *I, const SimplifyQuery &SQ,
break;
}
- // In general, it is possible for computeKnownBits to determine all bits in a
- // value even when the operands are not all constants.
- if (!Result && I->getType()->isIntOrIntVectorTy()) {
- KnownBits Known = computeKnownBits(I, Q.DL, /*Depth*/ 0, Q.AC, I, Q.DT, ORE);
- if (Known.isConstant())
- Result = ConstantInt::get(I->getType(), Known.getConstant());
- }
-
/// If called on unreachable code, the above logic may report that the
/// instruction simplified to itself. Make life easier for users by
/// detecting that case here, returning a safe value instead.