[llvm] [InstCombine] Remove `sub nuw C_Mask, X` -> `xor X, C_Mask` canoncalization (PR #122607)
via llvm-commits
llvm-commits at lists.llvm.org
Sat Jan 11 13:26:59 PST 2025
https://github.com/goldsteinn updated https://github.com/llvm/llvm-project/pull/122607
>From b6bba9ea2ce017348ea1f6a51ef0e83b3d182adb Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Sat, 11 Jan 2025 13:01:56 -0600
Subject: [PATCH 1/2] [InstCombine] Remove `sub nuw C_Mask, X` -> `xor X,
C_Mask` canoncalization
---
llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 10 ----------
llvm/test/Transforms/InstCombine/sub-xor.ll | 6 +++---
2 files changed, 3 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 73876d00e73a7c..b253af0a828b61 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2424,16 +2424,6 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
const APInt *Op0C;
if (match(Op0, m_APInt(Op0C))) {
- if (Op0C->isMask()) {
- // Turn this into a xor if LHS is 2^n-1 and the remaining bits are known
- // zero. We don't use information from dominating conditions so this
- // transform is easier to reverse if necessary.
- KnownBits RHSKnown = llvm::computeKnownBits(
- Op1, 0, SQ.getWithInstruction(&I).getWithoutDomCondCache());
- if ((*Op0C | RHSKnown.Zero).isAllOnes())
- return BinaryOperator::CreateXor(Op1, Op0);
- }
-
// C - ((C3 -nuw X) & C2) --> (C - (C2 & C3)) + (X & C2) when:
// (C3 - ((C2 & C3) - 1)) is pow2
// ((C2 + C3) & ((C2 & C3) - 1)) == ((C2 & C3) - 1)
diff --git a/llvm/test/Transforms/InstCombine/sub-xor.ll b/llvm/test/Transforms/InstCombine/sub-xor.ll
index a4135e0b514532..dc2113de546e51 100644
--- a/llvm/test/Transforms/InstCombine/sub-xor.ll
+++ b/llvm/test/Transforms/InstCombine/sub-xor.ll
@@ -6,7 +6,7 @@ declare void @use(i32)
define i32 @low_mask_nsw_nuw(i32 %x) {
; CHECK-LABEL: @low_mask_nsw_nuw(
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 31
-; CHECK-NEXT: [[SUB:%.*]] = xor i32 [[AND]], 63
+; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 63, [[AND]]
; CHECK-NEXT: ret i32 [[SUB]]
;
%and = and i32 %x, 31
@@ -17,7 +17,7 @@ define i32 @low_mask_nsw_nuw(i32 %x) {
define <2 x i32> @low_mask_nsw_nuw_vec(<2 x i32> %x) {
; CHECK-LABEL: @low_mask_nsw_nuw_vec(
; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X:%.*]], splat (i32 31)
-; CHECK-NEXT: [[SUB:%.*]] = xor <2 x i32> [[AND]], splat (i32 63)
+; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw <2 x i32> splat (i32 63), [[AND]]
; CHECK-NEXT: ret <2 x i32> [[SUB]]
;
%and = and <2 x i32> %x, <i32 31, i32 31>
@@ -98,7 +98,7 @@ declare i32 @llvm.ctlz.i32(i32, i1)
define i32 @range_masked_sub(i32 %x) {
; CHECK-LABEL: @range_masked_sub(
; CHECK-NEXT: [[COUNT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true) #[[ATTR1:[0-9]+]]
-; CHECK-NEXT: [[SUB:%.*]] = xor i32 [[COUNT]], 31
+; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 31, [[COUNT]]
; CHECK-NEXT: ret i32 [[SUB]]
;
%count = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) nounwind readnone
>From 8ee0ed1e361809d2cfb3c59ab777b2351c1ab191 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Sat, 11 Jan 2025 15:26:40 -0600
Subject: [PATCH 2/2] A bunch of xor like cases
---
llvm/include/llvm/IR/PatternMatch.h | 33 +++++++
llvm/lib/Analysis/InstructionSimplify.cpp | 30 +++---
llvm/lib/Analysis/ValueTracking.cpp | 6 +-
.../InstCombine/InstCombineAddSub.cpp | 24 ++---
.../InstCombine/InstCombineAndOrXor.cpp | 98 +++++++++----------
.../InstCombine/InstCombineCalls.cpp | 6 +-
.../InstCombine/InstCombineCasts.cpp | 4 +-
.../InstCombine/InstCombineCompares.cpp | 26 ++---
.../InstCombine/InstCombineSelect.cpp | 2 +-
.../InstCombine/InstructionCombining.cpp | 2 +-
10 files changed, 132 insertions(+), 99 deletions(-)
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index cd9a36029e6dbd..51ad1eed3a1c1f 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -1430,6 +1430,39 @@ m_NUWAddLike(const LHS &L, const RHS &R) {
return m_CombineOr(m_NUWAdd(L, R), m_DisjointOr(L, R));
}
+template <typename LHS, typename RHS, bool Commutable = false>
+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)) {
+ bool CheckCommuted = Commutable;
+ if (Op->getOpcode() == Instruction::Sub && Op->hasNoUnsignedWrap() &&
+ PatternMatch::match(Op->getOperand(0), m_LowBitMask()))
+ CheckCommuted = false;
+ else if (Op->getOpcode() != Instruction::Xor)
+ return false;
+ return (L.match(Op->getOperand(0)) && R.match(Op->getOperand(1))) ||
+ (CheckCommuted && L.match(Op->getOperand(1)) &&
+ R.match(Op->getOperand(0)));
+ }
+ return false;
+ }
+};
+
+template <typename LHS, typename RHS>
+inline auto m_XorLike(const LHS &L, const RHS &R) {
+ return XorLike_match<LHS, RHS>(L, R);
+}
+
+template <typename LHS, typename RHS>
+inline auto m_c_XorLike(const LHS &L, const RHS &R) {
+ return XorLike_match<LHS, RHS, /*Commutable=*/true>(L, R);
+}
+
//===----------------------------------------------------------------------===//
// Class that matches a group of binary opcodes.
//
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 999386c0a04917..f6af0dcb6534d1 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -624,7 +624,7 @@ static Value *simplifyAddInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW,
// The no-wrapping add guarantees that the top bit will be set by the add.
// Therefore, the xor must be clearing the already set sign bit of Y.
if ((IsNSW || IsNUW) && match(Op1, m_SignMask()) &&
- match(Op0, m_Xor(m_Value(Y), m_SignMask())))
+ match(Op0, m_XorLike(m_Value(Y), m_SignMask())))
return Y;
// add nuw %x, -1 -> -1, because %x can only be 0.
@@ -2154,17 +2154,17 @@ static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
// ((X | Y) ^ X ) & ((X | Y) ^ Y) --> 0
// ((X | Y) ^ Y ) & ((X | Y) ^ X) --> 0
BinaryOperator *Or;
- if (match(Op0, m_c_Xor(m_Value(X),
+ if (match(Op0, m_c_XorLike(m_Value(X),
m_CombineAnd(m_BinOp(Or),
m_c_Or(m_Deferred(X), m_Value(Y))))) &&
- match(Op1, m_c_Xor(m_Specific(Or), m_Specific(Y))))
+ match(Op1, m_c_XorLike(m_Specific(Or), m_Specific(Y))))
return Constant::getNullValue(Op0->getType());
const APInt *C1;
Value *A;
// (A ^ C) & (A ^ ~C) -> 0
- if (match(Op0, m_Xor(m_Value(A), m_APInt(C1))) &&
- match(Op1, m_Xor(m_Specific(A), m_SpecificInt(~*C1))))
+ if (match(Op0, m_XorLike(m_Value(A), m_APInt(C1))) &&
+ match(Op1, m_XorLike(m_Specific(A), m_SpecificInt(~*C1))))
return Constant::getNullValue(Op0->getType());
if (Op0->getType()->isIntOrIntVectorTy(1)) {
@@ -2217,13 +2217,13 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
// (A ^ B) | (A | B) --> A | B
// (A ^ B) | (B | A) --> B | A
- if (match(X, m_Xor(m_Value(A), m_Value(B))) &&
+ if (match(X, m_XorLike(m_Value(A), m_Value(B))) &&
match(Y, m_c_Or(m_Specific(A), m_Specific(B))))
return Y;
// ~(A ^ B) | (A | B) --> -1
// ~(A ^ B) | (B | A) --> -1
- if (match(X, m_Not(m_Xor(m_Value(A), m_Value(B)))) &&
+ if (match(X, m_Not(m_XorLike(m_Value(A), m_Value(B)))) &&
match(Y, m_c_Or(m_Specific(A), m_Specific(B))))
return ConstantInt::getAllOnesValue(Ty);
@@ -2232,14 +2232,14 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
// (A & ~B) | (B ^ A) --> B ^ A
// (~B & A) | (B ^ A) --> B ^ A
if (match(X, m_c_And(m_Value(A), m_Not(m_Value(B)))) &&
- match(Y, m_c_Xor(m_Specific(A), m_Specific(B))))
+ match(Y, m_c_XorLike(m_Specific(A), m_Specific(B))))
return Y;
// (~A ^ B) | (A & B) --> ~A ^ B
// (B ^ ~A) | (A & B) --> B ^ ~A
// (~A ^ B) | (B & A) --> ~A ^ B
// (B ^ ~A) | (B & A) --> B ^ ~A
- if (match(X, m_c_Xor(m_Not(m_Value(A)), m_Value(B))) &&
+ if (match(X, m_c_XorLike(m_Not(m_Value(A)), m_Value(B))) &&
match(Y, m_c_And(m_Specific(A), m_Specific(B))))
return X;
@@ -2248,7 +2248,7 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
// (B | ~A) | (A ^ B) --> -1
// (B | ~A) | (B ^ A) --> -1
if (match(X, m_c_Or(m_Not(m_Value(A)), m_Value(B))) &&
- match(Y, m_c_Xor(m_Specific(A), m_Specific(B))))
+ match(Y, m_c_XorLike(m_Specific(A), m_Specific(B))))
return ConstantInt::getAllOnesValue(Ty);
// (~A & B) | ~(A | B) --> ~A
@@ -2271,7 +2271,7 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
// ~(A ^ B) | (A & B) --> ~(A ^ B)
// ~(A ^ B) | (B & A) --> ~(A ^ B)
Value *NotAB;
- if (match(X, m_CombineAnd(m_Not(m_Xor(m_Value(A), m_Value(B))),
+ if (match(X, m_CombineAnd(m_Not(m_XorLike(m_Value(A), m_Value(B))),
m_Value(NotAB))) &&
match(Y, m_c_And(m_Specific(A), m_Specific(B))))
return NotAB;
@@ -2280,7 +2280,7 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
// ~(A & B) | (B ^ A) --> ~(A & B)
if (match(X, m_CombineAnd(m_Not(m_And(m_Value(A), m_Value(B))),
m_Value(NotAB))) &&
- match(Y, m_c_Xor(m_Specific(A), m_Specific(B))))
+ match(Y, m_c_XorLike(m_Specific(A), m_Specific(B))))
return NotAB;
return nullptr;
@@ -2435,8 +2435,8 @@ static Value *simplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
return V;
// (A ^ C) | (A ^ ~C) -> -1, i.e. all bits set to one.
- if (match(Op0, m_Xor(m_Value(A), m_APInt(C1))) &&
- match(Op1, m_Xor(m_Specific(A), m_SpecificInt(~*C1))))
+ if (match(Op0, m_XorLike(m_Value(A), m_APInt(C1))) &&
+ match(Op1, m_XorLike(m_Specific(A), m_SpecificInt(~*C1))))
return Constant::getAllOnesValue(Op0->getType());
if (Op0->getType()->isIntOrIntVectorTy(1)) {
@@ -5097,7 +5097,7 @@ static Value *simplifyGEPInst(Type *SrcTy, Value *Ptr,
}
// gep (gep V, C), (xor V, -1) -> C-1
if (match(Indices.back(),
- m_Xor(m_PtrToInt(m_Specific(StrippedBasePtr)), m_AllOnes())) &&
+ m_XorLike(m_PtrToInt(m_Specific(StrippedBasePtr)), m_AllOnes())) &&
!BasePtrOffset.isOne()) {
auto *CI = ConstantInt::get(GEPTy->getContext(), BasePtrOffset - 1);
return ConstantExpr::getIntToPtr(CI, GEPTy);
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 4b246c013e96f1..80729a46eaad9e 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -207,7 +207,7 @@ static bool haveNoCommonBitsSetSpecialCases(const Value *LHS, const Value *RHS,
// for constant Y.
Value *Y;
if (match(RHS,
- m_c_Xor(m_c_And(m_Specific(LHS), m_Value(Y)), m_Deferred(Y))) &&
+ m_c_XorLike(m_c_And(m_Specific(LHS), m_Value(Y)), m_Deferred(Y))) &&
isGuaranteedNotToBeUndef(LHS, SQ.AC, SQ.CxtI, SQ.DT) &&
isGuaranteedNotToBeUndef(Y, SQ.AC, SQ.CxtI, SQ.DT))
return true;
@@ -690,7 +690,7 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred,
if (match(Y, m_APInt(Mask)))
Known.One |= *C & ~*Mask;
// assume(V ^ Mask = C)
- } else if (match(LHS, m_Xor(m_V, m_APInt(Mask))) &&
+ } else if (match(LHS, m_XorLike(m_V, m_APInt(Mask))) &&
match(RHS, m_APInt(C))) {
// Equivalent to assume(V == Mask ^ C)
Known = Known.unionWith(KnownBits::makeConstant(*C ^ *Mask));
@@ -954,7 +954,7 @@ getKnownBitsFromAndXorOr(const Operator *I, const APInt &DemandedElts,
// Demanded) == (xor(x, x-1) & Demanded). Extend the xor pattern
// to use arbitrary C if xor(x, x-C) as the same as xor(x, x-1).
if (HasKnownOne &&
- match(I, m_c_Xor(m_Value(X), m_Add(m_Deferred(X), m_AllOnes())))) {
+ match(I, m_c_XorLike(m_Value(X), m_Add(m_Deferred(X), m_AllOnes())))) {
const KnownBits &XBits = I->getOperand(0) == X ? KnownLHS : KnownRHS;
KnownOut = XBits.blsmsk();
}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index b253af0a828b61..e24fbc3ca927ef 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -767,10 +767,10 @@ static Value *checkForNegativeOperand(BinaryOperator &I,
if (match(LHS, m_Add(m_Value(X), m_One()))) {
// if XOR on other side, swap
- if (match(RHS, m_Xor(m_Value(Y), m_APInt(C1))))
+ if (match(RHS, m_XorLike(m_Value(Y), m_APInt(C1))))
std::swap(X, RHS);
- if (match(X, m_Xor(m_Value(Y), m_APInt(C1)))) {
+ if (match(X, m_XorLike(m_Value(Y), m_APInt(C1)))) {
// X = XOR(Y, C1), Y = OR(Z, C2), C2 = NOT(C1) ==> X == NOT(AND(Z, C1))
// ADD(ADD(X, 1), RHS) == ADD(X, ADD(RHS, 1)) == SUB(RHS, AND(Z, C1))
if (match(Y, m_Or(m_Value(Z), m_APInt(C2))) && (*C2 == ~(*C1))) {
@@ -790,13 +790,13 @@ static Value *checkForNegativeOperand(BinaryOperator &I,
RHS = I.getOperand(1);
// if XOR is on other side, swap
- if (match(RHS, m_Xor(m_Value(Y), m_APInt(C1))))
+ if (match(RHS, m_XorLike(m_Value(Y), m_APInt(C1))))
std::swap(LHS, RHS);
// C2 is ODD
// LHS = XOR(Y, C1), Y = AND(Z, C2), C1 == (C2 + 1) => LHS == NEG(OR(Z, ~C2))
// ADD(LHS, RHS) == SUB(RHS, OR(Z, ~C2))
- if (match(LHS, m_Xor(m_Value(Y), m_APInt(C1))))
+ if (match(LHS, m_XorLike(m_Value(Y), m_APInt(C1))))
if (C1->countr_zero() == 0)
if (match(Y, m_And(m_Value(Z), m_APInt(C2))) && *C1 == (*C2 + 1)) {
Value *NewOr = Builder.CreateOr(Z, ~(*C2));
@@ -937,11 +937,11 @@ Instruction *InstCombinerImpl::foldAddWithConstant(BinaryOperator &Add) {
// Is this add the last step in a convoluted sext?
// add(zext(xor i16 X, -32768), -32768) --> sext X
- if (match(Op0, m_ZExt(m_Xor(m_Value(X), m_APInt(C2)))) &&
+ if (match(Op0, m_ZExt(m_XorLike(m_Value(X), m_APInt(C2)))) &&
C2->isMinSignedValue() && C2->sext(Ty->getScalarSizeInBits()) == *C)
return CastInst::Create(Instruction::SExt, X, Ty);
- if (match(Op0, m_Xor(m_Value(X), m_APInt(C2)))) {
+ if (match(Op0, m_XorLike(m_Value(X), m_APInt(C2)))) {
// (X ^ signmask) + C --> (X + (signmask ^ C))
if (C2->isSignMask())
return BinaryOperator::CreateAdd(X, ConstantInt::get(Ty, *C2 ^ *C));
@@ -1685,7 +1685,7 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
// (add (xor A, B) (and A, B)) --> (or A, B)
// (add (and A, B) (xor A, B)) --> (or A, B)
- if (match(&I, m_c_BinOp(m_Xor(m_Value(A), m_Value(B)),
+ if (match(&I, m_c_BinOp(m_XorLike(m_Value(A), m_Value(B)),
m_c_And(m_Deferred(A), m_Deferred(B)))))
return BinaryOperator::CreateOr(A, B);
@@ -1848,7 +1848,7 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
m_c_Add(
m_ZExt(m_ICmp(Pred, m_Intrinsic<Intrinsic::ctpop>(m_Value(A)),
m_One())),
- m_OneUse(m_ZExtOrSelf(m_OneUse(m_Xor(
+ m_OneUse(m_ZExtOrSelf(m_OneUse(m_XorLike(
m_OneUse(m_TruncOrSelf(m_OneUse(
m_Intrinsic<Intrinsic::ctlz>(m_Deferred(A), m_One())))),
m_APInt(XorC))))))) &&
@@ -2492,7 +2492,7 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
// (sub (or A, B), (xor A, B)) --> (and A, B)
{
Value *A, *B;
- if (match(Op1, m_Xor(m_Value(A), m_Value(B))) &&
+ if (match(Op1, m_XorLike(m_Value(A), m_Value(B))) &&
match(Op0, m_c_Or(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateAnd(A, B);
}
@@ -2500,7 +2500,7 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
// (sub (xor A, B) (or A, B)) --> neg (and A, B)
{
Value *A, *B;
- if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
+ if (match(Op0, m_XorLike(m_Value(A), m_Value(B))) &&
match(Op1, m_c_Or(m_Specific(A), m_Specific(B))) &&
(Op0->hasOneUse() || Op1->hasOneUse()))
return BinaryOperator::CreateNeg(Builder.CreateAnd(A, B));
@@ -2538,7 +2538,7 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
// (sub (sext C), (xor X, (sext C))) => (select C, X, (neg X))
Value *C, *X;
auto m_SubXorCmp = [&C, &X](Value *LHS, Value *RHS) {
- return match(LHS, m_OneUse(m_c_Xor(m_Value(X), m_Specific(RHS)))) &&
+ return match(LHS, m_OneUse(m_c_XorLike(m_Value(X), m_Specific(RHS)))) &&
match(RHS, m_SExt(m_Value(C))) &&
(C->getType()->getScalarSizeInBits() == 1);
};
@@ -2673,7 +2673,7 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
unsigned BitWidth = Ty->getScalarSizeInBits();
if (match(Op1, m_AShr(m_Value(A), m_APInt(ShAmt))) &&
Op1->hasNUses(2) && *ShAmt == BitWidth - 1 &&
- match(Op0, m_OneUse(m_c_Xor(m_Specific(A), m_Specific(Op1))))) {
+ match(Op0, m_OneUse(m_c_XorLike(m_Specific(A), m_Specific(Op1))))) {
// B = ashr i32 A, 31 ; smear the sign bit
// sub (xor A, B), B ; flip bits if negative and subtract -1 (add 1)
// --> (A < 0) ? -A : A
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index f82a557e5760c8..ced3677431acd9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1183,8 +1183,8 @@ Value *InstCombinerImpl::foldEqOfParts(Value *Cmp0, Value *Cmp1, bool IsAnd) {
// icmp ne (and x, 1), (and y, 1) <=> trunc (xor x, y) to i1
// icmp eq (and x, 1), (and y, 1) <=> not (trunc (xor x, y) to i1)
if (Pred == CmpInst::ICMP_NE
- ? match(CmpV, m_Trunc(m_Xor(m_Value(X), m_Value(Y))))
- : match(CmpV, m_Not(m_Trunc(m_Xor(m_Value(X), m_Value(Y))))))
+ ? match(CmpV, m_Trunc(m_XorLike(m_Value(X), m_Value(Y))))
+ : match(CmpV, m_Not(m_Trunc(m_XorLike(m_Value(X), m_Value(Y))))))
return {{OpNo == 0 ? X : Y, 0, 1}};
auto *Cmp = dyn_cast<ICmpInst>(CmpV);
@@ -1199,7 +1199,7 @@ Value *InstCombinerImpl::foldEqOfParts(Value *Cmp0, Value *Cmp1, bool IsAnd) {
// (icmp ult (xor x, y), 1 << C) so also look for that.
if (Pred == CmpInst::ICMP_EQ && Cmp->getPredicate() == CmpInst::ICMP_ULT) {
if (!match(Cmp->getOperand(1), m_Power2(C)) ||
- !match(Cmp->getOperand(0), m_Xor(m_Value(), m_Value())))
+ !match(Cmp->getOperand(0), m_XorLike(m_Value(), m_Value())))
return std::nullopt;
}
@@ -1208,7 +1208,7 @@ Value *InstCombinerImpl::foldEqOfParts(Value *Cmp0, Value *Cmp1, bool IsAnd) {
else if (Pred == CmpInst::ICMP_NE &&
Cmp->getPredicate() == CmpInst::ICMP_UGT) {
if (!match(Cmp->getOperand(1), m_LowBitMask(C)) ||
- !match(Cmp->getOperand(0), m_Xor(m_Value(), m_Value())))
+ !match(Cmp->getOperand(0), m_XorLike(m_Value(), m_Value())))
return std::nullopt;
} else {
return std::nullopt;
@@ -1914,7 +1914,7 @@ static Instruction *foldOrToXor(BinaryOperator &I,
// (A ^ B) | ~(A | B) --> ~(A & B)
// (A ^ B) | ~(B | A) --> ~(A & B)
if (Op0->hasOneUse() || Op1->hasOneUse())
- if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
+ if (match(Op0, m_XorLike(m_Value(A), m_Value(B))) &&
match(Op1, m_Not(m_c_Or(m_Specific(A), m_Specific(B)))))
return BinaryOperator::CreateNot(Builder.CreateAnd(A, B));
@@ -2058,7 +2058,7 @@ static Instruction *foldComplexAndOrPatterns(BinaryOperator &I,
match(Op1, m_OneUse(m_Not(m_CombineAnd(
m_Value(Y),
m_c_BinOp(Opcode, m_Specific(C),
- m_c_Xor(m_Specific(A), m_Specific(B)))))))) {
+ m_c_XorLike(m_Specific(A), m_Specific(B)))))))) {
// X = ~(A | B)
// Y = (C | (A ^ B)
Value *Or = cast<BinaryOperator>(X)->getOperand(0);
@@ -2427,7 +2427,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
if (match(Op1, m_APInt(C))) {
const APInt *XorC;
- if (match(Op0, m_OneUse(m_Xor(m_Value(X), m_APInt(XorC))))) {
+ if (match(Op0, m_OneUse(m_XorLike(m_Value(X), m_APInt(XorC))))) {
// (X ^ C1) & C2 --> (X & C2) ^ (C1&C2)
Constant *NewC = ConstantInt::get(Ty, *C & *XorC);
Value *And = Builder.CreateAnd(X, Op1);
@@ -2543,7 +2543,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
// This is intentionally placed after the narrowing transforms for
// efficiency (transform directly to the narrow logic op if possible).
// If the mask is only needed on one incoming arm, push the 'and' op up.
- if (match(Op0, m_OneUse(m_Xor(m_Value(X), m_Value(Y)))) ||
+ if (match(Op0, m_OneUse(m_XorLike(m_Value(X), m_Value(Y)))) ||
match(Op0, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
APInt NotAndMask(~(*C));
BinaryOperator::BinaryOps BinOp = cast<BinaryOperator>(Op0)->getOpcode();
@@ -2676,15 +2676,15 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
{
Value *A, *B, *C;
// A & ~(A ^ B) --> A & B
- if (match(Op1, m_Not(m_c_Xor(m_Specific(Op0), m_Value(B)))))
+ if (match(Op1, m_Not(m_c_XorLike(m_Specific(Op0), m_Value(B)))))
return BinaryOperator::CreateAnd(Op0, B);
// ~(A ^ B) & A --> A & B
- if (match(Op0, m_Not(m_c_Xor(m_Specific(Op1), m_Value(B)))))
+ if (match(Op0, m_Not(m_c_XorLike(m_Specific(Op1), m_Value(B)))))
return BinaryOperator::CreateAnd(Op1, B);
// (A ^ B) & ((B ^ C) ^ A) -> (A ^ B) & ~C
- if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
- match(Op1, m_Xor(m_Xor(m_Specific(B), m_Value(C)), m_Specific(A)))) {
+ if (match(Op0, m_XorLike(m_Value(A), m_Value(B))) &&
+ match(Op1, m_XorLike(m_XorLike(m_Specific(B), m_Value(C)), m_Specific(A)))) {
Value *NotC = Op1->hasOneUse()
? Builder.CreateNot(C)
: getFreelyInverted(C, C->hasOneUse(), &Builder);
@@ -2693,8 +2693,8 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
}
// ((A ^ C) ^ B) & (B ^ A) -> (B ^ A) & ~C
- if (match(Op0, m_Xor(m_Xor(m_Value(A), m_Value(C)), m_Value(B))) &&
- match(Op1, m_Xor(m_Specific(B), m_Specific(A)))) {
+ if (match(Op0, m_XorLike(m_XorLike(m_Value(A), m_Value(C)), m_Value(B))) &&
+ match(Op1, m_XorLike(m_Specific(B), m_Specific(A)))) {
Value *NotC = Op0->hasOneUse()
? Builder.CreateNot(C)
: getFreelyInverted(C, C->hasOneUse(), &Builder);
@@ -2706,7 +2706,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
// (A | B) & (B ^ ~A) -> A & B
// (B | A) & (~A ^ B) -> A & B
// (B | A) & (B ^ ~A) -> A & B
- if (match(Op1, m_c_Xor(m_Not(m_Value(A)), m_Value(B))) &&
+ if (match(Op1, m_c_XorLike(m_Not(m_Value(A)), m_Value(B))) &&
match(Op0, m_c_Or(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateAnd(A, B);
@@ -2714,7 +2714,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
// (~A ^ B) & (B | A) -> A & B
// (B ^ ~A) & (A | B) -> A & B
// (B ^ ~A) & (B | A) -> A & B
- if (match(Op0, m_c_Xor(m_Not(m_Value(A)), m_Value(B))) &&
+ if (match(Op0, m_c_XorLike(m_Not(m_Value(A)), m_Value(B))) &&
match(Op1, m_c_Or(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateAnd(A, B);
@@ -2723,7 +2723,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
// (B | ~A) & (A ^ B) -> ~A & B
// (B | ~A) & (B ^ A) -> ~A & B
if (match(Op0, m_c_Or(m_Not(m_Value(A)), m_Value(B))) &&
- match(Op1, m_c_Xor(m_Specific(A), m_Specific(B))))
+ match(Op1, m_c_XorLike(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateAnd(Builder.CreateNot(A), B);
// (A ^ B) & (~A | B) -> ~A & B
@@ -2731,7 +2731,7 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
// (A ^ B) & (B | ~A) -> ~A & B
// (B ^ A) & (B | ~A) -> ~A & B
if (match(Op1, m_c_Or(m_Not(m_Value(A)), m_Value(B))) &&
- match(Op0, m_c_Xor(m_Specific(A), m_Specific(B))))
+ match(Op0, m_c_XorLike(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateAnd(Builder.CreateNot(A), B);
}
@@ -3200,8 +3200,8 @@ Value *InstCombinerImpl::getSelectCondition(Value *A, Value *B,
// If both operands are xor'd with constants using the same sexted boolean
// operand, see if the constants are inverse bitmasks.
// TODO: Use ConstantExpr::getNot()?
- if (match(A, (m_Xor(m_SExt(m_Value(Cond)), m_Constant(AConst)))) &&
- match(B, (m_Xor(m_SExt(m_Specific(Cond)), m_Constant(BConst)))) &&
+ if (match(A, (m_XorLike(m_SExt(m_Value(Cond)), m_Constant(AConst)))) &&
+ match(B, (m_XorLike(m_SExt(m_Specific(Cond)), m_Constant(BConst)))) &&
Cond->getType()->isIntOrIntVectorTy(1) &&
areInverseVectorBitmasks(AConst, BConst)) {
AConst = ConstantExpr::getTrunc(AConst, CmpInst::makeCmpResultType(Ty));
@@ -3623,7 +3623,7 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
Value *X, *Y;
const APInt *CV;
- if (match(&I, m_c_Or(m_OneUse(m_Xor(m_Value(X), m_APInt(CV))), m_Value(Y))) &&
+ if (match(&I, m_c_Or(m_OneUse(m_XorLike(m_Value(X), m_APInt(CV))), m_Value(Y))) &&
!CV->isAllOnes() && MaskedValueIsZero(Y, *CV, 0, &I)) {
// (X ^ C) | Y -> (X | Y) ^ C iff Y & C == 0
// The check for a 'not' op is for efficiency (if Y is known zero --> ~X).
@@ -3657,10 +3657,10 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
return BinaryOperator::CreateOr(Builder.CreateAnd(X, *C1), A);
// ((X ^ B) & MaskC) | (B & ~MaskC) -> (X & MaskC) ^ B
- if (match(A, m_c_Xor(m_Value(X), m_Specific(B))))
+ if (match(A, m_c_XorLike(m_Value(X), m_Specific(B))))
return BinaryOperator::CreateXor(Builder.CreateAnd(X, *C0), B);
// (A & MaskC) | ((X ^ A) & ~MaskC) -> (X & ~MaskC) ^ A
- if (match(B, m_c_Xor(m_Specific(A), m_Value(X))))
+ if (match(B, m_c_XorLike(m_Specific(A), m_Value(X))))
return BinaryOperator::CreateXor(Builder.CreateAnd(X, *C1), A);
}
@@ -3731,17 +3731,17 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
}
// (A ^ B) | ((B ^ C) ^ A) -> (A ^ B) | C
- if (match(Op0, m_Xor(m_Value(A), m_Value(B))))
+ if (match(Op0, m_XorLike(m_Value(A), m_Value(B))))
if (match(Op1,
- m_c_Xor(m_c_Xor(m_Specific(B), m_Value(C)), m_Specific(A))) ||
- match(Op1, m_c_Xor(m_c_Xor(m_Specific(A), m_Value(C)), m_Specific(B))))
+ m_c_XorLike(m_c_XorLike(m_Specific(B), m_Value(C)), m_Specific(A))) ||
+ match(Op1, m_c_XorLike(m_c_XorLike(m_Specific(A), m_Value(C)), m_Specific(B))))
return BinaryOperator::CreateOr(Op0, C);
// ((B ^ C) ^ A) | (A ^ B) -> (A ^ B) | C
- if (match(Op1, m_Xor(m_Value(A), m_Value(B))))
+ if (match(Op1, m_XorLike(m_Value(A), m_Value(B))))
if (match(Op0,
- m_c_Xor(m_c_Xor(m_Specific(B), m_Value(C)), m_Specific(A))) ||
- match(Op0, m_c_Xor(m_c_Xor(m_Specific(A), m_Value(C)), m_Specific(B))))
+ m_c_XorLike(m_c_XorLike(m_Specific(B), m_Value(C)), m_Specific(A))) ||
+ match(Op0, m_c_XorLike(m_c_XorLike(m_Specific(A), m_Value(C)), m_Specific(B))))
return BinaryOperator::CreateOr(Op1, C);
if (Instruction *DeMorgan = matchDeMorgansLaws(I, *this))
@@ -3749,12 +3749,12 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
// Canonicalize xor to the RHS.
bool SwappedForXor = false;
- if (match(Op0, m_Xor(m_Value(), m_Value()))) {
+ if (match(Op0, m_XorLike(m_Value(), m_Value()))) {
std::swap(Op0, Op1);
SwappedForXor = true;
}
- if (match(Op1, m_Xor(m_Value(A), m_Value(B)))) {
+ if (match(Op1, m_XorLike(m_Value(A), m_Value(B)))) {
// (A | ?) | (A ^ B) --> (A | ?) | B
// (B | ?) | (A ^ B) --> (B | ?) | A
if (match(Op0, m_c_Or(m_Specific(A), m_Value())))
@@ -3881,9 +3881,9 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
// ((A & B) ^ B) | ((A & B) ^ A) -> A ^ B
// (B ^ (A & B)) | (A ^ (A & B)) -> A ^ B
const auto TryXorOpt = [&](Value *Lhs, Value *Rhs) -> Instruction * {
- if (match(Lhs, m_c_Xor(m_And(m_Value(A), m_Value(B)), m_Deferred(A))) &&
+ if (match(Lhs, m_c_XorLike(m_And(m_Value(A), m_Value(B)), m_Deferred(A))) &&
match(Rhs,
- m_c_Xor(m_And(m_Specific(A), m_Specific(B)), m_Specific(B)))) {
+ m_c_XorLike(m_And(m_Specific(A), m_Specific(B)), m_Specific(B)))) {
return BinaryOperator::CreateXor(A, B);
}
return nullptr;
@@ -4082,7 +4082,7 @@ static Instruction *foldXorToXor(BinaryOperator &I,
// (A & B) ^ (B | A) -> A ^ B
// (A | B) ^ (A & B) -> A ^ B
// (A | B) ^ (B & A) -> A ^ B
- if (match(&I, m_c_Xor(m_And(m_Value(A), m_Value(B)),
+ if (match(&I, m_c_XorLike(m_And(m_Value(A), m_Value(B)),
m_c_Or(m_Deferred(A), m_Deferred(B)))))
return BinaryOperator::CreateXor(A, B);
@@ -4090,7 +4090,7 @@ static Instruction *foldXorToXor(BinaryOperator &I,
// (~B | A) ^ (~A | B) -> A ^ B
// (~A | B) ^ (A | ~B) -> A ^ B
// (B | ~A) ^ (A | ~B) -> A ^ B
- if (match(&I, m_Xor(m_c_Or(m_Value(A), m_Not(m_Value(B))),
+ if (match(&I, m_XorLike(m_c_Or(m_Value(A), m_Not(m_Value(B))),
m_c_Or(m_Not(m_Deferred(A)), m_Deferred(B)))))
return BinaryOperator::CreateXor(A, B);
@@ -4098,7 +4098,7 @@ static Instruction *foldXorToXor(BinaryOperator &I,
// (~B & A) ^ (~A & B) -> A ^ B
// (~A & B) ^ (A & ~B) -> A ^ B
// (B & ~A) ^ (A & ~B) -> A ^ B
- if (match(&I, m_Xor(m_c_And(m_Value(A), m_Not(m_Value(B))),
+ if (match(&I, m_XorLike(m_c_And(m_Value(A), m_Not(m_Value(B))),
m_c_And(m_Not(m_Deferred(A)), m_Deferred(B)))))
return BinaryOperator::CreateXor(A, B);
@@ -4261,9 +4261,9 @@ static Instruction *visitMaskedMerge(BinaryOperator &I,
InstCombiner::BuilderTy &Builder) {
Value *B, *X, *D;
Value *M;
- if (!match(&I, m_c_Xor(m_Value(B),
+ if (!match(&I, m_c_XorLike(m_Value(B),
m_OneUse(m_c_And(
- m_CombineAnd(m_c_Xor(m_Deferred(B), m_Value(X)),
+ m_CombineAnd(m_c_XorLike(m_Deferred(B), m_Value(X)),
m_Value(D)),
m_Value(M))))))
return nullptr;
@@ -4295,7 +4295,7 @@ static Instruction *foldNotXor(BinaryOperator &I,
Value *X, *Y;
// FIXME: one-use check is not needed in general, but currently we are unable
// to fold 'not' into 'icmp', if that 'icmp' has multiple uses. (D35182)
- if (!match(&I, m_Not(m_OneUse(m_Xor(m_Value(X), m_Value(Y))))))
+ if (!match(&I, m_Not(m_OneUse(m_XorLike(m_Value(X), m_Value(Y))))))
return nullptr;
auto hasCommonOperand = [](Value *A, Value *B, Value *C, Value *D) {
@@ -4689,7 +4689,7 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
// (X | Y) ^ M -> (X ^ M) ^ Y
// (X | Y) ^ M -> (Y ^ M) ^ X
- if (match(&I, m_c_Xor(m_OneUse(m_DisjointOr(m_Value(X), m_Value(Y))),
+ if (match(&I, m_c_XorLike(m_OneUse(m_DisjointOr(m_Value(X), m_Value(Y))),
m_Value(M)))) {
if (Value *XorAC = simplifyXorInst(X, M, SQ.getWithInstruction(&I)))
return BinaryOperator::CreateXor(XorAC, Y);
@@ -4702,7 +4702,7 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
// This it a special case in haveNoCommonBitsSet, but the computeKnownBits
// calls in there are unnecessary as SimplifyDemandedInstructionBits should
// have already taken care of those cases.
- if (match(&I, m_c_Xor(m_c_And(m_Not(m_Value(M)), m_Value()),
+ if (match(&I, m_c_XorLike(m_c_And(m_Not(m_Value(M)), m_Value()),
m_c_And(m_Deferred(M), m_Value())))) {
if (isGuaranteedNotToBeUndef(M))
return BinaryOperator::CreateDisjointOr(Op0, Op1);
@@ -4836,7 +4836,7 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
ConstantInt *C1, *C2, *C3;
// ((X^C1) >> C2) ^ C3 -> (X>>C2) ^ ((C1>>C2)^C3)
if (match(Op1, m_ConstantInt(C3)) &&
- match(Op0, m_LShr(m_Xor(m_Value(X), m_ConstantInt(C1)),
+ match(Op0, m_LShr(m_XorLike(m_Value(X), m_ConstantInt(C1)),
m_ConstantInt(C2))) &&
Op0->hasOneUse()) {
// fold (C1 >> C2) ^ C3
@@ -4876,23 +4876,23 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
Value *A, *B, *C;
// (A ^ B) ^ (A | C) --> (~A & C) ^ B -- There are 4 commuted variants.
- if (match(&I, m_c_Xor(m_OneUse(m_Xor(m_Value(A), m_Value(B))),
+ if (match(&I, m_c_XorLike(m_OneUse(m_XorLike(m_Value(A), m_Value(B))),
m_OneUse(m_c_Or(m_Deferred(A), m_Value(C))))))
return BinaryOperator::CreateXor(
Builder.CreateAnd(Builder.CreateNot(A), C), B);
// (A ^ B) ^ (B | C) --> (~B & C) ^ A -- There are 4 commuted variants.
- if (match(&I, m_c_Xor(m_OneUse(m_Xor(m_Value(A), m_Value(B))),
+ if (match(&I, m_c_XorLike(m_OneUse(m_XorLike(m_Value(A), m_Value(B))),
m_OneUse(m_c_Or(m_Deferred(B), m_Value(C))))))
return BinaryOperator::CreateXor(
Builder.CreateAnd(Builder.CreateNot(B), C), A);
// (A & B) ^ (A ^ B) -> (A | B)
if (match(Op0, m_And(m_Value(A), m_Value(B))) &&
- match(Op1, m_c_Xor(m_Specific(A), m_Specific(B))))
+ match(Op1, m_c_XorLike(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateOr(A, B);
// (A ^ B) ^ (A & B) -> (A | B)
- if (match(Op0, m_Xor(m_Value(A), m_Value(B))) &&
+ if (match(Op0, m_XorLike(m_Value(A), m_Value(B))) &&
match(Op1, m_c_And(m_Specific(A), m_Specific(B))))
return BinaryOperator::CreateOr(A, B);
@@ -4903,7 +4903,7 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
return BinaryOperator::CreateNot(Builder.CreateAnd(A, B));
// (~A & B) ^ A --> A | B -- There are 4 commuted variants.
- if (match(&I, m_c_Xor(m_c_And(m_Not(m_Value(A)), m_Value(B)), m_Deferred(A))))
+ if (match(&I, m_c_XorLike(m_c_And(m_Not(m_Value(A)), m_Value(B)), m_Deferred(A))))
return BinaryOperator::CreateOr(A, B);
// (~A | B) ^ A --> ~(A & B)
@@ -4931,7 +4931,7 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
// (A & B) ^ (A | C) --> A ? ~B : C -- There are 4 commuted variants.
if (I.getType()->isIntOrIntVectorTy(1) &&
- match(&I, m_c_Xor(m_OneUse(m_LogicalAnd(m_Value(A), m_Value(B))),
+ match(&I, m_c_XorLike(m_OneUse(m_LogicalAnd(m_Value(A), m_Value(B))),
m_OneUse(m_LogicalOr(m_Value(C), m_Value(D)))))) {
bool NeedFreeze = isa<SelectInst>(Op0) && isa<SelectInst>(Op1) && B == D;
if (B == C || B == D)
@@ -4961,7 +4961,7 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
// (X ^ C) ^ Y --> (X ^ Y) ^ C
// Just like we do in other places, we completely avoid the fold
// for constantexprs, at least to avoid endless combine loop.
- if (match(&I, m_c_Xor(m_OneUse(m_Xor(m_CombineAnd(m_Value(X),
+ if (match(&I, m_c_XorLike(m_OneUse(m_XorLike(m_CombineAnd(m_Value(X),
m_Unless(m_ConstantExpr())),
m_ImmConstant(C1))),
m_Value(Y))))
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index c55c40c88bc845..f74e2a2bc99279 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1908,8 +1908,8 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// -> (and X, ~Neg_Pow2)
// (smin X, (xor X, Neg_Pow2))
// -> (or X, Neg_Pow2)
- if ((match(I0, m_c_Xor(m_Specific(I1), m_Value(X))) ||
- match(I1, m_c_Xor(m_Specific(I0), m_Value(X)))) &&
+ if ((match(I0, m_c_XorLike(m_Specific(I1), m_Value(X))) ||
+ match(I1, m_c_XorLike(m_Specific(I0), m_Value(X)))) &&
isKnownToBeAPowerOfTwo(X, /* OrZero */ true)) {
bool UseOr = IID == Intrinsic::smax || IID == Intrinsic::umax;
bool UseAndN = IID == Intrinsic::smin || IID == Intrinsic::umin;
@@ -2989,7 +2989,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// Try to use the builtin XOR in AESE and AESD to eliminate a prior XOR
Value *Data, *Key;
if (match(KeyArg, m_ZeroInt()) &&
- match(DataArg, m_Xor(m_Value(Data), m_Value(Key)))) {
+ match(DataArg, m_XorLike(m_Value(Data), m_Value(Key)))) {
replaceOperand(*II, 0, Data);
replaceOperand(*II, 1, Key);
return II;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
index 4ec1af394464bb..417dbcafa028c7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
@@ -832,7 +832,7 @@ Instruction *InstCombinerImpl::visitTrunc(TruncInst &Trunc) {
if (Trunc.hasNoUnsignedWrap() || Trunc.hasNoSignedWrap()) {
Value *X, *Y;
- if (match(Src, m_Xor(m_Value(X), m_Value(Y))))
+ if (match(Src, m_XorLike(m_Value(X), m_Value(Y))))
return new ICmpInst(ICmpInst::ICMP_NE, X, Y);
}
}
@@ -1280,7 +1280,7 @@ Instruction *InstCombinerImpl::visitZExt(ZExtInst &Zext) {
// zext((trunc(X) & C) ^ C) -> ((X & zext(C)) ^ zext(C)).
Value *And;
- if (match(Src, m_OneUse(m_Xor(m_Value(And), m_Constant(C)))) &&
+ if (match(Src, m_OneUse(m_XorLike(m_Value(And), m_Constant(C)))) &&
match(And, m_OneUse(m_And(m_Trunc(m_Value(X)), m_Specific(C)))) &&
X->getType() == DestTy) {
Value *ZC = Builder.CreateZExt(C, DestTy);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 2e457257599493..a02789cd05dae7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1662,7 +1662,7 @@ Instruction *InstCombinerImpl::foldICmpXorShiftConst(ICmpInst &Cmp,
return nullptr;
Value *X;
const APInt *ShiftC;
- if (!match(Xor, m_OneUse(m_c_Xor(m_Value(X),
+ if (!match(Xor, m_OneUse(m_c_XorLike(m_Value(X),
m_AShr(m_Deferred(X), m_APInt(ShiftC))))))
return nullptr;
uint64_t Shift = ShiftC->getLimitedValue();
@@ -2045,7 +2045,7 @@ static Value *foldICmpOrXorSubChain(ICmpInst &Cmp, BinaryOperator *Or,
Value *Lhs, *Rhs;
if (match(OrOperatorArgument,
- m_OneUse(m_Xor(m_Value(Lhs), m_Value(Rhs))))) {
+ m_OneUse(m_XorLike(m_Value(Lhs), m_Value(Rhs))))) {
CmpValues.emplace_back(Lhs, Rhs);
return;
}
@@ -4360,10 +4360,10 @@ static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q,
// (X ^ -X) is a ~Mask
if (Not)
- return match(V, m_c_Xor(m_Value(X), m_Neg(m_Deferred(X))));
+ return match(V, m_c_XorLike(m_Value(X), m_Neg(m_Deferred(X))));
// (X ^ (X - 1)) is a Mask
else
- return match(V, m_c_Xor(m_Value(X), m_Add(m_Deferred(X), m_AllOnes())));
+ return match(V, m_c_XorLike(m_Value(X), m_Add(m_Deferred(X), m_AllOnes())));
case Instruction::Select:
// c ? Mask0 : Mask1 is a Mask.
return isMaskOrZero(I->getOperand(1), Not, Q, Depth) &&
@@ -5013,11 +5013,11 @@ static Instruction *foldICmpXorXX(ICmpInst &I, const SimplifyQuery &Q,
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *A;
// Normalize xor operand as operand 0.
CmpInst::Predicate Pred = I.getPredicate();
- if (match(Op1, m_c_Xor(m_Specific(Op0), m_Value()))) {
+ if (match(Op1, m_c_XorLike(m_Specific(Op0), m_Value()))) {
std::swap(Op0, Op1);
Pred = ICmpInst::getSwappedPredicate(Pred);
}
- if (!match(Op0, m_c_Xor(m_Specific(Op1), m_Value(A))))
+ if (!match(Op0, m_c_XorLike(m_Specific(Op1), m_Value(A))))
return nullptr;
// icmp (X ^ Y_NonZero) u>= X --> icmp (X ^ Y_NonZero) u> X
@@ -5720,12 +5720,12 @@ static Instruction *foldICmpPow2Test(ICmpInst &I,
// ((A-1) ^ A) u< A --> ctpop(A) > 1 (two commuted variants)
if ((Pred == ICmpInst::ICMP_UGE || Pred == ICmpInst::ICMP_ULT) &&
- match(Op0, m_OneUse(m_c_Xor(m_Add(m_Specific(Op1), m_AllOnes()),
+ match(Op0, m_OneUse(m_c_XorLike(m_Add(m_Specific(Op1), m_AllOnes()),
m_Specific(Op1))))) {
A = Op1;
CheckIs = Pred == ICmpInst::ICMP_UGE;
} else if ((Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_ULE) &&
- match(Op1, m_OneUse(m_c_Xor(m_Add(m_Specific(Op0), m_AllOnes()),
+ match(Op1, m_OneUse(m_c_XorLike(m_Add(m_Specific(Op0), m_AllOnes()),
m_Specific(Op0))))) {
A = Op0;
CheckIs = Pred == ICmpInst::ICMP_ULE;
@@ -5751,13 +5751,13 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
const CmpInst::Predicate Pred = I.getPredicate();
Value *A, *B, *C, *D;
- if (match(Op0, m_Xor(m_Value(A), m_Value(B)))) {
+ if (match(Op0, m_XorLike(m_Value(A), m_Value(B)))) {
if (A == Op1 || B == Op1) { // (A^B) == A -> B == 0
Value *OtherVal = A == Op1 ? B : A;
return new ICmpInst(Pred, OtherVal, Constant::getNullValue(A->getType()));
}
- if (match(Op1, m_Xor(m_Value(C), m_Value(D)))) {
+ if (match(Op1, m_XorLike(m_Value(C), m_Value(D)))) {
// A^c1 == C^c2 --> A == C^(c1^c2)
ConstantInt *C1, *C2;
if (match(B, m_ConstantInt(C1)) && match(D, m_ConstantInt(C2)) &&
@@ -5779,7 +5779,7 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
}
}
- if (match(Op1, m_Xor(m_Value(A), m_Value(B))) && (A == Op0 || B == Op0)) {
+ if (match(Op1, m_XorLike(m_Value(A), m_Value(B))) && (A == Op0 || B == Op0)) {
// A == (A^B) -> B == 0
Value *OtherVal = A == Op0 ? B : A;
return new ICmpInst(Pred, OtherVal, Constant::getNullValue(A->getType()));
@@ -5961,7 +5961,7 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
// Canonicalize:
// icmp eq/ne OneUse(A ^ Cst), B --> icmp eq/ne (A ^ B), Cst
Constant *Cst;
- if (match(&I, m_c_ICmp(m_OneUse(m_Xor(m_Value(A), m_ImmConstant(Cst))),
+ if (match(&I, m_c_ICmp(m_OneUse(m_XorLike(m_Value(A), m_ImmConstant(Cst))),
m_CombineAnd(m_Value(B), m_Unless(m_ImmConstant())))))
return new ICmpInst(Pred, Builder.CreateXor(A, B), Cst);
@@ -5969,7 +5969,7 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) {
// (icmp eq/ne (and (add/sub/xor X, P2), P2), P2)
auto m_Matcher =
m_CombineOr(m_CombineOr(m_c_Add(m_Value(B), m_Deferred(A)),
- m_c_Xor(m_Value(B), m_Deferred(A))),
+ m_c_XorLike(m_Value(B), m_Deferred(A))),
m_Sub(m_Value(B), m_Deferred(A)));
std::optional<bool> IsZero = std::nullopt;
if (match(&I, m_c_ICmp(m_OneUse(m_c_And(m_Value(A), m_Matcher)),
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index f66a976ccb47fe..27ce207de082ba 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1141,7 +1141,7 @@ static Instruction *foldSelectCtlzToCttz(ICmpInst *ICI, Value *TrueVal,
Value *Ctlz;
if (!match(FalseVal,
- m_Xor(m_Value(Ctlz), m_SpecificInt(BitWidth - 1))))
+ m_XorLike(m_Value(Ctlz), m_SpecificInt(BitWidth - 1))))
return nullptr;
if (!match(Ctlz, m_Intrinsic<Intrinsic::ctlz>()))
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 2fb60ef11499c7..a27d448dd4c546 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2612,7 +2612,7 @@ Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
// If `V` is of the form `A ^ ~B` then `~(A ^ ~B)` can be folded
// into `A ^ B` if we are willing to invert all of the uses.
- if (match(V, m_Xor(m_Value(A), m_Value(B)))) {
+ if (match(V, m_XorLike(m_Value(A), m_Value(B)))) {
if (auto *BV = getFreelyInvertedImpl(B, B->hasOneUse(), Builder,
DoesConsume, Depth))
return Builder ? Builder->CreateXor(A, BV) : NonNull;
More information about the llvm-commits
mailing list