[llvm] 0a33532 - [PatternMatch] Add `m_c_XorLike` matcher; NFC (#122642)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 18 09:23:05 PST 2025
Author: goldsteinn
Date: 2025-01-18T11:23:01-06:00
New Revision: 0a33532500a90668f5cfe485134e9c9c388d3614
URL: https://github.com/llvm/llvm-project/commit/0a33532500a90668f5cfe485134e9c9c388d3614
DIFF: https://github.com/llvm/llvm-project/commit/0a33532500a90668f5cfe485134e9c9c388d3614.diff
LOG: [PatternMatch] Add `m_c_XorLike` matcher; NFC (#122642)
`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)`
Added:
Modified:
llvm/include/llvm/IR/PatternMatch.h
llvm/unittests/IR/PatternMatch.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index cd9a36029e6dbd..b3eeb1d7ba88a9 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..d06ada5953445d 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();
More information about the llvm-commits
mailing list