diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index cd9a36029e6db..51ad1eed3a1c1 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 +struct XorLike_match { + LHS L; + RHS R; + + XorLike_match(const LHS &L, const RHS &R) : L(L), R(R) {} + + template bool match(OpTy *V) { + if (auto *Op = dyn_cast(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 +inline auto m_XorLike(const LHS &L, const RHS &R) { + return XorLike_match(L, R); +} + +template +inline auto m_c_XorLike(const LHS &L, const RHS &R) { + return XorLike_match(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 999386c0a0491..f6af0dcb6534d 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 4b246c013e96f..80729a46eaad9 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 73876d00e73a7..e24fbc3ca927e 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(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(m_Deferred(A), m_One())))), m_APInt(XorC))))))) && @@ -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) @@ -2502,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); } @@ -2510,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)); @@ -2548,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); }; @@ -2683,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 f82a557e5760c..ced3677431acd 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(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(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(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(Op0) && isa(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 c55c40c88bc84..f74e2a2bc9927 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 4ec1af394464b..417dbcafa028c 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 2e45725759949..a02789cd05dae 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 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 f66a976ccb47f..27ce207de082b 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())) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index 2fb60ef11499c..a27d448dd4c54 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; diff --git a/llvm/test/Transforms/InstCombine/sub-xor.ll b/llvm/test/Transforms/InstCombine/sub-xor.ll index a4135e0b51453..dc2113de546e5 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, @@ -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