[llvm] 4a66a1d - [InstCombine] allow vectors for masked-add -> xor fold

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 17 10:36:18 PST 2020


Author: Sanjay Patel
Date: 2020-11-17T13:36:08-05:00
New Revision: 4a66a1d17abfb7cf34081f0620cb2f53b40cca97

URL: https://github.com/llvm/llvm-project/commit/4a66a1d17abfb7cf34081f0620cb2f53b40cca97
DIFF: https://github.com/llvm/llvm-project/commit/4a66a1d17abfb7cf34081f0620cb2f53b40cca97.diff

LOG: [InstCombine] allow vectors for masked-add -> xor fold

https://rise4fun.com/Alive/I4Ge

  Name: add with pow2 mask
  Pre: isPowerOf2(C2) && (C1 & C2) != 0 && (C1 & (C2-1)) == 0
  %a = add i8 %x, C1
  %r = and i8 %a, C2
  =>
  %n = and i8 %x, C2
  %r = xor i8 %n, C2

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/lib/Transforms/InstCombine/InstCombineInternal.h
    llvm/test/Transforms/InstCombine/and.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index c8a45509e1dc..a12957979190 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -114,33 +114,6 @@ static Value *SimplifyBSwap(BinaryOperator &I,
   return Builder.CreateCall(F, BinOp);
 }
 
-/// This handles expressions of the form ((X + OpRHS) & AndRHS).
-Instruction *InstCombinerImpl::OptAndOp(BinaryOperator *Op, ConstantInt *AndRHS,
-                                        BinaryOperator &TheAnd) {
-  Value *X;
-  const APInt *C;
-  if (!match(Op, m_OneUse(m_Add(m_Value(X), m_APInt(C)))))
-    return nullptr;
-
-  // If there is only one bit set.
-  const APInt &AndRHSV = AndRHS->getValue();
-  if (AndRHSV.isPowerOf2()) {
-    // Ok, at this point, we know that we are masking the result of the
-    // ADD down to exactly one bit.  If the constant we are adding has
-    // no bits set below this bit, then we can eliminate the ADD.
-    // Check to see if any bits below the one bit set in AndRHSV are set.
-    if ((*C & (AndRHSV - 1)).isNullValue()) {
-      // If not, the only thing that can effect the output of the AND is
-      // the bit specified by AndRHSV. If that bit is set, the effect of
-      // the XOR is to toggle the bit.
-      Value *NewAnd = Builder.CreateAnd(X, AndRHS);
-      NewAnd->takeName(Op);
-      return BinaryOperator::CreateXor(NewAnd, AndRHS);
-    }
-  }
-  return nullptr;
-}
-
 /// Emit a computation of: (V >= Lo && V < Hi) if Inside is true, otherwise
 /// (V < Lo || V >= Hi). This method expects that Lo < Hi. IsSigned indicates
 /// whether to treat V, Lo, and Hi as signed or not.
@@ -1820,6 +1793,16 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
       APInt LowMask(APInt::getLowBitsSet(Width, Width - Ctlz));
       if ((*AddC & LowMask).isNullValue())
         return BinaryOperator::CreateAnd(X, Op1);
+
+      // If we are masking the result of the add down to exactly one bit and
+      // the constant we are adding has no bits set below that bit, then the
+      // add is flipping a single bit. Example:
+      // (X + 4) & 4 --> (X & 4) ^ 4
+      if (Op0->hasOneUse() && C->isPowerOf2() && (*AddC & (*C - 1)) == 0) {
+        assert((*C & *AddC) != 0 && "Expected common bit");
+        Value *NewAnd = Builder.CreateAnd(X, Op1);
+        return BinaryOperator::CreateXor(NewAnd, Op1);
+      }
     }
   }
 
@@ -1860,9 +1843,6 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
           }
         }
       }
-
-      if (Instruction *Res = OptAndOp(Op0I, AndRHS, I))
-        return Res;
     }
   }
 

diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index c4f07313336f..e1a9e7515df0 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -711,9 +711,6 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
   Instruction *foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI);
   Instruction *foldSelectValueEquivalence(SelectInst &SI, ICmpInst &ICI);
 
-  Instruction *OptAndOp(BinaryOperator *Op, ConstantInt *AndRHS,
-                        BinaryOperator &TheAnd);
-
   Value *insertRangeTest(Value *V, const APInt &Lo, const APInt &Hi,
                          bool isSigned, bool Inside);
   Instruction *PromoteCastOfAllocation(BitCastInst &CI, AllocaInst &AI);

diff  --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index 415ce217396c..00d8ffe4c560 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1166,8 +1166,8 @@ define <2 x i8> @lowmask_add_vec(<2 x i8> %x, <2 x i8>* %p) {
 ; Only one bit set
 define i8 @flip_masked_bit(i8 %A) {
 ; CHECK-LABEL: @flip_masked_bit(
-; CHECK-NEXT:    [[B:%.*]] = and i8 [[A:%.*]], 16
-; CHECK-NEXT:    [[C:%.*]] = xor i8 [[B]], 16
+; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[A:%.*]], 16
+; CHECK-NEXT:    [[C:%.*]] = xor i8 [[TMP1]], 16
 ; CHECK-NEXT:    ret i8 [[C]]
 ;
   %B = add i8 %A, 16
@@ -1177,8 +1177,8 @@ define i8 @flip_masked_bit(i8 %A) {
 
 define <2 x i8> @flip_masked_bit_uniform(<2 x i8> %A) {
 ; CHECK-LABEL: @flip_masked_bit_uniform(
-; CHECK-NEXT:    [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 16>
-; CHECK-NEXT:    [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 16>
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i8> [[A:%.*]], <i8 16, i8 16>
+; CHECK-NEXT:    [[C:%.*]] = xor <2 x i8> [[TMP1]], <i8 16, i8 16>
 ; CHECK-NEXT:    ret <2 x i8> [[C]]
 ;
   %B = add <2 x i8> %A, <i8 16, i8 16>


        


More information about the llvm-commits mailing list