Skip to content

Commit 4a0d53a

Browse files
authored
PatternMatch: migrate to CmpPredicate (#118534)
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.
1 parent 89f1f32 commit 4a0d53a

36 files changed

+232
-192
lines changed

llvm/include/llvm/IR/CmpPredicate.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ class CmpPredicate {
2424
bool HasSameSign;
2525

2626
public:
27+
/// Default constructor.
28+
CmpPredicate() : Pred(CmpInst::BAD_ICMP_PREDICATE), HasSameSign(false) {}
29+
2730
/// Constructed implictly with a either Predicate and samesign information, or
2831
/// just a Predicate, dropping samesign information.
2932
CmpPredicate(CmpInst::Predicate Pred, bool HasSameSign = false)
@@ -52,11 +55,29 @@ class CmpPredicate {
5255

5356
/// An operator== on the underlying Predicate.
5457
bool operator==(CmpInst::Predicate P) const { return Pred == P; }
58+
bool operator!=(CmpInst::Predicate P) const { return Pred != P; }
5559

5660
/// There is no operator== defined on CmpPredicate. Use getMatching instead to
5761
/// get the canonicalized matching CmpPredicate.
5862
bool operator==(CmpPredicate) const = delete;
63+
bool operator!=(CmpPredicate) const = delete;
64+
65+
/// Do a ICmpInst::getCmpPredicate() or CmpInst::getPredicate(), as
66+
/// appropriate.
67+
static CmpPredicate get(const CmpInst *Cmp);
68+
69+
/// Get the swapped predicate of a CmpPredicate.
70+
static CmpPredicate getSwapped(CmpPredicate P);
71+
72+
/// Get the swapped predicate of a CmpInst.
73+
static CmpPredicate getSwapped(const CmpInst *Cmp);
74+
75+
/// Provided to facilitate storing a CmpPredicate in data structures that
76+
/// require hashing.
77+
friend hash_code hash_value(const CmpPredicate &Arg); // NOLINT
5978
};
79+
80+
[[nodiscard]] hash_code hash_value(const CmpPredicate &Arg);
6081
} // namespace llvm
6182

6283
#endif

llvm/include/llvm/IR/PatternMatch.h

Lines changed: 50 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ inline api_pred_ty<is_lowbit_mask_or_zero> m_LowBitMaskOrZero(const APInt *&V) {
688688
}
689689

690690
struct icmp_pred_with_threshold {
691-
ICmpInst::Predicate Pred;
691+
CmpPredicate Pred;
692692
const APInt *Thr;
693693
bool isValue(const APInt &C) { return ICmpInst::compare(C, *Thr, Pred); }
694694
};
@@ -1557,16 +1557,16 @@ template <typename T> inline Exact_match<T> m_Exact(const T &SubPattern) {
15571557
// Matchers for CmpInst classes
15581558
//
15591559

1560-
template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
1560+
template <typename LHS_t, typename RHS_t, typename Class,
15611561
bool Commutable = false>
15621562
struct CmpClass_match {
1563-
PredicateTy *Predicate;
1563+
CmpPredicate *Predicate;
15641564
LHS_t L;
15651565
RHS_t R;
15661566

15671567
// The evaluation order is always stable, regardless of Commutability.
15681568
// The LHS is always matched first.
1569-
CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
1569+
CmpClass_match(CmpPredicate &Pred, const LHS_t &LHS, const RHS_t &RHS)
15701570
: Predicate(&Pred), L(LHS), R(RHS) {}
15711571
CmpClass_match(const LHS_t &LHS, const RHS_t &RHS)
15721572
: Predicate(nullptr), L(LHS), R(RHS) {}
@@ -1575,12 +1575,13 @@ struct CmpClass_match {
15751575
if (auto *I = dyn_cast<Class>(V)) {
15761576
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
15771577
if (Predicate)
1578-
*Predicate = I->getPredicate();
1578+
*Predicate = CmpPredicate::get(I);
15791579
return true;
1580-
} else if (Commutable && L.match(I->getOperand(1)) &&
1581-
R.match(I->getOperand(0))) {
1580+
}
1581+
if (Commutable && L.match(I->getOperand(1)) &&
1582+
R.match(I->getOperand(0))) {
15821583
if (Predicate)
1583-
*Predicate = I->getSwappedPredicate();
1584+
*Predicate = CmpPredicate::getSwapped(I);
15841585
return true;
15851586
}
15861587
}
@@ -1589,60 +1590,58 @@ struct CmpClass_match {
15891590
};
15901591

15911592
template <typename LHS, typename RHS>
1592-
inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
1593-
m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
1594-
return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(Pred, L, R);
1593+
inline CmpClass_match<LHS, RHS, CmpInst> m_Cmp(CmpPredicate &Pred, const LHS &L,
1594+
const RHS &R) {
1595+
return CmpClass_match<LHS, RHS, CmpInst>(Pred, L, R);
15951596
}
15961597

15971598
template <typename LHS, typename RHS>
1598-
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
1599-
m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
1600-
return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(Pred, L, R);
1599+
inline CmpClass_match<LHS, RHS, ICmpInst> m_ICmp(CmpPredicate &Pred,
1600+
const LHS &L, const RHS &R) {
1601+
return CmpClass_match<LHS, RHS, ICmpInst>(Pred, L, R);
16011602
}
16021603

16031604
template <typename LHS, typename RHS>
1604-
inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
1605-
m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
1606-
return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Pred, L, R);
1605+
inline CmpClass_match<LHS, RHS, FCmpInst> m_FCmp(CmpPredicate &Pred,
1606+
const LHS &L, const RHS &R) {
1607+
return CmpClass_match<LHS, RHS, FCmpInst>(Pred, L, R);
16071608
}
16081609

16091610
template <typename LHS, typename RHS>
1610-
inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
1611-
m_Cmp(const LHS &L, const RHS &R) {
1612-
return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(L, R);
1611+
inline CmpClass_match<LHS, RHS, CmpInst> m_Cmp(const LHS &L, const RHS &R) {
1612+
return CmpClass_match<LHS, RHS, CmpInst>(L, R);
16131613
}
16141614

16151615
template <typename LHS, typename RHS>
1616-
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
1617-
m_ICmp(const LHS &L, const RHS &R) {
1618-
return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(L, R);
1616+
inline CmpClass_match<LHS, RHS, ICmpInst> m_ICmp(const LHS &L, const RHS &R) {
1617+
return CmpClass_match<LHS, RHS, ICmpInst>(L, R);
16191618
}
16201619

16211620
template <typename LHS, typename RHS>
1622-
inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
1623-
m_FCmp(const LHS &L, const RHS &R) {
1624-
return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(L, R);
1621+
inline CmpClass_match<LHS, RHS, FCmpInst> m_FCmp(const LHS &L, const RHS &R) {
1622+
return CmpClass_match<LHS, RHS, FCmpInst>(L, R);
16251623
}
16261624

16271625
// Same as CmpClass, but instead of saving Pred as out output variable, match a
16281626
// specific input pred for equality.
1629-
template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
1627+
template <typename LHS_t, typename RHS_t, typename Class,
16301628
bool Commutable = false>
16311629
struct SpecificCmpClass_match {
1632-
const PredicateTy Predicate;
1630+
const CmpPredicate Predicate;
16331631
LHS_t L;
16341632
RHS_t R;
16351633

1636-
SpecificCmpClass_match(PredicateTy Pred, const LHS_t &LHS, const RHS_t &RHS)
1634+
SpecificCmpClass_match(CmpPredicate Pred, const LHS_t &LHS, const RHS_t &RHS)
16371635
: Predicate(Pred), L(LHS), R(RHS) {}
16381636

16391637
template <typename OpTy> bool match(OpTy *V) {
16401638
if (auto *I = dyn_cast<Class>(V)) {
1641-
if (I->getPredicate() == Predicate && L.match(I->getOperand(0)) &&
1642-
R.match(I->getOperand(1)))
1639+
if (CmpPredicate::getMatching(CmpPredicate::get(I), Predicate) &&
1640+
L.match(I->getOperand(0)) && R.match(I->getOperand(1)))
16431641
return true;
16441642
if constexpr (Commutable) {
1645-
if (I->getPredicate() == Class::getSwappedPredicate(Predicate) &&
1643+
if (CmpPredicate::getMatching(CmpPredicate::get(I),
1644+
CmpPredicate::getSwapped(Predicate)) &&
16461645
L.match(I->getOperand(1)) && R.match(I->getOperand(0)))
16471646
return true;
16481647
}
@@ -1653,31 +1652,27 @@ struct SpecificCmpClass_match {
16531652
};
16541653

16551654
template <typename LHS, typename RHS>
1656-
inline SpecificCmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
1657-
m_SpecificCmp(CmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
1658-
return SpecificCmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(
1659-
MatchPred, L, R);
1655+
inline SpecificCmpClass_match<LHS, RHS, CmpInst>
1656+
m_SpecificCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
1657+
return SpecificCmpClass_match<LHS, RHS, CmpInst>(MatchPred, L, R);
16601658
}
16611659

16621660
template <typename LHS, typename RHS>
1663-
inline SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
1664-
m_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
1665-
return SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(
1666-
MatchPred, L, R);
1661+
inline SpecificCmpClass_match<LHS, RHS, ICmpInst>
1662+
m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
1663+
return SpecificCmpClass_match<LHS, RHS, ICmpInst>(MatchPred, L, R);
16671664
}
16681665

16691666
template <typename LHS, typename RHS>
1670-
inline SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
1671-
m_c_SpecificICmp(ICmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
1672-
return SpecificCmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(
1673-
MatchPred, L, R);
1667+
inline SpecificCmpClass_match<LHS, RHS, ICmpInst, true>
1668+
m_c_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
1669+
return SpecificCmpClass_match<LHS, RHS, ICmpInst, true>(MatchPred, L, R);
16741670
}
16751671

16761672
template <typename LHS, typename RHS>
1677-
inline SpecificCmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
1678-
m_SpecificFCmp(FCmpInst::Predicate MatchPred, const LHS &L, const RHS &R) {
1679-
return SpecificCmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(
1680-
MatchPred, L, R);
1673+
inline SpecificCmpClass_match<LHS, RHS, FCmpInst>
1674+
m_SpecificFCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R) {
1675+
return SpecificCmpClass_match<LHS, RHS, FCmpInst>(MatchPred, L, R);
16811676
}
16821677

16831678
//===----------------------------------------------------------------------===//
@@ -2468,7 +2463,7 @@ struct UAddWithOverflow_match {
24682463

24692464
template <typename OpTy> bool match(OpTy *V) {
24702465
Value *ICmpLHS, *ICmpRHS;
2471-
ICmpInst::Predicate Pred;
2466+
CmpPredicate Pred;
24722467
if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V))
24732468
return false;
24742469

@@ -2738,16 +2733,15 @@ inline AnyBinaryOp_match<LHS, RHS, true> m_c_BinOp(const LHS &L, const RHS &R) {
27382733
/// Matches an ICmp with a predicate over LHS and RHS in either order.
27392734
/// Swaps the predicate if operands are commuted.
27402735
template <typename LHS, typename RHS>
2741-
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
2742-
m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
2743-
return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(Pred, L,
2744-
R);
2736+
inline CmpClass_match<LHS, RHS, ICmpInst, true>
2737+
m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R) {
2738+
return CmpClass_match<LHS, RHS, ICmpInst, true>(Pred, L, R);
27452739
}
27462740

27472741
template <typename LHS, typename RHS>
2748-
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
2749-
m_c_ICmp(const LHS &L, const RHS &R) {
2750-
return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(L, R);
2742+
inline CmpClass_match<LHS, RHS, ICmpInst, true> m_c_ICmp(const LHS &L,
2743+
const RHS &R) {
2744+
return CmpClass_match<LHS, RHS, ICmpInst, true>(L, R);
27512745
}
27522746

27532747
/// Matches a specific opcode with LHS and RHS in either order.

llvm/lib/Analysis/IVDescriptors.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ RecurrenceDescriptor::isAnyOfPattern(Loop *Loop, PHINode *OrigPhi,
630630
Instruction *I, InstDesc &Prev) {
631631
// We must handle the select(cmp(),x,y) as a single instruction. Advance to
632632
// the select.
633-
CmpInst::Predicate Pred;
633+
CmpPredicate Pred;
634634
if (match(I, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) {
635635
if (auto *Select = dyn_cast<SelectInst>(*I->user_begin()))
636636
return InstDesc(Select, Prev.getRecKind());
@@ -759,7 +759,7 @@ RecurrenceDescriptor::isMinMaxPattern(Instruction *I, RecurKind Kind,
759759

760760
// We must handle the select(cmp()) as a single instruction. Advance to the
761761
// select.
762-
CmpInst::Predicate Pred;
762+
CmpPredicate Pred;
763763
if (match(I, m_OneUse(m_Cmp(Pred, m_Value(), m_Value())))) {
764764
if (auto *Select = dyn_cast<SelectInst>(*I->user_begin()))
765765
return InstDesc(Select, Prev.getRecKind());

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,12 +1500,12 @@ static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
15001500
const SimplifyQuery &Q) {
15011501
Value *X, *Y;
15021502

1503-
ICmpInst::Predicate EqPred;
1503+
CmpPredicate EqPred;
15041504
if (!match(ZeroICmp, m_ICmp(EqPred, m_Value(Y), m_Zero())) ||
15051505
!ICmpInst::isEquality(EqPred))
15061506
return nullptr;
15071507

1508-
ICmpInst::Predicate UnsignedPred;
1508+
CmpPredicate UnsignedPred;
15091509

15101510
Value *A, *B;
15111511
// Y = (A - B);
@@ -1644,7 +1644,7 @@ static Value *simplifyAndOrOfICmpsWithConstants(ICmpInst *Cmp0, ICmpInst *Cmp1,
16441644
static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
16451645
const InstrInfoQuery &IIQ) {
16461646
// (icmp (add V, C0), C1) & (icmp V, C0)
1647-
ICmpInst::Predicate Pred0, Pred1;
1647+
CmpPredicate Pred0, Pred1;
16481648
const APInt *C0, *C1;
16491649
Value *V;
16501650
if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_APInt(C0)), m_APInt(C1))))
@@ -1691,7 +1691,7 @@ static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
16911691
/// Try to simplify and/or of icmp with ctpop intrinsic.
16921692
static Value *simplifyAndOrOfICmpsWithCtpop(ICmpInst *Cmp0, ICmpInst *Cmp1,
16931693
bool IsAnd) {
1694-
ICmpInst::Predicate Pred0, Pred1;
1694+
CmpPredicate Pred0, Pred1;
16951695
Value *X;
16961696
const APInt *C;
16971697
if (!match(Cmp0, m_ICmp(Pred0, m_Intrinsic<Intrinsic::ctpop>(m_Value(X)),
@@ -1735,7 +1735,7 @@ static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1,
17351735
static Value *simplifyOrOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1,
17361736
const InstrInfoQuery &IIQ) {
17371737
// (icmp (add V, C0), C1) | (icmp V, C0)
1738-
ICmpInst::Predicate Pred0, Pred1;
1738+
CmpPredicate Pred0, Pred1;
17391739
const APInt *C0, *C1;
17401740
Value *V;
17411741
if (!match(Op0, m_ICmp(Pred0, m_Add(m_Value(V), m_APInt(C0)), m_APInt(C1))))
@@ -1891,7 +1891,7 @@ static Value *simplifyAndOrWithICmpEq(unsigned Opcode, Value *Op0, Value *Op1,
18911891
unsigned MaxRecurse) {
18921892
assert((Opcode == Instruction::And || Opcode == Instruction::Or) &&
18931893
"Must be and/or");
1894-
ICmpInst::Predicate Pred;
1894+
CmpPredicate Pred;
18951895
Value *A, *B;
18961896
if (!match(Op0, m_ICmp(Pred, m_Value(A), m_Value(B))) ||
18971897
!ICmpInst::isEquality(Pred))
@@ -4614,7 +4614,7 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
46144614
Value *FalseVal,
46154615
const SimplifyQuery &Q,
46164616
unsigned MaxRecurse) {
4617-
ICmpInst::Predicate Pred;
4617+
CmpPredicate Pred;
46184618
Value *CmpLHS, *CmpRHS;
46194619
if (!match(CondVal, m_ICmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
46204620
return nullptr;
@@ -4738,7 +4738,7 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
47384738
static Value *simplifySelectWithFCmp(Value *Cond, Value *T, Value *F,
47394739
const SimplifyQuery &Q,
47404740
unsigned MaxRecurse) {
4741-
FCmpInst::Predicate Pred;
4741+
CmpPredicate Pred;
47424742
Value *CmpLHS, *CmpRHS;
47434743
if (!match(Cond, m_FCmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
47444744
return nullptr;

llvm/lib/Analysis/OverflowInstAnalysis.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ using namespace llvm::PatternMatch;
2020

2121
bool llvm::isCheckForZeroAndMulWithOverflow(Value *Op0, Value *Op1, bool IsAnd,
2222
Use *&Y) {
23-
ICmpInst::Predicate Pred;
23+
CmpPredicate Pred;
2424
Value *X, *NotOp1;
2525
int XIdx;
2626
IntrinsicInst *II;

0 commit comments

Comments
 (0)