File tree Expand file tree Collapse file tree 2 files changed +43
-13
lines changed Expand file tree Collapse file tree 2 files changed +43
-13
lines changed Original file line number Diff line number Diff line change @@ -154,6 +154,27 @@ template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
154154// / Only unsigned integral types are allowed.
155155// /
156156// / Returns std::numeric_limits<T>::digits on an input of 0.
157+ template <typename T> [[nodiscard]] constexpr int countr_zero_constexpr (T Val) {
158+ static_assert (std::is_unsigned_v<T>,
159+ " Only unsigned integral types are allowed." );
160+ if (!Val)
161+ return std::numeric_limits<T>::digits;
162+
163+ // Use the bisection method.
164+ unsigned ZeroBits = 0 ;
165+ T Shift = std::numeric_limits<T>::digits >> 1 ;
166+ T Mask = std::numeric_limits<T>::max () >> Shift;
167+ while (Shift) {
168+ if ((Val & Mask) == 0 ) {
169+ Val >>= Shift;
170+ ZeroBits |= Shift;
171+ }
172+ Shift >>= 1 ;
173+ Mask >>= Shift;
174+ }
175+ return ZeroBits;
176+ }
177+
157178template <typename T> [[nodiscard]] int countr_zero (T Val) {
158179 static_assert (std::is_unsigned_v<T>,
159180 " Only unsigned integral types are allowed." );
@@ -179,19 +200,8 @@ template <typename T> [[nodiscard]] int countr_zero(T Val) {
179200#endif
180201 }
181202
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;
203+ // Fall back to the constexpr implementation.
204+ return countr_zero_constexpr (Val);
195205}
196206
197207// / Count number of 0's from the most significant bit to the least
Original file line number Diff line number Diff line change @@ -279,6 +279,26 @@ TEST(BitTest, CountlZero) {
279279 }
280280}
281281
282+ TEST (BitTest, CountrZeroConstexpr) {
283+ constexpr uint8_t Z8 = 0 ;
284+ constexpr uint16_t Z16 = 0 ;
285+ constexpr uint32_t Z32 = 0 ;
286+ constexpr uint64_t Z64 = 0 ;
287+ static_assert (llvm::countr_zero_constexpr (Z8) == 8 , " " );
288+ static_assert (llvm::countr_zero_constexpr (Z16) == 16 , " " );
289+ static_assert (llvm::countr_zero_constexpr (Z32) == 32 , " " );
290+ static_assert (llvm::countr_zero_constexpr (Z64) == 64 , " " );
291+
292+ constexpr uint8_t NZ8 = 42 ;
293+ constexpr uint16_t NZ16 = 42 ;
294+ constexpr uint32_t NZ32 = 42 ;
295+ constexpr uint64_t NZ64 = 42 ;
296+ static_assert (llvm::countr_zero_constexpr (NZ8) == 1 , " " );
297+ static_assert (llvm::countr_zero_constexpr (NZ16) == 1 , " " );
298+ static_assert (llvm::countr_zero_constexpr (NZ32) == 1 , " " );
299+ static_assert (llvm::countr_zero_constexpr (NZ64) == 1 , " " );
300+ }
301+
282302TEST (BitTest, CountrZero) {
283303 uint8_t Z8 = 0 ;
284304 uint16_t Z16 = 0 ;
You can’t perform that action at this time.
0 commit comments