diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index 0584b7e29f67b9..e577d0cc7ad410 100644 --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -136,6 +136,13 @@ bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth = 0); bool isKnownNegation(const Value *X, const Value *Y, bool NeedNSW = false, bool AllowPoison = true); +/// Return true iff: +/// 1. X is poison implies Y is poison. +/// 2. X is true implies Y is false. +/// 3. X is false implies Y is true. +/// Otherwise, return false. +bool isKnownInversion(const Value *X, const Value *Y); + /// Returns true if the give value is known to be non-negative. bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth = 0); diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 6a806d596efe75..8126d2a1acc27c 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -8176,6 +8176,28 @@ bool llvm::isKnownNegation(const Value *X, const Value *Y, bool NeedNSW, match(Y, m_NSWSub(m_Specific(B), m_Specific(A))))); } +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; + 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; + + if (B == C) + return Pred1 == ICmpInst::getInversePredicate(Pred2); + + // Try to infer the relationship from constant ranges. + const APInt *RHSC1, *RHSC2; + if (!match(B, m_APInt(RHSC1)) || !match(C, m_APInt(RHSC2))) + return false; + + const auto CR1 = ConstantRange::makeExactICmpRegion(Pred1, *RHSC1); + const auto CR2 = ConstantRange::makeExactICmpRegion(Pred2, *RHSC2); + + return CR1.inverse() == CR2; +} + static SelectPatternResult matchSelectPattern(CmpInst::Predicate Pred, FastMathFlags FMF, Value *CmpLHS, Value *CmpRHS, diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 588607b3fea2fb..7d26807544d7e0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3520,33 +3520,6 @@ static bool matchFMulByZeroIfResultEqZero(InstCombinerImpl &IC, Value *Cmp0, return false; } -/// Return true iff: -/// 1. X is poison implies Y is poison. -/// 2. X is true implies Y is false. -/// 3. X is false implies Y is true. -/// Otherwise, return false. -static bool isKnownInversion(Value *X, Value *Y) { - // Handle X = icmp pred A, B, Y = icmp pred A, C. - Value *A, *B, *C; - ICmpInst::Predicate 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; - - if (B == C) - return Pred1 == ICmpInst::getInversePredicate(Pred2); - - // Try to infer the relationship from constant ranges. - const APInt *RHSC1, *RHSC2; - if (!match(B, m_APInt(RHSC1)) || !match(C, m_APInt(RHSC2))) - return false; - - const auto CR1 = ConstantRange::makeExactICmpRegion(Pred1, *RHSC1); - const auto CR2 = ConstantRange::makeExactICmpRegion(Pred2, *RHSC2); - - return CR1.inverse() == CR2; -} - Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) { Value *CondVal = SI.getCondition(); Value *TrueVal = SI.getTrueValue();