[llvm] 45b9c6b - [GlobalISel] Add commutative matchers for compares.

Jessica Paquette via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 7 20:08:13 PDT 2022


Author: Jessica Paquette
Date: 2022-10-07T20:06:13-07:00
New Revision: 45b9c6b01f263d087a456b098b36e9ee90c607b2

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

LOG: [GlobalISel] Add commutative matchers for compares.

This adds:

* `m_c_GICmp`
* `m_c_GFCmp`

These work the same way as the standard matchers, but will also try to commute
the LHS and RHS of a compare to get a match.

E.g.

```
m_c_GICmp(m_Pred(...), m_GAdd(...), m_GSub(...))
```

Can match either of

```
icmp cc (add x, y), (sub a, b)
icmp swapped_cc (sub a, b), (add x, y)
```

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

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 91216cfc489e7..3879e22552ecb 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
@@ -636,7 +636,8 @@ inline UnaryOp_match<SrcTy, TargetOpcode::G_FSQRT> m_GFSqrt(const 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>
+template <typename Pred_P, typename LHS_P, typename RHS_P, unsigned Opcode,
+          bool Commutable = false>
 struct CompareOp_match {
   Pred_P P;
   LHS_P L;
@@ -655,9 +656,14 @@ struct CompareOp_match {
         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());
+    Register LHS = TmpMI->getOperand(2).getReg();
+    Register RHS = TmpMI->getOperand(3).getReg();
+    if (L.match(MRI, LHS) && R.match(MRI, RHS))
+      return true;
+    if (Commutable && L.match(MRI, RHS) && R.match(MRI, LHS) &&
+        P.match(MRI, CmpInst::getSwappedPredicate(TmpPred)))
+      return true;
+    return false;
   }
 };
 
@@ -673,6 +679,36 @@ m_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
   return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP>(P, L, R);
 }
 
+/// G_ICMP matcher that also matches commuted compares.
+/// E.g.
+///
+/// m_c_GICmp(m_Pred(...), m_GAdd(...), m_GSub(...))
+///
+/// Could match both of:
+///
+/// icmp ugt (add x, y) (sub a, b)
+/// icmp ult (sub a, b) (add x, y)
+template <typename Pred, typename LHS, typename RHS>
+inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP, true>
+m_c_GICmp(const Pred &P, const LHS &L, const RHS &R) {
+  return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_ICMP, true>(P, L, R);
+}
+
+/// G_FCMP matcher that also matches commuted compares.
+/// E.g.
+///
+/// m_c_GFCmp(m_Pred(...), m_FAdd(...), m_GFMul(...))
+///
+/// Could match both of:
+///
+/// fcmp ogt (fadd x, y) (fmul a, b)
+/// fcmp olt (fmul a, b) (fadd x, y)
+template <typename Pred, typename LHS, typename RHS>
+inline CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP, true>
+m_c_GFCmp(const Pred &P, const LHS &L, const RHS &R) {
+  return CompareOp_match<Pred, LHS, RHS, TargetOpcode::G_FCMP, true>(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 58219579a4705..9ed72c9b6f5fb 100644
--- a/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp
+++ b/llvm/unittests/CodeGen/GlobalISel/PatternMatchTest.cpp
@@ -323,6 +323,64 @@ TEST_F(AArch64GISelMITest, MatchFCmp) {
   EXPECT_EQ(Copies[1], Reg1);
 }
 
+TEST_F(AArch64GISelMITest, MatcCommutativeICmp) {
+  setUp();
+  if (!TM)
+    return;
+  const LLT s1 = LLT::scalar(1);
+  Register LHS = Copies[0];
+  Register RHS = Copies[1];
+  CmpInst::Predicate MatchedPred;
+  bool Match = false;
+  for (unsigned P = CmpInst::Predicate::FIRST_ICMP_PREDICATE;
+       P < CmpInst::Predicate::LAST_ICMP_PREDICATE; ++P) {
+    auto CurrPred = static_cast<CmpInst::Predicate>(P);
+    auto Cmp = B.buildICmp(CurrPred, s1, LHS, RHS);
+    // Basic matching.
+    Match = mi_match(
+        Cmp.getReg(0), *MRI,
+        m_c_GICmp(m_Pred(MatchedPred), m_SpecificReg(LHS), m_SpecificReg(RHS)));
+    EXPECT_TRUE(Match);
+    EXPECT_EQ(MatchedPred, CurrPred);
+    // Commuting operands should still match, but the predicate should be
+    // swapped.
+    Match = mi_match(
+        Cmp.getReg(0), *MRI,
+        m_c_GICmp(m_Pred(MatchedPred), m_SpecificReg(RHS), m_SpecificReg(LHS)));
+    EXPECT_TRUE(Match);
+    EXPECT_EQ(MatchedPred, CmpInst::getSwappedPredicate(CurrPred));
+  }
+}
+
+TEST_F(AArch64GISelMITest, MatcCommutativeFCmp) {
+  setUp();
+  if (!TM)
+    return;
+  const LLT s1 = LLT::scalar(1);
+  Register LHS = Copies[0];
+  Register RHS = Copies[1];
+  CmpInst::Predicate MatchedPred;
+  bool Match = false;
+  for (unsigned P = CmpInst::Predicate::FIRST_FCMP_PREDICATE;
+       P < CmpInst::Predicate::LAST_FCMP_PREDICATE; ++P) {
+    auto CurrPred = static_cast<CmpInst::Predicate>(P);
+    auto Cmp = B.buildFCmp(CurrPred, s1, LHS, RHS);
+    // Basic matching.
+    Match = mi_match(
+        Cmp.getReg(0), *MRI,
+        m_c_GFCmp(m_Pred(MatchedPred), m_SpecificReg(LHS), m_SpecificReg(RHS)));
+    EXPECT_TRUE(Match);
+    EXPECT_EQ(MatchedPred, CurrPred);
+    // Commuting operands should still match, but the predicate should be
+    // swapped.
+    Match = mi_match(
+        Cmp.getReg(0), *MRI,
+        m_c_GFCmp(m_Pred(MatchedPred), m_SpecificReg(RHS), m_SpecificReg(LHS)));
+    EXPECT_TRUE(Match);
+    EXPECT_EQ(MatchedPred, CmpInst::getSwappedPredicate(CurrPred));
+  }
+}
+
 TEST_F(AArch64GISelMITest, MatchFPUnaryOp) {
   setUp();
   if (!TM)


        


More information about the llvm-commits mailing list