Skip to content
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] Add matchers for m_{I,F,}Cmp and m_{I,F,}SpecificCmp; NFC #98282

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading