[llvm] [PatternMatch] Add `m_c_XorLike` matcher; NFC (PR #122642)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 15 09:10:04 PST 2025


https://github.com/goldsteinn updated https://github.com/llvm/llvm-project/pull/122642

>From d3aacf78ba3d1eba88a298b9c7e15ddd662c2069 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Sun, 12 Jan 2025 10:42:28 -0600
Subject: [PATCH 1/3] [PatternMatch] Add `m_c_XorLike` matcher; NFC

`m_c_XorLike` matches either:
    `(xor L, R)`, `(xor R, L)`, or `(sub nuw R, L)` iff `R.isMask()`.

This is in preperation for dropping the fold from:
    `(sub C_Mask, X)` -> `(xor X, C_Mask)`
---
 llvm/include/llvm/IR/PatternMatch.h | 28 ++++++++++++
 llvm/unittests/IR/PatternMatch.cpp  | 66 +++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+)

diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index cd9a36029e6dbd..e50459716fe0eb 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -1430,6 +1430,34 @@ m_NUWAddLike(const LHS &L, const RHS &R) {
   return m_CombineOr(m_NUWAdd(L, R), m_DisjointOr(L, R));
 }
 
+template <typename LHS, typename RHS>
+struct XorLike_match {
+  LHS L;
+  RHS R;
+
+  XorLike_match(const LHS &L, const RHS &R) : L(L), R(R) {}
+
+  template <typename OpTy> bool match(OpTy *V) {
+    if (auto *Op = dyn_cast<BinaryOperator>(V)) {
+      if (Op->getOpcode() == Instruction::Sub && Op->hasNoUnsignedWrap() &&
+          PatternMatch::match(Op->getOperand(0), m_LowBitMask()))
+		  ; // Pass
+      else if (Op->getOpcode() != Instruction::Xor)
+        return false;
+      return (L.match(Op->getOperand(0)) && R.match(Op->getOperand(1))) ||
+             (L.match(Op->getOperand(1)) && R.match(Op->getOperand(0)));
+    }
+    return false;
+  }
+};
+
+// Match either `(xor L, R)`, `(xor R, L)` or `(sub nuw R, L)` iff `R.isMask()`
+// Only commutative matcher as the `sub` will need to swap the L and R.
+template <typename LHS, typename RHS>
+inline auto m_c_XorLike(const LHS &L, const RHS &R) {
+  return XorLike_match<LHS, RHS>(L, R);
+}
+
 //===----------------------------------------------------------------------===//
 // Class that matches a group of binary opcodes.
 //
diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp
index 47fde5782a13bc..da2c09ea199290 100644
--- a/llvm/unittests/IR/PatternMatch.cpp
+++ b/llvm/unittests/IR/PatternMatch.cpp
@@ -533,6 +533,72 @@ TEST_F(PatternMatchTest, BitWise) {
   EXPECT_FALSE(m_c_BitwiseLogic(m_Zero(), m_Zero()).match(Xor));
 }
 
+TEST_F(PatternMatchTest, XorLike) {
+  Value *AllocaX = IRB.CreateAlloca(IRB.getInt32Ty());
+  Value *X = IRB.CreateLoad(IRB.getInt32Ty(), AllocaX);
+  Value *AllocaY = IRB.CreateAlloca(IRB.getInt32Ty());
+  Value *Y = IRB.CreateLoad(IRB.getInt32Ty(), AllocaY);
+  Value *MaskC = IRB.getInt32(31);
+  Value *NonMaskC = IRB.getInt32(32);
+
+  Value *OpA, *OpB;
+  {
+    Value *Xor = IRB.CreateXor(X, Y);
+    Value *Sub = IRB.CreateNUWSub(X, Y);
+    OpA = nullptr;
+    OpB = nullptr;
+    EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Xor));
+    EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) && (OpA == Y || OpB == Y));
+    OpA = nullptr;
+    OpB = nullptr;
+    EXPECT_FALSE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Sub));
+  }
+  {
+    Value *Xor = IRB.CreateXor(X, MaskC);
+    Value *Sub = IRB.CreateNUWSub(MaskC, X);
+    OpA = nullptr;
+    OpB = nullptr;	
+    EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Xor));
+    EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) &&
+                (OpA == MaskC || OpB == MaskC));
+    OpA = nullptr;
+    OpB = nullptr;
+    EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Sub));
+    EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) &&
+                (OpA == MaskC || OpB == MaskC));
+  }
+  {
+    Value *Xor = IRB.CreateXor(X, MaskC);
+    Value *Sub = IRB.CreateNSWSub(MaskC, X);
+    OpA = nullptr;
+    OpB = nullptr;	
+    EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Xor));
+    EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) &&
+                (OpA == MaskC || OpB == MaskC));
+    OpA = nullptr;
+    OpB = nullptr;
+    EXPECT_FALSE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Sub));
+  }
+  {
+    Value *Sub = IRB.CreateNUWSub(X, MaskC);
+    OpA = nullptr;
+    OpB = nullptr;
+    EXPECT_FALSE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Sub));
+  }
+  {
+    Value *Xor = IRB.CreateXor(X, NonMaskC);
+    Value *Sub = IRB.CreateNUWSub(NonMaskC, X);
+    OpA = nullptr;
+    OpB = nullptr;	
+    EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Xor));
+    EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) &&
+                (OpA == NonMaskC || OpB == NonMaskC));
+    OpA = nullptr;
+    OpB = nullptr;
+    EXPECT_FALSE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Sub));
+  }  
+}
+
 TEST_F(PatternMatchTest, ZExtSExtSelf) {
   LLVMContext &Ctx = IRB.getContext();
 

>From 544a29ca944e7bc34b9c2b3c46f81c37488a17ab Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Sun, 12 Jan 2025 10:54:55 -0600
Subject: [PATCH 2/3] Fix Fmt

---
 llvm/unittests/IR/PatternMatch.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp
index da2c09ea199290..d06ada5953445d 100644
--- a/llvm/unittests/IR/PatternMatch.cpp
+++ b/llvm/unittests/IR/PatternMatch.cpp
@@ -557,7 +557,7 @@ TEST_F(PatternMatchTest, XorLike) {
     Value *Xor = IRB.CreateXor(X, MaskC);
     Value *Sub = IRB.CreateNUWSub(MaskC, X);
     OpA = nullptr;
-    OpB = nullptr;	
+    OpB = nullptr;
     EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Xor));
     EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) &&
                 (OpA == MaskC || OpB == MaskC));
@@ -571,7 +571,7 @@ TEST_F(PatternMatchTest, XorLike) {
     Value *Xor = IRB.CreateXor(X, MaskC);
     Value *Sub = IRB.CreateNSWSub(MaskC, X);
     OpA = nullptr;
-    OpB = nullptr;	
+    OpB = nullptr;
     EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Xor));
     EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) &&
                 (OpA == MaskC || OpB == MaskC));
@@ -589,14 +589,14 @@ TEST_F(PatternMatchTest, XorLike) {
     Value *Xor = IRB.CreateXor(X, NonMaskC);
     Value *Sub = IRB.CreateNUWSub(NonMaskC, X);
     OpA = nullptr;
-    OpB = nullptr;	
+    OpB = nullptr;
     EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Xor));
     EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) &&
                 (OpA == NonMaskC || OpB == NonMaskC));
     OpA = nullptr;
     OpB = nullptr;
     EXPECT_FALSE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Sub));
-  }  
+  }
 }
 
 TEST_F(PatternMatchTest, ZExtSExtSelf) {

>From e192d736e366bb5508da6eb33a43d104b084441c Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Wed, 15 Jan 2025 11:09:29 -0600
Subject: [PATCH 3/3] Fix Cmt

---
 llvm/include/llvm/IR/PatternMatch.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index e50459716fe0eb..b3eeb1d7ba88a9 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -1451,8 +1451,8 @@ struct XorLike_match {
   }
 };
 
-// Match either `(xor L, R)`, `(xor R, L)` or `(sub nuw R, L)` iff `R.isMask()`
-// Only commutative matcher as the `sub` will need to swap the L and R.
+/// Match either `(xor L, R)`, `(xor R, L)` or `(sub nuw R, L)` iff `R.isMask()`
+/// Only commutative matcher as the `sub` will need to swap the L and R.
 template <typename LHS, typename RHS>
 inline auto m_c_XorLike(const LHS &L, const RHS &R) {
   return XorLike_match<LHS, RHS>(L, R);



More information about the llvm-commits mailing list