diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2020-07-26 19:36:28 +0000 |
commit | cfca06d7963fa0909f90483b42a6d7d194d01e08 (patch) | |
tree | 209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/Analysis/InstructionSimplify.cpp | |
parent | 706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff) |
Notes
Diffstat (limited to 'llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 401 |
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. |