[llvm-branch-commits] [llvm] [InstCombine] Fold trunc(ctpop(A)) + trunc(ctpop(B)) -> trunc(ctpop(A) + ctpop(B)) (PR #231332)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Oct 12 16:58:09 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Luke Lau (lukel97)
<details>
<summary>Changes</summary>
This allows the combine added in #<!-- -->231321 to kick in and fold the motivating ctpop case in automotive-bitcount:
```c
static char bits[256] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8};
int CDECL ntbl_bitcount(long int x)
{
return
bits[ (int) (x & 0x0000000FUL) ] +
bits[ (int)((x & 0x000000F0UL) >> 4) ] +
bits[ (int)((x & 0x00000F00UL) >> 8) ] +
bits[ (int)((x & 0x0000F000UL) >> 12)] +
bits[ (int)((x & 0x000F0000UL) >> 16)] +
bits[ (int)((x & 0x00F00000UL) >> 20)] +
bits[ (int)((x & 0x0F000000UL) >> 24)] +
bits[ (int)((x & 0xF0000000UL) >> 28)];
}
```
---
Full diff: https://github.com/llvm/llvm-project/pull/231332.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp (+6)
- (modified) llvm/test/Transforms/InstCombine/ctpop.ll (+19-10)
``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 9ff6991388433..72e6fb80beb10 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2046,6 +2046,12 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
Builder.CreateIntrinsic(Intrinsic::umax, {I.getType()}, {A, B}));
}
+ // trunc(ctpop(A)) + trunc(ctpop(B)) => trunc(ctpop(A) + ctpop(B))
+ if (match(LHS, m_OneUse(m_Trunc(m_Value(A, m_Ctpop(m_Value()))))) &&
+ match(RHS, m_OneUse(m_Trunc(m_Value(B, m_Ctpop(m_Value()))))) &&
+ A->getType() == B->getType())
+ return new TruncInst(Builder.CreateAdd(A, B), I.getType());
+
// ctpop(A) + ctpop(B) => ctpop(A | B) if A and B have no bits set in common.
if (match(LHS, m_OneUse(m_Ctpop(m_Value(A)))) &&
match(RHS, m_OneUse(m_Ctpop(m_Value(B)))) &&
diff --git a/llvm/test/Transforms/InstCombine/ctpop.ll b/llvm/test/Transforms/InstCombine/ctpop.ll
index 5bb8dafaf37c4..1886f0bbef0a9 100644
--- a/llvm/test/Transforms/InstCombine/ctpop.ll
+++ b/llvm/test/Transforms/InstCombine/ctpop.ll
@@ -263,6 +263,22 @@ define <2 x i32> @ctpop_add_no_common_bits_vec_use2(<2 x i32> %a, <2 x i32> %b,
ret <2 x i32> %res
}
+define i32 @ctpop_add_trunc(i64 %a, i64 %b) {
+; CHECK-LABEL: @ctpop_add_trunc(
+; CHECK-NEXT: [[CTPOP1:%.*]] = call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 [[A:%.*]])
+; CHECK-NEXT: [[CTPOP2:%.*]] = call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 [[B:%.*]])
+; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[CTPOP1]], [[CTPOP2]]
+; CHECK-NEXT: [[RES:%.*]] = trunc nuw nsw i64 [[TMP1]] to i32
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %ctpop1 = call i64 @llvm.ctpop.i64(i64 %a)
+ %t1 = trunc i64 %ctpop1 to i32
+ %ctpop2 = call i64 @llvm.ctpop.i64(i64 %b)
+ %t2 = trunc i64 %ctpop2 to i32
+ %res = add i32 %t1, %t2
+ ret i32 %res
+}
+
define i8 @ctpop_rotate_left(i8 %a, i8 %amt) {
; CHECK-LABEL: @ctpop_rotate_left(
; CHECK-NEXT: [[RES:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[A:%.*]])
@@ -519,19 +535,12 @@ define i32 @ctpop_add_no_common_bits_shifted(i32 %x) {
ret i32 %r
}
-; TODO: We can combine these two ctpops through the truncs
-
define i32 @ctpop_add_no_common_bits_shifted_trunc(i64 %x) {
; CHECK-LABEL: @ctpop_add_no_common_bits_shifted_trunc(
-; CHECK-NEXT: [[LO:%.*]] = and i64 [[X:%.*]], 15
-; CHECK-NEXT: [[C0:%.*]] = call range(i64 0, 5) i64 @llvm.ctpop.i64(i64 [[LO]])
-; CHECK-NEXT: [[T0:%.*]] = trunc nuw nsw i64 [[C0]] to i32
-; CHECK-NEXT: [[S:%.*]] = lshr i64 [[X]], 8
-; CHECK-NEXT: [[HI:%.*]] = and i64 [[S]], 15
-; CHECK-NEXT: [[C1:%.*]] = call range(i64 0, 5) i64 @llvm.ctpop.i64(i64 [[HI]])
+; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[X:%.*]], 3855
+; CHECK-NEXT: [[C1:%.*]] = call range(i64 0, 9) i64 @llvm.ctpop.i64(i64 [[TMP1]])
; CHECK-NEXT: [[T1:%.*]] = trunc nuw nsw i64 [[C1]] to i32
-; CHECK-NEXT: [[R:%.*]] = add nuw nsw i32 [[T0]], [[T1]]
-; CHECK-NEXT: ret i32 [[R]]
+; CHECK-NEXT: ret i32 [[T1]]
;
%lo = and i64 %x, 15
%c0 = call i64 @llvm.ctpop.i64(i64 %lo)
``````````
</details>
https://github.com/llvm/llvm-project/pull/231332
More information about the llvm-branch-commits
mailing list