Skip to content

Commit 0a33532

Browse files
authored
[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)`
1 parent bc386a8 commit 0a33532

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

llvm/include/llvm/IR/PatternMatch.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,34 @@ m_NUWAddLike(const LHS &L, const RHS &R) {
14301430
return m_CombineOr(m_NUWAdd(L, R), m_DisjointOr(L, R));
14311431
}
14321432

1433+
template <typename LHS, typename RHS>
1434+
struct XorLike_match {
1435+
LHS L;
1436+
RHS R;
1437+
1438+
XorLike_match(const LHS &L, const RHS &R) : L(L), R(R) {}
1439+
1440+
template <typename OpTy> bool match(OpTy *V) {
1441+
if (auto *Op = dyn_cast<BinaryOperator>(V)) {
1442+
if (Op->getOpcode() == Instruction::Sub && Op->hasNoUnsignedWrap() &&
1443+
PatternMatch::match(Op->getOperand(0), m_LowBitMask()))
1444+
; // Pass
1445+
else if (Op->getOpcode() != Instruction::Xor)
1446+
return false;
1447+
return (L.match(Op->getOperand(0)) && R.match(Op->getOperand(1))) ||
1448+
(L.match(Op->getOperand(1)) && R.match(Op->getOperand(0)));
1449+
}
1450+
return false;
1451+
}
1452+
};
1453+
1454+
/// Match either `(xor L, R)`, `(xor R, L)` or `(sub nuw R, L)` iff `R.isMask()`
1455+
/// Only commutative matcher as the `sub` will need to swap the L and R.
1456+
template <typename LHS, typename RHS>
1457+
inline auto m_c_XorLike(const LHS &L, const RHS &R) {
1458+
return XorLike_match<LHS, RHS>(L, R);
1459+
}
1460+
14331461
//===----------------------------------------------------------------------===//
14341462
// Class that matches a group of binary opcodes.
14351463
//

llvm/unittests/IR/PatternMatch.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,72 @@ TEST_F(PatternMatchTest, BitWise) {
533533
EXPECT_FALSE(m_c_BitwiseLogic(m_Zero(), m_Zero()).match(Xor));
534534
}
535535

536+
TEST_F(PatternMatchTest, XorLike) {
537+
Value *AllocaX = IRB.CreateAlloca(IRB.getInt32Ty());
538+
Value *X = IRB.CreateLoad(IRB.getInt32Ty(), AllocaX);
539+
Value *AllocaY = IRB.CreateAlloca(IRB.getInt32Ty());
540+
Value *Y = IRB.CreateLoad(IRB.getInt32Ty(), AllocaY);
541+
Value *MaskC = IRB.getInt32(31);
542+
Value *NonMaskC = IRB.getInt32(32);
543+
544+
Value *OpA, *OpB;
545+
{
546+
Value *Xor = IRB.CreateXor(X, Y);
547+
Value *Sub = IRB.CreateNUWSub(X, Y);
548+
OpA = nullptr;
549+
OpB = nullptr;
550+
EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Xor));
551+
EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) && (OpA == Y || OpB == Y));
552+
OpA = nullptr;
553+
OpB = nullptr;
554+
EXPECT_FALSE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Sub));
555+
}
556+
{
557+
Value *Xor = IRB.CreateXor(X, MaskC);
558+
Value *Sub = IRB.CreateNUWSub(MaskC, X);
559+
OpA = nullptr;
560+
OpB = nullptr;
561+
EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Xor));
562+
EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) &&
563+
(OpA == MaskC || OpB == MaskC));
564+
OpA = nullptr;
565+
OpB = nullptr;
566+
EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Sub));
567+
EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) &&
568+
(OpA == MaskC || OpB == MaskC));
569+
}
570+
{
571+
Value *Xor = IRB.CreateXor(X, MaskC);
572+
Value *Sub = IRB.CreateNSWSub(MaskC, X);
573+
OpA = nullptr;
574+
OpB = nullptr;
575+
EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Xor));
576+
EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) &&
577+
(OpA == MaskC || OpB == MaskC));
578+
OpA = nullptr;
579+
OpB = nullptr;
580+
EXPECT_FALSE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Sub));
581+
}
582+
{
583+
Value *Sub = IRB.CreateNUWSub(X, MaskC);
584+
OpA = nullptr;
585+
OpB = nullptr;
586+
EXPECT_FALSE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Sub));
587+
}
588+
{
589+
Value *Xor = IRB.CreateXor(X, NonMaskC);
590+
Value *Sub = IRB.CreateNUWSub(NonMaskC, X);
591+
OpA = nullptr;
592+
OpB = nullptr;
593+
EXPECT_TRUE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Xor));
594+
EXPECT_TRUE(OpA != OpB && (OpA == X || OpB == X) &&
595+
(OpA == NonMaskC || OpB == NonMaskC));
596+
OpA = nullptr;
597+
OpB = nullptr;
598+
EXPECT_FALSE(m_c_XorLike(m_Value(OpA), m_Value(OpB)).match(Sub));
599+
}
600+
}
601+
536602
TEST_F(PatternMatchTest, ZExtSExtSelf) {
537603
LLVMContext &Ctx = IRB.getContext();
538604

0 commit comments

Comments
 (0)