[clang] [CIR] Allow non-power-of-2-popcount (PR #216440)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 14 17:51:39 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Erich Keane (erichkeane)
<details>
<summary>Changes</summary>
Found in running a test suite, _BitInt of a non-power of 2 wasn't allowed in our cir.popcount operation, despite it lowering perfectly fine into the LLVM instruction. This patch relaxes the limitation to any size integer, and adds tests.
Note we have no tests >128 because we can't lay those out yet in memory, and the tests use local variables instead of arguments because _BitInt calling convention work isn't in place yet either.
---
Full diff: https://github.com/llvm/llvm-project/pull/216440.diff
2 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+1-3)
- (modified) clang/test/CIR/CodeGenBuiltins/builtin-bit.cpp (+161)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 4dfeef689e313..8f8159a356b5a 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -6724,9 +6724,7 @@ def CIR_BitParityOp : CIR_BitOpBase<"parity", CIR_UIntOfWidths<[32, 64]>> {
}];
}
-def CIR_BitPopcountOp : CIR_BitOpBase<"popcount",
- CIR_UIntOfWidths<[8, 16, 32, 64, 128]>
-> {
+def CIR_BitPopcountOp : CIR_BitOpBase<"popcount", CIR_AnyUIntType > {
let summary = "Get the number of 1-bits in input";
let description = [{
Compute the number of 1-bits in the input.
diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-bit.cpp b/clang/test/CIR/CodeGenBuiltins/builtin-bit.cpp
index 42daa8ea3f10b..bb5bb414eb8de 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtin-bit.cpp
+++ b/clang/test/CIR/CodeGenBuiltins/builtin-bit.cpp
@@ -358,6 +358,51 @@ int test_builtin_popcount(unsigned x) {
// OGCG-LABEL: _Z21test_builtin_popcountj
// OGCG: %{{.+}} = call i32 @llvm.ctpop.i32(i32 %{{.+}})
+int test_builtin_popcount_bitint() {
+ _BitInt(22) a;
+ _BitInt(64) b;
+ _BitInt(127) c;
+ _BitInt(128) d;
+
+ return __builtin_popcount(a) + __builtin_popcount(b) +
+ __builtin_popcount(c) + __builtin_popcount(d);
+}
+
+// CIR-LABEL: _Z28test_builtin_popcount_bitintv
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !cir.int<s, 22, bitint> -> !u32i
+// CIR: cir.popcount %[[CAST]] : !u32i
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !s64i_bitint -> !u32i
+// CIR: cir.popcount %[[CAST]] : !u32i
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !cir.int<s, 127, bitint> -> !u32i
+// CIR: cir.popcount %[[CAST]] : !u32i
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !s128i_bitint -> !u32i
+// CIR: cir.popcount %[[CAST]] : !u32i
+
+// LLVM-LABEL: _Z28test_builtin_popcount_bitintv
+// LLVM: %[[TRUNC:.*]] = trunc i32 %{{.*}} to i22
+// LLVM: %[[CAST:.*]] = sext i22 %[[TRUNC]] to i32
+// LLVM: call i32 @llvm.ctpop.i32(i32 %[[CAST]])
+// LLVM: %[[CAST:.*]] = trunc i64 %{{.*}} to i32
+// LLVM: call i32 @llvm.ctpop.i32(i32 %[[CAST]])
+// LLVM: %[[TRUNC:.*]] = trunc i128 %{{.*}} to i127
+// LLVM: %[[CAST:.*]] = trunc i127 %[[TRUNC]] to i32
+// LLVM: call i32 @llvm.ctpop.i32(i32 %[[CAST]])
+// LLVM: %[[CAST:.*]] = trunc i128 %{{.*}} to i32
+// LLVM: call i32 @llvm.ctpop.i32(i32 %[[CAST]])
+
+// OGCG-LABEL: _Z28test_builtin_popcount_bitintv
+// OGCG: %[[TRUNC:.*]] = trunc i32 %{{.*}} to i22
+// OGCG: %[[CAST:.*]] = sext i22 %[[TRUNC]] to i32
+// OGCG: call i32 @llvm.ctpop.i32(i32 %[[CAST]])
+// OGCG: %[[CAST:.*]] = trunc i64 %{{.*}} to i32
+// OGCG: call i32 @llvm.ctpop.i32(i32 %[[CAST]])
+// OGCG: %[[TRUNC:.*]] = trunc i128 %{{.*}} to i127
+// OGCG: %[[CAST:.*]] = trunc i127 %[[TRUNC]] to i32
+// OGCG: call i32 @llvm.ctpop.i32(i32 %[[CAST]])
+// OGCG: %[[CAST:.*]] = trunc i128 %{{.*}} to i32
+// OGCG: call i32 @llvm.ctpop.i32(i32 %[[CAST]])
+
+
int test_builtin_popcountl(unsigned long x) {
return __builtin_popcountl(x);
}
@@ -372,6 +417,48 @@ int test_builtin_popcountl(unsigned long x) {
// OGCG-LABEL: _Z22test_builtin_popcountlm
// OGCG: %{{.+}} = call i64 @llvm.ctpop.i64(i64 %{{.+}})
+int test_builtin_popcountl_bitint() {
+ _BitInt(22) a;
+ _BitInt(64) b;
+ _BitInt(127) c;
+ _BitInt(128) d;
+
+ return __builtin_popcountl(a) + __builtin_popcountl(b) +
+ __builtin_popcountl(c) + __builtin_popcountl(d);
+}
+
+// CIR-LABEL: _Z29test_builtin_popcountl_bitintv
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !cir.int<s, 22, bitint> -> !u64i
+// CIR: cir.popcount %[[CAST]] : !u64i
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !s64i_bitint -> !u64i
+// CIR: cir.popcount %[[CAST]] : !u64i
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !cir.int<s, 127, bitint> -> !u64i
+// CIR: cir.popcount %[[CAST]] : !u64i
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !s128i_bitint -> !u64i
+// CIR: cir.popcount %[[CAST]] : !u64i
+
+// LLVM-LABEL: _Z29test_builtin_popcountl_bitintv
+// LLVM: %[[TRUNC:.*]] = trunc i32 %{{.*}} to i22
+// LLVM: %[[CAST:.*]] = sext i22 %[[TRUNC]] to i64
+// LLVM: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+// LLVM: call i64 @llvm.ctpop.i64(i64 %{{.*}})
+// LLVM: %[[TRUNC:.*]] = trunc i128 %{{.*}} to i127
+// LLVM: %[[CAST:.*]] = trunc i127 %[[TRUNC]] to i64
+// LLVM: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+// LLVM: %[[CAST:.*]] = trunc i128 %{{.*}} to i64
+// LLVM: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+
+// OGCG-LABEL: _Z29test_builtin_popcountl_bitintv
+// OGCG: %[[TRUNC:.*]] = trunc i32 %{{.*}} to i22
+// OGCG: %[[CAST:.*]] = sext i22 %[[TRUNC]] to i64
+// OGCG: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+// OGCG: call i64 @llvm.ctpop.i64(i64 %{{.*}})
+// OGCG: %[[TRUNC:.*]] = trunc i128 %{{.*}} to i127
+// OGCG: %[[CAST:.*]] = trunc i127 %[[TRUNC]] to i64
+// OGCG: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+// OGCG: %[[CAST:.*]] = trunc i128 %{{.*}} to i64
+// OGCG: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+
int test_builtin_popcountll(unsigned long long x) {
return __builtin_popcountll(x);
}
@@ -386,6 +473,48 @@ int test_builtin_popcountll(unsigned long long x) {
// OGCG-LABEL: _Z23test_builtin_popcountlly
// OGCG: %{{.+}} = call i64 @llvm.ctpop.i64(i64 %{{.+}})
+int test_builtin_popcountll_bitint() {
+ _BitInt(22) a;
+ _BitInt(64) b;
+ _BitInt(127) c;
+ _BitInt(128) d;
+
+ return __builtin_popcountll(a) + __builtin_popcountll(b) +
+ __builtin_popcountll(c) + __builtin_popcountll(d);
+}
+
+// CIR-LABEL: _Z30test_builtin_popcountll_bitintv
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !cir.int<s, 22, bitint> -> !u64i
+// CIR: cir.popcount %[[CAST]] : !u64i
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !s64i_bitint -> !u64i
+// CIR: cir.popcount %[[CAST]] : !u64i
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !cir.int<s, 127, bitint> -> !u64i
+// CIR: cir.popcount %[[CAST]] : !u64i
+// CIR: %[[CAST:.*]] = cir.cast integral %{{.*}} : !s128i_bitint -> !u64i
+// CIR: cir.popcount %[[CAST]] : !u64i
+
+// LLVM-LABEL: _Z30test_builtin_popcountll_bitintv
+// LLVM: %[[TRUNC:.*]] = trunc i32 %{{.*}} to i22
+// LLVM: %[[CAST:.*]] = sext i22 %[[TRUNC]] to i64
+// LLVM: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+// LLVM: call i64 @llvm.ctpop.i64(i64 %{{.*}})
+// LLVM: %[[TRUNC:.*]] = trunc i128 %{{.*}} to i127
+// LLVM: %[[CAST:.*]] = trunc i127 %[[TRUNC]] to i64
+// LLVM: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+// LLVM: %[[CAST:.*]] = trunc i128 %{{.*}} to i64
+// LLVM: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+
+// OGCG-LABEL: _Z30test_builtin_popcountll_bitintv
+// OGCG: %[[TRUNC:.*]] = trunc i32 %{{.*}} to i22
+// OGCG: %[[CAST:.*]] = sext i22 %[[TRUNC]] to i64
+// OGCG: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+// OGCG: call i64 @llvm.ctpop.i64(i64 %{{.*}})
+// OGCG: %[[TRUNC:.*]] = trunc i128 %{{.*}} to i127
+// OGCG: %[[CAST:.*]] = trunc i127 %[[TRUNC]] to i64
+// OGCG: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+// OGCG: %[[CAST:.*]] = trunc i128 %{{.*}} to i64
+// OGCG: call i64 @llvm.ctpop.i64(i64 %[[CAST]])
+
int test_builtin_popcountg(unsigned x) {
return __builtin_popcountg(x);
}
@@ -400,6 +529,38 @@ int test_builtin_popcountg(unsigned x) {
// OGCG-LABEL: _Z22test_builtin_popcountgj
// OGCG: %{{.+}} = call i32 @llvm.ctpop.i32(i32 %{{.+}})
+int test_builtin_popcountg_bitint() {
+ unsigned _BitInt(22) a;
+ unsigned _BitInt(64) b;
+ unsigned _BitInt(127) c;
+ unsigned _BitInt(128) d;
+
+ return __builtin_popcountg(a) + __builtin_popcountg(b) +
+ __builtin_popcountg(c) + __builtin_popcountg(d);
+}
+// CIR-LABEL: _Z29test_builtin_popcountg_bitintv
+// CIR: %[[TMP:.*]] = cir.popcount %{{.*}} : <u, 22, bitint>
+// CIR: cir.cast integral %[[TMP]] : !cir.int<u, 22, bitint> -> !s32i
+// CIR: %[[TMP:.*]] = cir.popcount %{{.*}} : !u64i_bitint
+// CIR: cir.cast integral %[[TMP]] : !u64i_bitint -> !s32i
+// CIR: %[[TMP:.*]] = cir.popcount %{{.*}} : <u, 127, bitint>
+// CIR: cir.cast integral %[[TMP]] : !cir.int<u, 127, bitint> -> !s32i
+// CIR: %[[TMP:.*]] = cir.popcount %{{.*}} : !u128i_bitint
+// CIR: cir.cast integral %[[TMP]] : !u128i_bitint -> !s32i
+
+// LLVM-LABEL: _Z29test_builtin_popcountg_bitintv
+// LLVM: call i22 @llvm.ctpop.i22(i22 %{{.*}})
+// LLVM: call i64 @llvm.ctpop.i64(i64 %{{.*}})
+// LLVM: call i127 @llvm.ctpop.i127(i127 %{{.*}})
+// LLVM: call i128 @llvm.ctpop.i128(i128 %{{.*}})
+
+// OGCG-LABEL: _Z29test_builtin_popcountg_bitintv
+// OGCG: call i22 @llvm.ctpop.i22(i22 %{{.*}})
+// OGCG: call i64 @llvm.ctpop.i64(i64 %{{.*}})
+// OGCG: call i127 @llvm.ctpop.i127(i127 %{{.*}})
+// OGCG: call i128 @llvm.ctpop.i128(i128 %{{.*}})
+
+
unsigned test_builtin_popcountg_u8(unsigned char x) {
return __builtin_popcountg(x);
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/216440
More information about the cfe-commits
mailing list