From 4e93f2dc8ce3df93b7efd1e042d6cf85788ffd4c Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 17 Nov 2021 21:26:11 +0200 Subject: [PATCH 01/12] do stuff like _Select_popcount_impl --- stl/inc/limits | 40 +++++++++++++++++++++++++++++++------ stl/inc/numeric | 52 +++++++++++++++++++++++++------------------------ 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/stl/inc/limits b/stl/inc/limits index 9421c6d3088..d171b16c1e5 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -1052,6 +1052,12 @@ _NODISCARD constexpr int _Popcount_fallback(_Ty _Val) noexcept { } #if defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC)) +#define _HAS_BSF_TZNCNT_INTRINSICS 1 +#else // ^^^ intrinsics available ^^^ / vvv intrinsics unavailable vvv +#define _HAS_BSF_TZNCNT_INTRINSICS 0 +#endif // ^^^ intrinsics unavailable + +#if _HAS_BSF_TZNCNT_INTRINSICS extern "C" { extern int __isa_available; #ifdef __clang__ @@ -1139,7 +1145,7 @@ _NODISCARD int _Checked_x86_x64_countr_zero(const _Ty _Val) noexcept { #undef _TZCNT_U32 #undef _TZCNT_U64 -#endif // defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC)) +#endif // _HAS_BSF_TZNCNT_INTRINSICS #if (defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))) && !defined(_M_CEE_PURE) && !defined(__CUDACC__) \ && !defined(__INTEL_COMPILER) @@ -1190,17 +1196,39 @@ constexpr bool _Is_standard_unsigned_integer = template , int> = 0> _NODISCARD constexpr int _Countr_zero(const _Ty _Val) noexcept { -#if defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC)) +#if _HAS_BSF_TZNCNT_INTRINSICS #if _HAS_CXX20 - if (!_STD is_constant_evaluated()) { + if (!_STD is_constant_evaluated()) +#endif // _HAS_CXX20 + { return _Checked_x86_x64_countr_zero(_Val); } -#endif // _HAS_CXX20 -#endif // defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC)) - // C++17 constexpr gcd() calls this function, so it should be constexpr unless we detect runtime evaluation. +#endif // _HAS_BSF_TZNCNT_INTRINSICS return _Countr_zero_fallback(_Val); } +template +_CONSTEXPR20 decltype(auto) _Select_countr_zero_impl(_Fn _Callback) { + // TRANSITION, DevCom-1527995: Lambdas in this function ensure inlining +#if _HAS_BSF_TZNCNT_INTRINSICS && _HAS_CXX20 + if (!_STD is_constant_evaluated()) { +#ifndef __AVX2__ + const bool _Definitely_have_tzcnt = __isa_available >= __ISA_AVAILABLE_AVX2; + if (_Definitely_have_tzcnt) { + return _Callback([](_Ty _Val) { return _Countr_zero_tzcnt(_Val); }); + } else { + return _Callback([](_Ty _Val) { return _Countr_zero_bsf(_Val); }); + } +#else // ^^^ not AVX2 ^^^ / vvv AVX2 vvv + return _Callback([](_Ty _Val) { return _Countr_zero_tzcnt(_Val); }); +#endif // ^^^ AVX2 ^^^ + } +#endif // ^^^ _HAS_BSF_TZNCNT_INTRINSICS && _HAS_CXX20 ^^^ + // C++17 constexpr gcd() calls this function, so it should be constexpr unless we detect runtime evaluation. + return _Callback([](_Ty _Val) { return _Countr_zero_fallback(_Val); }); +} + + template , int> _Enabled = 0> _NODISCARD _CONSTEXPR20 int _Popcount(const _Ty _Val) noexcept { #if _HAS_POPCNT_INTRINSICS || _HAS_NEON_INTRINSICS diff --git a/stl/inc/numeric b/stl/inc/numeric index 1d6c90bf094..c2aa6e9a177 100644 --- a/stl/inc/numeric +++ b/stl/inc/numeric @@ -548,35 +548,37 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> gcd(const _Mt _Mx, const _Nt _Nx) n // calculate greatest common divisor static_assert(_Is_nonbool_integral<_Mt> && _Is_nonbool_integral<_Nt>, "GCD requires nonbool integral types"); - using _Common = common_type_t<_Mt, _Nt>; - using _Common_unsigned = make_unsigned_t<_Common>; - _Common_unsigned _Mx_magnitude = _Abs_u(_Mx); - _Common_unsigned _Nx_magnitude = _Abs_u(_Nx); - if (_Mx_magnitude == 0U) { - return static_cast<_Common>(_Nx_magnitude); - } - - if (_Nx_magnitude == 0U) { - return static_cast<_Common>(_Mx_magnitude); - } + using _Common = common_type_t<_Mt, _Nt>; + using _Common_unsigned = make_unsigned_t<_Common>; + + return _Select_countr_zero_impl<_Common_unsigned>([=](auto _Countr_zero) { + _Common_unsigned _Mx_magnitude = _Abs_u(_Mx); + _Common_unsigned _Nx_magnitude = _Abs_u(_Nx); + if (_Mx_magnitude == 0U) { + return static_cast<_Common>(_Nx_magnitude); + } - const auto _Mx_trailing_zeroes = static_cast(_Countr_zero(_Mx_magnitude)); - const auto _Common_factors_of_2 = - (_STD min) (_Mx_trailing_zeroes, static_cast(_Countr_zero(_Nx_magnitude))); - _Nx_magnitude >>= _Common_factors_of_2; - _Mx_magnitude >>= _Mx_trailing_zeroes; - do { - _Nx_magnitude >>= static_cast(_Countr_zero(_Nx_magnitude)); - if (_Mx_magnitude > _Nx_magnitude) { - _Common_unsigned _Temp = _Mx_magnitude; - _Mx_magnitude = _Nx_magnitude; - _Nx_magnitude = _Temp; + if (_Nx_magnitude == 0U) { + return static_cast<_Common>(_Mx_magnitude); } - _Nx_magnitude -= _Mx_magnitude; - } while (_Nx_magnitude != 0U); + const auto _Mx_trailing_zeroes = static_cast(_Countr_zero(_Mx_magnitude)); + const auto _Common_factors_of_2 = + (_STD min) (_Mx_trailing_zeroes, static_cast(_Countr_zero(_Nx_magnitude))); + _Nx_magnitude >>= _Common_factors_of_2; + _Mx_magnitude >>= _Mx_trailing_zeroes; + do { + _Nx_magnitude >>= static_cast(_Countr_zero(_Nx_magnitude)); + if (_Mx_magnitude > _Nx_magnitude) { + _Common_unsigned _Temp = _Mx_magnitude; + _Mx_magnitude = _Nx_magnitude; + _Nx_magnitude = _Temp; + } - return static_cast<_Common>(_Mx_magnitude << _Common_factors_of_2); + _Nx_magnitude -= _Mx_magnitude; + } while (_Nx_magnitude != 0U); + return static_cast<_Common>(_Mx_magnitude << _Common_factors_of_2); + }); } template From 2cc7af4745f886fc77120a9fe023ad432c961b8b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 22 Nov 2021 18:16:40 -0800 Subject: [PATCH 02/12] Add constexpr test coverage. --- .../tests/Dev11_1074023_constexpr/test.cpp | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/std/tests/Dev11_1074023_constexpr/test.cpp b/tests/std/tests/Dev11_1074023_constexpr/test.cpp index 3b2cec30167..5bd52e78b6a 100644 --- a/tests/std/tests/Dev11_1074023_constexpr/test.cpp +++ b/tests/std/tests/Dev11_1074023_constexpr/test.cpp @@ -30,6 +30,7 @@ #include #endif // _M_CEE #include +#include #include #include #include @@ -956,6 +957,27 @@ static_assert(hardware_constructive_interference_size == 64); static_assert(hardware_destructive_interference_size == 64); #endif // _HAS_CXX17 +// P0295R0 gcd(), lcm() +constexpr bool test_gcd_lcm() { +#if _HAS_CXX17 + assert(gcd(0, 0) == 0); + assert(gcd(3125, 2401) == 1); + assert(gcd(3840, 2160) == 240); + assert(gcd(4096, 8192) == 4096); + assert(gcd(19937, 19937) == 19937); + + assert(lcm(0, 0) == 0); + assert(lcm(0, 1729) == 0); + assert(lcm(1729, 0) == 0); + assert(lcm(1729, 1729) == 1729); + assert(lcm(4096, 8192) == 8192); + assert(lcm(1920, 1200) == 9600); + assert(lcm(25, 49) == 1225); +#endif // _HAS_CXX17 + + return true; +} + int main() { test_all_constants(); test_all_bitmasks(); @@ -1020,4 +1042,8 @@ int main() { == "1111111011011100101110101001100001110110010101000011001000010000"); assert(bitset<75>(0xFEDCBA9876543210ULL).to_string() == "000000000001111111011011100101110101001100001110110010101000011001000010000"); + + // P0295R0 gcd(), lcm() + test_gcd_lcm(); + STATIC_ASSERT(test_gcd_lcm()); } From 65c7fe58c2f67b71a68c9cb2f45e7a59dff15592 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 22 Nov 2021 18:17:33 -0800 Subject: [PATCH 03/12] Avoid shadowing by renaming to _Countr_zero_impl. --- stl/inc/numeric | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/numeric b/stl/inc/numeric index c2aa6e9a177..4bd4ed5fe65 100644 --- a/stl/inc/numeric +++ b/stl/inc/numeric @@ -551,7 +551,7 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> gcd(const _Mt _Mx, const _Nt _Nx) n using _Common = common_type_t<_Mt, _Nt>; using _Common_unsigned = make_unsigned_t<_Common>; - return _Select_countr_zero_impl<_Common_unsigned>([=](auto _Countr_zero) { + return _Select_countr_zero_impl<_Common_unsigned>([=](auto _Countr_zero_impl) { _Common_unsigned _Mx_magnitude = _Abs_u(_Mx); _Common_unsigned _Nx_magnitude = _Abs_u(_Nx); if (_Mx_magnitude == 0U) { @@ -562,13 +562,13 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> gcd(const _Mt _Mx, const _Nt _Nx) n return static_cast<_Common>(_Mx_magnitude); } - const auto _Mx_trailing_zeroes = static_cast(_Countr_zero(_Mx_magnitude)); + const auto _Mx_trailing_zeroes = static_cast(_Countr_zero_impl(_Mx_magnitude)); const auto _Common_factors_of_2 = - (_STD min) (_Mx_trailing_zeroes, static_cast(_Countr_zero(_Nx_magnitude))); + (_STD min) (_Mx_trailing_zeroes, static_cast(_Countr_zero_impl(_Nx_magnitude))); _Nx_magnitude >>= _Common_factors_of_2; _Mx_magnitude >>= _Mx_trailing_zeroes; do { - _Nx_magnitude >>= static_cast(_Countr_zero(_Nx_magnitude)); + _Nx_magnitude >>= static_cast(_Countr_zero_impl(_Nx_magnitude)); if (_Mx_magnitude > _Nx_magnitude) { _Common_unsigned _Temp = _Mx_magnitude; _Mx_magnitude = _Nx_magnitude; From 802d3fe9367806c99bc5d7aeaa34cebeb6aa8764 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 22 Nov 2021 18:18:59 -0800 Subject: [PATCH 04/12] Fix typo by renaming TZNCNT to TZCNT. --- stl/inc/limits | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stl/inc/limits b/stl/inc/limits index d171b16c1e5..41bf9aaa308 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -1052,12 +1052,12 @@ _NODISCARD constexpr int _Popcount_fallback(_Ty _Val) noexcept { } #if defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC)) -#define _HAS_BSF_TZNCNT_INTRINSICS 1 +#define _HAS_BSF_TZCNT_INTRINSICS 1 #else // ^^^ intrinsics available ^^^ / vvv intrinsics unavailable vvv -#define _HAS_BSF_TZNCNT_INTRINSICS 0 +#define _HAS_BSF_TZCNT_INTRINSICS 0 #endif // ^^^ intrinsics unavailable -#if _HAS_BSF_TZNCNT_INTRINSICS +#if _HAS_BSF_TZCNT_INTRINSICS extern "C" { extern int __isa_available; #ifdef __clang__ @@ -1145,7 +1145,7 @@ _NODISCARD int _Checked_x86_x64_countr_zero(const _Ty _Val) noexcept { #undef _TZCNT_U32 #undef _TZCNT_U64 -#endif // _HAS_BSF_TZNCNT_INTRINSICS +#endif // _HAS_BSF_TZCNT_INTRINSICS #if (defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))) && !defined(_M_CEE_PURE) && !defined(__CUDACC__) \ && !defined(__INTEL_COMPILER) @@ -1196,21 +1196,21 @@ constexpr bool _Is_standard_unsigned_integer = template , int> = 0> _NODISCARD constexpr int _Countr_zero(const _Ty _Val) noexcept { -#if _HAS_BSF_TZNCNT_INTRINSICS +#if _HAS_BSF_TZCNT_INTRINSICS #if _HAS_CXX20 if (!_STD is_constant_evaluated()) #endif // _HAS_CXX20 { return _Checked_x86_x64_countr_zero(_Val); } -#endif // _HAS_BSF_TZNCNT_INTRINSICS +#endif // _HAS_BSF_TZCNT_INTRINSICS return _Countr_zero_fallback(_Val); } template _CONSTEXPR20 decltype(auto) _Select_countr_zero_impl(_Fn _Callback) { // TRANSITION, DevCom-1527995: Lambdas in this function ensure inlining -#if _HAS_BSF_TZNCNT_INTRINSICS && _HAS_CXX20 +#if _HAS_BSF_TZCNT_INTRINSICS && _HAS_CXX20 if (!_STD is_constant_evaluated()) { #ifndef __AVX2__ const bool _Definitely_have_tzcnt = __isa_available >= __ISA_AVAILABLE_AVX2; @@ -1223,7 +1223,7 @@ _CONSTEXPR20 decltype(auto) _Select_countr_zero_impl(_Fn _Callback) { return _Callback([](_Ty _Val) { return _Countr_zero_tzcnt(_Val); }); #endif // ^^^ AVX2 ^^^ } -#endif // ^^^ _HAS_BSF_TZNCNT_INTRINSICS && _HAS_CXX20 ^^^ +#endif // ^^^ _HAS_BSF_TZCNT_INTRINSICS && _HAS_CXX20 ^^^ // C++17 constexpr gcd() calls this function, so it should be constexpr unless we detect runtime evaluation. return _Callback([](_Ty _Val) { return _Countr_zero_fallback(_Val); }); } From 5b7f056823196e9eef0e27524d447962407747e1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 22 Nov 2021 18:20:38 -0800 Subject: [PATCH 05/12] Undef the macro in reverse order of definition. --- stl/inc/limits | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/limits b/stl/inc/limits index 41bf9aaa308..a715ccb368f 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -1271,6 +1271,7 @@ _CONSTEXPR20 decltype(auto) _Select_popcount_impl(_Fn _Callback) { } #undef _HAS_POPCNT_INTRINSICS +#undef _HAS_BSF_TZCNT_INTRINSICS #undef _HAS_NEON_INTRINSICS _STD_END From 966eab541727d47b888975869a9775f32592ba7b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 22 Nov 2021 18:21:51 -0800 Subject: [PATCH 06/12] Arrow comment style. --- stl/inc/limits | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/limits b/stl/inc/limits index a715ccb368f..b7a3f17fc52 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -1055,7 +1055,7 @@ _NODISCARD constexpr int _Popcount_fallback(_Ty _Val) noexcept { #define _HAS_BSF_TZCNT_INTRINSICS 1 #else // ^^^ intrinsics available ^^^ / vvv intrinsics unavailable vvv #define _HAS_BSF_TZCNT_INTRINSICS 0 -#endif // ^^^ intrinsics unavailable +#endif // ^^^ intrinsics unavailable ^^^ #if _HAS_BSF_TZCNT_INTRINSICS extern "C" { From 405888ee1ad56eede8bb0c77001c33b62be2597c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 22 Nov 2021 18:23:08 -0800 Subject: [PATCH 07/12] _Countr_zero should be _CONSTEXPR20. --- stl/inc/limits | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/limits b/stl/inc/limits index b7a3f17fc52..83eaa514a39 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -1195,7 +1195,7 @@ constexpr bool _Is_standard_unsigned_integer = _Is_any_of_v, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long>; template , int> = 0> -_NODISCARD constexpr int _Countr_zero(const _Ty _Val) noexcept { +_NODISCARD _CONSTEXPR20 int _Countr_zero(const _Ty _Val) noexcept { #if _HAS_BSF_TZCNT_INTRINSICS #if _HAS_CXX20 if (!_STD is_constant_evaluated()) From e06ec5bf19c6b4e1f952f4b6cadc3c277ca01198 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 22 Nov 2021 18:23:56 -0800 Subject: [PATCH 08/12] _Select_countr_zero_impl should be constexpr. --- stl/inc/limits | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/limits b/stl/inc/limits index 83eaa514a39..b162b3b0aa0 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -1208,7 +1208,7 @@ _NODISCARD _CONSTEXPR20 int _Countr_zero(const _Ty _Val) noexcept { } template -_CONSTEXPR20 decltype(auto) _Select_countr_zero_impl(_Fn _Callback) { +constexpr decltype(auto) _Select_countr_zero_impl(_Fn _Callback) { // TRANSITION, DevCom-1527995: Lambdas in this function ensure inlining #if _HAS_BSF_TZCNT_INTRINSICS && _HAS_CXX20 if (!_STD is_constant_evaluated()) { From 0b40a5deccf457e9bc4d4c474b334c0f2582512a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 22 Nov 2021 18:25:54 -0800 Subject: [PATCH 09/12] Reverse AVX2 preprocessor logic. --- stl/inc/limits | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/limits b/stl/inc/limits index b162b3b0aa0..a92df559f41 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -1212,16 +1212,16 @@ constexpr decltype(auto) _Select_countr_zero_impl(_Fn _Callback) { // TRANSITION, DevCom-1527995: Lambdas in this function ensure inlining #if _HAS_BSF_TZCNT_INTRINSICS && _HAS_CXX20 if (!_STD is_constant_evaluated()) { -#ifndef __AVX2__ +#ifdef __AVX2__ + return _Callback([](_Ty _Val) { return _Countr_zero_tzcnt(_Val); }); +#else // ^^^ AVX2 ^^^ / vvv not AVX2 vvv const bool _Definitely_have_tzcnt = __isa_available >= __ISA_AVAILABLE_AVX2; if (_Definitely_have_tzcnt) { return _Callback([](_Ty _Val) { return _Countr_zero_tzcnt(_Val); }); } else { return _Callback([](_Ty _Val) { return _Countr_zero_bsf(_Val); }); } -#else // ^^^ not AVX2 ^^^ / vvv AVX2 vvv - return _Callback([](_Ty _Val) { return _Countr_zero_tzcnt(_Val); }); -#endif // ^^^ AVX2 ^^^ +#endif // ^^^ not AVX2 ^^^ } #endif // ^^^ _HAS_BSF_TZCNT_INTRINSICS && _HAS_CXX20 ^^^ // C++17 constexpr gcd() calls this function, so it should be constexpr unless we detect runtime evaluation. From 0aab3465bb7bc27e3470d595ccea9d87d91e1c20 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 17 Dec 2021 16:01:55 -0800 Subject: [PATCH 10/12] Rename macro to match GH 2337. --- stl/inc/limits | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stl/inc/limits b/stl/inc/limits index a92df559f41..90029ee3ac5 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -1052,12 +1052,12 @@ _NODISCARD constexpr int _Popcount_fallback(_Ty _Val) noexcept { } #if defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC)) -#define _HAS_BSF_TZCNT_INTRINSICS 1 +#define _HAS_TZCNT_BSF_INTRINSICS 1 #else // ^^^ intrinsics available ^^^ / vvv intrinsics unavailable vvv -#define _HAS_BSF_TZCNT_INTRINSICS 0 +#define _HAS_TZCNT_BSF_INTRINSICS 0 #endif // ^^^ intrinsics unavailable ^^^ -#if _HAS_BSF_TZCNT_INTRINSICS +#if _HAS_TZCNT_BSF_INTRINSICS extern "C" { extern int __isa_available; #ifdef __clang__ @@ -1145,7 +1145,7 @@ _NODISCARD int _Checked_x86_x64_countr_zero(const _Ty _Val) noexcept { #undef _TZCNT_U32 #undef _TZCNT_U64 -#endif // _HAS_BSF_TZCNT_INTRINSICS +#endif // _HAS_TZCNT_BSF_INTRINSICS #if (defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))) && !defined(_M_CEE_PURE) && !defined(__CUDACC__) \ && !defined(__INTEL_COMPILER) @@ -1196,21 +1196,21 @@ constexpr bool _Is_standard_unsigned_integer = template , int> = 0> _NODISCARD _CONSTEXPR20 int _Countr_zero(const _Ty _Val) noexcept { -#if _HAS_BSF_TZCNT_INTRINSICS +#if _HAS_TZCNT_BSF_INTRINSICS #if _HAS_CXX20 if (!_STD is_constant_evaluated()) #endif // _HAS_CXX20 { return _Checked_x86_x64_countr_zero(_Val); } -#endif // _HAS_BSF_TZCNT_INTRINSICS +#endif // _HAS_TZCNT_BSF_INTRINSICS return _Countr_zero_fallback(_Val); } template constexpr decltype(auto) _Select_countr_zero_impl(_Fn _Callback) { // TRANSITION, DevCom-1527995: Lambdas in this function ensure inlining -#if _HAS_BSF_TZCNT_INTRINSICS && _HAS_CXX20 +#if _HAS_TZCNT_BSF_INTRINSICS && _HAS_CXX20 if (!_STD is_constant_evaluated()) { #ifdef __AVX2__ return _Callback([](_Ty _Val) { return _Countr_zero_tzcnt(_Val); }); @@ -1223,7 +1223,7 @@ constexpr decltype(auto) _Select_countr_zero_impl(_Fn _Callback) { } #endif // ^^^ not AVX2 ^^^ } -#endif // ^^^ _HAS_BSF_TZCNT_INTRINSICS && _HAS_CXX20 ^^^ +#endif // ^^^ _HAS_TZCNT_BSF_INTRINSICS && _HAS_CXX20 ^^^ // C++17 constexpr gcd() calls this function, so it should be constexpr unless we detect runtime evaluation. return _Callback([](_Ty _Val) { return _Countr_zero_fallback(_Val); }); } @@ -1271,7 +1271,7 @@ _CONSTEXPR20 decltype(auto) _Select_popcount_impl(_Fn _Callback) { } #undef _HAS_POPCNT_INTRINSICS -#undef _HAS_BSF_TZCNT_INTRINSICS +#undef _HAS_TZCNT_BSF_INTRINSICS #undef _HAS_NEON_INTRINSICS _STD_END From f06025e6680a9bf287bad572a69c69121431c78d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 17 Dec 2021 16:25:23 -0800 Subject: [PATCH 11/12] Avoid adding empty line. --- stl/inc/limits | 1 - 1 file changed, 1 deletion(-) diff --git a/stl/inc/limits b/stl/inc/limits index 9964a4664b7..dc228a127e4 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -1235,7 +1235,6 @@ constexpr decltype(auto) _Select_countr_zero_impl(_Fn _Callback) { return _Callback([](_Ty _Val) { return _Countr_zero_fallback(_Val); }); } - template , int> _Enabled = 0> _NODISCARD _CONSTEXPR20 int _Popcount(const _Ty _Val) noexcept { #if _HAS_POPCNT_INTRINSICS || _HAS_NEON_INTRINSICS From 6785ef72758045836c19b643c5f1277597c7ba4b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 17 Dec 2021 16:31:19 -0800 Subject: [PATCH 12/12] _Checked_x86_x64_countr_zero is now called outside _HAS_CXX20. --- stl/inc/limits | 4 ---- 1 file changed, 4 deletions(-) diff --git a/stl/inc/limits b/stl/inc/limits index dc228a127e4..4456f450eda 100644 --- a/stl/inc/limits +++ b/stl/inc/limits @@ -1063,8 +1063,6 @@ extern "C" { extern int __isa_available; } -#if _HAS_CXX20 - #ifdef __clang__ #define _TZCNT_U32 __builtin_ia32_tzcnt_u32 #define _TZCNT_U64 __builtin_ia32_tzcnt_u64 @@ -1150,8 +1148,6 @@ _NODISCARD int _Checked_x86_x64_countr_zero(const _Ty _Val) noexcept { #endif // __AVX2__ } -#endif // _HAS_CXX20 - #endif // _HAS_TZCNT_BSF_INTRINSICS #if (defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))) && !defined(_M_CEE_PURE) && !defined(__CUDACC__) \