[llvm] 4c6eb38 - [MIPatternMatch]: Add matchers for binary instructions

Petar Avramovic via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 27 02:38:56 PDT 2021


Author: Petar Avramovic
Date: 2021-04-27T11:37:42+02:00
New Revision: 4c6eb3886c50ac11d23251625bd12e79cd56a1dd

URL: https://github.com/llvm/llvm-project/commit/4c6eb3886c50ac11d23251625bd12e79cd56a1dd
DIFF: https://github.com/llvm/llvm-project/commit/4c6eb3886c50ac11d23251625bd12e79cd56a1dd.diff

LOG: [MIPatternMatch]: Add matchers for binary instructions

Add matchers that support commutative and non-commutative binary opcodes.

Differential Revision: https://reviews.llvm.org/D99736

Added: 
    

Modified: 
    llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
    llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp

Removed: 
    


################################################################################
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 <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) {

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) {


        


More information about the llvm-commits mailing list