[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:30:14 PST 2025


github-actions[bot] wrote:

<!--LLVM CODE FORMAT COMMENT: {clang-format}-->


:warning: C/C++ code formatter, clang-format found issues in your code. :warning:

<details>
<summary>
You can test this locally with the following command:
</summary>

``````````bash
git-clang-format --diff 8a1174f06cb69c92290a2231ede0e2a8e8460e0c 8ee0ed1e361809d2cfb3c59ab777b2351c1ab191 --extensions cpp,h -- llvm/include/llvm/IR/PatternMatch.h llvm/lib/Analysis/InstructionSimplify.cpp llvm/lib/Analysis/ValueTracking.cpp llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
``````````

</details>

<details>
<summary>
View the diff from clang-format here.
</summary>

``````````diff
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index f6af0dcb65..f8e2cf05cd 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2155,8 +2155,8 @@ static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
   // ((X | Y) ^ Y ) & ((X | Y) ^ X) --> 0
   BinaryOperator *Or;
   if (match(Op0, m_c_XorLike(m_Value(X),
-                         m_CombineAnd(m_BinOp(Or),
-                                      m_c_Or(m_Deferred(X), m_Value(Y))))) &&
+                             m_CombineAnd(m_BinOp(Or), m_c_Or(m_Deferred(X),
+                                                              m_Value(Y))))) &&
       match(Op1, m_c_XorLike(m_Specific(Or), m_Specific(Y))))
     return Constant::getNullValue(Op0->getType());
 
@@ -5097,7 +5097,8 @@ static Value *simplifyGEPInst(Type *SrcTy, Value *Ptr,
       }
       // gep (gep V, C), (xor V, -1) -> C-1
       if (match(Indices.back(),
-                m_XorLike(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/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index e24fbc3ca9..9e907eaa73 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2671,8 +2671,8 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
   const APInt *ShAmt;
   Type *Ty = I.getType();
   unsigned BitWidth = Ty->getScalarSizeInBits();
-  if (match(Op1, m_AShr(m_Value(A), m_APInt(ShAmt))) &&
-      Op1->hasNUses(2) && *ShAmt == BitWidth - 1 &&
+  if (match(Op1, m_AShr(m_Value(A), m_APInt(ShAmt))) && Op1->hasNUses(2) &&
+      *ShAmt == BitWidth - 1 &&
       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)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index ced3677431..1f574ff9d7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2056,9 +2056,9 @@ static Instruction *foldComplexAndOrPatterns(BinaryOperator &I,
     // (~(A & B) | C) & ~(C & (A ^ B)) --> (A ^ B ^ C) | ~(A | C) is invalid.
     if (Opcode == Instruction::Or && Op0->hasOneUse() &&
         match(Op1, m_OneUse(m_Not(m_CombineAnd(
-                       m_Value(Y),
-                       m_c_BinOp(Opcode, m_Specific(C),
-                                 m_c_XorLike(m_Specific(A), m_Specific(B)))))))) {
+                       m_Value(Y), m_c_BinOp(Opcode, m_Specific(C),
+                                             m_c_XorLike(m_Specific(A),
+                                                         m_Specific(B)))))))) {
       // X = ~(A | B)
       // Y = (C | (A ^ B)
       Value *Or = cast<BinaryOperator>(X)->getOperand(0);
@@ -2684,7 +2684,8 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
 
     // (A ^ B) & ((B ^ C) ^ A) -> (A ^ B) & ~C
     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)))) {
+        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);
@@ -3623,7 +3624,8 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
 
   Value *X, *Y;
   const APInt *CV;
-  if (match(&I, m_c_Or(m_OneUse(m_XorLike(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).
@@ -3732,16 +3734,18 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
 
   // (A ^ B) | ((B ^ C) ^ A) -> (A ^ B) | C
   if (match(Op0, m_XorLike(m_Value(A), m_Value(B))))
-    if (match(Op1,
-              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))))
+    if (match(Op1, 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_XorLike(m_Value(A), m_Value(B))))
-    if (match(Op0,
-              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))))
+    if (match(Op0, 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))
@@ -3881,9 +3885,10 @@ 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_XorLike(m_And(m_Value(A), m_Value(B)), m_Deferred(A))) &&
-          match(Rhs,
-                m_c_XorLike(m_And(m_Specific(A), m_Specific(B)), m_Specific(B)))) {
+      if (match(Lhs,
+                m_c_XorLike(m_And(m_Value(A), m_Value(B)), m_Deferred(A))) &&
+          match(Rhs, m_c_XorLike(m_And(m_Specific(A), m_Specific(B)),
+                                 m_Specific(B)))) {
         return BinaryOperator::CreateXor(A, B);
       }
       return nullptr;
@@ -4083,7 +4088,7 @@ static Instruction *foldXorToXor(BinaryOperator &I,
   // (A | B) ^ (A & B) -> A ^ B
   // (A | B) ^ (B & A) -> A ^ B
   if (match(&I, m_c_XorLike(m_And(m_Value(A), m_Value(B)),
-                        m_c_Or(m_Deferred(A), m_Deferred(B)))))
+                            m_c_Or(m_Deferred(A), m_Deferred(B)))))
     return BinaryOperator::CreateXor(A, B);
 
   // (A | ~B) ^ (~A | B) -> A ^ B
@@ -4091,7 +4096,7 @@ static Instruction *foldXorToXor(BinaryOperator &I,
   // (~A | B) ^ (A | ~B) -> A ^ B
   // (B | ~A) ^ (A | ~B) -> A ^ 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)))))
+                          m_c_Or(m_Not(m_Deferred(A)), m_Deferred(B)))))
     return BinaryOperator::CreateXor(A, B);
 
   // (A & ~B) ^ (~A & B) -> A ^ B
