From 53ce12958ada9e31b01e53e46228d6e49fe878c9 Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 23 May 2025 11:24:32 +0200 Subject: [PATCH 1/4] ``: Use popcount for `has_single_bit()` if it's always available --- stl/inc/__msvc_bit_utils.hpp | 1 - stl/inc/bit | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/stl/inc/__msvc_bit_utils.hpp b/stl/inc/__msvc_bit_utils.hpp index 4217cb208a3..c765fa553b9 100644 --- a/stl/inc/__msvc_bit_utils.hpp +++ b/stl/inc/__msvc_bit_utils.hpp @@ -386,7 +386,6 @@ _CONSTEXPR20 decltype(auto) _Select_popcount_impl(_Fn _Callback) { #undef _HAS_POPCNT_INTRINSICS #undef _HAS_TZCNT_BSF_INTRINSICS -#undef _POPCNT_INTRINSICS_ALWAYS_AVAILABLE _STD_END diff --git a/stl/inc/bit b/stl/inc/bit index 6d82d9bc106..da79eb547d1 100644 --- a/stl/inc/bit +++ b/stl/inc/bit @@ -84,7 +84,14 @@ _NODISCARD constexpr int countl_zero(_Ty _Val) noexcept; _EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr bool has_single_bit(const _Ty _Val) noexcept { +#if defined(_POPCNT_INTRINSICS_ALWAYS_AVAILABLE) && _POPCNT_INTRINSICS_ALWAYS_AVAILABLE + if (_STD is_constant_evaluated()) { + return (_Val ^ (_Val - 1)) > _Val - 1; + } + return _Unchecked_popcount(_Val) == 1; +#else return (_Val ^ (_Val - 1)) > _Val - 1; +#endif // ! _POPCNT_INTRINSICS_ALWAYS_AVAILABLE } inline void _Precondition_violation_in_bit_ceil() noexcept {} From dda8819c04005c217114692273ed40d6f24cd43c Mon Sep 17 00:00:00 2001 From: Pavel P Date: Fri, 23 May 2025 12:57:27 +0200 Subject: [PATCH 2/4] comments --- stl/inc/bit | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/bit b/stl/inc/bit index da79eb547d1..ac861672c72 100644 --- a/stl/inc/bit +++ b/stl/inc/bit @@ -89,9 +89,9 @@ _NODISCARD constexpr bool has_single_bit(const _Ty _Val) noexcept { return (_Val ^ (_Val - 1)) > _Val - 1; } return _Unchecked_popcount(_Val) == 1; -#else +#else // ^^^ popcnt intrinsic always available / popcnt intrinsic not always available vvv return (_Val ^ (_Val - 1)) > _Val - 1; -#endif // ! _POPCNT_INTRINSICS_ALWAYS_AVAILABLE +#endif // ^^^ popcnt intrinsic not always available ^^^ } inline void _Precondition_violation_in_bit_ceil() noexcept {} From 420c3910bd036464a65b9fe5b35b996d3c6cd32c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 28 May 2025 09:17:22 -0700 Subject: [PATCH 3/4] Always define `_POPCNT_INTRINSICS_ALWAYS_AVAILABLE`, leave `_HAS_POPCNT_INTRINSICS` defined. --- stl/inc/__msvc_bit_utils.hpp | 4 ++-- stl/inc/bit | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stl/inc/__msvc_bit_utils.hpp b/stl/inc/__msvc_bit_utils.hpp index c765fa553b9..df0af9064d5 100644 --- a/stl/inc/__msvc_bit_utils.hpp +++ b/stl/inc/__msvc_bit_utils.hpp @@ -281,7 +281,8 @@ _NODISCARD int _Checked_x86_x64_countr_zero(const _Ty _Val) noexcept { #define _POPCNT_INTRINSICS_ALWAYS_AVAILABLE 0 #endif // ^^^ intrinsics not always available ^^^ #else // ^^^ intrinsics available / intrinsics unavailable vvv -#define _HAS_POPCNT_INTRINSICS 0 +#define _HAS_POPCNT_INTRINSICS 0 +#define _POPCNT_INTRINSICS_ALWAYS_AVAILABLE 0 #endif // ^^^ intrinsics unavailable ^^^ #if _HAS_POPCNT_INTRINSICS @@ -384,7 +385,6 @@ _CONSTEXPR20 decltype(auto) _Select_popcount_impl(_Fn _Callback) { return _Callback([](_Ty _Val) _STATIC_LAMBDA { return _Popcount_fallback(_Val); }); } -#undef _HAS_POPCNT_INTRINSICS #undef _HAS_TZCNT_BSF_INTRINSICS _STD_END diff --git a/stl/inc/bit b/stl/inc/bit index ac861672c72..51840f83aee 100644 --- a/stl/inc/bit +++ b/stl/inc/bit @@ -84,14 +84,14 @@ _NODISCARD constexpr int countl_zero(_Ty _Val) noexcept; _EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr bool has_single_bit(const _Ty _Val) noexcept { -#if defined(_POPCNT_INTRINSICS_ALWAYS_AVAILABLE) && _POPCNT_INTRINSICS_ALWAYS_AVAILABLE +#if _POPCNT_INTRINSICS_ALWAYS_AVAILABLE if (_STD is_constant_evaluated()) { return (_Val ^ (_Val - 1)) > _Val - 1; } return _Unchecked_popcount(_Val) == 1; -#else // ^^^ popcnt intrinsic always available / popcnt intrinsic not always available vvv +#else // ^^^ _POPCNT_INTRINSICS_ALWAYS_AVAILABLE / !_POPCNT_INTRINSICS_ALWAYS_AVAILABLE vvv return (_Val ^ (_Val - 1)) > _Val - 1; -#endif // ^^^ popcnt intrinsic not always available ^^^ +#endif // ^^^ !_POPCNT_INTRINSICS_ALWAYS_AVAILABLE ^^^ } inline void _Precondition_violation_in_bit_ceil() noexcept {} From 9f7ee2670b3177b761a19efc607a16fc23db061a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 28 May 2025 09:20:46 -0700 Subject: [PATCH 4/4] Avoid code duplication. --- stl/inc/bit | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/stl/inc/bit b/stl/inc/bit index 51840f83aee..f9be4e925fd 100644 --- a/stl/inc/bit +++ b/stl/inc/bit @@ -85,13 +85,12 @@ _NODISCARD constexpr int countl_zero(_Ty _Val) noexcept; _EXPORT_STD template <_Standard_unsigned_integral _Ty> _NODISCARD constexpr bool has_single_bit(const _Ty _Val) noexcept { #if _POPCNT_INTRINSICS_ALWAYS_AVAILABLE - if (_STD is_constant_evaluated()) { - return (_Val ^ (_Val - 1)) > _Val - 1; + if (!_STD is_constant_evaluated()) { + return _Unchecked_popcount(_Val) == 1; } - return _Unchecked_popcount(_Val) == 1; -#else // ^^^ _POPCNT_INTRINSICS_ALWAYS_AVAILABLE / !_POPCNT_INTRINSICS_ALWAYS_AVAILABLE vvv +#endif // ^^^ _POPCNT_INTRINSICS_ALWAYS_AVAILABLE ^^^ + return (_Val ^ (_Val - 1)) > _Val - 1; -#endif // ^^^ !_POPCNT_INTRINSICS_ALWAYS_AVAILABLE ^^^ } inline void _Precondition_violation_in_bit_ceil() noexcept {}