Skip to content

Commit c77bbea

Browse files
committed
GlobalISel: Add MIPatternMatch for G_ICMP/G_FCMP
1 parent 86e5b56 commit c77bbea

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "llvm/ADT/APInt.h"
1717
#include "llvm/CodeGen/GlobalISel/Utils.h"
1818
#include "llvm/CodeGen/MachineRegisterInfo.h"
19+
#include "llvm/IR/InstrTypes.h"
1920

2021
namespace llvm {
2122
namespace MIPatternMatch {
@@ -163,6 +164,8 @@ template <typename Class> struct bind_ty {
163164
inline bind_ty<Register> m_Reg(Register &R) { return R; }
164165
inline bind_ty<MachineInstr *> m_MInstr(MachineInstr *&MI) { return MI; }
165166
inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
167+
inline bind_ty<CmpInst::Predicate> m_Pred(CmpInst::Predicate &P) { return P; }
168+
inline operand_type_match m_Pred() { return operand_type_match(); }
166169

167170
// Helper for matching G_FCONSTANT
168171
inline bind_ty<const ConstantFP *> m_GFCst(const ConstantFP *&C) { return C; }
@@ -320,6 +323,45 @@ inline UnaryOp_match<SrcTy, TargetOpcode::COPY> m_Copy(SrcTy &&Src) {
320323
return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
321324
}
322325

326+
// General helper for generic MI compares, i.e. G_ICMP and G_FCMP
327+
// TODO: Allow checking a specific predicate.
328+
template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode>
329+
struct CompareOp_match {
330+
Pred_P P;
331+
LHS_P L;
332+
RHS_P R;
333+
334+
CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
335+
: P(Pred), L(LHS), R(RHS) {}
336+
337+
template <typename OpTy>
338+
bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
339+
MachineInstr *TmpMI;
340+
if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
341+
return false;
342+
343+
auto TmpPred =
344+
static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
345+
if (!P.match(MRI, TmpPred))
346+
return false;
347+
348+
return L.match(MRI, TmpMI->getOperand(2).getReg()) &&
349+
R.match(MRI, TmpMI->getOperand(3).getReg());
350+
}
351+
};
352+
353+
template <typename Pred, typename LHS, typename RHS>
354+
inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>
355+
m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
356+
return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>(P, L, R);
357+
}
358+
359+
template <typename Pred, typename LHS, typename RHS>
360+
inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>
361+
m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
362+
return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>(P, L, R);
363+
}
364+
323365
// Helper for checking if a Reg is of specific type.
324366
struct CheckType {
325367
LLT Ty;

llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,56 @@ TEST_F(GISelMITest, MatchBinaryOp) {
129129
EXPECT_EQ(Src1, Copies[1]);
130130
}
131131

132+
TEST_F(GISelMITest, MatchICmp) {
133+
setUp();
134+
if (!TM)
135+
return;
136+
137+
const LLT s1 = LLT::scalar(1);
138+
auto CmpEq = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]);
139+
140+
// Check match any predicate.
141+
bool match =
142+
mi_match(CmpEq.getReg(0), *MRI, m_GICmp(m_Pred(), m_Reg(), m_Reg()));
143+
EXPECT_TRUE(match);
144+
145+
// Check we get the predicate and registers.
146+
CmpInst::Predicate Pred;
147+
Register Reg0;
148+
Register Reg1;
149+
match = mi_match(CmpEq.getReg(0), *MRI,
150+
m_GICmp(m_Pred(Pred), m_Reg(Reg0), m_Reg(Reg1)));
151+
EXPECT_TRUE(match);
152+
EXPECT_EQ(CmpInst::ICMP_EQ, Pred);
153+
EXPECT_EQ(Copies[0], Reg0);
154+
EXPECT_EQ(Copies[1], Reg1);
155+
}
156+
157+
TEST_F(GISelMITest, MatchFCmp) {
158+
setUp();
159+
if (!TM)
160+
return;
161+
162+
const LLT s1 = LLT::scalar(1);
163+
auto CmpEq = B.buildFCmp(CmpInst::FCMP_OEQ, s1, Copies[0], Copies[1]);
164+
165+
// Check match any predicate.
166+
bool match =
167+
mi_match(CmpEq.getReg(0), *MRI, m_GFCmp(m_Pred(), m_Reg(), m_Reg()));
168+
EXPECT_TRUE(match);
169+
170+
// Check we get the predicate and registers.
171+
CmpInst::Predicate Pred;
172+
Register Reg0;
173+
Register Reg1;
174+
match = mi_match(CmpEq.getReg(0), *MRI,
175+
m_GFCmp(m_Pred(Pred), m_Reg(Reg0), m_Reg(Reg1)));
176+
EXPECT_TRUE(match);
177+
EXPECT_EQ(CmpInst::FCMP_OEQ, Pred);
178+
EXPECT_EQ(Copies[0], Reg0);
179+
EXPECT_EQ(Copies[1], Reg1);
180+
}
181+
132182
TEST_F(GISelMITest, MatchFPUnaryOp) {
133183
setUp();
134184
if (!TM)

0 commit comments

Comments
 (0)