forked from OSchip/llvm-project
[MIPatternMatch]: Add matchers for binary instructions
Add matchers that support commutative and non-commutative binary opcodes. Differential Revision: https://reviews.llvm.org/D99736
This commit is contained in:
parent
39662abf72
commit
4c6eb3886c
|
@ -255,6 +255,43 @@ struct BinaryOp_match {
|
|||
}
|
||||
};
|
||||
|
||||
// Helper for (commutative) binary generic MI that checks Opcode.
|
||||
template <typename LHS_P, typename RHS_P, bool Commutable = false>
|
||||
struct BinaryOpc_match {
|
||||
unsigned Opc;
|
||||
LHS_P L;
|
||||
RHS_P R;
|
||||
|
||||
BinaryOpc_match(unsigned Opcode, const LHS_P &LHS, const RHS_P &RHS)
|
||||
: Opc(Opcode), L(LHS), R(RHS) {}
|
||||
template <typename OpTy>
|
||||
bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
|
||||
MachineInstr *TmpMI;
|
||||
if (mi_match(Op, MRI, m_MInstr(TmpMI))) {
|
||||
if (TmpMI->getOpcode() == Opc && TmpMI->getNumDefs() == 1 &&
|
||||
TmpMI->getNumOperands() == 3) {
|
||||
return (L.match(MRI, TmpMI->getOperand(1).getReg()) &&
|
||||
R.match(MRI, TmpMI->getOperand(2).getReg())) ||
|
||||
(Commutable && (R.match(MRI, TmpMI->getOperand(1).getReg()) &&
|
||||
L.match(MRI, TmpMI->getOperand(2).getReg())));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename LHS, typename RHS>
|
||||
inline BinaryOpc_match<LHS, RHS, false> m_BinOp(unsigned Opcode, const LHS &L,
|
||||
const RHS &R) {
|
||||
return BinaryOpc_match<LHS, RHS, false>(Opcode, L, R);
|
||||
}
|
||||
|
||||
template <typename LHS, typename RHS>
|
||||
inline BinaryOpc_match<LHS, RHS, true>
|
||||
m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) {
|
||||
return BinaryOpc_match<LHS, RHS, true>(Opcode, L, R);
|
||||
}
|
||||
|
||||
template <typename LHS, typename RHS>
|
||||
inline BinaryOp_match<LHS, RHS, TargetOpcode::G_ADD, true>
|
||||
m_GAdd(const LHS &L, const RHS &R) {
|
||||
|
|
|
@ -194,6 +194,64 @@ TEST_F(AArch64GISelMITest, MatchBinaryOp) {
|
|||
EXPECT_TRUE(match);
|
||||
EXPECT_EQ(Src0, PtrAdd->getOperand(1).getReg());
|
||||
EXPECT_EQ(Src1, Copies[0]);
|
||||
|
||||
auto MIBCst = B.buildConstant(s64, 42);
|
||||
auto MIBAddCst = B.buildAdd(s64, MIBCst, Copies[0]);
|
||||
auto MIBUnmerge = B.buildUnmerge({s32, s32}, B.buildConstant(s64, 42));
|
||||
|
||||
// m_BinOp with opcode.
|
||||
// Match binary instruction, opcode and its non-commutative operands.
|
||||
match = mi_match(MIBAddCst, *MRI,
|
||||
m_BinOp(TargetOpcode::G_ADD, m_ICst(Cst), m_Reg(Src0)));
|
||||
EXPECT_TRUE(match);
|
||||
EXPECT_EQ(Src0, Copies[0]);
|
||||
EXPECT_EQ(Cst, 42);
|
||||
|
||||
// Opcode doesn't match.
|
||||
match = mi_match(MIBAddCst, *MRI,
|
||||
m_BinOp(TargetOpcode::G_MUL, m_ICst(Cst), m_Reg(Src0)));
|
||||
EXPECT_FALSE(match);
|
||||
|
||||
match = mi_match(MIBAddCst, *MRI,
|
||||
m_BinOp(TargetOpcode::G_ADD, m_Reg(Src0), m_ICst(Cst)));
|
||||
EXPECT_FALSE(match);
|
||||
|
||||
// Instruction is not binary.
|
||||
match = mi_match(MIBCst, *MRI,
|
||||
m_BinOp(TargetOpcode::G_MUL, m_Reg(Src0), m_Reg(Src1)));
|
||||
EXPECT_FALSE(match);
|
||||
match = mi_match(MIBUnmerge, *MRI,
|
||||
m_BinOp(TargetOpcode::G_MUL, m_Reg(Src0), m_Reg(Src1)));
|
||||
EXPECT_FALSE(match);
|
||||
|
||||
// m_CommutativeBinOp with opcode.
|
||||
match = mi_match(
|
||||
MIBAddCst, *MRI,
|
||||
m_CommutativeBinOp(TargetOpcode::G_ADD, m_ICst(Cst), m_Reg(Src0)));
|
||||
EXPECT_TRUE(match);
|
||||
EXPECT_EQ(Src0, Copies[0]);
|
||||
EXPECT_EQ(Cst, 42);
|
||||
|
||||
match = mi_match(
|
||||
MIBAddCst, *MRI,
|
||||
m_CommutativeBinOp(TargetOpcode::G_MUL, m_ICst(Cst), m_Reg(Src0)));
|
||||
EXPECT_FALSE(match);
|
||||
|
||||
match = mi_match(
|
||||
MIBAddCst, *MRI,
|
||||
m_CommutativeBinOp(TargetOpcode::G_ADD, m_Reg(Src0), m_ICst(Cst)));
|
||||
EXPECT_TRUE(match);
|
||||
EXPECT_EQ(Src0, Copies[0]);
|
||||
EXPECT_EQ(Cst, 42);
|
||||
|
||||
match = mi_match(
|
||||
MIBCst, *MRI,
|
||||
m_CommutativeBinOp(TargetOpcode::G_MUL, m_Reg(Src0), m_Reg(Src1)));
|
||||
EXPECT_FALSE(match);
|
||||
match = mi_match(
|
||||
MIBUnmerge, *MRI,
|
||||
m_CommutativeBinOp(TargetOpcode::G_MUL, m_Reg(Src0), m_Reg(Src1)));
|
||||
EXPECT_FALSE(match);
|
||||
}
|
||||
|
||||
TEST_F(AArch64GISelMITest, MatchICmp) {
|
||||
|
|
Loading…
Reference in New Issue