[llvm] [AggressiveInstCombine] POPCNT generation for bit-count pattern (PR #180917)
Rohit Aggarwal via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 13 00:24:06 PDT 2026
https://github.com/rohitaggarwal007 updated https://github.com/llvm/llvm-project/pull/180917
>From b1ae92139795d550cc94d425432c90cab1501241 Mon Sep 17 00:00:00 2001
From: Rohit Aggarwal <Rohit.Aggarwal at amd.com>
Date: Wed, 21 Jan 2026 12:52:41 +0530
Subject: [PATCH 1/9] [AggressiveInstCombine] POPCNT generation for bit-count
pattern
---
.../AggressiveInstCombine.cpp | 90 +++++++++++++++++++
.../AggressiveInstCombine/popcount.ll | 48 ++++++++++
2 files changed, 138 insertions(+)
diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
index 3341368208c24..5ca2fa14e1533 100644
--- a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
+++ b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
@@ -372,6 +372,95 @@ static bool tryToRecognizePopCount(Instruction &I) {
return false;
}
+// Try to recognize below function as popcount intrinsic.
+// https://doc.lagout.org/security/Hackers%20Delight.pdf
+// Also used in TargetLowering::expandCTPOP().
+//
+// int popcnt(unsigned x) {
+// x = x - ((x >> 1) & 0x55555555);
+// x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+// x = (x + (x >> 4)) & 0x0F0F0F0F;
+// x = x + (x >> 8);
+// x = x + (x >> 16);
+// return x & 0x0000003F;
+// }
+
+// int popcnt(unsigned x) {
+// x = x - ((x >> 1) & 0x55555555);
+// x = x - 3*((x >> 2) & 0x33333333);
+// x = (x + (x >> 4)) & 0x0F0F0F0F;
+// x = x + (x >> 8);
+// x = x + (x >> 16);
+// return x & 0x0000003F;
+// }
+
+static bool tryToRecognizePopCount2n3(Instruction &I) {
+ if (I.getOpcode() != Instruction::And)
+ return false;
+
+ Type *Ty = I.getType();
+ if (!Ty->isIntOrIntVectorTy())
+ return false;
+
+ unsigned Len = Ty->getScalarSizeInBits();
+ if (!(Len <= 128 && Len > 8 && Len % 8 == 0))
+ return false;
+
+ Value *Op0 = I.getOperand(0);
+ Value *Op1 = I.getOperand(1);
+ Value *LShrOp0;
+ Value *AddOp1;
+ // Matching "x & 0x0000003F".
+ if ((match(Op0, m_Add(m_Value(LShrOp0), m_Value(AddOp1)))) &&
+ match(Op1, m_SpecificInt(63))) {
+ Value *LShr1;
+ Value *And1;
+ // Matching "x = x + (x >> 16)".
+ if (match(LShrOp0, m_LShr(m_Add(m_Value(LShr1), m_Value(And1)),
+ m_SpecificInt(16)))) {
+ Value *Add2;
+ // Matching " x = x + (x >> 8)".
+ if (match(LShr1, m_LShr(m_Deferred(And1), m_SpecificInt(8))) &&
+ match(And1, m_c_And(m_Value(Add2), m_SpecificInt(252645135)))) {
+ Value *Add3;
+ // Matching "x = (x + (x >> 4)) & 0x0F0F0F0F".
+ if (match(Add2, m_c_Add(m_LShr(m_Value(Add3), m_SpecificInt(4)),
+ m_Deferred(Add3)))) {
+ Value *Sub1;
+ llvm::APInt NegThree(/*BitWidth=*/32, /*Value=*/-3,
+ /*isSigned=*/true);
+ // x = (x & 0x33333333) + ((x >> 2) & 0x33333333)".
+ if (match(Add3,
+ m_c_Add(
+ m_c_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
+ m_SpecificInt(858993459)),
+ m_c_And(m_Deferred(Sub1), m_SpecificInt(858993459)))) ||
+ // Matching "x = x - 3*((x >> 2) & 0x33333333)".
+ match(Add3,
+ m_Add(m_Mul(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
+ m_SpecificInt(858993459)),
+ m_SpecificInt(NegThree)),
+ m_Deferred(Sub1)))) {
+ Value *Root;
+ if (match(Sub1,
+ m_Sub(m_Value(Root),
+ m_And(m_LShr(m_Deferred(Root), m_SpecificInt(1)),
+ m_SpecificInt(1431655765))))) {
+ LLVM_DEBUG(dbgs() << "Recognized popcount intrinsic\n");
+ IRBuilder<> Builder(&I);
+ I.replaceAllUsesWith(Builder.CreateIntrinsic(
+ Intrinsic::ctpop, I.getType(), {Root}));
+ ++NumPopCountRecognized;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
/// Fold smin(smax(fptosi(x), C1), C2) to llvm.fptosi.sat(x), providing C1 and
/// C2 saturate the value of the fp conversion. The transform is not reversable
/// as the fptosi.sat is more defined than the input - all values produce a
@@ -1826,6 +1915,7 @@ static bool foldUnusualPatterns(Function &F, DominatorTree &DT,
MadeChange |= foldAnyOrAllBitsSet(I);
MadeChange |= foldGuardedFunnelShift(I, DT);
MadeChange |= tryToRecognizePopCount(I);
+ MadeChange |= tryToRecognizePopCount2n3(I);
MadeChange |= tryToFPToSat(I, TTI);
MadeChange |= tryToRecognizeTableBasedCttz(I, DL);
MadeChange |= foldConsecutiveLoads(I, DL, TTI, AA, DT);
diff --git a/llvm/test/Transforms/AggressiveInstCombine/popcount.ll b/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
index f56cab1503531..2c9fde6608984 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
@@ -239,3 +239,51 @@ define i32 @popcount64_mask(i64 %x) {
%13 = trunc nuw nsw i64 %12 to i32
ret i32 %13
}
+
+define dso_local noundef range(i32 0, 64) i32 @popcnt2(i32 noundef %0) local_unnamed_addr {
+; CHECK-LABEL: define dso_local noundef range(i32 0, 64) i32 @popcnt2(
+; CHECK-SAME: i32 noundef [[TMP0:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.ctpop.i32(i32 [[TMP0]])
+; CHECK-NEXT: ret i32 [[TMP2]]
+;
+ %2 = lshr i32 %0, 1
+ %3 = and i32 %2, 1431655765
+ %4 = sub i32 %0, %3
+ %5 = and i32 %4, 858993459
+ %6 = lshr i32 %4, 2
+ %7 = and i32 %6, 858993459
+ %8 = add nuw nsw i32 %7, %5
+ %9 = lshr i32 %8, 4
+ %10 = add nuw nsw i32 %9, %8
+ %11 = and i32 %10, 252645135
+ %12 = lshr i32 %11, 8
+ %13 = add nuw nsw i32 %12, %11
+ %14 = lshr i32 %13, 16
+ %15 = add nuw nsw i32 %14, %13
+ %16 = and i32 %15, 63
+ ret i32 %16
+}
+
+define dso_local noundef range(i32 0, 64) i32 @popcnt3(i32 noundef %0) local_unnamed_addr {
+; CHECK-LABEL: define dso_local noundef range(i32 0, 64) i32 @popcnt3(
+; CHECK-SAME: i32 noundef [[TMP0:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[TMP16:%.*]] = call i32 @llvm.ctpop.i32(i32 [[TMP0]])
+; CHECK-NEXT: ret i32 [[TMP16]]
+;
+ %2 = lshr i32 %0, 1
+ %3 = and i32 %2, 1431655765
+ %4 = sub i32 %0, %3
+ %5 = lshr i32 %4, 2
+ %6 = and i32 %5, 858993459
+ %7 = mul i32 %6, -3
+ %8 = add i32 %7, %4
+ %9 = lshr i32 %8, 4
+ %10 = add i32 %9, %8
+ %11 = and i32 %10, 252645135
+ %12 = lshr i32 %11, 8
+ %13 = add nuw nsw i32 %12, %11
+ %14 = lshr i32 %13, 16
+ %15 = add nuw nsw i32 %14, %13
+ %16 = and i32 %15, 63
+ ret i32 %16
+}
>From 13d9f15f4ab023f5fbe4e541835c4bf34da0172e Mon Sep 17 00:00:00 2001
From: Rohit Aggarwal <Rohit.Aggarwal at amd.com>
Date: Wed, 25 Feb 2026 17:00:56 +0530
Subject: [PATCH 2/9] Implement review comments
---
.../AggressiveInstCombine.cpp | 127 +++---
.../AggressiveInstCombine/popcount.ll | 384 +++++++++++++++++-
2 files changed, 456 insertions(+), 55 deletions(-)
diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
index 5ca2fa14e1533..e1ad6458187ce 100644
--- a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
+++ b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
@@ -403,61 +403,90 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
return false;
unsigned Len = Ty->getScalarSizeInBits();
- if (!(Len <= 128 && Len > 8 && Len % 8 == 0))
+ if (!(Len == 16 || Len == 32 || Len == 64))
return false;
+ APInt Mask55 = APInt::getSplat(Len, APInt(8, 0x55));
+ APInt Mask33 = APInt::getSplat(Len, APInt(8, 0x33));
+ APInt Mask0F = APInt::getSplat(Len, APInt(8, 0x0F));
+
+ APInt MaskRes = APInt(Len, 2 * Len - 1);
Value *Op0 = I.getOperand(0);
Value *Op1 = I.getOperand(1);
- Value *LShrOp0;
- Value *AddOp1;
- // Matching "x & 0x0000003F".
- if ((match(Op0, m_Add(m_Value(LShrOp0), m_Value(AddOp1)))) &&
- match(Op1, m_SpecificInt(63))) {
- Value *LShr1;
- Value *And1;
- // Matching "x = x + (x >> 16)".
- if (match(LShrOp0, m_LShr(m_Add(m_Value(LShr1), m_Value(And1)),
- m_SpecificInt(16)))) {
- Value *Add2;
- // Matching " x = x + (x >> 8)".
- if (match(LShr1, m_LShr(m_Deferred(And1), m_SpecificInt(8))) &&
- match(And1, m_c_And(m_Value(Add2), m_SpecificInt(252645135)))) {
- Value *Add3;
- // Matching "x = (x + (x >> 4)) & 0x0F0F0F0F".
- if (match(Add2, m_c_Add(m_LShr(m_Value(Add3), m_SpecificInt(4)),
- m_Deferred(Add3)))) {
- Value *Sub1;
- llvm::APInt NegThree(/*BitWidth=*/32, /*Value=*/-3,
- /*isSigned=*/true);
- // x = (x & 0x33333333) + ((x >> 2) & 0x33333333)".
- if (match(Add3,
- m_c_Add(
- m_c_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
- m_SpecificInt(858993459)),
- m_c_And(m_Deferred(Sub1), m_SpecificInt(858993459)))) ||
- // Matching "x = x - 3*((x >> 2) & 0x33333333)".
- match(Add3,
- m_Add(m_Mul(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
- m_SpecificInt(858993459)),
- m_SpecificInt(NegThree)),
- m_Deferred(Sub1)))) {
- Value *Root;
- if (match(Sub1,
- m_Sub(m_Value(Root),
- m_And(m_LShr(m_Deferred(Root), m_SpecificInt(1)),
- m_SpecificInt(1431655765))))) {
- LLVM_DEBUG(dbgs() << "Recognized popcount intrinsic\n");
- IRBuilder<> Builder(&I);
- I.replaceAllUsesWith(Builder.CreateIntrinsic(
- Intrinsic::ctpop, I.getType(), {Root}));
- ++NumPopCountRecognized;
- return true;
- }
- }
- }
- }
+
+ // Matching "x & 0x001F" (16-bit).
+ // Matching "x & 0x0000003F" (32-bit).
+ // Matching "x & 0x0000007F" (64-bit).
+ if (!(match(Op0, m_SpecificInt(MaskRes)) ||
+ match(Op1, m_SpecificInt(MaskRes)))) {
+ return false;
+ }
+
+ // Get the value being masked
+ Value *Add1 = (match(Op0, m_SpecificInt(MaskRes))) ? Op1 : Op0;
+
+ // Matching "x = x + (x >> 32)" for 64-bit.
+ Value *Add2 = Add1;
+ if (Len == 64) {
+ if (!match(Add1, m_c_Add(m_LShr(m_Value(Add2), m_SpecificInt(32)),
+ m_Deferred(Add2)))) {
+ return false;
}
}
+
+ // Matching "x = x + (x >> 16)" for 32-bit and 64-bit.
+ Value *Add3 = Add2;
+ if (Len == 32 || Len == 64) {
+ if (!match(Add2, m_c_Add(m_LShr(m_Value(Add3), m_SpecificInt(16)),
+ m_Deferred(Add3)))) {
+ return false;
+ }
+ }
+
+ // Matching "x = x + (x >> 8)".
+ Value *And1;
+ if (!match(Add3, m_c_Add(m_LShr(m_Value(And1), m_SpecificInt(8)),
+ m_Deferred(And1)))) {
+ return false;
+ }
+
+ // Matching "x = (x + (x >> 4)) & 0x0F0F0F0F".
+ Value *Add4;
+ if (!match(And1, m_c_And(m_c_Add(m_LShr(m_Value(Add4), m_SpecificInt(4)),
+ m_Deferred(Add4)),
+ m_SpecificInt(Mask0F)))) {
+ return false;
+ }
+
+ Value *Sub1;
+ llvm::APInt NegThree(/*BitWidth=*/Len, /*Value=*/-3,
+ /*isSigned=*/true);
+ // x = (x & 0x33333333) + ((x >> 2) & 0x33333333)".
+ if (!(match(Add4,
+ m_c_Add(m_c_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
+ m_SpecificInt(Mask33)),
+ m_c_And(m_Deferred(Sub1), m_SpecificInt(Mask33)))) ||
+ // Matching "x = x - 3*((x >> 2) & 0x33333333)".
+ match(Add4, m_Add(m_Mul(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
+ m_SpecificInt(Mask33)),
+ m_SpecificInt(NegThree)),
+ m_Deferred(Sub1))))) {
+ return false;
+ }
+
+ Value *Root;
+ // x = x - ((x >> 1) & 0x55555555);
+ if (match(Sub1, m_Sub(m_Value(Root),
+ m_c_And(m_LShr(m_Deferred(Root), m_SpecificInt(1)),
+ m_SpecificInt(Mask55))))) {
+ LLVM_DEBUG(dbgs() << "Recognized popcount intrinsic\n");
+ IRBuilder<> Builder(&I);
+ I.replaceAllUsesWith(
+ Builder.CreateIntrinsic(Intrinsic::ctpop, I.getType(), {Root}));
+ ++NumPopCountRecognized;
+ return true;
+ }
+
return false;
}
diff --git a/llvm/test/Transforms/AggressiveInstCombine/popcount.ll b/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
index 2c9fde6608984..9909854a8ac07 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
@@ -240,9 +240,9 @@ define i32 @popcount64_mask(i64 %x) {
ret i32 %13
}
-define dso_local noundef range(i32 0, 64) i32 @popcnt2(i32 noundef %0) local_unnamed_addr {
-; CHECK-LABEL: define dso_local noundef range(i32 0, 64) i32 @popcnt2(
-; CHECK-SAME: i32 noundef [[TMP0:%.*]]) local_unnamed_addr {
+define i32 @popcnt2_32(i32 noundef %0) {
+; CHECK-LABEL: define i32 @popcnt2_32(
+; CHECK-SAME: i32 noundef [[TMP0:%.*]]) {
; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.ctpop.i32(i32 [[TMP0]])
; CHECK-NEXT: ret i32 [[TMP2]]
;
@@ -264,9 +264,9 @@ define dso_local noundef range(i32 0, 64) i32 @popcnt2(i32 noundef %0) local_unn
ret i32 %16
}
-define dso_local noundef range(i32 0, 64) i32 @popcnt3(i32 noundef %0) local_unnamed_addr {
-; CHECK-LABEL: define dso_local noundef range(i32 0, 64) i32 @popcnt3(
-; CHECK-SAME: i32 noundef [[TMP0:%.*]]) local_unnamed_addr {
+define i32 @popcnt3_32(i32 noundef %0) {
+; CHECK-LABEL: define i32 @popcnt3_32(
+; CHECK-SAME: i32 noundef [[TMP0:%.*]]) {
; CHECK-NEXT: [[TMP16:%.*]] = call i32 @llvm.ctpop.i32(i32 [[TMP0]])
; CHECK-NEXT: ret i32 [[TMP16]]
;
@@ -287,3 +287,375 @@ define dso_local noundef range(i32 0, 64) i32 @popcnt3(i32 noundef %0) local_unn
%16 = and i32 %15, 63
ret i32 %16
}
+
+; 16-bit scalar popcount
+define i16 @popcnt2_16(i16 noundef %0) {
+; CHECK-LABEL: @popcnt2_16(
+; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.ctpop.i16(i16 [[TMP0:%.*]])
+; CHECK-NEXT: ret i16 [[TMP2]]
+;
+ %2 = lshr i16 %0, 1
+ %3 = and i16 %2, 21845
+ %4 = sub i16 %0, %3
+ %5 = and i16 %4, 13107
+ %6 = lshr i16 %4, 2
+ %7 = and i16 %6, 13107
+ %8 = add nuw nsw i16 %7, %5
+ %9 = lshr i16 %8, 4
+ %10 = add nuw nsw i16 %9, %8
+ %11 = and i16 %10, 3855
+ %12 = lshr i16 %11, 8
+ %13 = add nuw nsw i16 %12, %11
+ %14 = and i16 %13, 31
+ ret i16 %14
+}
+
+; 64-bit scalar popcount
+define i64 @popcnt2_64(i64 noundef %0) {
+; CHECK-LABEL: @popcnt2_64(
+; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP0:%.*]])
+; CHECK-NEXT: ret i64 [[TMP2]]
+;
+ %2 = lshr i64 %0, 1
+ %3 = and i64 %2, 6148914691236517205
+ %4 = sub i64 %0, %3
+ %5 = and i64 %4, 3689348814741910323
+ %6 = lshr i64 %4, 2
+ %7 = and i64 %6, 3689348814741910323
+ %8 = add nuw nsw i64 %7, %5
+ %9 = lshr i64 %8, 4
+ %10 = add nuw nsw i64 %9, %8
+ %11 = and i64 %10, 1085102592571150095
+ %12 = lshr i64 %11, 8
+ %13 = add nuw nsw i64 %12, %11
+ %14 = lshr i64 %13, 16
+ %15 = add nuw nsw i64 %14, %13
+ %16 = lshr i64 %15, 32
+ %17 = add nuw nsw i64 %16, %15
+ %18 = and i64 %17, 127
+ ret i64 %18
+}
+
+; 16-bit vector popcount
+define <8 x i16> @popcnt2_16vec(<8 x i16> %0) {
+; CHECK-LABEL: @popcnt2_16vec(
+; CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> [[TMP0:%.*]])
+; CHECK-NEXT: ret <8 x i16> [[TMP2]]
+;
+ %2 = lshr <8 x i16> %0, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
+ %3 = and <8 x i16> %2, <i16 21845, i16 21845, i16 21845, i16 21845, i16 21845, i16 21845, i16 21845, i16 21845>
+ %4 = sub <8 x i16> %0, %3
+ %5 = and <8 x i16> %4, <i16 13107, i16 13107, i16 13107, i16 13107, i16 13107, i16 13107, i16 13107, i16 13107>
+ %6 = lshr <8 x i16> %4, <i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2>
+ %7 = and <8 x i16> %6, <i16 13107, i16 13107, i16 13107, i16 13107, i16 13107, i16 13107, i16 13107, i16 13107>
+ %8 = add nuw nsw <8 x i16> %7, %5
+ %9 = lshr <8 x i16> %8, <i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4>
+ %10 = add nuw nsw <8 x i16> %9, %8
+ %11 = and <8 x i16> %10, <i16 3855, i16 3855, i16 3855, i16 3855, i16 3855, i16 3855, i16 3855, i16 3855>
+ %12 = lshr <8 x i16> %11, <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
+ %13 = add nuw nsw <8 x i16> %12, %11
+ %14 = and <8 x i16> %13, <i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31>
+ ret <8 x i16> %14
+}
+
+; 32-bit vector popcount (variant 2) - 4 elements
+define <4 x i32> @popcnt2_32vec(<4 x i32> %0) {
+; CHECK-LABEL: @popcnt2_32vec(
+; CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> [[TMP0:%.*]])
+; CHECK-NEXT: ret <4 x i32> [[TMP2]]
+;
+ %2 = lshr <4 x i32> %0, <i32 1, i32 1, i32 1, i32 1>
+ %3 = and <4 x i32> %2, <i32 1431655765, i32 1431655765, i32 1431655765, i32 1431655765>
+ %4 = sub <4 x i32> %0, %3
+ %5 = and <4 x i32> %4, <i32 858993459, i32 858993459, i32 858993459, i32 858993459>
+ %6 = lshr <4 x i32> %4, <i32 2, i32 2, i32 2, i32 2>
+ %7 = and <4 x i32> %6, <i32 858993459, i32 858993459, i32 858993459, i32 858993459>
+ %8 = add nuw nsw <4 x i32> %7, %5
+ %9 = lshr <4 x i32> %8, <i32 4, i32 4, i32 4, i32 4>
+ %10 = add nuw nsw <4 x i32> %9, %8
+ %11 = and <4 x i32> %10, <i32 252645135, i32 252645135, i32 252645135, i32 252645135>
+ %12 = lshr <4 x i32> %11, <i32 8, i32 8, i32 8, i32 8>
+ %13 = add nuw nsw <4 x i32> %12, %11
+ %14 = lshr <4 x i32> %13, <i32 16, i32 16, i32 16, i32 16>
+ %15 = add nuw nsw <4 x i32> %14, %13
+ %16 = and <4 x i32> %15, <i32 63, i32 63, i32 63, i32 63>
+ ret <4 x i32> %16
+}
+
+; 64-bit vector popcount
+define <2 x i64> @popcnt2_64vec(<2 x i64> %0) {
+; CHECK-LABEL: @popcnt2_64vec(
+; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> [[TMP0:%.*]])
+; CHECK-NEXT: ret <2 x i64> [[TMP2]]
+;
+ %2 = lshr <2 x i64> %0, <i64 1, i64 1>
+ %3 = and <2 x i64> %2, <i64 6148914691236517205, i64 6148914691236517205>
+ %4 = sub <2 x i64> %0, %3
+ %5 = and <2 x i64> %4, <i64 3689348814741910323, i64 3689348814741910323>
+ %6 = lshr <2 x i64> %4, <i64 2, i64 2>
+ %7 = and <2 x i64> %6, <i64 3689348814741910323, i64 3689348814741910323>
+ %8 = add nuw nsw <2 x i64> %7, %5
+ %9 = lshr <2 x i64> %8, <i64 4, i64 4>
+ %10 = add nuw nsw <2 x i64> %9, %8
+ %11 = and <2 x i64> %10, <i64 1085102592571150095, i64 1085102592571150095>
+ %12 = lshr <2 x i64> %11, <i64 8, i64 8>
+ %13 = add nuw nsw <2 x i64> %12, %11
+ %14 = lshr <2 x i64> %13, <i64 16, i64 16>
+ %15 = add nuw nsw <2 x i64> %14, %13
+ %16 = lshr <2 x i64> %15, <i64 32, i64 32>
+ %17 = add nuw nsw <2 x i64> %16, %15
+ %18 = and <2 x i64> %17, <i64 127, i64 127>
+ ret <2 x i64> %18
+}
+
+; 16-bit scalar popcount (variant 3 - using multiply by -3)
+define i16 @popcnt3_16(i16 noundef %0) {
+; CHECK-LABEL: @popcnt3_16(
+; CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.ctpop.i16(i16 [[TMP0:%.*]])
+; CHECK-NEXT: ret i16 [[TMP2]]
+;
+ %2 = lshr i16 %0, 1
+ %3 = and i16 %2, 21845
+ %4 = sub i16 %0, %3
+ %5 = lshr i16 %4, 2
+ %6 = and i16 %5, 13107
+ %7 = mul i16 %6, -3
+ %8 = add i16 %7, %4
+ %9 = lshr i16 %8, 4
+ %10 = add i16 %9, %8
+ %11 = and i16 %10, 3855
+ %12 = lshr i16 %11, 8
+ %13 = add nuw nsw i16 %12, %11
+ %14 = and i16 %13, 31
+ ret i16 %14
+}
+
+; 64-bit scalar popcount (variant 3 - using multiply by -3)
+define i64 @popcnt3_64(i64 noundef %0) {
+; CHECK-LABEL: @popcnt3_64(
+; CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.ctpop.i64(i64 [[TMP0:%.*]])
+; CHECK-NEXT: ret i64 [[TMP2]]
+;
+ %2 = lshr i64 %0, 1
+ %3 = and i64 %2, 6148914691236517205
+ %4 = sub i64 %0, %3
+ %5 = lshr i64 %4, 2
+ %6 = and i64 %5, 3689348814741910323
+ %7 = mul i64 %6, -3
+ %8 = add i64 %7, %4
+ %9 = lshr i64 %8, 4
+ %10 = add i64 %9, %8
+ %11 = and i64 %10, 1085102592571150095
+ %12 = lshr i64 %11, 8
+ %13 = add nuw nsw i64 %12, %11
+ %14 = lshr i64 %13, 16
+ %15 = add nuw nsw i64 %14, %13
+ %16 = lshr i64 %15, 32
+ %17 = add nuw nsw i64 %16, %15
+ %18 = and i64 %17, 127
+ ret i64 %18
+}
+
+; 16-bit vector popcount (variant 3 - using multiply by -3) - 8 elements
+define <8 x i16> @popcnt3_16vec(<8 x i16> %0) {
+; CHECK-LABEL: @popcnt3_16vec(
+; CHECK-NEXT: [[TMP2:%.*]] = call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> [[TMP0:%.*]])
+; CHECK-NEXT: ret <8 x i16> [[TMP2]]
+;
+ %2 = lshr <8 x i16> %0, <i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1, i16 1>
+ %3 = and <8 x i16> %2, <i16 21845, i16 21845, i16 21845, i16 21845, i16 21845, i16 21845, i16 21845, i16 21845>
+ %4 = sub <8 x i16> %0, %3
+ %5 = lshr <8 x i16> %4, <i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2, i16 2>
+ %6 = and <8 x i16> %5, <i16 13107, i16 13107, i16 13107, i16 13107, i16 13107, i16 13107, i16 13107, i16 13107>
+ %7 = mul <8 x i16> %6, <i16 -3, i16 -3, i16 -3, i16 -3, i16 -3, i16 -3, i16 -3, i16 -3>
+ %8 = add <8 x i16> %7, %4
+ %9 = lshr <8 x i16> %8, <i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4, i16 4>
+ %10 = add <8 x i16> %9, %8
+ %11 = and <8 x i16> %10, <i16 3855, i16 3855, i16 3855, i16 3855, i16 3855, i16 3855, i16 3855, i16 3855>
+ %12 = lshr <8 x i16> %11, <i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8, i16 8>
+ %13 = add nuw nsw <8 x i16> %12, %11
+ %14 = and <8 x i16> %13, <i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31, i16 31>
+ ret <8 x i16> %14
+}
+
+; 32-bit vector popcount (variant 3 - using multiply by -3) - 4 elements
+define <4 x i32> @popcnt3_32vec(<4 x i32> %0) {
+; CHECK-LABEL: @popcnt3_32vec(
+; CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> [[TMP0:%.*]])
+; CHECK-NEXT: ret <4 x i32> [[TMP2]]
+;
+ %2 = lshr <4 x i32> %0, <i32 1, i32 1, i32 1, i32 1>
+ %3 = and <4 x i32> %2, <i32 1431655765, i32 1431655765, i32 1431655765, i32 1431655765>
+ %4 = sub <4 x i32> %0, %3
+ %5 = lshr <4 x i32> %4, <i32 2, i32 2, i32 2, i32 2>
+ %6 = and <4 x i32> %5, <i32 858993459, i32 858993459, i32 858993459, i32 858993459>
+ %7 = mul <4 x i32> %6, <i32 -3, i32 -3, i32 -3, i32 -3>
+ %8 = add <4 x i32> %7, %4
+ %9 = lshr <4 x i32> %8, <i32 4, i32 4, i32 4, i32 4>
+ %10 = add <4 x i32> %9, %8
+ %11 = and <4 x i32> %10, <i32 252645135, i32 252645135, i32 252645135, i32 252645135>
+ %12 = lshr <4 x i32> %11, <i32 8, i32 8, i32 8, i32 8>
+ %13 = add nuw nsw <4 x i32> %12, %11
+ %14 = lshr <4 x i32> %13, <i32 16, i32 16, i32 16, i32 16>
+ %15 = add nuw nsw <4 x i32> %14, %13
+ %16 = and <4 x i32> %15, <i32 63, i32 63, i32 63, i32 63>
+ ret <4 x i32> %16
+}
+
+; 64-bit vector popcount (variant 3 - using multiply by -3) - 2 elements
+define <2 x i64> @popcnt3_64vec(<2 x i64> %0) {
+; CHECK-LABEL: @popcnt3_64vec(
+; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> [[TMP0:%.*]])
+; CHECK-NEXT: ret <2 x i64> [[TMP2]]
+;
+ %2 = lshr <2 x i64> %0, <i64 1, i64 1>
+ %3 = and <2 x i64> %2, <i64 6148914691236517205, i64 6148914691236517205>
+ %4 = sub <2 x i64> %0, %3
+ %5 = lshr <2 x i64> %4, <i64 2, i64 2>
+ %6 = and <2 x i64> %5, <i64 3689348814741910323, i64 3689348814741910323>
+ %7 = mul <2 x i64> %6, <i64 -3, i64 -3>
+ %8 = add <2 x i64> %7, %4
+ %9 = lshr <2 x i64> %8, <i64 4, i64 4>
+ %10 = add <2 x i64> %9, %8
+ %11 = and <2 x i64> %10, <i64 1085102592571150095, i64 1085102592571150095>
+ %12 = lshr <2 x i64> %11, <i64 8, i64 8>
+ %13 = add nuw nsw <2 x i64> %12, %11
+ %14 = lshr <2 x i64> %13, <i64 16, i64 16>
+ %15 = add nuw nsw <2 x i64> %14, %13
+ %16 = lshr <2 x i64> %15, <i64 32, i64 32>
+ %17 = add nuw nsw <2 x i64> %16, %15
+ %18 = and <2 x i64> %17, <i64 127, i64 127>
+ ret <2 x i64> %18
+}
+
+; Negative test case for popcnt2 i8 - wrong constant (should NOT optimize)
+define i8 @popcnt2_negative_i8(i8 noundef %0) {
+; CHECK-LABEL: @popcnt2_negative_i8(
+; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP0:%.*]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 85
+; CHECK-NEXT: [[TMP4:%.*]] = sub i8 [[TMP0]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = and i8 [[TMP4]], 51
+; CHECK-NEXT: [[TMP6:%.*]] = lshr i8 [[TMP4]], 2
+; CHECK-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], 51
+; CHECK-NEXT: [[TMP8:%.*]] = add nuw nsw i8 [[TMP7]], [[TMP5]]
+; CHECK-NEXT: [[TMP9:%.*]] = lshr i8 [[TMP8]], 4
+; CHECK-NEXT: [[TMP10:%.*]] = add nuw nsw i8 [[TMP9]], [[TMP8]]
+; CHECK-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 15
+; CHECK-NEXT: ret i8 [[TMP11]]
+;
+ %2 = lshr i8 %0, 1
+ %3 = and i8 %2, 85
+ %4 = sub i8 %0, %3
+ %5 = and i8 %4, 51
+ %6 = lshr i8 %4, 2
+ %7 = and i8 %6, 51
+ %8 = add nuw nsw i8 %7, %5
+ %9 = lshr i8 %8, 4
+ %10 = add nuw nsw i8 %9, %8
+ %11 = and i8 %10, 15
+ ret i8 %11
+}
+
+; Negative test case for popcnt3 i8 - using wrong multiplier (should NOT optimize)
+define i8 @popcnt3_negative_i8(i8 noundef %0) {
+; CHECK-LABEL: @popcnt3_negative_i8(
+; CHECK-NEXT: [[TMP2:%.*]] = lshr i8 [[TMP0:%.*]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = and i8 [[TMP2]], 85
+; CHECK-NEXT: [[TMP4:%.*]] = sub i8 [[TMP0]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = lshr i8 [[TMP4]], 2
+; CHECK-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 51
+; CHECK-NEXT: [[TMP7:%.*]] = mul i8 [[TMP6]], -3
+; CHECK-NEXT: [[TMP8:%.*]] = add i8 [[TMP7]], [[TMP4]]
+; CHECK-NEXT: [[TMP9:%.*]] = lshr i8 [[TMP8]], 4
+; CHECK-NEXT: [[TMP10:%.*]] = add i8 [[TMP9]], [[TMP8]]
+; CHECK-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], 15
+; CHECK-NEXT: ret i8 [[TMP11]]
+;
+ %2 = lshr i8 %0, 1
+ %3 = and i8 %2, 85
+ %4 = sub i8 %0, %3
+ %5 = lshr i8 %4, 2
+ %6 = and i8 %5, 51
+ %7 = mul i8 %6, -3
+ %8 = add i8 %7, %4
+ %9 = lshr i8 %8, 4
+ %10 = add i8 %9, %8
+ %11 = and i8 %10, 15
+ ret i8 %11
+}
+
+; Negative test case for popcnt2 i32 - wrong constant in second step (should NOT optimize)
+define i32 @popcnt2_negative_i32(i32 noundef %0) {
+; CHECK-LABEL: @popcnt2_negative_i32(
+; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP0:%.*]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 1431655765
+; CHECK-NEXT: [[TMP4:%.*]] = sub i32 [[TMP0]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP4]], 858993460
+; CHECK-NEXT: [[TMP6:%.*]] = lshr i32 [[TMP4]], 2
+; CHECK-NEXT: [[TMP7:%.*]] = and i32 [[TMP6]], 858993459
+; CHECK-NEXT: [[TMP8:%.*]] = add nuw nsw i32 [[TMP7]], [[TMP5]]
+; CHECK-NEXT: [[TMP9:%.*]] = lshr i32 [[TMP8]], 4
+; CHECK-NEXT: [[TMP10:%.*]] = add nuw nsw i32 [[TMP9]], [[TMP8]]
+; CHECK-NEXT: [[TMP11:%.*]] = and i32 [[TMP10]], 252645135
+; CHECK-NEXT: [[TMP12:%.*]] = lshr i32 [[TMP11]], 8
+; CHECK-NEXT: [[TMP13:%.*]] = add nuw nsw i32 [[TMP12]], [[TMP11]]
+; CHECK-NEXT: [[TMP14:%.*]] = lshr i32 [[TMP13]], 16
+; CHECK-NEXT: [[TMP15:%.*]] = add nuw nsw i32 [[TMP14]], [[TMP13]]
+; CHECK-NEXT: [[TMP16:%.*]] = and i32 [[TMP15]], 63
+; CHECK-NEXT: ret i32 [[TMP16]]
+;
+ %2 = lshr i32 %0, 1
+ %3 = and i32 %2, 1431655765
+ %4 = sub i32 %0, %3
+ %5 = and i32 %4, 858993460 ; Wrong constant (should be 858993459)
+ %6 = lshr i32 %4, 2
+ %7 = and i32 %6, 858993459
+ %8 = add nuw nsw i32 %7, %5
+ %9 = lshr i32 %8, 4
+ %10 = add nuw nsw i32 %9, %8
+ %11 = and i32 %10, 252645135
+ %12 = lshr i32 %11, 8
+ %13 = add nuw nsw i32 %12, %11
+ %14 = lshr i32 %13, 16
+ %15 = add nuw nsw i32 %14, %13
+ %16 = and i32 %15, 63
+ ret i32 %16
+}
+
+; Negative test case for popcnt3 i32 - using wrong multiplier (should NOT optimize)
+define i32 @popcnt3_negative_i32(i32 noundef %0) {
+; CHECK-LABEL: @popcnt3_negative_i32(
+; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP0:%.*]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 1431655765
+; CHECK-NEXT: [[TMP4:%.*]] = sub i32 [[TMP0]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = lshr i32 [[TMP4]], 2
+; CHECK-NEXT: [[TMP6:%.*]] = and i32 [[TMP5]], 858993459
+; CHECK-NEXT: [[TMP7:%.*]] = mul i32 [[TMP6]], -2
+; CHECK-NEXT: [[TMP8:%.*]] = add i32 [[TMP7]], [[TMP4]]
+; CHECK-NEXT: [[TMP9:%.*]] = lshr i32 [[TMP8]], 4
+; CHECK-NEXT: [[TMP10:%.*]] = add i32 [[TMP9]], [[TMP8]]
+; CHECK-NEXT: [[TMP11:%.*]] = and i32 [[TMP10]], 252645135
+; CHECK-NEXT: [[TMP12:%.*]] = lshr i32 [[TMP11]], 8
+; CHECK-NEXT: [[TMP13:%.*]] = add nuw nsw i32 [[TMP12]], [[TMP11]]
+; CHECK-NEXT: [[TMP14:%.*]] = lshr i32 [[TMP13]], 16
+; CHECK-NEXT: [[TMP15:%.*]] = add nuw nsw i32 [[TMP14]], [[TMP13]]
+; CHECK-NEXT: [[TMP16:%.*]] = and i32 [[TMP15]], 63
+; CHECK-NEXT: ret i32 [[TMP16]]
+;
+ %2 = lshr i32 %0, 1
+ %3 = and i32 %2, 1431655765
+ %4 = sub i32 %0, %3
+ %5 = lshr i32 %4, 2
+ %6 = and i32 %5, 858993459
+ %7 = mul i32 %6, -2 ; Wrong multiplier (should be -3)
+ %8 = add i32 %7, %4
+ %9 = lshr i32 %8, 4
+ %10 = add i32 %9, %8
+ %11 = and i32 %10, 252645135
+ %12 = lshr i32 %11, 8
+ %13 = add nuw nsw i32 %12, %11
+ %14 = lshr i32 %13, 16
+ %15 = add nuw nsw i32 %14, %13
+ %16 = and i32 %15, 63
+ ret i32 %16
+}
>From 74dde1550f505c68572d25f08bc06b5f5f9b787e Mon Sep 17 00:00:00 2001
From: Rohit Aggarwal <Rohit.Aggarwal at amd.com>
Date: Thu, 12 Mar 2026 20:52:03 +0530
Subject: [PATCH 3/9] Fix the review comments
---
.../AggressiveInstCombine.cpp | 37 +++++++------------
1 file changed, 13 insertions(+), 24 deletions(-)
diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
index e1ad6458187ce..8da569c660121 100644
--- a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
+++ b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
@@ -373,7 +373,7 @@ static bool tryToRecognizePopCount(Instruction &I) {
}
// Try to recognize below function as popcount intrinsic.
-// https://doc.lagout.org/security/Hackers%20Delight.pdf
+// Ref. Hackers Delight
// Also used in TargetLowering::expandCTPOP().
//
// int popcnt(unsigned x) {
@@ -403,7 +403,7 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
return false;
unsigned Len = Ty->getScalarSizeInBits();
- if (!(Len == 16 || Len == 32 || Len == 64))
+ if (Len != 16 && Len != 32 && Len != 64)
return false;
APInt Mask55 = APInt::getSplat(Len, APInt(8, 0x55));
APInt Mask33 = APInt::getSplat(Len, APInt(8, 0x33));
@@ -411,19 +411,9 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
APInt MaskRes = APInt(Len, 2 * Len - 1);
- Value *Op0 = I.getOperand(0);
- Value *Op1 = I.getOperand(1);
-
- // Matching "x & 0x001F" (16-bit).
- // Matching "x & 0x0000003F" (32-bit).
- // Matching "x & 0x0000007F" (64-bit).
- if (!(match(Op0, m_SpecificInt(MaskRes)) ||
- match(Op1, m_SpecificInt(MaskRes)))) {
+ Value *Add1;
+ if (!match(&I, m_And(m_Value(Add1), m_SpecificInt(MaskRes))))
return false;
- }
-
- // Get the value being masked
- Value *Add1 = (match(Op0, m_SpecificInt(MaskRes))) ? Op1 : Op0;
// Matching "x = x + (x >> 32)" for 64-bit.
Value *Add2 = Add1;
@@ -436,7 +426,7 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
// Matching "x = x + (x >> 16)" for 32-bit and 64-bit.
Value *Add3 = Add2;
- if (Len == 32 || Len == 64) {
+ if (Len >= 32) {
if (!match(Add2, m_c_Add(m_LShr(m_Value(Add3), m_SpecificInt(16)),
m_Deferred(Add3)))) {
return false;
@@ -452,9 +442,9 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
// Matching "x = (x + (x >> 4)) & 0x0F0F0F0F".
Value *Add4;
- if (!match(And1, m_c_And(m_c_Add(m_LShr(m_Value(Add4), m_SpecificInt(4)),
- m_Deferred(Add4)),
- m_SpecificInt(Mask0F)))) {
+ if (!match(And1, m_And(m_c_Add(m_LShr(m_Value(Add4), m_SpecificInt(4)),
+ m_Deferred(Add4)),
+ m_SpecificInt(Mask0F)))) {
return false;
}
@@ -462,10 +452,9 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
llvm::APInt NegThree(/*BitWidth=*/Len, /*Value=*/-3,
/*isSigned=*/true);
// x = (x & 0x33333333) + ((x >> 2) & 0x33333333)".
- if (!(match(Add4,
- m_c_Add(m_c_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
- m_SpecificInt(Mask33)),
- m_c_And(m_Deferred(Sub1), m_SpecificInt(Mask33)))) ||
+ if (!(match(Add4, m_c_Add(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
+ m_SpecificInt(Mask33)),
+ m_And(m_Deferred(Sub1), m_SpecificInt(Mask33)))) ||
// Matching "x = x - 3*((x >> 2) & 0x33333333)".
match(Add4, m_Add(m_Mul(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
m_SpecificInt(Mask33)),
@@ -477,8 +466,8 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
Value *Root;
// x = x - ((x >> 1) & 0x55555555);
if (match(Sub1, m_Sub(m_Value(Root),
- m_c_And(m_LShr(m_Deferred(Root), m_SpecificInt(1)),
- m_SpecificInt(Mask55))))) {
+ m_And(m_LShr(m_Deferred(Root), m_SpecificInt(1)),
+ m_SpecificInt(Mask55))))) {
LLVM_DEBUG(dbgs() << "Recognized popcount intrinsic\n");
IRBuilder<> Builder(&I);
I.replaceAllUsesWith(
>From 3366217bed357307ceebb81118bcffdd685b8df8 Mon Sep 17 00:00:00 2001
From: Rohit Aggarwal <Rohit.Aggarwal at amd.com>
Date: Mon, 23 Mar 2026 13:20:15 +0530
Subject: [PATCH 4/9] Improve the code
---
.../AggressiveInstCombine.cpp | 72 ++++++++-----------
1 file changed, 29 insertions(+), 43 deletions(-)
diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
index 8da569c660121..ca139f2c74c7c 100644
--- a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
+++ b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
@@ -403,8 +403,10 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
return false;
unsigned Len = Ty->getScalarSizeInBits();
- if (Len != 16 && Len != 32 && Len != 64)
+
+ if (Len > 64 || Len <= 8 || Len % 8 != 0)
return false;
+
APInt Mask55 = APInt::getSplat(Len, APInt(8, 0x55));
APInt Mask33 = APInt::getSplat(Len, APInt(8, 0x33));
APInt Mask0F = APInt::getSplat(Len, APInt(8, 0x0F));
@@ -415,68 +417,52 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
if (!match(&I, m_And(m_Value(Add1), m_SpecificInt(MaskRes))))
return false;
- // Matching "x = x + (x >> 32)" for 64-bit.
- Value *Add2 = Add1;
- if (Len == 64) {
- if (!match(Add1, m_c_Add(m_LShr(m_Value(Add2), m_SpecificInt(32)),
- m_Deferred(Add2)))) {
- return false;
- }
- }
-
- // Matching "x = x + (x >> 16)" for 32-bit and 64-bit.
- Value *Add3 = Add2;
- if (Len >= 32) {
- if (!match(Add2, m_c_Add(m_LShr(m_Value(Add3), m_SpecificInt(16)),
- m_Deferred(Add3)))) {
+ Value *Add2;
+ for (unsigned I = Len; I >= 16; I = I / 2) {
+ // Matching "x = x + (x >> I/2)" for I-bit.
+ if (Len >= I &&
+ !match(Add1, m_c_Add(m_LShr(m_Value(Add2), m_SpecificInt(I / 2)),
+ m_Deferred(Add2))))
return false;
- }
- }
-
- // Matching "x = x + (x >> 8)".
- Value *And1;
- if (!match(Add3, m_c_Add(m_LShr(m_Value(And1), m_SpecificInt(8)),
- m_Deferred(And1)))) {
- return false;
+ Add1 = Add2;
+ Add2 = nullptr;
}
+ Value *And1 = Add1;
+ Add2 = nullptr;
// Matching "x = (x + (x >> 4)) & 0x0F0F0F0F".
- Value *Add4;
- if (!match(And1, m_And(m_c_Add(m_LShr(m_Value(Add4), m_SpecificInt(4)),
- m_Deferred(Add4)),
- m_SpecificInt(Mask0F)))) {
+ if (!match(And1, m_And(m_c_Add(m_LShr(m_Value(Add2), m_SpecificInt(4)),
+ m_Deferred(Add2)),
+ m_SpecificInt(Mask0F))))
return false;
- }
Value *Sub1;
llvm::APInt NegThree(/*BitWidth=*/Len, /*Value=*/-3,
/*isSigned=*/true);
// x = (x & 0x33333333) + ((x >> 2) & 0x33333333)".
- if (!(match(Add4, m_c_Add(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
+ if (!(match(Add2, m_c_Add(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
m_SpecificInt(Mask33)),
m_And(m_Deferred(Sub1), m_SpecificInt(Mask33)))) ||
// Matching "x = x - 3*((x >> 2) & 0x33333333)".
- match(Add4, m_Add(m_Mul(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
+ match(Add2, m_Add(m_Mul(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
m_SpecificInt(Mask33)),
m_SpecificInt(NegThree)),
- m_Deferred(Sub1))))) {
+ m_Deferred(Sub1)))))
return false;
- }
Value *Root;
// x = x - ((x >> 1) & 0x55555555);
- if (match(Sub1, m_Sub(m_Value(Root),
- m_And(m_LShr(m_Deferred(Root), m_SpecificInt(1)),
- m_SpecificInt(Mask55))))) {
- LLVM_DEBUG(dbgs() << "Recognized popcount intrinsic\n");
- IRBuilder<> Builder(&I);
- I.replaceAllUsesWith(
- Builder.CreateIntrinsic(Intrinsic::ctpop, I.getType(), {Root}));
- ++NumPopCountRecognized;
- return true;
- }
+ if (!match(Sub1, m_Sub(m_Value(Root),
+ m_And(m_LShr(m_Deferred(Root), m_SpecificInt(1)),
+ m_SpecificInt(Mask55)))))
+ return false;
- return false;
+ LLVM_DEBUG(dbgs() << "Recognized popcount intrinsic\n");
+ IRBuilder<> Builder(&I);
+ I.replaceAllUsesWith(
+ Builder.CreateIntrinsic(Intrinsic::ctpop, I.getType(), {Root}));
+ ++NumPopCountRecognized;
+ return true;
}
/// Fold smin(smax(fptosi(x), C1), C2) to llvm.fptosi.sat(x), providing C1 and
>From bc2d45b07b9d65f3ea77e155949d65322315323a Mon Sep 17 00:00:00 2001
From: Rohit Aggarwal <Rohit.Aggarwal at amd.com>
Date: Tue, 24 Mar 2026 17:57:51 +0530
Subject: [PATCH 5/9] Add the power of 2 check
---
.../AggressiveInstCombine.cpp | 4 +
.../AggressiveInstCombine/popcount.ll | 164 ++++++++++++++++++
2 files changed, 168 insertions(+)
diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
index ca139f2c74c7c..df799abb426e9 100644
--- a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
+++ b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
@@ -407,6 +407,10 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
if (Len > 64 || Len <= 8 || Len % 8 != 0)
return false;
+ // Len should be a power of 2 for the loop to work correctly
+ if (!isPowerOf2_32(Len))
+ return false;
+
APInt Mask55 = APInt::getSplat(Len, APInt(8, 0x55));
APInt Mask33 = APInt::getSplat(Len, APInt(8, 0x33));
APInt Mask0F = APInt::getSplat(Len, APInt(8, 0x0F));
diff --git a/llvm/test/Transforms/AggressiveInstCombine/popcount.ll b/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
index 9909854a8ac07..5f18e4e172443 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
@@ -659,3 +659,167 @@ define i32 @popcnt3_negative_i32(i32 noundef %0) {
%16 = and i32 %15, 63
ret i32 %16
}
+
+; Negative test case for popcnt2 i24 - non-power-of-2 bit width (should NOT optimize)
+define i24 @popcnt2_negative_i24(i24 noundef %0) {
+; CHECK-LABEL: @popcnt2_negative_i24(
+; CHECK-NEXT: [[TMP2:%.*]] = lshr i24 [[TMP0:%.*]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = and i24 [[TMP2]], 5592405
+; CHECK-NEXT: [[TMP4:%.*]] = sub i24 [[TMP0]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = and i24 [[TMP4]], 3355443
+; CHECK-NEXT: [[TMP6:%.*]] = lshr i24 [[TMP4]], 2
+; CHECK-NEXT: [[TMP7:%.*]] = and i24 [[TMP6]], 3355443
+; CHECK-NEXT: [[TMP8:%.*]] = add nuw nsw i24 [[TMP7]], [[TMP5]]
+; CHECK-NEXT: [[TMP9:%.*]] = lshr i24 [[TMP8]], 4
+; CHECK-NEXT: [[TMP10:%.*]] = add nuw nsw i24 [[TMP9]], [[TMP8]]
+; CHECK-NEXT: [[TMP11:%.*]] = and i24 [[TMP10]], 986895
+; CHECK-NEXT: [[TMP12:%.*]] = lshr i24 [[TMP11]], 8
+; CHECK-NEXT: [[TMP13:%.*]] = add nuw nsw i24 [[TMP12]], [[TMP11]]
+; CHECK-NEXT: [[TMP14:%.*]] = lshr i24 [[TMP13]], 16
+; CHECK-NEXT: [[TMP15:%.*]] = add nuw nsw i24 [[TMP14]], [[TMP13]]
+; CHECK-NEXT: [[TMP16:%.*]] = and i24 [[TMP15]], 47
+; CHECK-NEXT: ret i24 [[TMP16]]
+;
+ %2 = lshr i24 %0, 1
+ %3 = and i24 %2, 5592405 ; 0x555555
+ %4 = sub i24 %0, %3
+ %5 = and i24 %4, 3355443 ; 0x333333
+ %6 = lshr i24 %4, 2
+ %7 = and i24 %6, 3355443
+ %8 = add nuw nsw i24 %7, %5
+ %9 = lshr i24 %8, 4
+ %10 = add nuw nsw i24 %9, %8
+ %11 = and i24 %10, 986895 ; 0x0F0F0F
+ %12 = lshr i24 %11, 8
+ %13 = add nuw nsw i24 %12, %11
+ %14 = lshr i24 %13, 16
+ %15 = add nuw nsw i24 %14, %13
+ %16 = and i24 %15, 47 ; 2*24-1 = 47
+ ret i24 %16
+}
+
+; Negative test case for popcnt2 i40 - non-power-of-2 bit width (should NOT optimize)
+define i40 @popcnt2_negative_i40(i40 noundef %0) {
+; CHECK-LABEL: @popcnt2_negative_i40(
+; CHECK-NEXT: [[TMP2:%.*]] = lshr i40 [[TMP0:%.*]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = and i40 [[TMP2]], 366503875925
+; CHECK-NEXT: [[TMP4:%.*]] = sub i40 [[TMP0]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = and i40 [[TMP4]], 219902325555
+; CHECK-NEXT: [[TMP6:%.*]] = lshr i40 [[TMP4]], 2
+; CHECK-NEXT: [[TMP7:%.*]] = and i40 [[TMP6]], 219902325555
+; CHECK-NEXT: [[TMP8:%.*]] = add nuw nsw i40 [[TMP7]], [[TMP5]]
+; CHECK-NEXT: [[TMP9:%.*]] = lshr i40 [[TMP8]], 4
+; CHECK-NEXT: [[TMP10:%.*]] = add nuw nsw i40 [[TMP9]], [[TMP8]]
+; CHECK-NEXT: [[TMP11:%.*]] = and i40 [[TMP10]], 67818775935
+; CHECK-NEXT: [[TMP12:%.*]] = lshr i40 [[TMP11]], 8
+; CHECK-NEXT: [[TMP13:%.*]] = add nuw nsw i40 [[TMP12]], [[TMP11]]
+; CHECK-NEXT: [[TMP14:%.*]] = lshr i40 [[TMP13]], 16
+; CHECK-NEXT: [[TMP15:%.*]] = add nuw nsw i40 [[TMP14]], [[TMP13]]
+; CHECK-NEXT: [[TMP16:%.*]] = lshr i40 [[TMP15]], 32
+; CHECK-NEXT: [[TMP17:%.*]] = add nuw nsw i40 [[TMP16]], [[TMP15]]
+; CHECK-NEXT: [[TMP18:%.*]] = and i40 [[TMP17]], 79
+; CHECK-NEXT: ret i40 [[TMP18]]
+;
+ %2 = lshr i40 %0, 1
+ %3 = and i40 %2, 366503875925 ; 0x5555555555
+ %4 = sub i40 %0, %3
+ %5 = and i40 %4, 219902325555 ; 0x3333333333
+ %6 = lshr i40 %4, 2
+ %7 = and i40 %6, 219902325555
+ %8 = add nuw nsw i40 %7, %5
+ %9 = lshr i40 %8, 4
+ %10 = add nuw nsw i40 %9, %8
+ %11 = and i40 %10, 67818775935 ; 0x0F0F0F0F0F
+ %12 = lshr i40 %11, 8
+ %13 = add nuw nsw i40 %12, %11
+ %14 = lshr i40 %13, 16
+ %15 = add nuw nsw i40 %14, %13
+ %16 = lshr i40 %15, 32
+ %17 = add nuw nsw i40 %16, %15
+ %18 = and i40 %17, 79 ; 2*40-1 = 79
+ ret i40 %18
+}
+
+; Negative test case for popcnt2 i48 - non-power-of-2 bit width (should NOT optimize)
+define i48 @popcnt2_negative_i48(i48 noundef %0) {
+; CHECK-LABEL: @popcnt2_negative_i48(
+; CHECK-NEXT: [[TMP2:%.*]] = lshr i48 [[TMP0:%.*]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = and i48 [[TMP2]], 93824992236885
+; CHECK-NEXT: [[TMP4:%.*]] = sub i48 [[TMP0]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = and i48 [[TMP4]], 56294995342131
+; CHECK-NEXT: [[TMP6:%.*]] = lshr i48 [[TMP4]], 2
+; CHECK-NEXT: [[TMP7:%.*]] = and i48 [[TMP6]], 56294995342131
+; CHECK-NEXT: [[TMP8:%.*]] = add nuw nsw i48 [[TMP7]], [[TMP5]]
+; CHECK-NEXT: [[TMP9:%.*]] = lshr i48 [[TMP8]], 4
+; CHECK-NEXT: [[TMP10:%.*]] = add nuw nsw i48 [[TMP9]], [[TMP8]]
+; CHECK-NEXT: [[TMP11:%.*]] = and i48 [[TMP10]], 17361641481615
+; CHECK-NEXT: [[TMP12:%.*]] = lshr i48 [[TMP11]], 8
+; CHECK-NEXT: [[TMP13:%.*]] = add nuw nsw i48 [[TMP12]], [[TMP11]]
+; CHECK-NEXT: [[TMP14:%.*]] = lshr i48 [[TMP13]], 16
+; CHECK-NEXT: [[TMP15:%.*]] = add nuw nsw i48 [[TMP14]], [[TMP13]]
+; CHECK-NEXT: [[TMP16:%.*]] = lshr i48 [[TMP15]], 32
+; CHECK-NEXT: [[TMP17:%.*]] = add nuw nsw i48 [[TMP16]], [[TMP15]]
+; CHECK-NEXT: [[TMP18:%.*]] = and i48 [[TMP17]], 95
+; CHECK-NEXT: ret i48 [[TMP18]]
+;
+ %2 = lshr i48 %0, 1
+ %3 = and i48 %2, 93824992236885 ; 0x555555555555
+ %4 = sub i48 %0, %3
+ %5 = and i48 %4, 56294995342131 ; 0x333333333333
+ %6 = lshr i48 %4, 2
+ %7 = and i48 %6, 56294995342131
+ %8 = add nuw nsw i48 %7, %5
+ %9 = lshr i48 %8, 4
+ %10 = add nuw nsw i48 %9, %8
+ %11 = and i48 %10, 17361641481615 ; 0x0F0F0F0F0F0F
+ %12 = lshr i48 %11, 8
+ %13 = add nuw nsw i48 %12, %11
+ %14 = lshr i48 %13, 16
+ %15 = add nuw nsw i48 %14, %13
+ %16 = lshr i48 %15, 32
+ %17 = add nuw nsw i48 %16, %15
+ %18 = and i48 %17, 95 ; 2*48-1 = 95
+ ret i48 %18
+}
+
+; Negative test case for popcnt2 i56 - non-power-of-2 bit width (should NOT optimize)
+define i56 @popcnt2_negative_i56(i56 noundef %0) {
+; CHECK-LABEL: @popcnt2_negative_i56(
+; CHECK-NEXT: [[TMP2:%.*]] = lshr i56 [[TMP0:%.*]], 1
+; CHECK-NEXT: [[TMP3:%.*]] = and i56 [[TMP2]], 24019198012642645
+; CHECK-NEXT: [[TMP4:%.*]] = sub i56 [[TMP0]], [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = and i56 [[TMP4]], 14411518807585587
+; CHECK-NEXT: [[TMP6:%.*]] = lshr i56 [[TMP4]], 2
+; CHECK-NEXT: [[TMP7:%.*]] = and i56 [[TMP6]], 14411518807585587
+; CHECK-NEXT: [[TMP8:%.*]] = add nuw nsw i56 [[TMP7]], [[TMP5]]
+; CHECK-NEXT: [[TMP9:%.*]] = lshr i56 [[TMP8]], 4
+; CHECK-NEXT: [[TMP10:%.*]] = add nuw nsw i56 [[TMP9]], [[TMP8]]
+; CHECK-NEXT: [[TMP11:%.*]] = and i56 [[TMP10]], 4444132406286415
+; CHECK-NEXT: [[TMP12:%.*]] = lshr i56 [[TMP11]], 8
+; CHECK-NEXT: [[TMP13:%.*]] = add nuw nsw i56 [[TMP12]], [[TMP11]]
+; CHECK-NEXT: [[TMP14:%.*]] = lshr i56 [[TMP13]], 16
+; CHECK-NEXT: [[TMP15:%.*]] = add nuw nsw i56 [[TMP14]], [[TMP13]]
+; CHECK-NEXT: [[TMP16:%.*]] = lshr i56 [[TMP15]], 32
+; CHECK-NEXT: [[TMP17:%.*]] = add nuw nsw i56 [[TMP16]], [[TMP15]]
+; CHECK-NEXT: [[TMP18:%.*]] = and i56 [[TMP17]], 111
+; CHECK-NEXT: ret i56 [[TMP18]]
+;
+ %2 = lshr i56 %0, 1
+ %3 = and i56 %2, 24019198012642645 ; 0x55555555555555
+ %4 = sub i56 %0, %3
+ %5 = and i56 %4, 14411518807585587 ; 0x33333333333333
+ %6 = lshr i56 %4, 2
+ %7 = and i56 %6, 14411518807585587
+ %8 = add nuw nsw i56 %7, %5
+ %9 = lshr i56 %8, 4
+ %10 = add nuw nsw i56 %9, %8
+ %11 = and i56 %10, 4444132406286415 ; 0x0F0F0F0F0F0F0F
+ %12 = lshr i56 %11, 8
+ %13 = add nuw nsw i56 %12, %11
+ %14 = lshr i56 %13, 16
+ %15 = add nuw nsw i56 %14, %13
+ %16 = lshr i56 %15, 32
+ %17 = add nuw nsw i56 %16, %15
+ %18 = and i56 %17, 111 ; 2*56-1 = 111
+ ret i56 %18
+}
>From 83f1608f917ca34ffe3706b20b457484e08ca930 Mon Sep 17 00:00:00 2001
From: Rohit Aggarwal <Rohit.Aggarwal at amd.com>
Date: Tue, 31 Mar 2026 12:13:26 +0530
Subject: [PATCH 6/9] Removing unwanted check for Len >= I
---
.../Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
index df799abb426e9..243d6f5031aca 100644
--- a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
+++ b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
@@ -424,8 +424,7 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
Value *Add2;
for (unsigned I = Len; I >= 16; I = I / 2) {
// Matching "x = x + (x >> I/2)" for I-bit.
- if (Len >= I &&
- !match(Add1, m_c_Add(m_LShr(m_Value(Add2), m_SpecificInt(I / 2)),
+ if (!match(Add1, m_c_Add(m_LShr(m_Value(Add2), m_SpecificInt(I / 2)),
m_Deferred(Add2))))
return false;
Add1 = Add2;
>From 31a35f3eff9e64f9245fd75f84c82b00631e711a Mon Sep 17 00:00:00 2001
From: Rohit Aggarwal <Rohit.Aggarwal at amd.com>
Date: Wed, 1 Apr 2026 11:09:30 +0530
Subject: [PATCH 7/9] Remove unwanted nullptr initialization.
---
.../Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
index 243d6f5031aca..0b699ecf85348 100644
--- a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
+++ b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
@@ -428,11 +428,9 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
m_Deferred(Add2))))
return false;
Add1 = Add2;
- Add2 = nullptr;
}
Value *And1 = Add1;
- Add2 = nullptr;
// Matching "x = (x + (x >> 4)) & 0x0F0F0F0F".
if (!match(And1, m_And(m_c_Add(m_LShr(m_Value(Add2), m_SpecificInt(4)),
m_Deferred(Add2)),
>From fc485e93de56f8363d71f9a4e5bfe35d3cfa4645 Mon Sep 17 00:00:00 2001
From: Rohit Aggarwal <Rohit.Aggarwal at amd.com>
Date: Wed, 1 Apr 2026 13:01:50 +0530
Subject: [PATCH 8/9] Implement more review comments
---
.../AggressiveInstCombine.cpp | 18 ++++++++----------
1 file changed, 8 insertions(+), 10 deletions(-)
diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
index 0b699ecf85348..5860b1787f673 100644
--- a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
+++ b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
@@ -374,8 +374,6 @@ static bool tryToRecognizePopCount(Instruction &I) {
// Try to recognize below function as popcount intrinsic.
// Ref. Hackers Delight
-// Also used in TargetLowering::expandCTPOP().
-//
// int popcnt(unsigned x) {
// x = x - ((x >> 1) & 0x55555555);
// x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
@@ -441,14 +439,14 @@ static bool tryToRecognizePopCount2n3(Instruction &I) {
llvm::APInt NegThree(/*BitWidth=*/Len, /*Value=*/-3,
/*isSigned=*/true);
// x = (x & 0x33333333) + ((x >> 2) & 0x33333333)".
- if (!(match(Add2, m_c_Add(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
- m_SpecificInt(Mask33)),
- m_And(m_Deferred(Sub1), m_SpecificInt(Mask33)))) ||
- // Matching "x = x - 3*((x >> 2) & 0x33333333)".
- match(Add2, m_Add(m_Mul(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
- m_SpecificInt(Mask33)),
- m_SpecificInt(NegThree)),
- m_Deferred(Sub1)))))
+ if (!match(Add2, m_c_Add(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
+ m_SpecificInt(Mask33)),
+ m_And(m_Deferred(Sub1), m_SpecificInt(Mask33)))) &&
+ // Matching "x = x - 3*((x >> 2) & 0x33333333)".
+ !match(Add2, m_Add(m_Mul(m_And(m_LShr(m_Value(Sub1), m_SpecificInt(2)),
+ m_SpecificInt(Mask33)),
+ m_SpecificInt(NegThree)),
+ m_Deferred(Sub1))))
return false;
Value *Root;
>From 322bf3f49572fb866729aa8002a7f7b097c8e289 Mon Sep 17 00:00:00 2001
From: Rohit Aggarwal <Rohit.Aggarwal at amd.com>
Date: Mon, 13 Apr 2026 12:53:37 +0530
Subject: [PATCH 9/9] Improve test case as per review
---
llvm/test/Transforms/AggressiveInstCombine/popcount.ll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/test/Transforms/AggressiveInstCombine/popcount.ll b/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
index 5f18e4e172443..33125073f3bf9 100644
--- a/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
+++ b/llvm/test/Transforms/AggressiveInstCombine/popcount.ll
@@ -681,7 +681,7 @@ define i24 @popcnt2_negative_i24(i24 noundef %0) {
; CHECK-NEXT: ret i24 [[TMP16]]
;
%2 = lshr i24 %0, 1
- %3 = and i24 %2, 5592405 ; 0x555555
+ %3 = and i24 %2, u0x555555 ; 0x555555
%4 = sub i24 %0, %3
%5 = and i24 %4, 3355443 ; 0x333333
%6 = lshr i24 %4, 2
More information about the llvm-commits
mailing list