From 4c6eb3886c50ac11d23251625bd12e79cd56a1dd Mon Sep 17 00:00:00 2001 From: Petar Avramovic Date: Tue, 27 Apr 2021 11:37:42 +0200 Subject: [PATCH] [MIPatternMatch]: Add matchers for binary instructions Add matchers that support commutative and non-commutative binary opcodes. Differential Revision: https://reviews.llvm.org/D99736 --- .../llvm/CodeGen/GlobalISel/MIPatternMatch.h | 37 ++++++++++++ .../CodeGen/GlobalISel/PatternMatchTest.cpp | 58 +++++++++++++++++++ 2 files changed, 95 insertions(+) diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h index 2d08b22399fe..4c6b47ab9bc8 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h @@ -255,6 +255,43 @@ struct BinaryOp_match { } }; +// Helper for (commutative) binary generic MI that checks Opcode. +template +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 + 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 +inline BinaryOpc_match m_BinOp(unsigned Opcode, const LHS &L, + const RHS &R) { + return BinaryOpc_match(Opcode, L, R); +} + +template +inline BinaryOpc_match +m_CommutativeBinOp(unsigned Opcode, const LHS &L, const RHS &R) { + return BinaryOpc_match(Opcode, L, R); +} + template inline BinaryOp_match m_GAdd(const LHS &L, const RHS &R) { diff --git a/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp b/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp index c978b9e28344..676c7eeb5cd7 100644 --- a/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp @@ -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) {