Skip to content

Commit 6d74dbe

Browse files
committed
[PatternMatch] Add matchers for m_{I,F,}Cmp and m_{I,F,}SpecificCmp; NFC
These matchers either take no predicate argument or match a specific predicate respectively. We have a lot of cases where the Pred argument is either unused and requiring the argument reduces code clarity. Likewise we have a lot of cases where we only pass in Pred to test equality which the new `*Specific*` helpers can simplify.
1 parent 015526b commit 6d74dbe

File tree

2 files changed

+214
-7
lines changed

2 files changed

+214
-7
lines changed

llvm/include/llvm/IR/PatternMatch.h

Lines changed: 71 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,25 +1548,38 @@ template <typename T> inline Exact_match<T> m_Exact(const T &SubPattern) {
15481548
//
15491549

15501550
template <typename LHS_t, typename RHS_t, typename Class, typename PredicateTy,
1551-
bool Commutable = false>
1551+
bool Commutable = false, bool MatchExistingPred = false>
15521552
struct CmpClass_match {
1553-
PredicateTy &Predicate;
1553+
static_assert(!Commutable || !MatchExistingPred,
1554+
"Can't match predicate when using commutable matcher");
1555+
1556+
// Make predicate ty const ref if we are matching. Not strictly necessary but
1557+
// will cause a compilation warning if we accidentally try to set it with
1558+
// MatchExistingPred enabled.
1559+
using InternalPredTy =
1560+
std::conditional_t<MatchExistingPred, const PredicateTy &, PredicateTy &>;
1561+
InternalPredTy Predicate;
15541562
LHS_t L;
15551563
RHS_t R;
15561564

15571565
// The evaluation order is always stable, regardless of Commutability.
15581566
// The LHS is always matched first.
1559-
CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS)
1567+
CmpClass_match(InternalPredTy Pred, const LHS_t &LHS, const RHS_t &RHS)
15601568
: Predicate(Pred), L(LHS), R(RHS) {}
15611569

15621570
template <typename OpTy> bool match(OpTy *V) {
15631571
if (auto *I = dyn_cast<Class>(V)) {
15641572
if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) {
1565-
Predicate = I->getPredicate();
1566-
return true;
1573+
if constexpr (MatchExistingPred)
1574+
return I->getPredicate() == Predicate;
1575+
else {
1576+
Predicate = I->getPredicate();
1577+
return true;
1578+
}
15671579
} else if (Commutable && L.match(I->getOperand(1)) &&
15681580
R.match(I->getOperand(0))) {
1569-
Predicate = I->getSwappedPredicate();
1581+
if constexpr (!MatchExistingPred)
1582+
Predicate = I->getSwappedPredicate();
15701583
return true;
15711584
}
15721585
}
@@ -1592,6 +1605,50 @@ m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
15921605
return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Pred, L, R);
15931606
}
15941607

1608+
template <typename LHS, typename RHS>
1609+
inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
1610+
m_Cmp(const LHS &L, const RHS &R) {
1611+
CmpInst::Predicate Unused;
1612+
return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(Unused, L, R);
1613+
}
1614+
1615+
template <typename LHS, typename RHS>
1616+
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
1617+
m_ICmp(const LHS &L, const RHS &R) {
1618+
ICmpInst::Predicate Unused;
1619+
return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(Unused, L, R);
1620+
}
1621+
1622+
template <typename LHS, typename RHS>
1623+
inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
1624+
m_FCmp(const LHS &L, const RHS &R) {
1625+
FCmpInst::Predicate Unused;
1626+
return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Unused, L, R);
1627+
}
1628+
1629+
template <typename LHS, typename RHS>
1630+
inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate, false, true>
1631+
m_SpecificCmp(const CmpInst::Predicate &MatchPred, const LHS &L, const RHS &R) {
1632+
return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate, false, true>(
1633+
MatchPred, L, R);
1634+
}
1635+
1636+
template <typename LHS, typename RHS>
1637+
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, false, true>
1638+
m_SpecificICmp(const ICmpInst::Predicate &MatchPred, const LHS &L,
1639+
const RHS &R) {
1640+
return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, false, true>(
1641+
MatchPred, L, R);
1642+
}
1643+
1644+
template <typename LHS, typename RHS>
1645+
inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate, false, true>
1646+
m_SpecificFCmp(const FCmpInst::Predicate &MatchPred, const LHS &L,
1647+
const RHS &R) {
1648+
return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate, false, true>(
1649+
MatchPred, L, R);
1650+
}
1651+
15951652
//===----------------------------------------------------------------------===//
15961653
// Matchers for instructions with a given opcode and number of operands.
15971654
//
@@ -2617,6 +2674,14 @@ m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
26172674
R);
26182675
}
26192676

2677+
template <typename LHS, typename RHS>
2678+
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
2679+
m_c_ICmp(const LHS &L, const RHS &R) {
2680+
ICmpInst::Predicate Unused;
2681+
return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(Unused,
2682+
L, R);
2683+
}
2684+
26202685
/// Matches a specific opcode with LHS and RHS in either order.
26212686
template <typename LHS, typename RHS>
26222687
inline SpecificBinaryOp_match<LHS, RHS, true>

llvm/unittests/IR/PatternMatch.cpp

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2250,9 +2250,151 @@ TYPED_TEST(MutableConstTest, ICmp) {
22502250
ICmpInst::Predicate MatchPred;
22512251

22522252
EXPECT_TRUE(m_ICmp(MatchPred, m_Value(MatchL), m_Value(MatchR))
2253-
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2253+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
22542254
EXPECT_EQ(L, MatchL);
22552255
EXPECT_EQ(R, MatchR);
2256+
2257+
EXPECT_TRUE(m_Cmp(MatchPred, m_Value(MatchL), m_Value(MatchR))
2258+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2259+
EXPECT_EQ(L, MatchL);
2260+
EXPECT_EQ(R, MatchR);
2261+
2262+
EXPECT_TRUE(m_ICmp(m_Specific(L), m_Specific(R))
2263+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2264+
2265+
EXPECT_TRUE(m_Cmp(m_Specific(L), m_Specific(R))
2266+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2267+
2268+
EXPECT_FALSE(m_ICmp(m_Specific(R), m_Specific(L))
2269+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2270+
EXPECT_FALSE(m_Cmp(m_Specific(R), m_Specific(L))
2271+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2272+
2273+
EXPECT_TRUE(m_c_ICmp(m_Specific(R), m_Specific(L))
2274+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2275+
2276+
EXPECT_FALSE(m_c_ICmp(m_Specific(R), m_Specific(R))
2277+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2278+
2279+
EXPECT_TRUE(m_SpecificICmp(Pred, m_Specific(L), m_Specific(R))
2280+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2281+
EXPECT_TRUE(m_SpecificCmp(Pred, m_Specific(L), m_Specific(R))
2282+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2283+
2284+
EXPECT_FALSE(m_SpecificICmp(Pred, m_Specific(R), m_Specific(L))
2285+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2286+
EXPECT_FALSE(m_SpecificCmp(Pred, m_Specific(R), m_Specific(L))
2287+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2288+
2289+
MatchL = nullptr;
2290+
MatchR = nullptr;
2291+
EXPECT_TRUE(m_SpecificICmp(Pred, m_Value(MatchL), m_Value(MatchR))
2292+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2293+
EXPECT_EQ(L, MatchL);
2294+
EXPECT_EQ(R, MatchR);
2295+
MatchL = nullptr;
2296+
MatchR = nullptr;
2297+
EXPECT_TRUE(m_SpecificCmp(Pred, m_Value(MatchL), m_Value(MatchR))
2298+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2299+
EXPECT_EQ(L, MatchL);
2300+
EXPECT_EQ(R, MatchR);
2301+
2302+
EXPECT_FALSE(m_SpecificICmp(Pred, m_Specific(R), m_Specific(L))
2303+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2304+
EXPECT_FALSE(m_SpecificCmp(Pred, m_Specific(R), m_Specific(L))
2305+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2306+
2307+
EXPECT_FALSE(m_SpecificICmp(ICmpInst::getInversePredicate(Pred),
2308+
m_Specific(L), m_Specific(R))
2309+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2310+
EXPECT_FALSE(m_SpecificCmp(ICmpInst::getInversePredicate(Pred), m_Specific(L),
2311+
m_Specific(R))
2312+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2313+
2314+
EXPECT_FALSE(m_SpecificICmp(ICmpInst::getInversePredicate(Pred),
2315+
m_Value(MatchL), m_Value(MatchR))
2316+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2317+
EXPECT_FALSE(m_SpecificCmp(ICmpInst::getInversePredicate(Pred),
2318+
m_Value(MatchL), m_Value(MatchR))
2319+
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
2320+
}
2321+
2322+
TYPED_TEST(MutableConstTest, FCmp) {
2323+
auto &IRB = PatternMatchTest::IRB;
2324+
2325+
typedef std::tuple_element_t<0, TypeParam> ValueType;
2326+
typedef std::tuple_element_t<1, TypeParam> InstructionType;
2327+
2328+
Value *L = Constant::getNullValue(IRB.getFloatTy());
2329+
Value *R = ConstantFP::getInfinity(IRB.getFloatTy(), true);
2330+
FCmpInst::Predicate Pred = FCmpInst::FCMP_OGT;
2331+
2332+
ValueType MatchL;
2333+
ValueType MatchR;
2334+
FCmpInst::Predicate MatchPred;
2335+
2336+
EXPECT_TRUE(m_FCmp(MatchPred, m_Value(MatchL), m_Value(MatchR))
2337+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2338+
EXPECT_EQ(L, MatchL);
2339+
EXPECT_EQ(R, MatchR);
2340+
2341+
EXPECT_TRUE(m_Cmp(MatchPred, m_Value(MatchL), m_Value(MatchR))
2342+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2343+
EXPECT_EQ(L, MatchL);
2344+
EXPECT_EQ(R, MatchR);
2345+
2346+
EXPECT_TRUE(m_FCmp(m_Specific(L), m_Specific(R))
2347+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2348+
2349+
EXPECT_TRUE(m_Cmp(m_Specific(L), m_Specific(R))
2350+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2351+
2352+
EXPECT_FALSE(m_FCmp(m_Specific(R), m_Specific(L))
2353+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2354+
EXPECT_FALSE(m_Cmp(m_Specific(R), m_Specific(L))
2355+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2356+
2357+
EXPECT_TRUE(m_SpecificFCmp(Pred, m_Specific(L), m_Specific(R))
2358+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2359+
EXPECT_TRUE(m_SpecificCmp(Pred, m_Specific(L), m_Specific(R))
2360+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2361+
2362+
EXPECT_FALSE(m_SpecificFCmp(Pred, m_Specific(R), m_Specific(L))
2363+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2364+
EXPECT_FALSE(m_SpecificCmp(Pred, m_Specific(R), m_Specific(L))
2365+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2366+
2367+
MatchL = nullptr;
2368+
MatchR = nullptr;
2369+
EXPECT_TRUE(m_SpecificFCmp(Pred, m_Value(MatchL), m_Value(MatchR))
2370+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2371+
EXPECT_EQ(L, MatchL);
2372+
EXPECT_EQ(R, MatchR);
2373+
MatchL = nullptr;
2374+
MatchR = nullptr;
2375+
EXPECT_TRUE(m_SpecificCmp(Pred, m_Value(MatchL), m_Value(MatchR))
2376+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2377+
EXPECT_EQ(L, MatchL);
2378+
EXPECT_EQ(R, MatchR);
2379+
2380+
EXPECT_FALSE(m_SpecificFCmp(Pred, m_Specific(R), m_Specific(L))
2381+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2382+
EXPECT_FALSE(m_SpecificCmp(Pred, m_Specific(R), m_Specific(L))
2383+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2384+
2385+
EXPECT_FALSE(m_SpecificFCmp(FCmpInst::getInversePredicate(Pred),
2386+
m_Specific(L), m_Specific(R))
2387+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2388+
EXPECT_FALSE(m_SpecificCmp(FCmpInst::getInversePredicate(Pred), m_Specific(L),
2389+
m_Specific(R))
2390+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2391+
2392+
EXPECT_FALSE(m_SpecificFCmp(FCmpInst::getInversePredicate(Pred),
2393+
m_Value(MatchL), m_Value(MatchR))
2394+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
2395+
EXPECT_FALSE(m_SpecificCmp(FCmpInst::getInversePredicate(Pred),
2396+
m_Value(MatchL), m_Value(MatchR))
2397+
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
22562398
}
22572399

22582400
TEST_F(PatternMatchTest, ConstExpr) {

0 commit comments

Comments
 (0)