[llvm] e10d7d4 - [InstCombine] fold 'not' of ctpop in parity pattern

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 23 10:25:40 PDT 2021


Author: Sanjay Patel
Date: 2021-04-23T13:23:24-04:00
New Revision: e10d7d455d4ec0dccab9a74764a8988e1301069f

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

LOG: [InstCombine] fold 'not' of ctpop in parity pattern

As discussed in https://llvm.org/PR50096 , we could
convert the 'not' into a 'sub' and see the same
fold. That's because we already have another demanded
bits optimization for 'sub'.

We could add a related transform for
odd-number-of-type-bits, but that seems unlikely
to be practical.

https://alive2.llvm.org/ce/z/TWJZXr

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
    llvm/test/Transforms/InstCombine/ctpop.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 9e4451919a00..a97a50b88753 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -739,6 +739,19 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
           return II->getArgOperand(0);
         break;
       }
+      case Intrinsic::ctpop: {
+        // Checking if the number of clear bits is odd (parity)? If the type has
+        // an even number of bits, that's the same as checking if the number of
+        // set bits is odd, so we can eliminate the 'not' op.
+        Value *X;
+        if (DemandedMask == 1 && VTy->getScalarSizeInBits() % 2 == 0 &&
+            match(II->getArgOperand(0), m_Not(m_Value(X)))) {
+          Function *Ctpop = Intrinsic::getDeclaration(
+              II->getModule(), Intrinsic::ctpop, II->getType());
+          return InsertNewInstWith(CallInst::Create(Ctpop, {X}), *I);
+        }
+        break;
+      }
       case Intrinsic::bswap: {
         // If the only bits demanded come from one byte of the bswap result,
         // just shift the input byte into position to eliminate the bswap.

diff  --git a/llvm/test/Transforms/InstCombine/ctpop.ll b/llvm/test/Transforms/InstCombine/ctpop.ll
index c25b1f3b8729..85c3a0a49f5e 100644
--- a/llvm/test/Transforms/InstCombine/ctpop.ll
+++ b/llvm/test/Transforms/InstCombine/ctpop.ll
@@ -121,9 +121,8 @@ define <2 x i32> @mask_one_bit_splat(<2 x i32> %x, <2 x i32>* %p) {
 
 define i32 @_parity_of_not(i32 %x) {
 ; CHECK-LABEL: @_parity_of_not(
-; CHECK-NEXT:    [[NEG:%.*]] = xor i32 [[X:%.*]], -1
-; CHECK-NEXT:    [[CNT:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[NEG]]), !range [[RNG1:![0-9]+]]
-; CHECK-NEXT:    [[R:%.*]] = and i32 [[CNT]], 1
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG1:![0-9]+]]
+; CHECK-NEXT:    [[R:%.*]] = and i32 [[TMP1]], 1
 ; CHECK-NEXT:    ret i32 [[R]]
 ;
   %neg = xor i32 %x, -1
@@ -132,6 +131,8 @@ define i32 @_parity_of_not(i32 %x) {
   ret i32 %r
 }
 
+; Negative test - need even # of bits in type.
+
 define i7 @_parity_of_not_odd_type(i7 %x) {
 ; CHECK-LABEL: @_parity_of_not_odd_type(
 ; CHECK-NEXT:    [[NEG:%.*]] = xor i7 [[X:%.*]], -1
@@ -147,9 +148,8 @@ define i7 @_parity_of_not_odd_type(i7 %x) {
 
 define <2 x i32> @_parity_of_not_vec(<2 x i32> %x) {
 ; CHECK-LABEL: @_parity_of_not_vec(
-; CHECK-NEXT:    [[NEG:%.*]] = xor <2 x i32> [[X:%.*]], <i32 -1, i32 -1>
-; CHECK-NEXT:    [[CNT:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[NEG]])
-; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[CNT]], <i32 1, i32 1>
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])
+; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[TMP1]], <i32 1, i32 1>
 ; CHECK-NEXT:    ret <2 x i32> [[R]]
 ;
   %neg = xor <2 x i32> %x, <i32 -1 ,i32 -1>
@@ -160,9 +160,8 @@ define <2 x i32> @_parity_of_not_vec(<2 x i32> %x) {
 
 define <2 x i32> @_parity_of_not_undef(<2 x i32> %x) {
 ; CHECK-LABEL: @_parity_of_not_undef(
-; CHECK-NEXT:    [[NEG:%.*]] = xor <2 x i32> [[X:%.*]], <i32 undef, i32 -1>
-; CHECK-NEXT:    [[CNT:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[NEG]])
-; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[CNT]], <i32 1, i32 1>
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])
+; CHECK-NEXT:    [[R:%.*]] = and <2 x i32> [[TMP1]], <i32 1, i32 1>
 ; CHECK-NEXT:    ret <2 x i32> [[R]]
 ;
   %neg = xor <2 x i32> %x, <i32 undef ,i32 -1>


        


More information about the llvm-commits mailing list