@@ -4099,7 +4104,7 @@ static Instruction *foldXorToXor(BinaryOperator &I,
   // (~A & B) ^ (A & ~B) -> A ^ B
   // (B & ~A) ^ (A & ~B) -> A ^ 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)))))
+                          m_c_And(m_Not(m_Deferred(A)), m_Deferred(B)))))
     return BinaryOperator::CreateXor(A, B);
 
   // For the remaining cases we need to get rid of one of the operands.
@@ -4261,11 +4266,12 @@ static Instruction *visitMaskedMerge(BinaryOperator &I,
                                      InstCombiner::BuilderTy &Builder) {
   Value *B, *X, *D;
   Value *M;
-  if (!match(&I, m_c_XorLike(m_Value(B),
-                         m_OneUse(m_c_And(
-                             m_CombineAnd(m_c_XorLike(m_Deferred(B), m_Value(X)),
-                                          m_Value(D)),
-                             m_Value(M))))))
+  if (!match(&I, m_c_XorLike(
+                     m_Value(B),
+                     m_OneUse(m_c_And(
+                         m_CombineAnd(m_c_XorLike(m_Deferred(B), m_Value(X)),
+                                      m_Value(D)),
+                         m_Value(M))))))
     return nullptr;
 
   Value *NotM;
@@ -4690,7 +4696,7 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
   // (X | Y) ^ M -> (X ^ M) ^ Y
   // (X | Y) ^ M -> (Y ^ M) ^ X
   if (match(&I, m_c_XorLike(m_OneUse(m_DisjointOr(m_Value(X), m_Value(Y))),
-                        m_Value(M)))) {
+                            m_Value(M)))) {
     if (Value *XorAC = simplifyXorInst(X, M, SQ.getWithInstruction(&I)))
       return BinaryOperator::CreateXor(XorAC, Y);
 
@@ -4703,7 +4709,7 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
   // calls in there are unnecessary as SimplifyDemandedInstructionBits should
   // have already taken care of those cases.
   if (match(&I, m_c_XorLike(m_c_And(m_Not(m_Value(M)), m_Value()),
-                        m_c_And(m_Deferred(M), m_Value())))) {
+                            m_c_And(m_Deferred(M), m_Value())))) {
     if (isGuaranteedNotToBeUndef(M))
       return BinaryOperator::CreateDisjointOr(Op0, Op1);
     else
@@ -4877,15 +4883,15 @@ 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_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);
+                            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_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);
+                            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))) &&
@@ -4903,7 +4909,8 @@ 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_XorLike(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)
@@ -4932,7 +4939,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_XorLike(m_OneUse(m_LogicalAnd(m_Value(A), m_Value(B))),
-                        m_OneUse(m_LogicalOr(m_Value(C), m_Value(D)))))) {
+                            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)
       std::swap(A, B);
@@ -4961,10 +4968,11 @@ 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_XorLike(m_OneUse(m_XorLike(m_CombineAnd(m_Value(X),
-                                                    m_Unless(m_ConstantExpr())),
-                                       m_ImmConstant(C1))),
-                        m_Value(Y))))
+  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))))
     return BinaryOperator::CreateXor(Builder.CreateXor(X, Y), C1);
 
   if (Instruction *R = reassociateForUses(I, Builder))
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index a02789cd05..d3d571573f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -1662,8 +1662,8 @@ Instruction *InstCombinerImpl::foldICmpXorShiftConst(ICmpInst &Cmp,
     return nullptr;
   Value *X;
   const APInt *ShiftC;
-  if (!match(Xor, m_OneUse(m_c_XorLike(m_Value(X),
-                                   m_AShr(m_Deferred(X), m_APInt(ShiftC))))))
+  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();
   Type *XType = X->getType();
@@ -4363,7 +4363,8 @@ static bool isMaskOrZero(const Value *V, bool Not, const SimplifyQuery &Q,
       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_XorLike(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) &&
@@ -5721,12 +5722,13 @@ static Instruction *foldICmpPow2Test(ICmpInst &I,
 
     if ((Pred == ICmpInst::ICMP_UGE || Pred == ICmpInst::ICMP_ULT) &&
         match(Op0, m_OneUse(m_c_XorLike(m_Add(m_Specific(Op1), m_AllOnes()),
-                                    m_Specific(Op1))))) {
+                                        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_XorLike(m_Add(m_Specific(Op0), m_AllOnes()),
-                                           m_Specific(Op0))))) {
+               match(Op1,
+                     m_OneUse(m_c_XorLike(m_Add(m_Specific(Op0), m_AllOnes()),
+                                          m_Specific(Op0))))) {
       A = Op0;
       CheckIs = Pred == ICmpInst::ICMP_ULE;
     }
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 27ce207de0..5320a3271e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1140,8 +1140,7 @@ static Instruction *foldSelectCtlzToCttz(ICmpInst *ICI, Value *TrueVal,
     std::swap(TrueVal, FalseVal);
 
   Value *Ctlz;
-  if (!match(FalseVal,
-             m_XorLike(m_Value(Ctlz), m_SpecificInt(BitWidth - 1))))
+  if (!match(FalseVal, m_XorLike(m_Value(Ctlz), m_SpecificInt(BitWidth - 1))))
     return nullptr;
 
   if (!match(Ctlz, m_Intrinsic<Intrinsic::ctlz>()))

``````````

</details>


https://github.com/llvm/llvm-project/pull/122607


More information about the llvm-commits mailing list