Skip to content

[ADT] Simplify popcount with constexpr if (NFC) #143339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 9, 2025

Conversation

kazutakahirata
Copy link
Contributor

Without this patch, we implement 4-byte and 8-byte popcount as
structs.

This patch replaces the template trick with constexpr if, putting the
entire logic in the body of popcount.

Without this patch, we implement 4-byte and 8-byte popcount as
structs.

This patch replaces the template trick with constexpr if, putting the
entire logic in the body of popcount.
@llvmbot
Copy link
Member

llvmbot commented Jun 9, 2025

@llvm/pr-subscribers-llvm-adt

Author: Kazu Hirata (kazutakahirata)

Changes

Without this patch, we implement 4-byte and 8-byte popcount as
structs.

This patch replaces the template trick with constexpr if, putting the
entire logic in the body of popcount.


Full diff: https://github.com/llvm/llvm-project/pull/143339.diff

1 Files Affected:

  • (modified) llvm/include/llvm/ADT/bit.h (+9-19)
diff --git a/llvm/include/llvm/ADT/bit.h b/llvm/include/llvm/ADT/bit.h
index b952825e574bc..d6e33c3e6133a 100644
--- a/llvm/include/llvm/ADT/bit.h
+++ b/llvm/include/llvm/ADT/bit.h
@@ -300,11 +300,12 @@ template <typename T> [[nodiscard]] T bit_ceil(T Value) {
   return T(1) << llvm::bit_width<T>(Value - 1u);
 }
 
-namespace detail {
-template <typename T, std::size_t SizeOfT> struct PopulationCounter {
-  static int count(T Value) {
-    // Generic version, forward to 32 bits.
-    static_assert(SizeOfT <= 4, "Not implemented!");
+/// Count the number of set bits in a value.
+/// Ex. popcount(0xF000F000) = 8
+/// Returns 0 if the word is zero.
+template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
+[[nodiscard]] inline int popcount(T Value) noexcept {
+  if constexpr (sizeof(T) <= 4) {
 #if defined(__GNUC__)
     return (int)__builtin_popcount(Value);
 #else
@@ -313,11 +314,7 @@ template <typename T, std::size_t SizeOfT> struct PopulationCounter {
     v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
     return int(((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24);
 #endif
-  }
-};
-
-template <typename T> struct PopulationCounter<T, 8> {
-  static int count(T Value) {
+  } else if constexpr (sizeof(T) <= 8) {
 #if defined(__GNUC__)
     return (int)__builtin_popcountll(Value);
 #else
@@ -327,16 +324,9 @@ template <typename T> struct PopulationCounter<T, 8> {
     v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
     return int((uint64_t)(v * 0x0101010101010101ULL) >> 56);
 #endif
+  } else {
+    static_assert(sizeof(T) == 0, "T must be 8 bytes or less");
   }
-};
-} // namespace detail
-
-/// Count the number of set bits in a value.
-/// Ex. popcount(0xF000F000) = 8
-/// Returns 0 if the word is zero.
-template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
-[[nodiscard]] inline int popcount(T Value) noexcept {
-  return detail::PopulationCounter<T, sizeof(T)>::count(Value);
 }
 
 // Forward-declare rotr so that rotl can use it.

@kazutakahirata kazutakahirata merged commit 3dabeed into llvm:main Jun 9, 2025
9 checks passed
@kazutakahirata kazutakahirata deleted the cleanup_20250608_popcount branch June 9, 2025 05:38
rorth pushed a commit to rorth/llvm-project that referenced this pull request Jun 11, 2025
Without this patch, we implement 4-byte and 8-byte popcount as
structs.

This patch replaces the template trick with constexpr if, putting the
entire logic in the body of popcount.
DhruvSrivastavaX pushed a commit to DhruvSrivastavaX/lldb-for-aix that referenced this pull request Jun 12, 2025
Without this patch, we implement 4-byte and 8-byte popcount as
structs.

This patch replaces the template trick with constexpr if, putting the
entire logic in the body of popcount.
tomtor pushed a commit to tomtor/llvm-project that referenced this pull request Jun 14, 2025
Without this patch, we implement 4-byte and 8-byte popcount as
structs.

This patch replaces the template trick with constexpr if, putting the
entire logic in the body of popcount.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants