From c77bbea9a671cf30d9f650383d8c5c189fe6c868 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Thu, 23 Jan 2020 08:45:40 -0500 Subject: [PATCH] GlobalISel: Add MIPatternMatch for G_ICMP/G_FCMP --- .../llvm/CodeGen/GlobalISel/MIPatternMatch.h | 42 ++++++++++++++++++ .../CodeGen/GlobalISel/PatternMatchTest.cpp | 50 ++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h index fca3e1dc415..c05b3caf9fb 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 struct bind_ty { inline bind_ty m_Reg(Register &R) { return R; } inline bind_ty m_MInstr(MachineInstr *&MI) { return MI; } inline bind_ty m_Type(LLT &Ty) { return Ty; } +inline bind_ty 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 m_GFCst(const ConstantFP *&C) { return C; } @@ -320,6 +323,45 @@ inline UnaryOp_match m_Copy(SrcTy &&Src) { return UnaryOp_match(std::forward(Src)); } +// General helper for generic MI compares, i.e. G_ICMP and G_FCMP +// TODO: Allow checking a specific predicate. +template +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 + 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(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 +inline CompareOp_match +m_GICmp(const Pred &P, const LHS &L, const RHS &R) { + return CompareOp_match(P, L, R); +} + +template +inline CompareOp_match +m_GFCmp(const Pred &P, const LHS &L, const RHS &R) { + return CompareOp_match(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 2b160fba8ec..1ceedbe420e 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) -- 2.11.0