[llvm] c77bbea - GlobalISel: Add MIPatternMatch for G_ICMP/G_FCMP

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 23 13:31:05 PST 2020


Author: Matt Arsenault
Date: 2020-01-23T13:30:47-08:00
New Revision: c77bbea9a671cf30d9f650383d8c5c189fe6c868

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

LOG: GlobalISel: Add MIPatternMatch for G_ICMP/G_FCMP

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 fca3e1dc415a..c05b3caf9fb4 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
@@ -16,6 +16,7 @@
 #include "llvm/ADT/APInt.h"
 #include "llvm/CodeGen/GlobalISel/Utils.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/InstrTypes.h"
 
 namespace llvm {
 namespace MIPatternMatch {
@@ -163,6 +164,8 @@ template <typename Class> struct bind_ty {
 inline bind_ty<Register> m_Reg(Register &R) { return R; }
 inline bind_ty<MachineInstr *> m_MInstr(MachineInstr *&MI) { return MI; }
 inline bind_ty<LLT> m_Type(LLT &Ty) { return Ty; }
+inline bind_ty<CmpInst::Predicate> m_Pred(CmpInst::Predicate &P) { return P; }
+inline operand_type_match m_Pred() { return operand_type_match(); }
 
 // Helper for matching G_FCONSTANT
 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) {
   return UnaryOp_match<SrcTy, TargetOpcode::COPY>(std::forward<SrcTy>(Src));
 }
 
+// General helper for generic MI compares, i.e. G_ICMP and G_FCMP
+// TODO: Allow checking a specific predicate.
+template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode>
+struct CompareOp_match {
+  Pred_P P;
+  LHS_P L;
+  RHS_P R;
+
+  CompareOp_match(const Pred_P &Pred, const LHS_P &LHS, const RHS_P &RHS)
+      : P(Pred), L(LHS), R(RHS) {}
+
+  template <typename OpTy>
+  bool match(const MachineRegisterInfo &MRI, OpTy &&Op) {
+    MachineInstr *TmpMI;
+    if (!mi_match(Op, MRI, m_MInstr(TmpMI)) || TmpMI->getOpcode() != Opcode)
+      return false;
+
+    auto TmpPred =
+        static_cast<CmpInst::Predicate>(TmpMI->getOperand(1).getPredicate());
+    if (!P.match(MRI, TmpPred))
+      return false;
+
+    return L.match(MRI, TmpMI->getOperand(2).getReg()) &&
+           R.match(MRI, TmpMI->getOperand(3).getReg());
+  }
+};
+
+template <typename Pred, typename LHS, typename RHS>
+inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>
+m_GICmp(const Pred &P, const LHS &L, const RHS &R) {
+  return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP>(P, L, R);
+}
+
+template <typename Pred, typename LHS, typename RHS>
+inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>
+m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
+  return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>(P, L, R);
+}
+
 // Helper for checking if a Reg is of specific type.
 struct CheckType {
   LLT Ty;

diff  --git a/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp b/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp
index 2b160fba8ec7..1ceedbe420e7 100644
--- a/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp
@@ -129,6 +129,56 @@ TEST_F(GISelMITest, MatchBinaryOp) {
   EXPECT_EQ(Src1, Copies[1]);
 }
 
+TEST_F(GISelMITest, MatchICmp) {
+  setUp();
+  if (!TM)
+    return;
+
+  const LLT s1 = LLT::scalar(1);
+  auto CmpEq = B.buildICmp(CmpInst::ICMP_EQ, s1, Copies[0], Copies[1]);
+
+  // Check match any predicate.
+  bool match =
+      mi_match(CmpEq.getReg(0), *MRI, m_GICmp(m_Pred(), m_Reg(), m_Reg()));
+  EXPECT_TRUE(match);
+
+  // Check we get the predicate and registers.
+  CmpInst::Predicate Pred;
+  Register Reg0;
+  Register Reg1;
+  match = mi_match(CmpEq.getReg(0), *MRI,
+                   m_GICmp(m_Pred(Pred), m_Reg(Reg0), m_Reg(Reg1)));
+  EXPECT_TRUE(match);
+  EXPECT_EQ(CmpInst::ICMP_EQ, Pred);
+  EXPECT_EQ(Copies[0], Reg0);
+  EXPECT_EQ(Copies[1], Reg1);
+}
+
+TEST_F(GISelMITest, MatchFCmp) {
+  setUp();
+  if (!TM)
+    return;
+
+  const LLT s1 = LLT::scalar(1);
+  auto CmpEq = B.buildFCmp(CmpInst::FCMP_OEQ, s1, Copies[0], Copies[1]);
+
+  // Check match any predicate.
+  bool match =
+      mi_match(CmpEq.getReg(0), *MRI, m_GFCmp(m_Pred(), m_Reg(), m_Reg()));
+  EXPECT_TRUE(match);
+
+  // Check we get the predicate and registers.
+  CmpInst::Predicate Pred;
+  Register Reg0;
+  Register Reg1;
+  match = mi_match(CmpEq.getReg(0), *MRI,
+                   m_GFCmp(m_Pred(Pred), m_Reg(Reg0), m_Reg(Reg1)));
+  EXPECT_TRUE(match);
+  EXPECT_EQ(CmpInst::FCMP_OEQ, Pred);
+  EXPECT_EQ(Copies[0], Reg0);
+  EXPECT_EQ(Copies[1], Reg1);
+}
+
 TEST_F(GISelMITest, MatchFPUnaryOp) {
   setUp();
   if (!TM)


        


More information about the llvm-commits mailing list