[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