@@ -148,6 +148,35 @@ template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
148148 return (Value != 0 ) && ((Value & (Value - 1 )) == 0 );
149149}
150150
151+ // / Count the number of set bits in a value.
152+ // / Ex. popcount(0xF000F000) = 8
153+ // / Returns 0 if Value is zero.
154+ template <typename T> [[nodiscard]] inline int popcount (T Value) noexcept {
155+ static_assert (std::is_unsigned_v<T>, " T must be an unsigned integer type" );
156+ static_assert (sizeof (T) <= 8 , " T must be 8 bytes or less" );
157+
158+ if constexpr (sizeof (T) <= 4 ) {
159+ #if defined(__GNUC__)
160+ return (int )__builtin_popcount (Value);
161+ #else
162+ uint32_t V = Value;
163+ V = V - ((V >> 1 ) & 0x55555555 );
164+ V = (V & 0x33333333 ) + ((V >> 2 ) & 0x33333333 );
165+ return int (((V + (V >> 4 ) & 0xF0F0F0F ) * 0x1010101 ) >> 24 );
166+ #endif
167+ } else {
168+ #if defined(__GNUC__)
169+ return (int )__builtin_popcountll (Value);
170+ #else
171+ uint64_t V = Value;
172+ V = V - ((V >> 1 ) & 0x5555555555555555ULL );
173+ V = (V & 0x3333333333333333ULL ) + ((V >> 2 ) & 0x3333333333333333ULL );
174+ V = (V + (V >> 4 )) & 0x0F0F0F0F0F0F0F0FULL ;
175+ return int ((uint64_t )(V * 0x0101010101010101ULL ) >> 56 );
176+ #endif
177+ }
178+ }
179+
151180// / Count number of 0's from the least significant bit to the most
152181// / stopping at the first 1.
153182// /
@@ -179,19 +208,9 @@ template <typename T> [[nodiscard]] int countr_zero(T Val) {
179208#endif
180209 }
181210
182- // Fall back to the bisection method.
183- unsigned ZeroBits = 0 ;
184- T Shift = std::numeric_limits<T>::digits >> 1 ;
185- T Mask = std::numeric_limits<T>::max () >> Shift;
186- while (Shift) {
187- if ((Val & Mask) == 0 ) {
188- Val >>= Shift;
189- ZeroBits |= Shift;
190- }
191- Shift >>= 1 ;
192- Mask >>= Shift;
193- }
194- return ZeroBits;
211+ // Fallback to popcount. "(Val & -Val) - 1" is a bitmask with all bits below
212+ // the least significant 1 set.
213+ return llvm::popcount (static_cast <std::make_unsigned_t <T>>((Val & -Val) - 1 ));
195214}
196215
197216// / Count number of 0's from the most significant bit to the least
@@ -300,35 +319,6 @@ template <typename T> [[nodiscard]] T bit_ceil(T Value) {
300319 return T (1 ) << llvm::bit_width<T>(Value - 1u );
301320}
302321
303- // / Count the number of set bits in a value.
304- // / Ex. popcount(0xF000F000) = 8
305- // / Returns 0 if the word is zero.
306- template <typename T, typename = std::enable_if_t <std::is_unsigned_v<T>>>
307- [[nodiscard]] inline int popcount (T Value) noexcept {
308- if constexpr (sizeof (T) <= 4 ) {
309- #if defined(__GNUC__)
310- return (int )__builtin_popcount (Value);
311- #else
312- uint32_t v = Value;
313- v = v - ((v >> 1 ) & 0x55555555 );
314- v = (v & 0x33333333 ) + ((v >> 2 ) & 0x33333333 );
315- return int (((v + (v >> 4 ) & 0xF0F0F0F ) * 0x1010101 ) >> 24 );
316- #endif
317- } else if constexpr (sizeof (T) <= 8 ) {
318- #if defined(__GNUC__)
319- return (int )__builtin_popcountll (Value);
320- #else
321- uint64_t v = Value;
322- v = v - ((v >> 1 ) & 0x5555555555555555ULL );
323- v = (v & 0x3333333333333333ULL ) + ((v >> 2 ) & 0x3333333333333333ULL );
324- v = (v + (v >> 4 )) & 0x0F0F0F0F0F0F0F0FULL ;
325- return int ((uint64_t )(v * 0x0101010101010101ULL ) >> 56 );
326- #endif
327- } else {
328- static_assert (sizeof (T) == 0 , " T must be 8 bytes or less" );
329- }
330- }
331-
332322// Forward-declare rotr so that rotl can use it.
333323template <typename T, typename = std::enable_if_t <std::is_unsigned_v<T>>>
334324[[nodiscard]] constexpr T rotr (T V, int R);
0 commit comments