[llvm] 6ddc237 - [InstCombine] reduce code for flip of masked bit; NFC

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 15 12:51:43 PST 2020


Author: Sanjay Patel
Date: 2020-11-15T15:43:34-05:00
New Revision: 6ddc2377669243e93c1d6fa931f3eaef370e55e0

URL: https://github.com/llvm/llvm-project/commit/6ddc2377669243e93c1d6fa931f3eaef370e55e0
DIFF: https://github.com/llvm/llvm-project/commit/6ddc2377669243e93c1d6fa931f3eaef370e55e0.diff

LOG: [InstCombine] reduce code for flip of masked bit; NFC

There are 1-2 potential follow-up NFC commits to reduce
this further on the way to generalizing this for vectors.

The operand replacing path should be dead code because demanded
bits handles that more generally (D91415).

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 7b5647e9d990..b31009df6835 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -114,47 +114,39 @@ static Value *SimplifyBSwap(BinaryOperator &I,
   return Builder.CreateCall(F, BinOp);
 }
 
-/// This handles expressions of the form ((val OP C1) & C2).  Where
-/// the Op parameter is 'OP', OpRHS is 'C1', and AndRHS is 'C2'.
-Instruction *InstCombinerImpl::OptAndOp(BinaryOperator *Op, ConstantInt *OpRHS,
-                                        ConstantInt *AndRHS,
+/// This handles expressions of the form ((X + OpRHS) & AndRHS).
+Instruction *InstCombinerImpl::OptAndOp(BinaryOperator *Op, ConstantInt *AndRHS,
                                         BinaryOperator &TheAnd) {
-  Value *X = Op->getOperand(0);
-
-  switch (Op->getOpcode()) {
-  default: break;
-  case Instruction::Add:
-    if (Op->hasOneUse()) {
-      // 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.
-      const APInt &AndRHSV = AndRHS->getValue();
-
-      // If there is only one bit set.
-      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.
-        const APInt& AddRHS = OpRHS->getValue();
-
-        // Check to see if any bits below the one bit set in AndRHSV are set.
-        if ((AddRHS & (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 ((AddRHS & AndRHSV).isNullValue()) { // Bit is not set, noop
-            return replaceOperand(TheAnd, 0, X);
-          } else {
-            // Pull the XOR out of the AND.
-            Value *NewAnd = Builder.CreateAnd(X, AndRHS);
-            NewAnd->takeName(Op);
-            return BinaryOperator::CreateXor(NewAnd, AndRHS);
-          }
-        }
-      }
+  Value *X;
+  const APInt *C;
+  if (!match(Op, m_OneUse(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.
+  const APInt &AndRHSV = AndRHS->getValue();
+
+  // If there is only one bit set.
+  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.  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.
+      Value *NewAnd = Builder.CreateAnd(X, AndRHS);
+      NewAnd->takeName(Op);
+      return BinaryOperator::CreateXor(NewAnd, AndRHS);
     }
-    break;
   }
   return nullptr;
 }
@@ -1868,9 +1860,8 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
         }
       }
 
-      if (ConstantInt *Op0CI = dyn_cast<ConstantInt>(Op0I->getOperand(1)))
-        if (Instruction *Res = OptAndOp(Op0I, Op0CI, AndRHS, I))
-          return Res;
+      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 6c18d217c385..c4f07313336f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -711,8 +711,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
   Instruction *foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI);
   Instruction *foldSelectValueEquivalence(SelectInst &SI, ICmpInst &ICI);
 
-  Instruction *OptAndOp(BinaryOperator *Op, ConstantInt *OpRHS,
-                        ConstantInt *AndRHS, BinaryOperator &TheAnd);
+  Instruction *OptAndOp(BinaryOperator *Op, ConstantInt *AndRHS,
+                        BinaryOperator &TheAnd);
 
   Value *insertRangeTest(Value *V, const APInt &Lo, const APInt &Hi,
                          bool isSigned, bool Inside);

diff  --git a/llvm/test/Transforms/InstCombine/add.ll b/llvm/test/Transforms/InstCombine/add.ll
index e8f696a54557..b6a7a52ed126 100644
--- a/llvm/test/Transforms/InstCombine/add.ll
+++ b/llvm/test/Transforms/InstCombine/add.ll
@@ -336,51 +336,6 @@ define i8 @test15(i8 %A) {
   ret i8 %C
 }
 
-; Only one bit set
-define i8 @test16(i8 %A) {
-; CHECK-LABEL: @test16(
-; CHECK-NEXT:    [[B:%.*]] = and i8 [[A:%.*]], 16
-; CHECK-NEXT:    [[C:%.*]] = xor i8 [[B]], 16
-; CHECK-NEXT:    ret i8 [[C]]
-;
-  %B = add i8 %A, 16
-  %C = and i8 %B, 16
-  ret i8 %C
-}
-
-define <2 x i8> @test16_uniform(<2 x i8> %A) {
-; CHECK-LABEL: @test16_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:    ret <2 x i8> [[C]]
-;
-  %B = add <2 x i8> %A, <i8 16, i8 16>
-  %C = and <2 x i8> %B, <i8 16, i8 16>
-  ret <2 x i8> %C
-}
-
-define <2 x i8> @test16_undef(<2 x i8> %A) {
-; CHECK-LABEL: @test16_undef(
-; CHECK-NEXT:    [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 undef>
-; CHECK-NEXT:    [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 undef>
-; CHECK-NEXT:    ret <2 x i8> [[C]]
-;
-  %B = add <2 x i8> %A, <i8 16, i8 undef>
-  %C = and <2 x i8> %B, <i8 16, i8 undef>
-  ret <2 x i8> %C
-}
-
-define <2 x i8> @test16_nonuniform(<2 x i8> %A) {
-; CHECK-LABEL: @test16_nonuniform(
-; CHECK-NEXT:    [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 4>
-; CHECK-NEXT:    [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 4>
-; CHECK-NEXT:    ret <2 x i8> [[C]]
-;
-  %B = add <2 x i8> %A, <i8 16, i8 4>
-  %C = and <2 x i8> %B, <i8 16, i8 4>
-  ret <2 x i8> %C
-}
-
 define i32 @test17(i32 %A) {
 ; CHECK-LABEL: @test17(
 ; CHECK-NEXT:    [[C:%.*]] = sub i32 0, [[A:%.*]]

diff  --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll
index f4e0e01e6fed..cd52c6591155 100644
--- a/llvm/test/Transforms/InstCombine/and.ll
+++ b/llvm/test/Transforms/InstCombine/and.ll
@@ -1134,3 +1134,48 @@ define <2 x i8> @lowmask_add_vec(<2 x i8> %x, <2 x i8>* %p) {
   %r = and <2 x i8> %a, <i8 16, i8 32> ; 0x10, 0x20
   ret <2 x i8> %r
 }
+
+; 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:    ret i8 [[C]]
+;
+  %B = add i8 %A, 16
+  %C = and i8 %B, 16
+  ret i8 %C
+}
+
+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:    ret <2 x i8> [[C]]
+;
+  %B = add <2 x i8> %A, <i8 16, i8 16>
+  %C = and <2 x i8> %B, <i8 16, i8 16>
+  ret <2 x i8> %C
+}
+
+define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) {
+; CHECK-LABEL: @flip_masked_bit_undef(
+; CHECK-NEXT:    [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 undef>
+; CHECK-NEXT:    [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 undef>
+; CHECK-NEXT:    ret <2 x i8> [[C]]
+;
+  %B = add <2 x i8> %A, <i8 16, i8 undef>
+  %C = and <2 x i8> %B, <i8 16, i8 undef>
+  ret <2 x i8> %C
+}
+
+define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) {
+; CHECK-LABEL: @flip_masked_bit_nonuniform(
+; CHECK-NEXT:    [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 4>
+; CHECK-NEXT:    [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 4>
+; CHECK-NEXT:    ret <2 x i8> [[C]]
+;
+  %B = add <2 x i8> %A, <i8 16, i8 4>
+  %C = and <2 x i8> %B, <i8 16, i8 4>
+  ret <2 x i8> %C
+}


        


More information about the llvm-commits mailing list