Skip to content

Commit

Permalink
[PatternMatch] Add matchers for m_{I,F,}Cmp and `m_{I,F,}SpecificCm…
Browse files Browse the repository at this point in the history
…p`; 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.

Closes llvm#98282
  • Loading branch information
goldsteinn authored and aaryanshukla committed Jul 14, 2024
1 parent 66704a9 commit 664d803
Show file tree
Hide file tree
Showing 2 changed files with 212 additions and 1 deletion.
69 changes: 69 additions & 0 deletions llvm/include/llvm/IR/PatternMatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,67 @@ m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Pred, L, R);
}

template <typename LHS, typename RHS>
inline CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>
m_Cmp(const LHS &L, const RHS &R) {
CmpInst::Predicate Unused;
return CmpClass_match<LHS, RHS, CmpInst, CmpInst::Predicate>(Unused, L, R);
}

template <typename LHS, typename RHS>
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>
m_ICmp(const LHS &L, const RHS &R) {
ICmpInst::Predicate Unused;
return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate>(Unused, L, R);
}

template <typename LHS, typename RHS>
inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>
m_FCmp(const LHS &L, const RHS &R) {
FCmpInst::Predicate Unused;
return CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate>(Unused, 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>
struct SpecificCmpClass_match {
const PredicateTy Predicate;
LHS_t L;
RHS_t R;

SpecificCmpClass_match(PredicateTy 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))
return I->getPredicate() == Predicate && L.match(I->getOperand(0)) &&
R.match(I->getOperand(1));
return false;
}
};

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);
}

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);
}

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);
}

//===----------------------------------------------------------------------===//
// Matchers for instructions with a given opcode and number of operands.
//
Expand Down Expand Up @@ -2617,6 +2678,14 @@ m_c_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) {
R);
}

template <typename LHS, typename RHS>
inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>
m_c_ICmp(const LHS &L, const RHS &R) {
ICmpInst::Predicate Unused;
return CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate, true>(Unused,
L, R);
}

/// Matches a specific opcode with LHS and RHS in either order.
template <typename LHS, typename RHS>
inline SpecificBinaryOp_match<LHS, RHS, true>
Expand Down
144 changes: 143 additions & 1 deletion llvm/unittests/IR/PatternMatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2250,9 +2250,151 @@ TYPED_TEST(MutableConstTest, ICmp) {
ICmpInst::Predicate MatchPred;

EXPECT_TRUE(m_ICmp(MatchPred, m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);

EXPECT_TRUE(m_Cmp(MatchPred, m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);

EXPECT_TRUE(m_ICmp(m_Specific(L), m_Specific(R))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));

EXPECT_TRUE(m_Cmp(m_Specific(L), m_Specific(R))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));

EXPECT_FALSE(m_ICmp(m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
EXPECT_FALSE(m_Cmp(m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));

EXPECT_TRUE(m_c_ICmp(m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));

EXPECT_FALSE(m_c_ICmp(m_Specific(R), m_Specific(R))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));

EXPECT_TRUE(m_SpecificICmp(Pred, m_Specific(L), m_Specific(R))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
EXPECT_TRUE(m_SpecificCmp(Pred, m_Specific(L), m_Specific(R))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));

EXPECT_FALSE(m_SpecificICmp(Pred, m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
EXPECT_FALSE(m_SpecificCmp(Pred, m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));

MatchL = nullptr;
MatchR = nullptr;
EXPECT_TRUE(m_SpecificICmp(Pred, m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);
MatchL = nullptr;
MatchR = nullptr;
EXPECT_TRUE(m_SpecificCmp(Pred, m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);

EXPECT_FALSE(m_SpecificICmp(Pred, m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
EXPECT_FALSE(m_SpecificCmp(Pred, m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));

EXPECT_FALSE(m_SpecificICmp(ICmpInst::getInversePredicate(Pred),
m_Specific(L), m_Specific(R))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
EXPECT_FALSE(m_SpecificCmp(ICmpInst::getInversePredicate(Pred), m_Specific(L),
m_Specific(R))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));

EXPECT_FALSE(m_SpecificICmp(ICmpInst::getInversePredicate(Pred),
m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
EXPECT_FALSE(m_SpecificCmp(ICmpInst::getInversePredicate(Pred),
m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateICmp(Pred, L, R)));
}

TYPED_TEST(MutableConstTest, FCmp) {
auto &IRB = PatternMatchTest::IRB;

typedef std::tuple_element_t<0, TypeParam> ValueType;
typedef std::tuple_element_t<1, TypeParam> InstructionType;

Value *L = Constant::getNullValue(IRB.getFloatTy());
Value *R = ConstantFP::getInfinity(IRB.getFloatTy(), true);
FCmpInst::Predicate Pred = FCmpInst::FCMP_OGT;

ValueType MatchL;
ValueType MatchR;
FCmpInst::Predicate MatchPred;

EXPECT_TRUE(m_FCmp(MatchPred, m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);

EXPECT_TRUE(m_Cmp(MatchPred, m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);

EXPECT_TRUE(m_FCmp(m_Specific(L), m_Specific(R))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));

EXPECT_TRUE(m_Cmp(m_Specific(L), m_Specific(R))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));

EXPECT_FALSE(m_FCmp(m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
EXPECT_FALSE(m_Cmp(m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));

EXPECT_TRUE(m_SpecificFCmp(Pred, m_Specific(L), m_Specific(R))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
EXPECT_TRUE(m_SpecificCmp(Pred, m_Specific(L), m_Specific(R))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));

EXPECT_FALSE(m_SpecificFCmp(Pred, m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
EXPECT_FALSE(m_SpecificCmp(Pred, m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));

MatchL = nullptr;
MatchR = nullptr;
EXPECT_TRUE(m_SpecificFCmp(Pred, m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);
MatchL = nullptr;
MatchR = nullptr;
EXPECT_TRUE(m_SpecificCmp(Pred, m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);

EXPECT_FALSE(m_SpecificFCmp(Pred, m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
EXPECT_FALSE(m_SpecificCmp(Pred, m_Specific(R), m_Specific(L))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));

EXPECT_FALSE(m_SpecificFCmp(FCmpInst::getInversePredicate(Pred),
m_Specific(L), m_Specific(R))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
EXPECT_FALSE(m_SpecificCmp(FCmpInst::getInversePredicate(Pred), m_Specific(L),
m_Specific(R))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));

EXPECT_FALSE(m_SpecificFCmp(FCmpInst::getInversePredicate(Pred),
m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
EXPECT_FALSE(m_SpecificCmp(FCmpInst::getInversePredicate(Pred),
m_Value(MatchL), m_Value(MatchR))
.match((InstructionType)IRB.CreateFCmp(Pred, L, R)));
}

TEST_F(PatternMatchTest, ConstExpr) {
Expand Down

0 comments on commit 664d803

Please sign in to comment.