-
Notifications
You must be signed in to change notification settings - Fork 12.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PatternMatch: migrate to CmpPredicate #118534
Conversation
@llvm/pr-subscribers-backend-hexagon @llvm/pr-subscribers-backend-amdgpu Author: Ramkumar Ramachandra (artagnon) ChangesWith the introduction of CmpPredicate in 51a895a (IR: introduce struct with CmpInst::Predicate and samesign), PatternMatch is one of the first key pieces of infrastructure that must be updated to match a CmpInst respecting samesign information. Implement this change to Cmp-matchers. This is a preparatory step in migrating the codebase over to CmpPredicate. Since we no functional changes are desired at this stage, we have chosen not to migrate CmpPredicate::operator==(CmpPredicate) calls to use CmpPredicate::getMatching(), as that would have visible impact on tests that are not yet written: instead, we call CmpPredicate::operator==(Predicate), preserving the old behavior, while also inserting a few FIXME comments for follow-ups. Patch is 69.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/118534.diff 36 Files Affected:
diff --git a/llvm/include/llvm/IR/CmpPredicate.h b/llvm/include/llvm/IR/CmpPredicate.h
index 4b1be7beb2b663..ae027305cb4199 100644
--- a/llvm/include/llvm/IR/CmpPredicate.h
+++ b/llvm/include/llvm/IR/CmpPredicate.h
@@ -24,6 +24,9 @@ class CmpPredicate {
bool HasSameSign;
public:
+ /// Default constructor.
+ CmpPredicate() : Pred(CmpInst::BAD_ICMP_PREDICATE), HasSameSign(false) {}
+
/// Constructed implictly with a either Predicate and samesign information, or
/// just a Predicate, dropping samesign information.
CmpPredicate(CmpInst::Predicate Pred, bool HasSameSign = false)
@@ -52,11 +55,30 @@ class CmpPredicate {
/// An operator== on the underlying Predicate.
bool operator==(CmpInst::Predicate P) const { return Pred == P; }
+ bool operator!=(CmpInst::Predicate P) const { return Pred != P; }
/// There is no operator== defined on CmpPredicate. Use getMatching instead to
/// get the canonicalized matching CmpPredicate.
bool operator==(CmpPredicate) const = delete;
+ bool operator!=(CmpPredicate) const = delete;
+
+ /// TypeSwitch over the CmpInst and either do ICmpInst::getCmpPredicate() or
+ /// FCmpInst::getPredicate().
+ static CmpPredicate get(const CmpInst *Cmp);
+
+ /// Get the swapped predicate of a CmpPredicate, using
+ /// CmpInst::isIntPredicate().
+ static CmpPredicate getSwapped(CmpPredicate P);
+
+ /// Get the swapped predicate of a CmpInst.
+ static CmpPredicate getSwapped(const CmpInst *Cmp);
+
+ /// Provided to facilitate storing a CmpPredicate in data structures that
+ /// require hashing.
+ friend hash_code hash_value(const CmpPredicate &Arg); // NOLINT
};
+
+[[nodiscard]] hash_code hash_value(const CmpPredicate &Arg);
} // namespace llvm
#endif
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index fc4c0124d00b84..ed7e1eff6f0005 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -688,14 +688,14 @@ inline api_pred_ty<is_lowbit_mask_or_zero> m_LowBitMaskOrZero(const APInt *&V) {
}
struct icmp_pred_with_threshold {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
const APInt *Thr;
bool isValue(const APInt &C) { return ICmpInst::compare(C, *Thr, Pred); }
};
/// Match an integer or vector with every element comparing 'pred' (eg/ne/...)
/// to Threshold. For vectors, this includes constants with undefined elements.
inline cst_pred_ty<icmp_pred_with_threshold>
-m_SpecificInt_ICMP(ICmpInst::Predicate Predicate, const APInt &Threshold) {
+m_SpecificInt_ICMP(CmpPredicate Predicate, const APInt &Threshold) {
cst_pred_ty<icmp_pred_with_threshold> P;
P.Pred = Predicate;
P.Thr = &Threshold;
@@ -1557,16 +1557,16 @@ template <typename T> inline Exact_match<T> m_Exact(const T &SubPattern) {
// Matchers for CmpInst classes
//
-template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
+template <typename LHS_t, typename RHS_t, typename Class,
bool Commutable = false>
struct CmpClass_match {
- PredicateTy *Predicate;
+ CmpPredicate *Predicate;
LHS_t L;
RHS_t R;
// The evaluation order is always stable, regardless of Commutability.
// The LHS is always matched first.
- CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
+ CmpClass_match(CmpPredicate &Pred, const LHS_t &LHS, const RHS_t &RHS)
: Predicate(&Pred), L(LHS), R(RHS) {}
CmpClass_match(const LHS_t &LHS, const RHS_t &RHS)
: Predicate(nullptr), L(LHS), R(RHS) {}
@@ -1575,12 +1575,13 @@ struct CmpClass_match {
if (auto *I = dyn_cast<Class>(V)) {
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
if (Predicate)
- *Predicate = I->getPredicate();
+ *Predicate = CmpPredicate::get(I);
return true;
- } else if (Commutable && L.match(I->getOperand(1)) &&
- R.match(I->getOperand(0))) {
+ }
+ if (Commutable && L.match(I->getOperand(1)) &&
+ R.match(I->getOperand(0))) {
if (Predicate)
- *Predicate = I->getSwappedPredicate();
+ *Predicate = CmpPredicate::getSwapped(I);
return true;
}
}
@@ -1589,60 +1590,58 @@ struct CmpClass_match {
};
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, CmpInst> m_Cmp(CmpPredicate &Pred, const LHS &L,
+ const RHS &R) {
+ return CmpClass_match<LHS, RHS, CmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst> m_ICmp(CmpPredicate &Pred,
+ const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, FCmpInst> m_FCmp(CmpPredicate &Pred,
+ const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, FCmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_Cmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, CmpInst> m_Cmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, CmpInst>(L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_ICmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst> m_ICmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst>(L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_FCmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, FCmpInst> m_FCmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, FCmpInst>(L, R);
}
// Same as CmpClass, but instead of saving Pred as out output variable, match a
// specific input pred for equality.
-template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
+template <typename LHS_t, typename RHS_t, typename Class,
bool Commutable = false>
struct SpecificCmpClass_match {
- const PredicateTy Predicate;
+ const CmpPredicate Predicate;
LHS_t L;
RHS_t R;
- SpecificCmpClass_match(PredicateTy Pred, const LHS_t &LHS, const RHS_t &RHS)
+ SpecificCmpClass_match(CmpPredicate Pred, const LHS_t &LHS, const RHS_t &RHS)
: Predicate(Pred), L(LHS), R(RHS) {}
template <typename OpTy> bool match(OpTy *V) {
if (auto *I = dyn_cast<Class>(V)) {
- if (I->getPredicate() == Predicate && L.match(I->getOperand(0)) &&
- R.match(I->getOperand(1)))
+ if (CmpPredicate::getMatching(CmpPredicate::get(I), Predicate) &&
+ L.match(I->getOperand(0)) && R.match(I->getOperand(1)))
return true;
if constexpr (Commutable) {
- if (I->getPredicate() == Class::getSwappedPredicate(Predicate) &&
+ if (CmpPredicate::getMatching(CmpPredicate::get(I),
+ CmpPredicate::getSwapped(Predicate)) &&
L.match(I->getOperand(1)) && R.match(I->getOperand(0)))
return true;
}
@@ -1653,31 +1652,27 @@ struct SpecificCmpClass_match {
};
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_SpecificCmp(CmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, CmpInst>
+m_SpecificCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, CmpInst>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, ICmpInst>
+m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, ICmpInst>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, ICmpInst, true>
+m_c_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, ICmpInst, true>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_SpecificFCmp(FCmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, FCmpInst>
+m_SpecificFCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, FCmpInst>(MatchPred, L, R);
}
//===----------------------------------------------------------------------===//
@@ -2468,7 +2463,7 @@ struct UAddWithOverflow_match {
template <typename OpTy> bool match(OpTy *V) {
Value *ICmpLHS, *ICmpRHS;
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V))
return false;
@@ -2738,16 +2733,15 @@ inline AnyBinaryOp_match<LHS, RHS, true> m_c_BinOp(const LHS &L, const RHS &R) {
/// Matches an ICmp with a predicate over LHS and RHS in either order.
/// Swaps the predicate if operands are commuted.
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(Pred, L,
- R);
+inline CmpClass_match<LHS, RHS, ICmpInst, true>
+m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst, true>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_ICmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst, true> m_c_ICmp(const LHS &L,
+ const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst, true>(L, R);
}
/// Matches a specific opcode with LHS and RHS in either order.
diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp
index e1eb219cf977e1..9670ec7f043944 100644
--- a/llvm/lib/Analysis/IVDescriptors.cpp
+++ b/llvm/lib/Analysis/IVDescriptors.cpp
@@ -628,7 +628,7 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
Instruction *I, InstDesc &Prev) {
// We must handle the select(cmp(),x,y) as a single instruction. Advance to
// the select.
- CmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (match(I, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) {
if (auto *Select = dyn_cast<SelectInst>(*I->user_begin()))
return InstDesc(Select, Prev.getRecKind());
@@ -668,7 +668,7 @@ RecurrenceDescriptor::isMinMaxPattern(Instruction *I, RecurKind Kind,
// We must handle the select(cmp()) as a single instruction. Advance to the
// select.
- CmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (match(I, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) {
if (auto *Select = dyn_cast<SelectInst>(*I->user_begin()))
return InstDesc(Select, Prev.getRecKind());
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 05e8f5761c13cf..d08fe44e78cd40 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1542,12 +1542,12 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
const SimplifyQuery &Q) {
Value *X, *Y;
- ICmpInst::Predicate EqPred;
+ CmpPredicate EqPred;
if (!match(ZeroICmp, m_ICmp(EqPred, m_Value(Y), m_Zero())) ||
!ICmpInst::isEquality(EqPred))
return nullptr;
- ICmpInst::Predicate UnsignedPred;
+ CmpPredicate UnsignedPred;
Value *A, *B;
// Y = (A - B);
@@ -1686,7 +1686,7 @@ static Value *simplifyAndOrOfICmpsWithConstants(ICmpInst *Cmp0, ICmpInst *Cmp1,
static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
const InstrInfoQuery &IIQ) {
// (icmp (add V, C0), C1) & (icmp V, C0)
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
const APInt *C0, *C1;
Value *V;
if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_APInt(C0)), m_APInt(C1))))
@@ -1733,7 +1733,7 @@ static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
/// Try to simplify and/or of icmp with ctpop intrinsic.
static Value *simplifyAndOrOfICmpsWithCtpop(ICmpInst *Cmp0, ICmpInst *Cmp1,
bool IsAnd) {
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
Value *X;
const APInt *C;
if (!match(Cmp0, m_ICmp(Pred0, m_Intrinsic<Intrinsic::ctpop>(m_Value(X)),
@@ -1777,7 +1777,7 @@ static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1,
static Value *simplifyOrOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
const InstrInfoQuery &IIQ) {
// (icmp (add V, C0), C1) | (icmp V, C0)
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
const APInt *C0, *C1;
Value *V;
if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_APInt(C0)), m_APInt(C1))))
@@ -1933,7 +1933,7 @@ static Value *simplifyAndOrWithICmpEq(unsigned Opcode, Value *Op0, Value *Op1,
unsigned MaxRecurse) {
assert((Opcode == Instruction::And || Opcode == Instruction::Or) &&
"Must be and/or");
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *A, *B;
if (!match(Op0, m_ICmp(Pred, m_Value(A), m_Value(B))) ||
!ICmpInst::isEquality(Pred))
@@ -4656,7 +4656,7 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
Value *FalseVal,
const SimplifyQuery &Q,
unsigned MaxRecurse) {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *CmpLHS, *CmpRHS;
if (!match(CondVal, m_ICmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
return nullptr;
@@ -4780,7 +4780,7 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
const SimplifyQuery &Q,
unsigned MaxRecurse) {
- FCmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *CmpLHS, *CmpRHS;
if (!match(Cond, m_FCmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
return nullptr;
diff --git a/llvm/lib/Analysis/OverflowInstAnalysis.cpp b/llvm/lib/Analysis/OverflowInstAnalysis.cpp
index 8bfd6642f76027..40f71f4a8db46d 100644
--- a/llvm/lib/Analysis/OverflowInstAnalysis.cpp
+++ b/llvm/lib/Analysis/OverflowInstAnalysis.cpp
@@ -20,7 +20,7 @@ using namespace llvm::PatternMatch;
bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd,
Use *&Y) {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *X, *NotOp1;
int XIdx;
IntrinsicInst *II;
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f2c6949e535d2a..4b940557903daf 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;
@@ -1602,7 +1602,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.
@@ -2255,7 +2255,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 +2580,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 +3009,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 +3037,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,
@@ -4895,7 +4895,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;
@@ -5135,7 +5135,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 +8571,7 @@ bool llvm::isKno...
[truncated]
|
@llvm/pr-subscribers-backend-x86 Author: Ramkumar Ramachandra (artagnon) ChangesWith the introduction of CmpPredicate in 51a895a (IR: introduce struct with CmpInst::Predicate and samesign), PatternMatch is one of the first key pieces of infrastructure that must be updated to match a CmpInst respecting samesign information. Implement this change to Cmp-matchers. This is a preparatory step in migrating the codebase over to CmpPredicate. Since we no functional changes are desired at this stage, we have chosen not to migrate CmpPredicate::operator==(CmpPredicate) calls to use CmpPredicate::getMatching(), as that would have visible impact on tests that are not yet written: instead, we call CmpPredicate::operator==(Predicate), preserving the old behavior, while also inserting a few FIXME comments for follow-ups. Patch is 69.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/118534.diff 36 Files Affected:
diff --git a/llvm/include/llvm/IR/CmpPredicate.h b/llvm/include/llvm/IR/CmpPredicate.h
index 4b1be7beb2b663..ae027305cb4199 100644
--- a/llvm/include/llvm/IR/CmpPredicate.h
+++ b/llvm/include/llvm/IR/CmpPredicate.h
@@ -24,6 +24,9 @@ class CmpPredicate {
bool HasSameSign;
public:
+ /// Default constructor.
+ CmpPredicate() : Pred(CmpInst::BAD_ICMP_PREDICATE), HasSameSign(false) {}
+
/// Constructed implictly with a either Predicate and samesign information, or
/// just a Predicate, dropping samesign information.
CmpPredicate(CmpInst::Predicate Pred, bool HasSameSign = false)
@@ -52,11 +55,30 @@ class CmpPredicate {
/// An operator== on the underlying Predicate.
bool operator==(CmpInst::Predicate P) const { return Pred == P; }
+ bool operator!=(CmpInst::Predicate P) const { return Pred != P; }
/// There is no operator== defined on CmpPredicate. Use getMatching instead to
/// get the canonicalized matching CmpPredicate.
bool operator==(CmpPredicate) const = delete;
+ bool operator!=(CmpPredicate) const = delete;
+
+ /// TypeSwitch over the CmpInst and either do ICmpInst::getCmpPredicate() or
+ /// FCmpInst::getPredicate().
+ static CmpPredicate get(const CmpInst *Cmp);
+
+ /// Get the swapped predicate of a CmpPredicate, using
+ /// CmpInst::isIntPredicate().
+ static CmpPredicate getSwapped(CmpPredicate P);
+
+ /// Get the swapped predicate of a CmpInst.
+ static CmpPredicate getSwapped(const CmpInst *Cmp);
+
+ /// Provided to facilitate storing a CmpPredicate in data structures that
+ /// require hashing.
+ friend hash_code hash_value(const CmpPredicate &Arg); // NOLINT
};
+
+[[nodiscard]] hash_code hash_value(const CmpPredicate &Arg);
} // namespace llvm
#endif
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index fc4c0124d00b84..ed7e1eff6f0005 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -688,14 +688,14 @@ inline api_pred_ty<is_lowbit_mask_or_zero> m_LowBitMaskOrZero(const APInt *&V) {
}
struct icmp_pred_with_threshold {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
const APInt *Thr;
bool isValue(const APInt &C) { return ICmpInst::compare(C, *Thr, Pred); }
};
/// Match an integer or vector with every element comparing 'pred' (eg/ne/...)
/// to Threshold. For vectors, this includes constants with undefined elements.
inline cst_pred_ty<icmp_pred_with_threshold>
-m_SpecificInt_ICMP(ICmpInst::Predicate Predicate, const APInt &Threshold) {
+m_SpecificInt_ICMP(CmpPredicate Predicate, const APInt &Threshold) {
cst_pred_ty<icmp_pred_with_threshold> P;
P.Pred = Predicate;
P.Thr = &Threshold;
@@ -1557,16 +1557,16 @@ template <typename T> inline Exact_match<T> m_Exact(const T &SubPattern) {
// Matchers for CmpInst classes
//
-template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
+template <typename LHS_t, typename RHS_t, typename Class,
bool Commutable = false>
struct CmpClass_match {
- PredicateTy *Predicate;
+ CmpPredicate *Predicate;
LHS_t L;
RHS_t R;
// The evaluation order is always stable, regardless of Commutability.
// The LHS is always matched first.
- CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
+ CmpClass_match(CmpPredicate &Pred, const LHS_t &LHS, const RHS_t &RHS)
: Predicate(&Pred), L(LHS), R(RHS) {}
CmpClass_match(const LHS_t &LHS, const RHS_t &RHS)
: Predicate(nullptr), L(LHS), R(RHS) {}
@@ -1575,12 +1575,13 @@ struct CmpClass_match {
if (auto *I = dyn_cast<Class>(V)) {
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
if (Predicate)
- *Predicate = I->getPredicate();
+ *Predicate = CmpPredicate::get(I);
return true;
- } else if (Commutable && L.match(I->getOperand(1)) &&
- R.match(I->getOperand(0))) {
+ }
+ if (Commutable && L.match(I->getOperand(1)) &&
+ R.match(I->getOperand(0))) {
if (Predicate)
- *Predicate = I->getSwappedPredicate();
+ *Predicate = CmpPredicate::getSwapped(I);
return true;
}
}
@@ -1589,60 +1590,58 @@ struct CmpClass_match {
};
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, CmpInst> m_Cmp(CmpPredicate &Pred, const LHS &L,
+ const RHS &R) {
+ return CmpClass_match<LHS, RHS, CmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst> m_ICmp(CmpPredicate &Pred,
+ const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, FCmpInst> m_FCmp(CmpPredicate &Pred,
+ const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, FCmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_Cmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, CmpInst> m_Cmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, CmpInst>(L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_ICmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst> m_ICmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst>(L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_FCmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, FCmpInst> m_FCmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, FCmpInst>(L, R);
}
// Same as CmpClass, but instead of saving Pred as out output variable, match a
// specific input pred for equality.
-template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
+template <typename LHS_t, typename RHS_t, typename Class,
bool Commutable = false>
struct SpecificCmpClass_match {
- const PredicateTy Predicate;
+ const CmpPredicate Predicate;
LHS_t L;
RHS_t R;
- SpecificCmpClass_match(PredicateTy Pred, const LHS_t &LHS, const RHS_t &RHS)
+ SpecificCmpClass_match(CmpPredicate Pred, const LHS_t &LHS, const RHS_t &RHS)
: Predicate(Pred), L(LHS), R(RHS) {}
template <typename OpTy> bool match(OpTy *V) {
if (auto *I = dyn_cast<Class>(V)) {
- if (I->getPredicate() == Predicate && L.match(I->getOperand(0)) &&
- R.match(I->getOperand(1)))
+ if (CmpPredicate::getMatching(CmpPredicate::get(I), Predicate) &&
+ L.match(I->getOperand(0)) && R.match(I->getOperand(1)))
return true;
if constexpr (Commutable) {
- if (I->getPredicate() == Class::getSwappedPredicate(Predicate) &&
+ if (CmpPredicate::getMatching(CmpPredicate::get(I),
+ CmpPredicate::getSwapped(Predicate)) &&
L.match(I->getOperand(1)) && R.match(I->getOperand(0)))
return true;
}
@@ -1653,31 +1652,27 @@ struct SpecificCmpClass_match {
};
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_SpecificCmp(CmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, CmpInst>
+m_SpecificCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, CmpInst>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, ICmpInst>
+m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, ICmpInst>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, ICmpInst, true>
+m_c_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, ICmpInst, true>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_SpecificFCmp(FCmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, FCmpInst>
+m_SpecificFCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, FCmpInst>(MatchPred, L, R);
}
//===----------------------------------------------------------------------===//
@@ -2468,7 +2463,7 @@ struct UAddWithOverflow_match {
template <typename OpTy> bool match(OpTy *V) {
Value *ICmpLHS, *ICmpRHS;
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V))
return false;
@@ -2738,16 +2733,15 @@ inline AnyBinaryOp_match<LHS, RHS, true> m_c_BinOp(const LHS &L, const RHS &R) {
/// Matches an ICmp with a predicate over LHS and RHS in either order.
/// Swaps the predicate if operands are commuted.
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(Pred, L,
- R);
+inline CmpClass_match<LHS, RHS, ICmpInst, true>
+m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst, true>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_ICmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst, true> m_c_ICmp(const LHS &L,
+ const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst, true>(L, R);
}
/// Matches a specific opcode with LHS and RHS in either order.
diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp
index e1eb219cf977e1..9670ec7f043944 100644
--- a/llvm/lib/Analysis/IVDescriptors.cpp
+++ b/llvm/lib/Analysis/IVDescriptors.cpp
@@ -628,7 +628,7 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
Instruction *I, InstDesc &Prev) {
// We must handle the select(cmp(),x,y) as a single instruction. Advance to
// the select.
- CmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (match(I, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) {
if (auto *Select = dyn_cast<SelectInst>(*I->user_begin()))
return InstDesc(Select, Prev.getRecKind());
@@ -668,7 +668,7 @@ RecurrenceDescriptor::isMinMaxPattern(Instruction *I, RecurKind Kind,
// We must handle the select(cmp()) as a single instruction. Advance to the
// select.
- CmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (match(I, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) {
if (auto *Select = dyn_cast<SelectInst>(*I->user_begin()))
return InstDesc(Select, Prev.getRecKind());
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 05e8f5761c13cf..d08fe44e78cd40 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1542,12 +1542,12 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
const SimplifyQuery &Q) {
Value *X, *Y;
- ICmpInst::Predicate EqPred;
+ CmpPredicate EqPred;
if (!match(ZeroICmp, m_ICmp(EqPred, m_Value(Y), m_Zero())) ||
!ICmpInst::isEquality(EqPred))
return nullptr;
- ICmpInst::Predicate UnsignedPred;
+ CmpPredicate UnsignedPred;
Value *A, *B;
// Y = (A - B);
@@ -1686,7 +1686,7 @@ static Value *simplifyAndOrOfICmpsWithConstants(ICmpInst *Cmp0, ICmpInst *Cmp1,
static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
const InstrInfoQuery &IIQ) {
// (icmp (add V, C0), C1) & (icmp V, C0)
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
const APInt *C0, *C1;
Value *V;
if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_APInt(C0)), m_APInt(C1))))
@@ -1733,7 +1733,7 @@ static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
/// Try to simplify and/or of icmp with ctpop intrinsic.
static Value *simplifyAndOrOfICmpsWithCtpop(ICmpInst *Cmp0, ICmpInst *Cmp1,
bool IsAnd) {
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
Value *X;
const APInt *C;
if (!match(Cmp0, m_ICmp(Pred0, m_Intrinsic<Intrinsic::ctpop>(m_Value(X)),
@@ -1777,7 +1777,7 @@ static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1,
static Value *simplifyOrOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
const InstrInfoQuery &IIQ) {
// (icmp (add V, C0), C1) | (icmp V, C0)
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
const APInt *C0, *C1;
Value *V;
if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_APInt(C0)), m_APInt(C1))))
@@ -1933,7 +1933,7 @@ static Value *simplifyAndOrWithICmpEq(unsigned Opcode, Value *Op0, Value *Op1,
unsigned MaxRecurse) {
assert((Opcode == Instruction::And || Opcode == Instruction::Or) &&
"Must be and/or");
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *A, *B;
if (!match(Op0, m_ICmp(Pred, m_Value(A), m_Value(B))) ||
!ICmpInst::isEquality(Pred))
@@ -4656,7 +4656,7 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
Value *FalseVal,
const SimplifyQuery &Q,
unsigned MaxRecurse) {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *CmpLHS, *CmpRHS;
if (!match(CondVal, m_ICmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
return nullptr;
@@ -4780,7 +4780,7 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
const SimplifyQuery &Q,
unsigned MaxRecurse) {
- FCmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *CmpLHS, *CmpRHS;
if (!match(Cond, m_FCmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
return nullptr;
diff --git a/llvm/lib/Analysis/OverflowInstAnalysis.cpp b/llvm/lib/Analysis/OverflowInstAnalysis.cpp
index 8bfd6642f76027..40f71f4a8db46d 100644
--- a/llvm/lib/Analysis/OverflowInstAnalysis.cpp
+++ b/llvm/lib/Analysis/OverflowInstAnalysis.cpp
@@ -20,7 +20,7 @@ using namespace llvm::PatternMatch;
bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd,
Use *&Y) {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *X, *NotOp1;
int XIdx;
IntrinsicInst *II;
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f2c6949e535d2a..4b940557903daf 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;
@@ -1602,7 +1602,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.
@@ -2255,7 +2255,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 +2580,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 +3009,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 +3037,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,
@@ -4895,7 +4895,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;
@@ -5135,7 +5135,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 +8571,7 @@ bool llvm::isKno...
[truncated]
|
@llvm/pr-subscribers-backend-aarch64 Author: Ramkumar Ramachandra (artagnon) ChangesWith the introduction of CmpPredicate in 51a895a (IR: introduce struct with CmpInst::Predicate and samesign), PatternMatch is one of the first key pieces of infrastructure that must be updated to match a CmpInst respecting samesign information. Implement this change to Cmp-matchers. This is a preparatory step in migrating the codebase over to CmpPredicate. Since we no functional changes are desired at this stage, we have chosen not to migrate CmpPredicate::operator==(CmpPredicate) calls to use CmpPredicate::getMatching(), as that would have visible impact on tests that are not yet written: instead, we call CmpPredicate::operator==(Predicate), preserving the old behavior, while also inserting a few FIXME comments for follow-ups. Patch is 69.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/118534.diff 36 Files Affected:
diff --git a/llvm/include/llvm/IR/CmpPredicate.h b/llvm/include/llvm/IR/CmpPredicate.h
index 4b1be7beb2b663..ae027305cb4199 100644
--- a/llvm/include/llvm/IR/CmpPredicate.h
+++ b/llvm/include/llvm/IR/CmpPredicate.h
@@ -24,6 +24,9 @@ class CmpPredicate {
bool HasSameSign;
public:
+ /// Default constructor.
+ CmpPredicate() : Pred(CmpInst::BAD_ICMP_PREDICATE), HasSameSign(false) {}
+
/// Constructed implictly with a either Predicate and samesign information, or
/// just a Predicate, dropping samesign information.
CmpPredicate(CmpInst::Predicate Pred, bool HasSameSign = false)
@@ -52,11 +55,30 @@ class CmpPredicate {
/// An operator== on the underlying Predicate.
bool operator==(CmpInst::Predicate P) const { return Pred == P; }
+ bool operator!=(CmpInst::Predicate P) const { return Pred != P; }
/// There is no operator== defined on CmpPredicate. Use getMatching instead to
/// get the canonicalized matching CmpPredicate.
bool operator==(CmpPredicate) const = delete;
+ bool operator!=(CmpPredicate) const = delete;
+
+ /// TypeSwitch over the CmpInst and either do ICmpInst::getCmpPredicate() or
+ /// FCmpInst::getPredicate().
+ static CmpPredicate get(const CmpInst *Cmp);
+
+ /// Get the swapped predicate of a CmpPredicate, using
+ /// CmpInst::isIntPredicate().
+ static CmpPredicate getSwapped(CmpPredicate P);
+
+ /// Get the swapped predicate of a CmpInst.
+ static CmpPredicate getSwapped(const CmpInst *Cmp);
+
+ /// Provided to facilitate storing a CmpPredicate in data structures that
+ /// require hashing.
+ friend hash_code hash_value(const CmpPredicate &Arg); // NOLINT
};
+
+[[nodiscard]] hash_code hash_value(const CmpPredicate &Arg);
} // namespace llvm
#endif
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index fc4c0124d00b84..ed7e1eff6f0005 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -688,14 +688,14 @@ inline api_pred_ty<is_lowbit_mask_or_zero> m_LowBitMaskOrZero(const APInt *&V) {
}
struct icmp_pred_with_threshold {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
const APInt *Thr;
bool isValue(const APInt &C) { return ICmpInst::compare(C, *Thr, Pred); }
};
/// Match an integer or vector with every element comparing 'pred' (eg/ne/...)
/// to Threshold. For vectors, this includes constants with undefined elements.
inline cst_pred_ty<icmp_pred_with_threshold>
-m_SpecificInt_ICMP(ICmpInst::Predicate Predicate, const APInt &Threshold) {
+m_SpecificInt_ICMP(CmpPredicate Predicate, const APInt &Threshold) {
cst_pred_ty<icmp_pred_with_threshold> P;
P.Pred = Predicate;
P.Thr = &Threshold;
@@ -1557,16 +1557,16 @@ template <typename T> inline Exact_match<T> m_Exact(const T &SubPattern) {
// Matchers for CmpInst classes
//
-template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
+template <typename LHS_t, typename RHS_t, typename Class,
bool Commutable = false>
struct CmpClass_match {
- PredicateTy *Predicate;
+ CmpPredicate *Predicate;
LHS_t L;
RHS_t R;
// The evaluation order is always stable, regardless of Commutability.
// The LHS is always matched first.
- CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
+ CmpClass_match(CmpPredicate &Pred, const LHS_t &LHS, const RHS_t &RHS)
: Predicate(&Pred), L(LHS), R(RHS) {}
CmpClass_match(const LHS_t &LHS, const RHS_t &RHS)
: Predicate(nullptr), L(LHS), R(RHS) {}
@@ -1575,12 +1575,13 @@ struct CmpClass_match {
if (auto *I = dyn_cast<Class>(V)) {
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
if (Predicate)
- *Predicate = I->getPredicate();
+ *Predicate = CmpPredicate::get(I);
return true;
- } else if (Commutable && L.match(I->getOperand(1)) &&
- R.match(I->getOperand(0))) {
+ }
+ if (Commutable && L.match(I->getOperand(1)) &&
+ R.match(I->getOperand(0))) {
if (Predicate)
- *Predicate = I->getSwappedPredicate();
+ *Predicate = CmpPredicate::getSwapped(I);
return true;
}
}
@@ -1589,60 +1590,58 @@ struct CmpClass_match {
};
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, CmpInst> m_Cmp(CmpPredicate &Pred, const LHS &L,
+ const RHS &R) {
+ return CmpClass_match<LHS, RHS, CmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst> m_ICmp(CmpPredicate &Pred,
+ const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, FCmpInst> m_FCmp(CmpPredicate &Pred,
+ const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, FCmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_Cmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, CmpInst> m_Cmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, CmpInst>(L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_ICmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst> m_ICmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst>(L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_FCmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, FCmpInst> m_FCmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, FCmpInst>(L, R);
}
// Same as CmpClass, but instead of saving Pred as out output variable, match a
// specific input pred for equality.
-template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
+template <typename LHS_t, typename RHS_t, typename Class,
bool Commutable = false>
struct SpecificCmpClass_match {
- const PredicateTy Predicate;
+ const CmpPredicate Predicate;
LHS_t L;
RHS_t R;
- SpecificCmpClass_match(PredicateTy Pred, const LHS_t &LHS, const RHS_t &RHS)
+ SpecificCmpClass_match(CmpPredicate Pred, const LHS_t &LHS, const RHS_t &RHS)
: Predicate(Pred), L(LHS), R(RHS) {}
template <typename OpTy> bool match(OpTy *V) {
if (auto *I = dyn_cast<Class>(V)) {
- if (I->getPredicate() == Predicate && L.match(I->getOperand(0)) &&
- R.match(I->getOperand(1)))
+ if (CmpPredicate::getMatching(CmpPredicate::get(I), Predicate) &&
+ L.match(I->getOperand(0)) && R.match(I->getOperand(1)))
return true;
if constexpr (Commutable) {
- if (I->getPredicate() == Class::getSwappedPredicate(Predicate) &&
+ if (CmpPredicate::getMatching(CmpPredicate::get(I),
+ CmpPredicate::getSwapped(Predicate)) &&
L.match(I->getOperand(1)) && R.match(I->getOperand(0)))
return true;
}
@@ -1653,31 +1652,27 @@ struct SpecificCmpClass_match {
};
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_SpecificCmp(CmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, CmpInst>
+m_SpecificCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, CmpInst>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, ICmpInst>
+m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, ICmpInst>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, ICmpInst, true>
+m_c_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, ICmpInst, true>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_SpecificFCmp(FCmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, FCmpInst>
+m_SpecificFCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, FCmpInst>(MatchPred, L, R);
}
//===----------------------------------------------------------------------===//
@@ -2468,7 +2463,7 @@ struct UAddWithOverflow_match {
template <typename OpTy> bool match(OpTy *V) {
Value *ICmpLHS, *ICmpRHS;
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V))
return false;
@@ -2738,16 +2733,15 @@ inline AnyBinaryOp_match<LHS, RHS, true> m_c_BinOp(const LHS &L, const RHS &R) {
/// Matches an ICmp with a predicate over LHS and RHS in either order.
/// Swaps the predicate if operands are commuted.
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(Pred, L,
- R);
+inline CmpClass_match<LHS, RHS, ICmpInst, true>
+m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst, true>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_ICmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst, true> m_c_ICmp(const LHS &L,
+ const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst, true>(L, R);
}
/// Matches a specific opcode with LHS and RHS in either order.
diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp
index e1eb219cf977e1..9670ec7f043944 100644
--- a/llvm/lib/Analysis/IVDescriptors.cpp
+++ b/llvm/lib/Analysis/IVDescriptors.cpp
@@ -628,7 +628,7 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
Instruction *I, InstDesc &Prev) {
// We must handle the select(cmp(),x,y) as a single instruction. Advance to
// the select.
- CmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (match(I, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) {
if (auto *Select = dyn_cast<SelectInst>(*I->user_begin()))
return InstDesc(Select, Prev.getRecKind());
@@ -668,7 +668,7 @@ RecurrenceDescriptor::isMinMaxPattern(Instruction *I, RecurKind Kind,
// We must handle the select(cmp()) as a single instruction. Advance to the
// select.
- CmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (match(I, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) {
if (auto *Select = dyn_cast<SelectInst>(*I->user_begin()))
return InstDesc(Select, Prev.getRecKind());
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 05e8f5761c13cf..d08fe44e78cd40 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1542,12 +1542,12 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
const SimplifyQuery &Q) {
Value *X, *Y;
- ICmpInst::Predicate EqPred;
+ CmpPredicate EqPred;
if (!match(ZeroICmp, m_ICmp(EqPred, m_Value(Y), m_Zero())) ||
!ICmpInst::isEquality(EqPred))
return nullptr;
- ICmpInst::Predicate UnsignedPred;
+ CmpPredicate UnsignedPred;
Value *A, *B;
// Y = (A - B);
@@ -1686,7 +1686,7 @@ static Value *simplifyAndOrOfICmpsWithConstants(ICmpInst *Cmp0, ICmpInst *Cmp1,
static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
const InstrInfoQuery &IIQ) {
// (icmp (add V, C0), C1) & (icmp V, C0)
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
const APInt *C0, *C1;
Value *V;
if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_APInt(C0)), m_APInt(C1))))
@@ -1733,7 +1733,7 @@ static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
/// Try to simplify and/or of icmp with ctpop intrinsic.
static Value *simplifyAndOrOfICmpsWithCtpop(ICmpInst *Cmp0, ICmpInst *Cmp1,
bool IsAnd) {
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
Value *X;
const APInt *C;
if (!match(Cmp0, m_ICmp(Pred0, m_Intrinsic<Intrinsic::ctpop>(m_Value(X)),
@@ -1777,7 +1777,7 @@ static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1,
static Value *simplifyOrOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
const InstrInfoQuery &IIQ) {
// (icmp (add V, C0), C1) | (icmp V, C0)
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
const APInt *C0, *C1;
Value *V;
if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_APInt(C0)), m_APInt(C1))))
@@ -1933,7 +1933,7 @@ static Value *simplifyAndOrWithICmpEq(unsigned Opcode, Value *Op0, Value *Op1,
unsigned MaxRecurse) {
assert((Opcode == Instruction::And || Opcode == Instruction::Or) &&
"Must be and/or");
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *A, *B;
if (!match(Op0, m_ICmp(Pred, m_Value(A), m_Value(B))) ||
!ICmpInst::isEquality(Pred))
@@ -4656,7 +4656,7 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
Value *FalseVal,
const SimplifyQuery &Q,
unsigned MaxRecurse) {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *CmpLHS, *CmpRHS;
if (!match(CondVal, m_ICmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
return nullptr;
@@ -4780,7 +4780,7 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
const SimplifyQuery &Q,
unsigned MaxRecurse) {
- FCmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *CmpLHS, *CmpRHS;
if (!match(Cond, m_FCmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
return nullptr;
diff --git a/llvm/lib/Analysis/OverflowInstAnalysis.cpp b/llvm/lib/Analysis/OverflowInstAnalysis.cpp
index 8bfd6642f76027..40f71f4a8db46d 100644
--- a/llvm/lib/Analysis/OverflowInstAnalysis.cpp
+++ b/llvm/lib/Analysis/OverflowInstAnalysis.cpp
@@ -20,7 +20,7 @@ using namespace llvm::PatternMatch;
bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd,
Use *&Y) {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *X, *NotOp1;
int XIdx;
IntrinsicInst *II;
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f2c6949e535d2a..4b940557903daf 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;
@@ -1602,7 +1602,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.
@@ -2255,7 +2255,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 +2580,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 +3009,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 +3037,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,
@@ -4895,7 +4895,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;
@@ -5135,7 +5135,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 +8571,7 @@ bool llvm::isKno...
[truncated]
|
This is going to have a sizable compile-time impact, but again, I'm not sure we can help it. |
@llvm/pr-subscribers-llvm-analysis Author: Ramkumar Ramachandra (artagnon) ChangesWith the introduction of CmpPredicate in 51a895a (IR: introduce struct with CmpInst::Predicate and samesign), PatternMatch is one of the first key pieces of infrastructure that must be updated to match a CmpInst respecting samesign information. Implement this change to Cmp-matchers. This is a preparatory step in migrating the codebase over to CmpPredicate. Since we no functional changes are desired at this stage, we have chosen not to migrate CmpPredicate::operator==(CmpPredicate) calls to use CmpPredicate::getMatching(), as that would have visible impact on tests that are not yet written: instead, we call CmpPredicate::operator==(Predicate), preserving the old behavior, while also inserting a few FIXME comments for follow-ups. Patch is 69.62 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/118534.diff 36 Files Affected:
diff --git a/llvm/include/llvm/IR/CmpPredicate.h b/llvm/include/llvm/IR/CmpPredicate.h
index 4b1be7beb2b663..ae027305cb4199 100644
--- a/llvm/include/llvm/IR/CmpPredicate.h
+++ b/llvm/include/llvm/IR/CmpPredicate.h
@@ -24,6 +24,9 @@ class CmpPredicate {
bool HasSameSign;
public:
+ /// Default constructor.
+ CmpPredicate() : Pred(CmpInst::BAD_ICMP_PREDICATE), HasSameSign(false) {}
+
/// Constructed implictly with a either Predicate and samesign information, or
/// just a Predicate, dropping samesign information.
CmpPredicate(CmpInst::Predicate Pred, bool HasSameSign = false)
@@ -52,11 +55,30 @@ class CmpPredicate {
/// An operator== on the underlying Predicate.
bool operator==(CmpInst::Predicate P) const { return Pred == P; }
+ bool operator!=(CmpInst::Predicate P) const { return Pred != P; }
/// There is no operator== defined on CmpPredicate. Use getMatching instead to
/// get the canonicalized matching CmpPredicate.
bool operator==(CmpPredicate) const = delete;
+ bool operator!=(CmpPredicate) const = delete;
+
+ /// TypeSwitch over the CmpInst and either do ICmpInst::getCmpPredicate() or
+ /// FCmpInst::getPredicate().
+ static CmpPredicate get(const CmpInst *Cmp);
+
+ /// Get the swapped predicate of a CmpPredicate, using
+ /// CmpInst::isIntPredicate().
+ static CmpPredicate getSwapped(CmpPredicate P);
+
+ /// Get the swapped predicate of a CmpInst.
+ static CmpPredicate getSwapped(const CmpInst *Cmp);
+
+ /// Provided to facilitate storing a CmpPredicate in data structures that
+ /// require hashing.
+ friend hash_code hash_value(const CmpPredicate &Arg); // NOLINT
};
+
+[[nodiscard]] hash_code hash_value(const CmpPredicate &Arg);
} // namespace llvm
#endif
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index fc4c0124d00b84..ed7e1eff6f0005 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -688,14 +688,14 @@ inline api_pred_ty<is_lowbit_mask_or_zero> m_LowBitMaskOrZero(const APInt *&V) {
}
struct icmp_pred_with_threshold {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
const APInt *Thr;
bool isValue(const APInt &C) { return ICmpInst::compare(C, *Thr, Pred); }
};
/// Match an integer or vector with every element comparing 'pred' (eg/ne/...)
/// to Threshold. For vectors, this includes constants with undefined elements.
inline cst_pred_ty<icmp_pred_with_threshold>
-m_SpecificInt_ICMP(ICmpInst::Predicate Predicate, const APInt &Threshold) {
+m_SpecificInt_ICMP(CmpPredicate Predicate, const APInt &Threshold) {
cst_pred_ty<icmp_pred_with_threshold> P;
P.Pred = Predicate;
P.Thr = &Threshold;
@@ -1557,16 +1557,16 @@ template <typename T> inline Exact_match<T> m_Exact(const T &SubPattern) {
// Matchers for CmpInst classes
//
-template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
+template <typename LHS_t, typename RHS_t, typename Class,
bool Commutable = false>
struct CmpClass_match {
- PredicateTy *Predicate;
+ CmpPredicate *Predicate;
LHS_t L;
RHS_t R;
// The evaluation order is always stable, regardless of Commutability.
// The LHS is always matched first.
- CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
+ CmpClass_match(CmpPredicate &Pred, const LHS_t &LHS, const RHS_t &RHS)
: Predicate(&Pred), L(LHS), R(RHS) {}
CmpClass_match(const LHS_t &LHS, const RHS_t &RHS)
: Predicate(nullptr), L(LHS), R(RHS) {}
@@ -1575,12 +1575,13 @@ struct CmpClass_match {
if (auto *I = dyn_cast<Class>(V)) {
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
if (Predicate)
- *Predicate = I->getPredicate();
+ *Predicate = CmpPredicate::get(I);
return true;
- } else if (Commutable && L.match(I->getOperand(1)) &&
- R.match(I->getOperand(0))) {
+ }
+ if (Commutable && L.match(I->getOperand(1)) &&
+ R.match(I->getOperand(0))) {
if (Predicate)
- *Predicate = I->getSwappedPredicate();
+ *Predicate = CmpPredicate::getSwapped(I);
return true;
}
}
@@ -1589,60 +1590,58 @@ struct CmpClass_match {
};
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, CmpInst> m_Cmp(CmpPredicate &Pred, const LHS &L,
+ const RHS &R) {
+ return CmpClass_match<LHS, RHS, CmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst> m_ICmp(CmpPredicate &Pred,
+ const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Pred, L, R);
+inline CmpClass_match<LHS, RHS, FCmpInst> m_FCmp(CmpPredicate &Pred,
+ const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, FCmpInst>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_Cmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, CmpInst> m_Cmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, CmpInst>(L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_ICmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst> m_ICmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst>(L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_FCmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(L, R);
+inline CmpClass_match<LHS, RHS, FCmpInst> m_FCmp(const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, FCmpInst>(L, R);
}
// Same as CmpClass, but instead of saving Pred as out output variable, match a
// specific input pred for equality.
-template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
+template <typename LHS_t, typename RHS_t, typename Class,
bool Commutable = false>
struct SpecificCmpClass_match {
- const PredicateTy Predicate;
+ const CmpPredicate Predicate;
LHS_t L;
RHS_t R;
- SpecificCmpClass_match(PredicateTy Pred, const LHS_t &LHS, const RHS_t &RHS)
+ SpecificCmpClass_match(CmpPredicate Pred, const LHS_t &LHS, const RHS_t &RHS)
: Predicate(Pred), L(LHS), R(RHS) {}
template <typename OpTy> bool match(OpTy *V) {
if (auto *I = dyn_cast<Class>(V)) {
- if (I->getPredicate() == Predicate && L.match(I->getOperand(0)) &&
- R.match(I->getOperand(1)))
+ if (CmpPredicate::getMatching(CmpPredicate::get(I), Predicate) &&
+ L.match(I->getOperand(0)) && R.match(I->getOperand(1)))
return true;
if constexpr (Commutable) {
- if (I->getPredicate() == Class::getSwappedPredicate(Predicate) &&
+ if (CmpPredicate::getMatching(CmpPredicate::get(I),
+ CmpPredicate::getSwapped(Predicate)) &&
L.match(I->getOperand(1)) && R.match(I->getOperand(0)))
return true;
}
@@ -1653,31 +1652,27 @@ struct SpecificCmpClass_match {
};
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
-m_SpecificCmp(CmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, CmpInst>
+m_SpecificCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, CmpInst>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
-m_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, ICmpInst>
+m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, ICmpInst>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, ICmpInst, true>
+m_c_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, ICmpInst, true>(MatchPred, L, R);
}
template <typename LHS, typename RHS>
-inline SpecificCmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
-m_SpecificFCmp(FCmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
- return SpecificCmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(
- MatchPred, L, R);
+inline SpecificCmpClass_match<LHS, RHS, FCmpInst>
+m_SpecificFCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
+ return SpecificCmpClass_match<LHS, RHS, FCmpInst>(MatchPred, L, R);
}
//===----------------------------------------------------------------------===//
@@ -2468,7 +2463,7 @@ struct UAddWithOverflow_match {
template <typename OpTy> bool match(OpTy *V) {
Value *ICmpLHS, *ICmpRHS;
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V))
return false;
@@ -2738,16 +2733,15 @@ inline AnyBinaryOp_match<LHS, RHS, true> m_c_BinOp(const LHS &L, const RHS &R) {
/// Matches an ICmp with a predicate over LHS and RHS in either order.
/// Swaps the predicate if operands are commuted.
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(Pred, L,
- R);
+inline CmpClass_match<LHS, RHS, ICmpInst, true>
+m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst, true>(Pred, L, R);
}
template <typename LHS, typename RHS>
-inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
-m_c_ICmp(const LHS &L, const RHS &R) {
- return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(L, R);
+inline CmpClass_match<LHS, RHS, ICmpInst, true> m_c_ICmp(const LHS &L,
+ const RHS &R) {
+ return CmpClass_match<LHS, RHS, ICmpInst, true>(L, R);
}
/// Matches a specific opcode with LHS and RHS in either order.
diff --git a/llvm/lib/Analysis/IVDescriptors.cpp b/llvm/lib/Analysis/IVDescriptors.cpp
index e1eb219cf977e1..9670ec7f043944 100644
--- a/llvm/lib/Analysis/IVDescriptors.cpp
+++ b/llvm/lib/Analysis/IVDescriptors.cpp
@@ -628,7 +628,7 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
Instruction *I, InstDesc &Prev) {
// We must handle the select(cmp(),x,y) as a single instruction. Advance to
// the select.
- CmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (match(I, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) {
if (auto *Select = dyn_cast<SelectInst>(*I->user_begin()))
return InstDesc(Select, Prev.getRecKind());
@@ -668,7 +668,7 @@ RecurrenceDescriptor::isMinMaxPattern(Instruction *I, RecurKind Kind,
// We must handle the select(cmp()) as a single instruction. Advance to the
// select.
- CmpInst::Predicate Pred;
+ CmpPredicate Pred;
if (match(I, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) {
if (auto *Select = dyn_cast<SelectInst>(*I->user_begin()))
return InstDesc(Select, Prev.getRecKind());
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 05e8f5761c13cf..d08fe44e78cd40 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -1542,12 +1542,12 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
const SimplifyQuery &Q) {
Value *X, *Y;
- ICmpInst::Predicate EqPred;
+ CmpPredicate EqPred;
if (!match(ZeroICmp, m_ICmp(EqPred, m_Value(Y), m_Zero())) ||
!ICmpInst::isEquality(EqPred))
return nullptr;
- ICmpInst::Predicate UnsignedPred;
+ CmpPredicate UnsignedPred;
Value *A, *B;
// Y = (A - B);
@@ -1686,7 +1686,7 @@ static Value *simplifyAndOrOfICmpsWithConstants(ICmpInst *Cmp0, ICmpInst *Cmp1,
static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
const InstrInfoQuery &IIQ) {
// (icmp (add V, C0), C1) & (icmp V, C0)
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
const APInt *C0, *C1;
Value *V;
if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_APInt(C0)), m_APInt(C1))))
@@ -1733,7 +1733,7 @@ static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
/// Try to simplify and/or of icmp with ctpop intrinsic.
static Value *simplifyAndOrOfICmpsWithCtpop(ICmpInst *Cmp0, ICmpInst *Cmp1,
bool IsAnd) {
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
Value *X;
const APInt *C;
if (!match(Cmp0, m_ICmp(Pred0, m_Intrinsic<Intrinsic::ctpop>(m_Value(X)),
@@ -1777,7 +1777,7 @@ static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1,
static Value *simplifyOrOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
const InstrInfoQuery &IIQ) {
// (icmp (add V, C0), C1) | (icmp V, C0)
- ICmpInst::Predicate Pred0, Pred1;
+ CmpPredicate Pred0, Pred1;
const APInt *C0, *C1;
Value *V;
if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_APInt(C0)), m_APInt(C1))))
@@ -1933,7 +1933,7 @@ static Value *simplifyAndOrWithICmpEq(unsigned Opcode, Value *Op0, Value *Op1,
unsigned MaxRecurse) {
assert((Opcode == Instruction::And || Opcode == Instruction::Or) &&
"Must be and/or");
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *A, *B;
if (!match(Op0, m_ICmp(Pred, m_Value(A), m_Value(B))) ||
!ICmpInst::isEquality(Pred))
@@ -4656,7 +4656,7 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
Value *FalseVal,
const SimplifyQuery &Q,
unsigned MaxRecurse) {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *CmpLHS, *CmpRHS;
if (!match(CondVal, m_ICmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
return nullptr;
@@ -4780,7 +4780,7 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
const SimplifyQuery &Q,
unsigned MaxRecurse) {
- FCmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *CmpLHS, *CmpRHS;
if (!match(Cond, m_FCmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
return nullptr;
diff --git a/llvm/lib/Analysis/OverflowInstAnalysis.cpp b/llvm/lib/Analysis/OverflowInstAnalysis.cpp
index 8bfd6642f76027..40f71f4a8db46d 100644
--- a/llvm/lib/Analysis/OverflowInstAnalysis.cpp
+++ b/llvm/lib/Analysis/OverflowInstAnalysis.cpp
@@ -20,7 +20,7 @@ using namespace llvm::PatternMatch;
bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd,
Use *&Y) {
- ICmpInst::Predicate Pred;
+ CmpPredicate Pred;
Value *X, *NotOp1;
int XIdx;
IntrinsicInst *II;
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f2c6949e535d2a..4b940557903daf 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;
@@ -1602,7 +1602,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.
@@ -2255,7 +2255,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 +2580,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 +3009,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 +3037,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,
@@ -4895,7 +4895,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;
@@ -5135,7 +5135,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 +8571,7 @@ bool llvm::isKno...
[truncated]
|
Can you share what the compile-time impact is? We could just provide two overloads in PatternMatch. There isn't really a need to migrate everything to CmpPredicate if it's not free, I expect only a small fraction of code will actually care about samesign (the bits interacting with implied conditions). |
Okay, I was wrong, and it's essentially free. |
Gentle ping. |
With the introduction of CmpPredicate in 51a895a (IR: introduce struct with CmpInst::Predicate and samesign), PatternMatch is one of the first key pieces of infrastructure that must be updated to match a CmpInst respecting samesign information. Implement this change to Cmp-matchers. This is a preparatory step in migrating the codebase over to CmpPredicate. Since we no functional changes are desired at this stage, we have chosen not to migrate CmpPredicate::operator==(CmpPredicate) calls to use CmpPredicate::getMatching(), as that would have visible impact on tests that are not yet written: instead, we call CmpPredicate::operator==(Predicate), preserving the old behavior, while also inserting a few FIXME comments for follow-ups.
61823cd
to
f46e64f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
revert: breaks spirv 4a0d53a PatternMatch: migrate to CmpPredicate (llvm#118534) Change-Id: I0311c30089f70d9f063cc1e0af8379e406168f40
With the introduction of CmpPredicate in 51a895a (IR: introduce struct with CmpInst::Predicate and samesign), PatternMatch is one of the first key pieces of infrastructure that must be updated to match a CmpInst respecting samesign information. Implement this change to Cmp-matchers. This is a preparatory step in migrating the codebase over to CmpPredicate. Since we no functional changes are desired at this stage, we have chosen not to migrate CmpPredicate::operator==(CmpPredicate) calls to use CmpPredicate::getMatching(), as that would have visible impact on tests that are not yet written: instead, we call CmpPredicate::operator==(Predicate), preserving the old behavior, while also inserting a few FIXME comments for follow-ups. Change-Id: I33f52609ffc5092c200780e93639b880f4ab423a
With the introduction of CmpPredicate in 51a895a (IR: introduce struct with CmpInst::Predicate and samesign), PatternMatch is one of the first key pieces of infrastructure that must be updated to match a CmpInst respecting samesign information. Implement this change to Cmp-matchers.
This is a preparatory step in migrating the codebase over to CmpPredicate. Since we no functional changes are desired at this stage, we have chosen not to migrate CmpPredicate::operator==(CmpPredicate) calls to use CmpPredicate::getMatching(), as that would have visible impact on tests that are not yet written: instead, we call CmpPredicate::operator==(Predicate), preserving the old behavior, while also inserting a few FIXME comments for follow-ups.