diff options
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
| -rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 228 |
1 files changed, 133 insertions, 95 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index f2c6949e535d..2f6e869ae7b7 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -259,7 +259,7 @@ bool llvm::isOnlyUsedInZeroComparison(const Instruction *I) { bool llvm::isOnlyUsedInZeroEqualityComparison(const Instruction *I) { return !I->user_empty() && all_of(I->users(), [](const User *U) { - ICmpInst::Predicate P; + CmpPredicate P; return match(U, m_ICmp(P, m_Value(), m_Zero())) && ICmpInst::isEquality(P); }); } @@ -614,7 +614,7 @@ static bool isKnownNonZeroFromAssume(const Value *V, const SimplifyQuery &Q) { // runtime of ~O(#assumes * #values). Value *RHS; - CmpInst::Predicate Pred; + CmpPredicate Pred; auto m_V = m_CombineOr(m_Specific(V), m_PtrToInt(m_Specific(V))); if (!match(I->getArgOperand(0), m_c_ICmp(Pred, m_V, m_Value(RHS)))) continue; @@ -1065,6 +1065,64 @@ void llvm::adjustKnownBitsForSelectArm(KnownBits &Known, Value *Cond, Known = CondRes; } +// Match a signed min+max clamp pattern like smax(smin(In, CHigh), CLow). +// Returns the input and lower/upper bounds. +static bool isSignedMinMaxClamp(const Value *Select, const Value *&In, + const APInt *&CLow, const APInt *&CHigh) { + assert(isa<Operator>(Select) && + cast<Operator>(Select)->getOpcode() == Instruction::Select && + "Input should be a Select!"); + + const Value *LHS = nullptr, *RHS = nullptr; + SelectPatternFlavor SPF = matchSelectPattern(Select, LHS, RHS).Flavor; + if (SPF != SPF_SMAX && SPF != SPF_SMIN) + return false; + + if (!match(RHS, m_APInt(CLow))) + return false; + + const Value *LHS2 = nullptr, *RHS2 = nullptr; + SelectPatternFlavor SPF2 = matchSelectPattern(LHS, LHS2, RHS2).Flavor; + if (getInverseMinMaxFlavor(SPF) != SPF2) + return false; + + if (!match(RHS2, m_APInt(CHigh))) + return false; + + if (SPF == SPF_SMIN) + std::swap(CLow, CHigh); + + In = LHS2; + return CLow->sle(*CHigh); +} + +static bool isSignedMinMaxIntrinsicClamp(const IntrinsicInst *II, + const APInt *&CLow, + const APInt *&CHigh) { + assert((II->getIntrinsicID() == Intrinsic::smin || + II->getIntrinsicID() == Intrinsic::smax) && + "Must be smin/smax"); + + Intrinsic::ID InverseID = getInverseMinMaxIntrinsic(II->getIntrinsicID()); + auto *InnerII = dyn_cast<IntrinsicInst>(II->getArgOperand(0)); + if (!InnerII || InnerII->getIntrinsicID() != InverseID || + !match(II->getArgOperand(1), m_APInt(CLow)) || + !match(InnerII->getArgOperand(1), m_APInt(CHigh))) + return false; + + if (II->getIntrinsicID() == Intrinsic::smin) + std::swap(CLow, CHigh); + return CLow->sle(*CHigh); +} + +static void unionWithMinMaxIntrinsicClamp(const IntrinsicInst *II, + KnownBits &Known) { + const APInt *CLow, *CHigh; + if (isSignedMinMaxIntrinsicClamp(II, CLow, CHigh)) + Known = Known.unionWith( + ConstantRange::getNonEmpty(*CLow, *CHigh + 1).toKnownBits()); +} + static void computeKnownBitsFromOperator(const Operator *I, const APInt &DemandedElts, KnownBits &Known, unsigned Depth, @@ -1602,7 +1660,7 @@ static void computeKnownBitsFromOperator(const Operator *I, // See if we can further use a conditional branch into the phi // to help us determine the range of the value. if (!Known2.isConstant()) { - ICmpInst::Predicate Pred; + CmpPredicate Pred; const APInt *RHSC; BasicBlock *TrueSucc, *FalseSucc; // TODO: Use RHS Value and compute range from its known bits. @@ -1804,11 +1862,13 @@ static void computeKnownBitsFromOperator(const Operator *I, computeKnownBits(I->getOperand(0), DemandedElts, Known, Depth + 1, Q); computeKnownBits(I->getOperand(1), DemandedElts, Known2, Depth + 1, Q); Known = KnownBits::smin(Known, Known2); + unionWithMinMaxIntrinsicClamp(II, Known); break; case Intrinsic::smax: computeKnownBits(I->getOperand(0), DemandedElts, Known, Depth + 1, Q); computeKnownBits(I->getOperand(1), DemandedElts, Known2, Depth + 1, Q); Known = KnownBits::smax(Known, Known2); + unionWithMinMaxIntrinsicClamp(II, Known); break; case Intrinsic::ptrmask: { computeKnownBits(I->getOperand(0), DemandedElts, Known, Depth + 1, Q); @@ -2255,7 +2315,7 @@ static bool isPowerOfTwoRecurrence(const PHINode *PN, bool OrZero, static bool isImpliedToBeAPowerOfTwoFromCond(const Value *V, bool OrZero, const Value *Cond, bool CondIsTrue) { - ICmpInst::Predicate Pred; + CmpPredicate Pred; const APInt *RHSC; if (!match(Cond, m_ICmp(Pred, m_Intrinsic<Intrinsic::ctpop>(m_Specific(V)), m_APInt(RHSC)))) @@ -2580,7 +2640,7 @@ static bool isKnownNonNullFromDominatingCondition(const Value *V, // Consider only compare instructions uniquely controlling a branch Value *RHS; - CmpInst::Predicate Pred; + CmpPredicate Pred; if (!match(U, m_c_ICmp(Pred, m_Specific(V), m_Value(RHS)))) continue; @@ -3009,7 +3069,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I, // The condition of the select dominates the true/false arm. Check if the // condition implies that a given arm is non-zero. Value *X; - CmpInst::Predicate Pred; + CmpPredicate Pred; if (!match(I->getOperand(0), m_c_ICmp(Pred, m_Specific(Op), m_Value(X)))) return false; @@ -3037,7 +3097,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I, return true; RecQ.CxtI = PN->getIncomingBlock(U)->getTerminator(); // Check if the branch on the phi excludes zero. - ICmpInst::Predicate Pred; + CmpPredicate Pred; Value *X; BasicBlock *TrueSucc, *FalseSucc; if (match(RecQ.CxtI, @@ -3751,55 +3811,6 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, return false; } -// Match a signed min+max clamp pattern like smax(smin(In, CHigh), CLow). -// Returns the input and lower/upper bounds. -static bool isSignedMinMaxClamp(const Value *Select, const Value *&In, - const APInt *&CLow, const APInt *&CHigh) { - assert(isa<Operator>(Select) && - cast<Operator>(Select)->getOpcode() == Instruction::Select && - "Input should be a Select!"); - - const Value *LHS = nullptr, *RHS = nullptr; - SelectPatternFlavor SPF = matchSelectPattern(Select, LHS, RHS).Flavor; - if (SPF != SPF_SMAX && SPF != SPF_SMIN) - return false; - - if (!match(RHS, m_APInt(CLow))) - return false; - - const Value *LHS2 = nullptr, *RHS2 = nullptr; - SelectPatternFlavor SPF2 = matchSelectPattern(LHS, LHS2, RHS2).Flavor; - if (getInverseMinMaxFlavor(SPF) != SPF2) - return false; - - if (!match(RHS2, m_APInt(CHigh))) - return false; - - if (SPF == SPF_SMIN) - std::swap(CLow, CHigh); - - In = LHS2; - return CLow->sle(*CHigh); -} - -static bool isSignedMinMaxIntrinsicClamp(const IntrinsicInst *II, - const APInt *&CLow, - const APInt *&CHigh) { - assert((II->getIntrinsicID() == Intrinsic::smin || - II->getIntrinsicID() == Intrinsic::smax) && "Must be smin/smax"); - - Intrinsic::ID InverseID = getInverseMinMaxIntrinsic(II->getIntrinsicID()); - auto *InnerII = dyn_cast<IntrinsicInst>(II->getArgOperand(0)); - if (!InnerII || InnerII->getIntrinsicID() != InverseID || - !match(II->getArgOperand(1), m_APInt(CLow)) || - !match(InnerII->getArgOperand(1), m_APInt(CHigh))) - return false; - - if (II->getIntrinsicID() == Intrinsic::smin) - std::swap(CLow, CHigh); - return CLow->sle(*CHigh); -} - /// For vector constants, loop over the elements and find the constant with the /// minimum number of sign bits. Return 0 if the value is not a vector constant /// or if any element was not analyzed; otherwise, return the count for the @@ -4895,7 +4906,7 @@ static void computeKnownFPClassFromCond(const Value *V, Value *Cond, KnownFromContext); return; } - CmpInst::Predicate Pred; + CmpPredicate Pred; Value *LHS; uint64_t ClassVal = 0; const APFloat *CRHS; @@ -4906,10 +4917,10 @@ static void computeKnownFPClassFromCond(const Value *V, Value *Cond, if (CmpVal == V) KnownFromContext.knownNot(~(CondIsTrue ? MaskIfTrue : MaskIfFalse)); } else if (match(Cond, m_Intrinsic<Intrinsic::is_fpclass>( - m_Value(LHS), m_ConstantInt(ClassVal)))) { + m_Specific(V), m_ConstantInt(ClassVal)))) { FPClassTest Mask = static_cast<FPClassTest>(ClassVal); KnownFromContext.knownNot(CondIsTrue ? ~Mask : Mask); - } else if (match(Cond, m_ICmp(Pred, m_ElementWiseBitCast(m_Value(LHS)), + } else if (match(Cond, m_ICmp(Pred, m_ElementWiseBitCast(m_Specific(V)), m_APInt(RHS)))) { bool TrueIfSigned; if (!isSignBitCheck(Pred, *RHS, TrueIfSigned)) @@ -5135,7 +5146,7 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest MaskIfFalse = fcAllFlags; uint64_t ClassVal = 0; const Function *F = cast<Instruction>(Op)->getFunction(); - CmpInst::Predicate Pred; + CmpPredicate Pred; Value *CmpLHS, *CmpRHS; if (F && match(Cond, m_FCmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS)))) { // If the select filters out a value based on the class, it no longer @@ -8571,7 +8582,7 @@ bool llvm::isKnownNegation(const Value *X, const Value *Y, bool NeedNSW, bool llvm::isKnownInversion(const Value *X, const Value *Y) { // Handle X = icmp pred A, B, Y = icmp pred A, C. Value *A, *B, *C; - ICmpInst::Predicate Pred1, Pred2; + CmpPredicate Pred1, Pred2; if (!match(X, m_ICmp(Pred1, m_Value(A), m_Value(B))) || !match(Y, m_c_ICmp(Pred2, m_Specific(A), m_Value(C)))) return false; @@ -8803,40 +8814,10 @@ static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred, return matchFastFloatClamp(Pred, CmpLHS, CmpRHS, TrueVal, FalseVal, LHS, RHS); } -/// Helps to match a select pattern in case of a type mismatch. -/// -/// The function processes the case when type of true and false values of a -/// select instruction differs from type of the cmp instruction operands because -/// of a cast instruction. The function checks if it is legal to move the cast -/// operation after "select". If yes, it returns the new second value of -/// "select" (with the assumption that cast is moved): -/// 1. As operand of cast instruction when both values of "select" are same cast -/// instructions. -/// 2. As restored constant (by applying reverse cast operation) when the first -/// value of the "select" is a cast operation and the second value is a -/// constant. -/// NOTE: We return only the new second value because the first value could be -/// accessed as operand of cast instruction. -static Value *lookThroughCast(CmpInst *CmpI, Value *V1, Value *V2, - Instruction::CastOps *CastOp) { - auto *Cast1 = dyn_cast<CastInst>(V1); - if (!Cast1) - return nullptr; - - *CastOp = Cast1->getOpcode(); - Type *SrcTy = Cast1->getSrcTy(); - if (auto *Cast2 = dyn_cast<CastInst>(V2)) { - // If V1 and V2 are both the same cast from the same type, look through V1. - if (*CastOp == Cast2->getOpcode() && SrcTy == Cast2->getSrcTy()) - return Cast2->getOperand(0); - return nullptr; - } - - auto *C = dyn_cast<Constant>(V2); - if (!C) - return nullptr; - +static Value *lookThroughCastConst(CmpInst *CmpI, Type *SrcTy, Constant *C, + Instruction::CastOps *CastOp) { const DataLayout &DL = CmpI->getDataLayout(); + Constant *CastedTo = nullptr; switch (*CastOp) { case Instruction::ZExt: @@ -8912,6 +8893,63 @@ static Value *lookThroughCast(CmpInst *CmpI, Value *V1, Value *V2, return CastedTo; } +/// Helps to match a select pattern in case of a type mismatch. +/// +/// The function processes the case when type of true and false values of a +/// select instruction differs from type of the cmp instruction operands because +/// of a cast instruction. The function checks if it is legal to move the cast +/// operation after "select". If yes, it returns the new second value of +/// "select" (with the assumption that cast is moved): +/// 1. As operand of cast instruction when both values of "select" are same cast +/// instructions. +/// 2. As restored constant (by applying reverse cast operation) when the first +/// value of the "select" is a cast operation and the second value is a +/// constant. It is implemented in lookThroughCastConst(). +/// 3. As one operand is cast instruction and the other is not. The operands in +/// sel(cmp) are in different type integer. +/// NOTE: We return only the new second value because the first value could be +/// accessed as operand of cast instruction. +static Value *lookThroughCast(CmpInst *CmpI, Value *V1, Value *V2, + Instruction::CastOps *CastOp) { + auto *Cast1 = dyn_cast<CastInst>(V1); + if (!Cast1) + return nullptr; + + *CastOp = Cast1->getOpcode(); + Type *SrcTy = Cast1->getSrcTy(); + if (auto *Cast2 = dyn_cast<CastInst>(V2)) { + // If V1 and V2 are both the same cast from the same type, look through V1. + if (*CastOp == Cast2->getOpcode() && SrcTy == Cast2->getSrcTy()) + return Cast2->getOperand(0); + return nullptr; + } + + auto *C = dyn_cast<Constant>(V2); + if (C) + return lookThroughCastConst(CmpI, SrcTy, C, CastOp); + + Value *CastedTo = nullptr; + if (*CastOp == Instruction::Trunc) { + if (match(CmpI->getOperand(1), m_ZExtOrSExt(m_Specific(V2)))) { + // Here we have the following case: + // %y_ext = sext iK %y to iN + // %cond = cmp iN %x, %y_ext + // %tr = trunc iN %x to iK + // %narrowsel = select i1 %cond, iK %tr, iK %y + // + // We can always move trunc after select operation: + // %y_ext = sext iK %y to iN + // %cond = cmp iN %x, %y_ext + // %widesel = select i1 %cond, iN %x, iN %y_ext + // %tr = trunc iN %widesel to iK + assert(V2->getType() == Cast1->getType() && + "V2 and Cast1 should be the same type."); + CastedTo = CmpI->getOperand(1); + } + } + + return CastedTo; +} SelectPatternResult llvm::matchSelectPattern(Value *V, Value *&LHS, Value *&RHS, Instruction::CastOps *CastOp, unsigned Depth) { @@ -10054,7 +10092,7 @@ void llvm::findValuesAffectedByCondition( if (!Visited.insert(V).second) continue; - CmpInst::Predicate Pred; + CmpPredicate Pred; Value *A, *B, *X; if (IsAssume) { |
