[llvm] 4336969 - [InstCombine] relax constraints on mask-of-add

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 17 09:13:59 PST 2020


Author: Sanjay Patel
Date: 2020-11-17T12:13:44-05:00
New Revision: 433696911a0b8e1b94abd8d8f192380ba7867b61

URL: https://github.com/llvm/llvm-project/commit/433696911a0b8e1b94abd8d8f192380ba7867b61
DIFF: https://github.com/llvm/llvm-project/commit/433696911a0b8e1b94abd8d8f192380ba7867b61.diff

LOG: [InstCombine] relax constraints on mask-of-add

There are 2 changes:
1. Remove the unnecessary one-use check.
2. Remove the unnecessary power-of-2 check.

https://rise4fun.com/Alive/V6fP

  Name: add with low mask
  Pre: (C1 & (-1 u>> countLeadingZeros(C2))) == 0
  %a = add i8 %x, C1
  %r = and i8 %a, C2
  =>
  %r = and i8 %x, C2

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b31009df6835..78562fce5e32 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -119,30 +119,28 @@ 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)))))
+  if (!match(Op, m_Add(m_Value(X), m_APInt(C))))
     return nullptr;
 
-  // Adding a one to a single bit bit-field should be turned into an XOR
-  // of the bit.  First thing to check is to see if this AND is with a
-  // single bit constant.
+  // If we are adding zeros to every bit below a mask, the add has no effect:
+  // (X + HighC) & LowMaskC --> X & LowMaskC
   const APInt &AndRHSV = AndRHS->getValue();
+  unsigned Ctlz = AndRHSV.countLeadingZeros();
+  unsigned BitWidth = AndRHSV.getBitWidth();
+  APInt LowMask(APInt::getLowBitsSet(BitWidth, BitWidth - Ctlz));
+  if ((*C & LowMask).isNullValue())
+    return BinaryOperator::CreateAnd(X, TheAnd.getOperand(1));
 
   // If there is only one bit set.
-  if (AndRHSV.isPowerOf2()) {
+  if (AndRHSV.isPowerOf2() && Op->hasOneUse()) {
     // 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.  If it is clear, then the ADD has
-      // no effect.
-      if ((*C & AndRHSV).isNullValue()) // Bit is not set, noop
-        return replaceOperand(TheAnd, 0, X);
-
-      // Pull the XOR out of the AND.
+      // 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);

diff  --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index 68743ca15555..554024eff9ef 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1053,7 +1053,7 @@ define i8 @lowmask_add(i8 %x) {
 ; CHECK-LABEL: @lowmask_add(
 ; CHECK-NEXT:    [[A:%.*]] = add i8 [[X:%.*]], -64
 ; CHECK-NEXT:    call void @use8(i8 [[A]])
-; CHECK-NEXT:    [[R:%.*]] = and i8 [[A]], 32
+; CHECK-NEXT:    [[R:%.*]] = and i8 [[X]], 32
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %a = add i8 %x, -64 ; 0xc0
@@ -1076,7 +1076,7 @@ define i8 @lowmask_add_2_uses(i8 %x) {
 ; CHECK-LABEL: @lowmask_add_2_uses(
 ; CHECK-NEXT:    [[A:%.*]] = add i8 [[X:%.*]], -64
 ; CHECK-NEXT:    call void @use8(i8 [[A]])
-; CHECK-NEXT:    [[R:%.*]] = and i8 [[A]], 63
+; CHECK-NEXT:    [[R:%.*]] = and i8 [[X]], 63
 ; CHECK-NEXT:    ret i8 [[R]]
 ;
   %a = add i8 %x, -64 ; 0xc0


        


More information about the llvm-commits mailing list