Index: include/llvm/Analysis/ValueTracking.h =================================================================== --- include/llvm/Analysis/ValueTracking.h +++ include/llvm/Analysis/ValueTracking.h @@ -105,6 +105,13 @@ const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); + /// Returns true if the given value is known be negative (i.e. non-positive + /// and non-zero). + bool isKnownNegative(Value *V, const DataLayout &DL, unsigned Depth = 0, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); + /// isKnownNonEqual - Return true if the given values are known to be /// non-equal when defined. Supports scalar integer types only. bool isKnownNonEqual(Value *V1, Value *V2, const DataLayout &DL, Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -2616,21 +2616,50 @@ } } - // icmp pred (or X, Y), X - if (LBO && match(LBO, m_CombineOr(m_Or(m_Value(), m_Specific(RHS)), - m_Or(m_Specific(RHS), m_Value())))) { - if (Pred == ICmpInst::ICMP_ULT) - return getFalse(ITy); - if (Pred == ICmpInst::ICMP_UGE) - return getTrue(ITy); - } - // icmp pred X, (or X, Y) - if (RBO && match(RBO, m_CombineOr(m_Or(m_Value(), m_Specific(LHS)), - m_Or(m_Specific(LHS), m_Value())))) { - if (Pred == ICmpInst::ICMP_ULE) - return getTrue(ITy); - if (Pred == ICmpInst::ICMP_UGT) - return getFalse(ITy); + { + Value *Y = 0; + // icmp pred (or X, Y), X + if (LBO && match(LBO, m_CombineOr(m_Or(m_Value(Y), m_Specific(RHS)), + m_Or(m_Specific(RHS), m_Value(Y))))) { + if (Pred == ICmpInst::ICMP_ULT) + return getFalse(ITy); + if (Pred == ICmpInst::ICMP_UGE) + return getTrue(ITy); + + if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE) { + bool RHSKnownNonNegative, RHSKnownNegative; + bool YKnownNonNegative, YKnownNegative; + ComputeSignBit(RHS, RHSKnownNonNegative, RHSKnownNegative, Q.DL, 0, + Q.AC, Q.CxtI, Q.DT); + ComputeSignBit(Y, YKnownNonNegative, YKnownNegative, Q.DL, 0, Q.AC, + Q.CxtI, Q.DT); + if (RHSKnownNonNegative && YKnownNegative) + return Pred == ICmpInst::ICMP_SLT ? getTrue(ITy) : getFalse(ITy); + if (RHSKnownNegative || YKnownNonNegative) + return Pred == ICmpInst::ICMP_SLT ? getFalse(ITy) : getTrue(ITy); + } + } + // icmp pred X, (or X, Y) + if (RBO && match(RBO, m_CombineOr(m_Or(m_Value(Y), m_Specific(LHS)), + m_Or(m_Specific(LHS), m_Value(Y))))) { + if (Pred == ICmpInst::ICMP_ULE) + return getTrue(ITy); + if (Pred == ICmpInst::ICMP_UGT) + return getFalse(ITy); + + if (Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SLE) { + bool LHSKnownNonNegative, LHSKnownNegative; + bool YKnownNonNegative, YKnownNegative; + ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, Q.DL, 0, + Q.AC, Q.CxtI, Q.DT); + ComputeSignBit(Y, YKnownNonNegative, YKnownNegative, Q.DL, 0, Q.AC, + Q.CxtI, Q.DT); + if (LHSKnownNonNegative && YKnownNegative) + return Pred == ICmpInst::ICMP_SGT ? getTrue(ITy) : getFalse(ITy); + if (LHSKnownNegative || YKnownNonNegative) + return Pred == ICmpInst::ICMP_SGT ? getFalse(ITy) : getTrue(ITy); + } + } } // icmp pred (and X, Y), X Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -195,6 +195,14 @@ isKnownNonZero(V, DL, Depth, AC, CxtI, DT); } +bool llvm::isKnownNegative(Value *V, const DataLayout &DL, unsigned Depth, + AssumptionCache *AC, const Instruction *CxtI, + const DominatorTree *DT) { + bool NonNegative, Negative; + ComputeSignBit(V, NonNegative, Negative, DL, Depth, AC, CxtI, DT); + return Negative; +} + static bool isKnownNonEqual(Value *V1, Value *V2, const Query &Q); bool llvm::isKnownNonEqual(Value *V1, Value *V2, const DataLayout &DL,