From 29f7aa8821043c4fc2286eb4187cb92a8a14054b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 05:22:21 -0700 Subject: [PATCH 01/33] Set up the new macro system. --- stl/inc/xutility | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 935ced63c13..b433129e8a5 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -41,17 +41,47 @@ _STL_DISABLE_CLANG_WARNINGS #elif _USE_STD_VECTOR_ALGORITHMS #error Vector algorithms are not supported when building msvcp140.dll, but _USE_STD_VECTOR_ALGORITHMS is set. #endif // ^^^ _USE_STD_VECTOR_ALGORITHMS != 0 ^^^ -#elif (defined(_M_IX86) || defined(_M_X64)) && !defined(_M_CEE_PURE) && !defined(_M_HYBRID) && !defined(_M_ARM64EC) -#ifndef _USE_STD_VECTOR_ALGORITHMS -#define _USE_STD_VECTOR_ALGORITHMS 1 -#endif // !defined(_USE_STD_VECTOR_ALGORITHMS) -#else // ^^^ arch supports vector algorithms / no support for vector algorithms vvv +#elif defined(_M_CEE_PURE) || defined(_M_HYBRID) #ifndef _USE_STD_VECTOR_ALGORITHMS #define _USE_STD_VECTOR_ALGORITHMS 0 #elif _USE_STD_VECTOR_ALGORITHMS #error Vector algorithms are not supported on this architecture, but _USE_STD_VECTOR_ALGORITHMS is set. #endif // ^^^ _USE_STD_VECTOR_ALGORITHMS != 0 ^^^ -#endif // ^^^ no support for vector algorithms ^^^ +#else // ^^^ vector algorithms unsupported for /clr:pure or CHPE / vector algorithms supported by default vvv +#ifndef _USE_STD_VECTOR_ALGORITHMS +#define _USE_STD_VECTOR_ALGORITHMS 1 +#endif // !defined(_USE_STD_VECTOR_ALGORITHMS) +#endif // ^^^ vector algorithms supported by default ^^^ + +// _USE_STD_VECTOR_ALGORITHMS is our documented control macro: +// https://learn.microsoft.com/en-us/cpp/standard-library/vectorized-stl-algorithms?view=msvc-170 +// In the STL's implementation, we inspect the following architecture-specific detection macros, +// because various algorithms are vectorized for various architectures: +#if defined(_VECTORIZED_FOR_X64_X86) +#error _VECTORIZED_FOR_X64_X86 is not a control macro; define _USE_STD_VECTOR_ALGORITHMS instead. +#elif defined(_VECTORIZED_FOR_X64_X86_ARM64) +#error _VECTORIZED_FOR_X64_X86_ARM64 is not a control macro; define _USE_STD_VECTOR_ALGORITHMS instead. +#elif defined(_VECTORIZED_FOR_X64_X86_ARM64_ARM64EC) +#error _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC is not a control macro; define _USE_STD_VECTOR_ALGORITHMS instead. +#elif !_USE_STD_VECTOR_ALGORITHMS +#define _VECTORIZED_FOR_X64_X86 0 +#define _VECTORIZED_FOR_X64_X86_ARM64 0 +#define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 0 +#elif defined(_M_ARM64EC) +#define _VECTORIZED_FOR_X64_X86 0 +#define _VECTORIZED_FOR_X64_X86_ARM64 0 +#define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 1 +#elif defined(_M_X64) || defined(_M_IX86) +#define _VECTORIZED_FOR_X64_X86 1 +#define _VECTORIZED_FOR_X64_X86_ARM64 1 +#define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 1 +#elif defined(_M_ARM64) +#define _VECTORIZED_FOR_X64_X86 0 +#define _VECTORIZED_FOR_X64_X86_ARM64 1 +#define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 1 +#else // ^^^ known architecture / unknown architecture vvv +#error Unknown architecture. +#endif // ^^^ unknown architecture ^^^ #ifndef _USE_STD_VECTOR_FLOATING_ALGORITHMS #if _USE_STD_VECTOR_ALGORITHMS && !defined(_M_FP_EXCEPT) From 9df2f9b56ef0aadf1a67d052d71496d231e1e00f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 05:50:16 -0700 Subject: [PATCH 02/33] Inspect `_VECTORIZED_FOR_X64_X86`. --- stl/inc/__msvc_string_view.hpp | 48 +++--- stl/inc/algorithm | 150 +++++++++--------- stl/inc/bitset | 12 +- stl/inc/functional | 4 +- stl/inc/xmemory | 8 +- stl/inc/xutility | 110 ++++++------- .../test.compile.pass.cpp | 4 +- .../test.compile.pass.cpp | 2 +- 8 files changed, 169 insertions(+), 169 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index cc82be25c53..1e45eae2540 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -19,7 +19,7 @@ _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 extern "C" { // The "noalias" attribute tells the compiler optimizer that pointers going into these hand-vectorized algorithms // won't be stored beyond the lifetime of the function, and that the function will only reference arrays denoted by @@ -158,7 +158,7 @@ size_t _Find_last_not_of_pos_vectorized(const _Ty1* const _Haystack, const size_ _STD_END -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _STD_BEGIN #ifdef __clang__ @@ -360,7 +360,7 @@ struct _WChar_traits : private _Char_traits<_Elem, unsigned short> { _NODISCARD static _CONSTEXPR17 int compare(_In_reads_(_Count) const _Elem* const _First1, _In_reads_(_Count) const _Elem* const _First2, const size_t _Count) noexcept /* strengthened */ { // compare [_First1, _First1 + _Count) with [_First2, ...) -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if (!_STD _Is_constant_evaluated()) { // TRANSITION, GH-2289: Use vectorized algorithms for better performance than __builtin_wmemcmp. const size_t _Pos = _Mismatch_vectorized(_First1, _First2, _Count); @@ -370,7 +370,7 @@ struct _WChar_traits : private _Char_traits<_Elem, unsigned short> { return _First1[_Pos] < _First2[_Pos] ? -1 : +1; } } -#endif // ^^^ _USE_STD_VECTOR_ALGORITHMS ^^^ +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ if constexpr (is_same_v<_Elem, wchar_t>) { return __builtin_wmemcmp(_First1, _First2, _Count); @@ -728,7 +728,7 @@ constexpr size_t _Traits_find(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits> return _Start_at; } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { const auto _End = _Haystack + _Hay_size; @@ -741,7 +741,7 @@ constexpr size_t _Traits_find(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits> } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ const auto _Possible_matches_end = _Haystack + (_Hay_size - _Needle_size) + 1; for (auto _Match_try = _Haystack + _Start_at;; ++_Match_try) { @@ -764,7 +764,7 @@ constexpr size_t _Traits_find_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_Trai return static_cast(-1); // (npos) no room for match } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { const auto _End = _Haystack + _Hay_size; @@ -777,7 +777,7 @@ constexpr size_t _Traits_find_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_Trai } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ const auto _Found_at = _Traits::find(_Haystack + _Start_at, _Hay_size - _Start_at, _Ch); if (_Found_at) { @@ -802,7 +802,7 @@ constexpr size_t _Traits_rfind(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits const size_t _Actual_start_at = (_STD min) (_Start_at, _Hay_size - _Needle_size); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { // _Find_end_vectorized takes into account the needle length when locating the search start. @@ -819,7 +819,7 @@ constexpr size_t _Traits_rfind(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (auto _Match_try = _Haystack + _Actual_start_at;; --_Match_try) { if (_Traits::eq(*_Match_try, *_Needle) && _Traits::compare(_Match_try, _Needle, _Needle_size) == 0) { @@ -843,7 +843,7 @@ constexpr size_t _Traits_rfind_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_Tra const size_t _Actual_start_at = (_STD min) (_Start_at, _Hay_size - 1); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { const auto _End = _Haystack + _Actual_start_at + 1; @@ -856,7 +856,7 @@ constexpr size_t _Traits_rfind_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_Tra } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (auto _Match_try = _Haystack + _Actual_start_at;; --_Match_try) { if (_Traits::eq(*_Match_try, _Ch)) { @@ -934,7 +934,7 @@ constexpr size_t _Traits_find_first_of(_In_reads_(_Hay_size) const _Traits_ptr_t const auto _Hay_end = _Haystack + _Hay_size; if constexpr (_Is_implementation_handled_char_traits<_Traits>) { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if (!_STD _Is_constant_evaluated()) { const size_t _Remaining_size = _Hay_size - _Start_at; if (_Remaining_size + _Needle_size >= _Threshold_find_first_of) { @@ -945,7 +945,7 @@ constexpr size_t _Traits_find_first_of(_In_reads_(_Hay_size) const _Traits_ptr_t return _Pos; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _String_bitmap _Matches; @@ -983,7 +983,7 @@ constexpr size_t _Traits_find_last_of(_In_reads_(_Hay_size) const _Traits_ptr_t< if constexpr (_Is_implementation_handled_char_traits<_Traits>) { using _Elem = typename _Traits::char_type; -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (sizeof(_Elem) <= 2) { if (!_STD _Is_constant_evaluated()) { const size_t _Remaining_size = _Hay_start + 1; @@ -992,7 +992,7 @@ constexpr size_t _Traits_find_last_of(_In_reads_(_Hay_size) const _Traits_ptr_t< } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _String_bitmap<_Elem> _Matches; if (_Matches._Mark(_Needle, _Needle + _Needle_size)) { @@ -1035,7 +1035,7 @@ constexpr size_t _Traits_find_first_not_of(_In_reads_(_Hay_size) const _Traits_p if constexpr (_Is_implementation_handled_char_traits<_Traits>) { using _Elem = typename _Traits::char_type; -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (sizeof(_Elem) <= 2) { if (!_STD _Is_constant_evaluated()) { const size_t _Remaining_size = _Hay_size - _Start_at; @@ -1048,7 +1048,7 @@ constexpr size_t _Traits_find_first_not_of(_In_reads_(_Hay_size) const _Traits_p } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _String_bitmap<_Elem> _Matches; if (_Matches._Mark(_Needle, _Needle + _Needle_size)) { @@ -1082,7 +1082,7 @@ constexpr size_t _Traits_find_not_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_ const auto _End = _Haystack + _Hay_size; -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { const auto _Result = _STD _Find_not_ch_vectorized(_Haystack + _Start_at, _End, _Ch); @@ -1093,7 +1093,7 @@ constexpr size_t _Traits_find_not_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_ } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (auto _Match_try = _Haystack + _Start_at; _Match_try < _End; ++_Match_try) { if (!_Traits::eq(*_Match_try, _Ch)) { @@ -1117,7 +1117,7 @@ constexpr size_t _Traits_find_last_not_of(_In_reads_(_Hay_size) const _Traits_pt if constexpr (_Is_implementation_handled_char_traits<_Traits>) { using _Elem = typename _Traits::char_type; -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (sizeof(_Elem) <= 2) { if (!_STD _Is_constant_evaluated()) { const size_t _Remaining_size = _Hay_start + 1; @@ -1126,7 +1126,7 @@ constexpr size_t _Traits_find_last_not_of(_In_reads_(_Hay_size) const _Traits_pt } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _String_bitmap<_Elem> _Matches; if (_Matches._Mark(_Needle, _Needle + _Needle_size)) { @@ -1165,13 +1165,13 @@ constexpr size_t _Traits_rfind_not_ch(_In_reads_(_Hay_size) const _Traits_ptr_t< const size_t _Actual_start_at = (_STD min) (_Start_at, _Hay_size - 1); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { return _STD _Find_last_not_ch_pos_vectorized(_Haystack, _Haystack + _Actual_start_at + 1, _Ch); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (auto _Match_try = _Haystack + _Actual_start_at;; --_Match_try) { if (!_Traits::eq(*_Match_try, _Ch)) { diff --git a/stl/inc/algorithm b/stl/inc/algorithm index cb5511d5742..137a35087be 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -29,7 +29,7 @@ _STL_DISABLE_CLANG_WARNINGS #undef msvc #undef lifetimebound -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 extern "C" { // The "noalias" attribute tells the compiler optimizer that pointers going into these hand-vectorized algorithms @@ -425,7 +425,7 @@ constexpr bool _Vector_alg_includes_iterators_safe = && is_same_v<_Elem, _Iter_value_t<_Iter2>> // Iterators have the same value type. && disjunction_v, is_pointer<_Elem>>; // Integral or pointer type. _STD_END -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _STD_BEGIN #define _REQUIRE_CPP17_MUTABLE_RANDOM_ACCESS_ITERATOR(_Iter) \ @@ -748,7 +748,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt adjacent_find(const _FwdIt _First, _FwdIt _Last, auto _UFirst = _STD _Get_unwrapped(_First); auto _ULast = _STD _Get_unwrapped(_Last); if (_UFirst != _ULast) { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_search_is_safe) { if (!_STD _Is_constant_evaluated()) { const auto _First_ptr = _STD _To_address(_UFirst); @@ -764,7 +764,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt adjacent_find(const _FwdIt _First, _FwdIt _Last, return _Last; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (auto _UNext = _UFirst; ++_UNext != _ULast; _UFirst = _UNext) { if (_Pred(*_UFirst, *_UNext)) { @@ -822,7 +822,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_binary_predicate, const _Ty*>); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && _Vector_alg_in_find_is_safe<_It, _Ty> && sized_sentinel_for<_Se, _It>) { if (!_STD is_constant_evaluated()) { @@ -836,7 +836,7 @@ namespace ranges { return static_cast>(_STD _Count_vectorized(_First_ptr, _Last_ptr, _Val)); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ iter_difference_t<_It> _Count = 0; for (; _First != _Last; ++_First) { @@ -924,7 +924,7 @@ _NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch(_InIt1 _First1, const _InI auto _UFirst1 = _STD _Get_unwrapped(_First1); const auto _ULast1 = _STD _Get_unwrapped(_Last1); auto _UFirst2 = _STD _Get_unwrapped_n(_First2, _STD _Idl_distance<_InIt1>(_UFirst1, _ULast1)); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Equal_memcmp_is_safe) { if (!_STD _Is_constant_evaluated()) { constexpr size_t _Elem_size = sizeof(_Iter_value_t<_InIt1>); @@ -940,7 +940,7 @@ _NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch(_InIt1 _First1, const _InI return {_First1, _First2}; } } -#endif // ^^^ _USE_STD_VECTOR_ALGORITHMS ^^^ +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ while (_UFirst1 != _ULast1 && _Pred(*_UFirst1, *_UFirst2)) { ++_UFirst1; ++_UFirst2; @@ -988,7 +988,7 @@ _NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch( const _CT _Count2 = _ULast2 - _UFirst2; const auto _Count = static_cast<_Iter_diff_t<_InIt1>>((_STD min) (_Count1, _Count2)); _ULast1 = _UFirst1 + _Count; -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Equal_memcmp_is_safe) { if (!_STD _Is_constant_evaluated()) { constexpr size_t _Elem_size = sizeof(_Iter_value_t<_InIt1>); @@ -1004,7 +1004,7 @@ _NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch( return {_First1, _First2}; } } -#endif // ^^^ _USE_STD_VECTOR_ALGORITHMS ^^^ +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ while (_UFirst1 != _ULast1 && _Pred(*_UFirst1, *_UFirst2)) { ++_UFirst1; ++_UFirst2; @@ -2354,7 +2354,7 @@ _NODISCARD _CONSTEXPR20 _FwdItHaystack search(_FwdItHaystack _First1, _FwdItHays if constexpr (_Is_ranges_random_iter_v<_FwdItHaystack> && _Is_ranges_random_iter_v<_FwdItPat>) { const _Iter_diff_t<_FwdItPat> _Count2 = _ULast2 - _UFirst2; if (_ULast1 - _UFirst1 >= _Count2) { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_search_is_safe) { if (!_STD _Is_constant_evaluated()) { const auto _Ptr1 = _STD _To_address(_UFirst1); @@ -2372,7 +2372,7 @@ _NODISCARD _CONSTEXPR20 _FwdItHaystack search(_FwdItHaystack _First1, _FwdItHays return _Last1; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ const auto _Last_possible = _ULast1 - static_cast<_Iter_diff_t<_FwdItHaystack>>(_Count2); for (;; ++_UFirst1) { @@ -2463,7 +2463,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt search_n( auto _UFirst = _STD _Get_unwrapped(_First); const auto _ULast = _STD _Get_unwrapped(_Last); if constexpr (_Is_ranges_random_iter_v<_FwdIt>) { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_search_n_is_safe) { if (!_STD _Is_constant_evaluated()) { if (!_STD _Could_compare_equal_to_value_type(_Val)) { @@ -2484,7 +2484,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt search_n( return _Last; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ const auto _Count_diff = static_cast<_Iter_diff_t<_FwdIt>>(_Count); auto _UOld_first = _UFirst; @@ -2658,7 +2658,7 @@ namespace ranges { return {_First, _First}; } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_search_n_is_safe<_It, _Ty, _Pr> && is_same_v<_Pj, identity>) { if (!_STD is_constant_evaluated()) { if (!_STD _Could_compare_equal_to_value_type<_It>(_Val)) { @@ -2688,7 +2688,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ auto _Last = _RANGES next(_First, _Count); auto _Mid1 = _First; @@ -3348,7 +3348,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_binary_predicate, const _Ty*>); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && _Vector_alg_in_find_is_safe<_It, _Ty> && sized_sentinel_for<_Se, _It>) { if (!_STD is_constant_evaluated()) { @@ -3369,7 +3369,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ if constexpr (_Bidi_common<_It, _Se>) { for (auto _Result = _Last; _Result != _First;) { @@ -3509,7 +3509,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_end( if constexpr (_Is_ranges_random_iter_v<_FwdIt1> && _Is_ranges_random_iter_v<_FwdIt2>) { const _Iter_diff_t<_FwdIt2> _Count2 = _ULast2 - _UFirst2; if (_Count2 > 0 && _Count2 <= _ULast1 - _UFirst1) { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_search_is_safe) { if (!_STD _Is_constant_evaluated()) { const auto _Ptr1 = _STD _To_address(_UFirst1); @@ -3527,7 +3527,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_end( return _First1; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (auto _UCandidate = _ULast1 - static_cast<_Iter_diff_t<_FwdIt1>>(_Count2);; --_UCandidate) { if (_STD _Equal_rev_pred_unchecked(_UCandidate, _UFirst2, _ULast2, _STD _Pass_fn(_Pred))) { @@ -3632,7 +3632,7 @@ namespace ranges { if (_Count2 > 0 && _Count2 <= _Count1) { const auto _Count2_as1 = static_cast>(_Count2); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_search_is_safe<_It1, _It2, _Pr> && is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>) { if (!_STD is_constant_evaluated()) { @@ -3659,7 +3659,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (auto _Candidate = _First1 + (_Count1 - _Count2_as1);; --_Candidate) { auto _Match_and_mid1 = @@ -3832,7 +3832,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_first_of( } } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_search_is_safe) { if (!_STD _Is_constant_evaluated() && _ULast1 - _UFirst1 >= _Threshold_find_first_of) { const auto _First1_ptr = _STD _To_address(_UFirst1); @@ -3848,7 +3848,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_first_of( return _First1; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _UFirst1 != _ULast1; ++_UFirst1) { for (auto _UMid2 = _UFirst2; _UMid2 != _ULast2; ++_UMid2) { @@ -3936,7 +3936,7 @@ namespace ranges { } } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_search_is_safe<_It1, _It2, _Pr> && sized_sentinel_for<_Se1, _It1> && sized_sentinel_for<_Se2, _It2> && is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>) { if (!_STD is_constant_evaluated() && _Last1 - _First1 >= _Threshold_find_first_of) { @@ -3958,7 +3958,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _First1 != _Last1; ++_First1) { for (auto _Mid2 = _First2; _Mid2 != _Last2; ++_Mid2) { if (_STD invoke(_Pred, _STD invoke(_Proj1, *_First1), _STD invoke(_Proj2, *_Mid2))) { @@ -3995,7 +3995,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se2, _It2>); _STL_INTERNAL_STATIC_ASSERT(indirectly_swappable<_It1, _It2>); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 using _Elem1 = remove_reference_t>; using _Elem2 = remove_reference_t>; if constexpr (same_as<_Elem1, _Elem2> && _Is_trivially_ranges_swappable_v<_Elem1> // @@ -4028,7 +4028,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _First1 != _Last1 && _First2 != _Last2; ++_First1, (void) ++_First2) { _RANGES iter_swap(_First1, _First2); @@ -4331,7 +4331,7 @@ _CONSTEXPR20 void replace(const _FwdIt _First, const _FwdIt _Last, const _Ty& _O auto _UFirst = _STD _Get_unwrapped(_First); const auto _ULast = _STD _Get_unwrapped(_Last); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_replace_is_safe) { #if _HAS_CXX20 if (!_STD is_constant_evaluated()) @@ -4344,7 +4344,7 @@ _CONSTEXPR20 void replace(const _FwdIt _First, const _FwdIt _Last, const _Ty& _O return; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _UFirst != _ULast; ++_UFirst) { if (*_UFirst == _Oldval) { @@ -4399,7 +4399,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(indirectly_writable<_It, const _Ty2&>); _STL_INTERNAL_STATIC_ASSERT(indirect_binary_predicate, const _Ty1*>); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for<_Se, _It> && _Vector_alg_in_ranges_replace_is_safe<_It, _Ty1, _Ty2>) { if (!_STD is_constant_evaluated()) { @@ -4414,7 +4414,7 @@ namespace ranges { return _First + _Count; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _First != _Last; ++_First) { if (_STD invoke(_Proj, *_First) == _Oldval) { @@ -4893,7 +4893,7 @@ _CONSTEXPR20 _OutIt remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _ const auto _ULast = _STD _Get_unwrapped(_Last); auto _UDest = _STD _Get_unwrapped_unverified(_Dest); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_find_is_safe && _Output_iterator_for_vector_alg_is_safe()) { if (!_STD _Is_constant_evaluated()) { @@ -4917,7 +4917,7 @@ _CONSTEXPR20 _OutIt remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _ return _Dest; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _UFirst != _ULast; ++_UFirst) { if (!(*_UFirst == _Val)) { @@ -5016,7 +5016,7 @@ namespace ranges { return {_STD move(_Next), _STD move(_First)}; } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_find_is_safe<_It, _Ty> && sized_sentinel_for<_Se, _It> && is_same_v<_Pj, identity>) { if (!_STD is_constant_evaluated()) { @@ -5032,7 +5032,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ while (++_First != _Last) { if (_STD invoke(_Proj, *_First) != _Val) { @@ -5144,7 +5144,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(indirectly_copyable<_It, _Out>); _STL_INTERNAL_STATIC_ASSERT(indirect_binary_predicate, const _Ty*>); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_find_is_safe<_It, _Ty> && _Output_iterator_for_vector_alg_is_safe<_Out, _It>() && sized_sentinel_for<_Se, _It> && is_same_v<_Pj, identity>) { if (!_STD is_constant_evaluated()) { @@ -5168,7 +5168,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _First != _Last; ++_First) { if (_STD invoke(_Proj, *_First) != _Val) { @@ -5251,7 +5251,7 @@ _NODISCARD_UNIQUE_ALG _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last, _P auto _UFirst = _STD _Get_unwrapped(_First); const auto _ULast = _STD _Get_unwrapped(_Last); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_unique_is_safe) { if (!_STD _Is_constant_evaluated()) { const auto _First_ptr = _STD _To_address(_UFirst); @@ -5267,7 +5267,7 @@ _NODISCARD_UNIQUE_ALG _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last, _P return _Last; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ if (_UFirst != _ULast) { for (auto _UFirstb = _UFirst; ++_UFirst != _ULast; _UFirstb = _UFirst) { @@ -5345,7 +5345,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_equivalence_relation<_Pr, projected<_It, _Pj>>); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for<_Se, _It> && _Vector_alg_in_unique_is_safe<_It, _Pr>) { if (!_STD is_constant_evaluated()) { @@ -5361,7 +5361,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ auto _Current = _First; if (_First == _Last) { @@ -5417,7 +5417,7 @@ _CONSTEXPR20 _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pr auto _UDest = _STD _Get_unwrapped_unverified(_Dest); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_unique_is_safe && _Output_iterator_for_vector_alg_is_safe()) { if (!_STD _Is_constant_evaluated()) { @@ -5435,7 +5435,7 @@ _CONSTEXPR20 _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pr return _Dest; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ if constexpr (_Is_ranges_fwd_iter_v<_InIt>) { // can reread the source for comparison auto _Firstb = _UFirst; @@ -5564,7 +5564,7 @@ namespace ranges { return {_STD move(_First), _STD move(_Output)}; } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for<_Se, _It> && _Vector_alg_in_unique_is_safe<_It, _Pr> && _Output_iterator_for_vector_alg_is_safe<_Out, _It>()) { @@ -5583,7 +5583,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ if constexpr (_Is_input_with_value_type<_Out, iter_value_t<_It>>) { // Can reread _Output @@ -5632,7 +5632,7 @@ namespace ranges { template requires permutable<_It> constexpr void _Reverse_common(_It _First, _It _Last) { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (contiguous_iterator<_It>) { using _Elem = remove_reference_t>; constexpr size_t _Nx = sizeof(_Elem); @@ -5646,7 +5646,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _First != _Last && _First != --_Last; ++_First) { _RANGES iter_swap(_First, _Last); @@ -5692,7 +5692,7 @@ _CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) { auto _ULast = _STD _Get_unwrapped(_Last); auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_BidIt>(_UFirst, _ULast)); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 using _Elem = remove_reference_t<_Iter_ref_t>>; using _DestElem = remove_reference_t<_Iter_ref_t>; constexpr bool _Allow_vectorization = conjunction_v, _DestElem>, @@ -5712,7 +5712,7 @@ _CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) { return _Dest; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _UFirst != _ULast; ++_UDest) { *_UDest = *--_ULast; @@ -5781,7 +5781,7 @@ namespace ranges { _STD _Verify_ranges_do_not_overlap(_First, _Last, _Output); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (contiguous_iterator<_It> && contiguous_iterator<_Out>) { using _Elem = remove_reference_t>; using _DestElem = remove_reference_t>; @@ -5798,7 +5798,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _First != _Last; ++_Output) { *_Output = *--_Last; @@ -5843,7 +5843,7 @@ namespace ranges { } if constexpr (bidirectional_iterator<_It>) { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 using _Elem = remove_reference_t>; if constexpr (contiguous_iterator<_It> && sized_sentinel_for<_Se, _It> @@ -5854,7 +5854,7 @@ namespace ranges { return {_First + (_Last - _Mid), _Last}; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _RANGES _Reverse_common(_First, _Mid); auto _Final = _RANGES _Get_final_iterator_unwrapped<_It>(_Mid, _STD move(_Last)); @@ -8480,7 +8480,7 @@ namespace ranges { return _First; } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_min_max_iterators_safe<_It> && sized_sentinel_for<_Se, _It> && is_same_v<_Pj, identity>) { constexpr bool _Is_greater = _Is_predicate_greater<_It, _Pr>; if constexpr (_Is_greater || _Is_predicate_less<_It, _Pr>) { @@ -8497,7 +8497,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (auto _Prev = _First; ++_First != _Last; ++_Prev) { if (_STD invoke(_Pred, _STD invoke(_Proj, *_First), _STD invoke(_Proj, *_Prev))) { @@ -10310,14 +10310,14 @@ _NODISCARD _CONSTEXPR20 bool includes(_InIt1 _First1, _InIt1 _Last1, _InIt2 _Fir return false; } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_includes_iterators_safe<_InIt1, _InIt2> && _Is_predicate_less<_InIt1, _Pr>) { if (!_STD _Is_constant_evaluated()) { return _STD _Includes_vectorized(_STD _To_address(_First1), _STD _To_address(_Last1), _STD _To_address(_First2), _STD _To_address(_Last2)); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (;;) { if (_DEBUG_LT_PRED(_Pred, *_UFirst1, *_UFirst2)) { @@ -10408,7 +10408,7 @@ namespace ranges { return false; } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_includes_iterators_safe<_It1, _It2> && _Is_predicate_less<_It1, _Pr> && sized_sentinel_for<_Se1, _It1> && sized_sentinel_for<_Se2, _It2> && is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>) { @@ -10420,7 +10420,7 @@ namespace ranges { return _STD _Includes_vectorized(_First1_ptr, _Last1_ptr, _First2_ptr, _Last2_ptr); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (;;) { if (_STD invoke(_Pred, _STD invoke(_Proj1, *_First1), _STD invoke(_Proj2, *_First2))) { @@ -11008,7 +11008,7 @@ namespace ranges { template constexpr pair<_FwdIt, _FwdIt> _Minmax_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_min_max_optimization_safe<_FwdIt, _Pr>) { if (!_Is_constant_evaluated()) { const auto _First_ptr = _STD _To_address(_First); @@ -11021,7 +11021,7 @@ constexpr pair<_FwdIt, _FwdIt> _Minmax_element_unchecked(_FwdIt _First, _FwdIt _ } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ // find smallest and largest elements pair<_FwdIt, _FwdIt> _Found(_First, _First); @@ -11134,7 +11134,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_strict_weak_order<_Pr, projected<_It, _Pj>>); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && _Is_min_max_optimization_safe<_It, _Pr> && sized_sentinel_for<_Se, _It>) { if (!_STD is_constant_evaluated()) { @@ -11149,7 +11149,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ min_max_result<_It> _Found{_First, _First}; @@ -11216,14 +11216,14 @@ _NODISCARD constexpr pair<_Ty, _Ty> minmax(initializer_list<_Ty> _Ilist, _Pr _Pr // return {leftmost/smallest, rightmost/largest} _STL_ASSERT( _Ilist.size() != 0, "An initializer_list passed to std::minmax must not be empty. (N4971 [alg.min.max]/21)"); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_min_max_value_optimization_safe) { if (!_STD _Is_constant_evaluated()) { const auto _Result = _STD _Minmax_vectorized(_Ilist.begin(), _Ilist.end()); return {static_cast<_Ty>(_Result._Min), static_cast<_Ty>(_Result._Max)}; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ pair _Res = _STD _Minmax_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); return pair<_Ty, _Ty>(*_Res.first, *_Res.second); @@ -11274,7 +11274,7 @@ namespace ranges { const auto _Last = _Range.end(); _STL_ASSERT(_First != _Last, "An initializer_list passed to std::ranges::minmax must not be empty. (N4971 [alg.min.max]/21)"); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity>) { if constexpr (_Is_min_max_value_optimization_safe) { if (!_STD is_constant_evaluated()) { @@ -11288,7 +11288,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ return _Minmax_fwd_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); } @@ -11302,7 +11302,7 @@ namespace ranges { _STL_ASSERT( _UFirst != _ULast, "A range passed to std::ranges::minmax must not be empty. (N4971 [alg.min.max]/21)"); using _Vty = range_value_t<_Rng>; -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for) { if constexpr (_Is_min_max_value_optimization_safe) { if (!_STD is_constant_evaluated()) { @@ -11320,7 +11320,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ if constexpr (forward_range<_Rng> && _Prefer_iterator_copies) { return _Minmax_fwd_unchecked( _STD move(_UFirst), _STD move(_ULast), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); @@ -11648,7 +11648,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt is_sorted_until(const _FwdIt _First, _FwdIt _Last auto _UFirst = _STD _Get_unwrapped(_First); auto _ULast = _STD _Get_unwrapped(_Last); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_min_max_iterators_safe) { constexpr bool _Is_greater = _Is_predicate_greater; if constexpr (_Is_greater || _Is_predicate_less) { @@ -11668,7 +11668,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt is_sorted_until(const _FwdIt _First, _FwdIt _Last } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ if (_UFirst != _ULast) { for (auto _UNext = _UFirst; ++_UNext != _ULast; ++_UFirst) { @@ -11901,7 +11901,7 @@ namespace ranges { } const size_t _Num = (_STD min) (_Num1, _Num2); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 const auto _First1_ptr = _STD to_address(_First1); const auto _First2_ptr = _STD to_address(_First2); const size_t _Pos = _Mismatch_vectorized(_First1_ptr, _First2_ptr, _Num); @@ -11912,10 +11912,10 @@ namespace ranges { } else { return _STD invoke(_Pred, _First1_ptr[_Pos], _First2_ptr[_Pos]); } -#else // ^^^ _USE_STD_VECTOR_ALGORITHMS / !_USE_STD_VECTOR_ALGORITHMS vvv +#else // ^^^ _VECTORIZED_FOR_X64_X86 / !_VECTORIZED_FOR_X64_X86 vvv const int _Ans = _STD _Memcmp_count(_First1, _First2, _Num); return _Memcmp_classification_pred{}(_Ans, 0) || (_Ans == 0 && _Num1 < _Num2); -#endif // ^^^ !_USE_STD_VECTOR_ALGORITHMS ^^^ +#endif // ^^^ !_VECTORIZED_FOR_X64_X86 ^^^ } } diff --git a/stl/inc/bitset b/stl/inc/bitset index 372f8784018..0d1cbca3154 100644 --- a/stl/inc/bitset +++ b/stl/inc/bitset @@ -22,7 +22,7 @@ _STL_DISABLE_CLANG_WARNINGS #define _STD_BITSET_TO_STREAM_STACK_RESERVATION 128 #endif // !defined(_STD_BITSET_TO_STREAM_STACK_RESERVATION) -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 // These bitset functions sometimes assume that the bit array has zero padding to a multiple of 2 or 4 bytes. // The assumptions hold true even for the vNext suggestion to use smaller types for small bitsets (see GH-1498) // due to vectorization thresholds. @@ -37,7 +37,7 @@ __declspec(noalias) bool __stdcall __std_bitset_from_string_1(void* _Dest, const __declspec(noalias) bool __stdcall __std_bitset_from_string_2(void* _Dest, const wchar_t* _Src, size_t _Size_bytes, size_t _Size_bits, size_t _Size_chars, wchar_t _Elem0, wchar_t _Elem1) noexcept; } // extern "C" -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _STD_BEGIN template _STD_BITSET_TO_STREAM_STACK_RESERVATION)> @@ -147,7 +147,7 @@ public: private: template _CONSTEXPR23 void _Construct(const _Elem* const _Ptr, size_t _Count, const _Elem _Elem0, const _Elem _Elem1) { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 constexpr size_t _Bitset_from_string_vector_threshold = 16; if constexpr (_Bits >= _Bitset_from_string_vector_threshold && _Is_implementation_handled_char_traits<_Traits> && sizeof(_Elem) <= 2) { @@ -170,7 +170,7 @@ private: return; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ if (_Count > _Bits) { for (size_t _Idx = _Bits; _Idx < _Count; ++_Idx) { const auto _Ch = _Ptr[_Idx]; @@ -516,7 +516,7 @@ public: template _CONSTEXPR23 void _To_string( _Elem* const _Buf, const size_t _Len, const _Elem _Elem0, const _Elem _Elem1) const noexcept { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 constexpr size_t _Bitset_to_string_vector_threshold = 32; if constexpr (_Bits >= _Bitset_to_string_vector_threshold && is_integral_v<_Elem> && sizeof(_Elem) <= 2) { if (!_Is_constant_evaluated()) { @@ -532,7 +532,7 @@ public: return; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (size_t _Pos = 0; _Pos < _Len; ++_Pos) { _Buf[_Pos] = _Subscript(_Len - 1 - _Pos) ? _Elem1 : _Elem0; diff --git a/stl/inc/functional b/stl/inc/functional index 48feddd89c4..20259397b13 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -2556,7 +2556,7 @@ _CONSTEXPR20 pair<_FwdItHaystack, _FwdItHaystack> _Search_pair_unchecked( _Iter_diff_t<_FwdItHaystack> _Count1 = _Last1 - _First1; _Iter_diff_t<_FwdItPat> _Count2 = _Last2 - _First2; -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_search_is_safe<_FwdItHaystack, _FwdItPat, _Pred_eq>) { if (!_STD _Is_constant_evaluated()) { const auto _Ptr1 = _STD _To_address(_First1); @@ -2577,7 +2577,7 @@ _CONSTEXPR20 pair<_FwdItHaystack, _FwdItHaystack> _Search_pair_unchecked( } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _Count2 <= _Count1; ++_First1, (void) --_Count1) { // room for match, try it _FwdItHaystack _Mid1 = _First1; diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 5305b74b45a..d5b0d1dd8c0 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -31,7 +31,7 @@ _STL_DISABLE_CLANG_WARNINGS #undef msvc #undef no_specializations -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 extern "C" { void* __stdcall __std_remove_1(void* _First, void* _Last, uint8_t _Val) noexcept; void* __stdcall __std_remove_2(void* _First, void* _Last, uint16_t _Val) noexcept; @@ -56,7 +56,7 @@ _Ty* _Remove_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) n } _STD_END -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _STD_BEGIN template @@ -2330,7 +2330,7 @@ _NODISCARD_REMOVE_ALG _CONSTEXPR20 _FwdIt remove(_FwdIt _First, const _FwdIt _La _UFirst = _STD _Find_unchecked(_UFirst, _ULast, _Val); auto _UNext = _UFirst; if (_UFirst != _ULast) { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_find_is_safe) { #if _HAS_CXX20 if (!_STD is_constant_evaluated()) @@ -2349,7 +2349,7 @@ _NODISCARD_REMOVE_ALG _CONSTEXPR20 _FwdIt remove(_FwdIt _First, const _FwdIt _La return _First; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ while (++_UFirst != _ULast) { if (!(*_UFirst == _Val)) { diff --git a/stl/inc/xutility b/stl/inc/xutility index b433129e8a5..c290d9ba1be 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -103,7 +103,7 @@ _STL_DISABLE_CLANG_WARNINGS #endif // ^^^ !defined(__clang__) || __clang_major__ < 19 ^^^ #endif // ^^^ !defined(_USE_BUILTIN_IS_TRIVIALLY_EQUALITY_COMPARABLE) ^^^ -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 extern "C" { // The "noalias" attribute tells the compiler optimizer that pointers going into these hand-vectorized algorithms // won't be stored beyond the lifetime of the function, and that the function will only reference arrays denoted by @@ -204,7 +204,7 @@ __declspec(noalias) size_t __stdcall __std_mismatch_2(const void* _First1, const __declspec(noalias) size_t __stdcall __std_mismatch_4(const void* _First1, const void* _First2, size_t _Count) noexcept; __declspec(noalias) size_t __stdcall __std_mismatch_8(const void* _First1, const void* _First2, size_t _Count) noexcept; } // extern "C" -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _STD_BEGIN @@ -217,7 +217,7 @@ _Target _Find_arg_cast(const _Source _Val) noexcept { } } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 template __declspec(noalias) void _Reverse_vectorized(void* _First, void* _Last) noexcept { if constexpr (_Nx == 1) { @@ -477,7 +477,7 @@ size_t _Mismatch_vectorized(const void* const _First1, const void* const _First2 return __std_mismatch_1(_First1, _First2, _Count * _Element_size) / _Element_size; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ template struct _Get_first_parameter; @@ -5625,7 +5625,7 @@ template constexpr bool _Equal_memcmp_is_safe = _Equal_memcmp_is_safe_helper, remove_const_t<_Iter2>, remove_const_t<_Pr>>; -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 template constexpr bool _Is_vector_element_size = _Size == 1 || _Size == 2 || _Size == 4 || _Size == 8; @@ -5633,7 +5633,7 @@ constexpr bool _Is_vector_element_size = _Size == 1 || _Size == 2 || _Size == 4 template constexpr bool _Vector_alg_in_search_is_safe = _Equal_memcmp_is_safe<_It1, _It2, _Pr> && _Is_vector_element_size)>; -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ template _NODISCARD int _Memcmp_count(_CtgIt1 _First1, _CtgIt2 _First2, const size_t _Count) { @@ -5790,7 +5790,7 @@ namespace ranges { _NODISCARD constexpr mismatch_result<_It1, _It2> _Mismatch_n( _It1 _First1, _It2 _First2, iter_difference_t<_It1> _Count, _Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) { _STL_INTERNAL_CHECK(_Count >= 0); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Equal_memcmp_is_safe<_It1, _It2, _Pr> && is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>) { if (!_STD is_constant_evaluated()) { @@ -5803,7 +5803,7 @@ namespace ranges { _First2 + static_cast>(_Pos)}; } } -#endif // ^^^ _USE_STD_VECTOR_ALGORITHMS ^^^ +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _Count != 0; ++_First1, (void) ++_First2, --_Count) { if (!_STD invoke(_Pred, _STD invoke(_Proj1, *_First1), _STD invoke(_Proj2, *_First2))) { break; @@ -5902,13 +5902,13 @@ namespace ranges { template constexpr bool _Lex_compare_memcmp_classify_elements = -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 is_integral_v<_Elem1> && is_integral_v<_Elem2> && sizeof(_Elem1) == sizeof(_Elem2) && is_unsigned_v<_Elem1> == is_unsigned_v<_Elem2>; -#else // ^^^ _USE_STD_VECTOR_ALGORITHMS / !_USE_STD_VECTOR_ALGORITHMS vvv +#else // ^^^ _VECTORIZED_FOR_X64_X86 / !_VECTORIZED_FOR_X64_X86 vvv conjunction_v<_Is_character_or_bool<_Elem1>, _Is_character_or_bool<_Elem2>, is_unsigned<_Elem1>, is_unsigned<_Elem2>>; -#endif // ^^^ !_USE_STD_VECTOR_ALGORITHMS ^^^ +#endif // ^^^ !_VECTORIZED_FOR_X64_X86 ^^^ #ifdef __cpp_lib_byte template <> @@ -5983,7 +5983,7 @@ _NODISCARD _CONSTEXPR20 bool lexicographical_compare( const auto _Num1 = static_cast(_ULast1 - _UFirst1); const auto _Num2 = static_cast(_ULast2 - _UFirst2); const size_t _Num = (_STD min) (_Num1, _Num2); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 const auto _First1_ptr = _STD _To_address(_UFirst1); const auto _First2_ptr = _STD _To_address(_UFirst2); const size_t _Pos = _Mismatch_vectorized(_First1_ptr, _First2_ptr, _Num); @@ -5994,10 +5994,10 @@ _NODISCARD _CONSTEXPR20 bool lexicographical_compare( } else { return _Pred(_First1_ptr[_Pos], _First2_ptr[_Pos]); } -#else // ^^^ _USE_STD_VECTOR_ALGORITHMS / !_USE_STD_VECTOR_ALGORITHMS vvv +#else // ^^^ _VECTORIZED_FOR_X64_X86 / !_VECTORIZED_FOR_X64_X86 vvv const int _Ans = _STD _Memcmp_count(_UFirst1, _UFirst2, _Num); return _Memcmp_pred{}(_Ans, 0) || (_Ans == 0 && _Num1 < _Num2); -#endif // ^^^ !_USE_STD_VECTOR_ALGORITHMS ^^^ +#endif // ^^^ !_VECTORIZED_FOR_X64_X86 ^^^ } } @@ -6108,7 +6108,7 @@ _NODISCARD constexpr auto lexicographical_compare_three_way(const _InIt1 _First1 const auto _Num1 = static_cast(_ULast1 - _UFirst1); const auto _Num2 = static_cast(_ULast2 - _UFirst2); const size_t _Num = (_STD min) (_Num1, _Num2); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 const auto _First1_ptr = _STD to_address(_UFirst1); const auto _First2_ptr = _STD to_address(_UFirst2); const size_t _Pos = _Mismatch_vectorized(_First1_ptr, _First2_ptr, _Num); @@ -6122,14 +6122,14 @@ _NODISCARD constexpr auto lexicographical_compare_three_way(const _InIt1 _First1 __assume(_Val1 != _Val2); // avoid one comparison return _Comp(_Val1, _Val2); } -#else // ^^^ _USE_STD_VECTOR_ALGORITHMS / !_USE_STD_VECTOR_ALGORITHMS vvv +#else // ^^^ _VECTORIZED_FOR_X64_X86 / !_VECTORIZED_FOR_X64_X86 vvv const int _Ans = _STD _Memcmp_count(_UFirst1, _UFirst2, _Num); if (_Ans == 0) { return _Num1 <=> _Num2; } else { return _Memcmp_pred{}(_Ans, 0); } -#endif // ^^^ !_USE_STD_VECTOR_ALGORITHMS ^^^ +#endif // ^^^ !_VECTORIZED_FOR_X64_X86 ^^^ } } @@ -6268,7 +6268,7 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c if (!_STD _Could_compare_equal_to_value_type<_InIt>(_Val)) { return _Last; } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 const auto _First_ptr = _STD _To_address(_First); const auto _Result = _STD _Find_vectorized(_First_ptr, _STD _To_address(_Last), _Val); if constexpr (is_pointer_v<_InIt>) { @@ -6276,7 +6276,7 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c } else { return _First + static_cast<_Iter_diff_t<_InIt>>(_Result - _First_ptr); } -#else // ^^^ _USE_STD_VECTOR_ALGORITHMS / !_USE_STD_VECTOR_ALGORITHMS vvv +#else // ^^^ _VECTORIZED_FOR_X64_X86 / !_VECTORIZED_FOR_X64_X86 vvv if constexpr (sizeof(_Iter_value_t<_InIt>) <= 2) { const auto _First_ptr = _STD _To_address(_First); const auto _Count = static_cast(_Last - _First); @@ -6299,7 +6299,7 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c return _Result ? _First + (_Result - _First_ptr) : _Last; } } -#endif // ^^^ !_USE_STD_VECTOR_ALGORITHMS ^^^ +#endif // ^^^ !_VECTORIZED_FOR_X64_X86 ^^^ } } @@ -6348,7 +6348,7 @@ namespace ranges { if constexpr (_Vector_alg_in_find_is_safe<_It, _Ty> && same_as<_Pj, identity> && (_Elements_are_1_byte ? _Is_sized || same_as<_Se, unreachable_sentinel_t> : _Elements_are_2_bytes ? _Is_sized - : _Is_sized && _USE_STD_VECTOR_ALGORITHMS)) { + : _Is_sized && _VECTORIZED_FOR_X64_X86)) { if (!_STD is_constant_evaluated()) { if (!_STD _Could_compare_equal_to_value_type<_It>(_Val)) { if constexpr (_Is_sized) { @@ -6363,13 +6363,13 @@ namespace ranges { const auto _First_ptr = _STD _To_address(_First); _Ptr_t _Result; -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_sized) { // Prefer this over memchr()/wmemchr() below for performance const auto _Last_ptr = _First_ptr + static_cast(_Last - _First); _Result = _STD _Find_vectorized(_First_ptr, _Last_ptr, _Val); } else -#endif // ^^^ _USE_STD_VECTOR_ALGORITHMS ^^^ +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ { if constexpr (_Elements_are_2_bytes) { _STL_INTERNAL_STATIC_ASSERT(_Is_sized); @@ -6458,7 +6458,7 @@ _NODISCARD _CONSTEXPR20 _Iter_diff_t<_InIt> count(const _InIt _First, const _InI auto _UFirst = _STD _Get_unwrapped(_First); const auto _ULast = _STD _Get_unwrapped(_Last); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_find_is_safe) { #if _HAS_CXX20 if (!_STD is_constant_evaluated()) @@ -6472,7 +6472,7 @@ _NODISCARD _CONSTEXPR20 _Iter_diff_t<_InIt> count(const _InIt _First, const _InI _STD _Count_vectorized(_STD _To_address(_UFirst), _STD _To_address(_ULast), _Val)); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _Iter_diff_t<_InIt> _Count = 0; @@ -6662,7 +6662,7 @@ _CONSTEXPR20 void reverse(const _BidIt _First, const _BidIt _Last) { // reverse _STD _Adl_verify_range(_First, _Last); auto _UFirst = _STD _Get_unwrapped(_First); auto _ULast = _STD _Get_unwrapped(_Last); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 using _Elem = remove_reference_t<_Iter_ref_t>; constexpr bool _Allow_vectorization = conjunction_v>, _Is_trivially_swappable<_Elem>, negation>>; @@ -6677,7 +6677,7 @@ _CONSTEXPR20 void reverse(const _BidIt _First, const _BidIt _Last) { // reverse return; } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _UFirst != _ULast && _UFirst != --_ULast; ++_UFirst) { swap(*_UFirst, *_ULast); // intentional ADL @@ -6724,7 +6724,7 @@ _CONSTEXPR20 _FwdIt rotate(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last) { } if constexpr (_Is_cpp17_random_iter_v<_FwdIt>) { -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 using _Elem = remove_reference_t<_Iter_ref_t>; if constexpr (conjunction_v>, @@ -6734,7 +6734,7 @@ _CONSTEXPR20 _FwdIt rotate(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last) { return _First + (_Last - _Mid); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _STD reverse(_UFirst, _UMid); _STD reverse(_UMid, _ULast); _STD reverse(_UFirst, _ULast); @@ -6953,7 +6953,7 @@ namespace ranges { return _First; } -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_search_is_safe<_It, _It, _Pr> && sized_sentinel_for<_Se, _It> && is_same_v<_Pj, identity>) { if (!_STD is_constant_evaluated()) { @@ -6968,7 +6968,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (auto _Next = _First;; ++_First) { if (++_Next == _Last) { @@ -7057,7 +7057,7 @@ namespace ranges { _STL_INTERNAL_CHECK(_RANGES distance(_First1, _Last1) == _Count1); _STL_INTERNAL_CHECK(_RANGES distance(_First2, _Last2) == _Count2); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Vector_alg_in_search_is_safe<_It1, _It2, _Pr> && is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>) { if (!_STD is_constant_evaluated()) { @@ -7090,7 +7090,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _Count1 >= _Count2; ++_First1, (void) --_Count1) { auto _Match_and_mid1 = _RANGES _Equal_rev_pred(_First1, _First2, _Last2, _Pred, _Proj1, _Proj2); @@ -7187,7 +7187,7 @@ constexpr bool _Is_min_max_value_optimization_safe = // Activate the vector algo template constexpr _FwdIt _Max_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // find largest element -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_min_max_optimization_safe<_FwdIt, _Pr>) { if (!_Is_constant_evaluated()) { const auto _First_ptr = _STD _To_address(_First); @@ -7199,7 +7199,7 @@ constexpr _FwdIt _Max_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _FwdIt _Found = _First; if (_First != _Last) { @@ -7251,7 +7251,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_strict_weak_order<_Pr, projected<_It, _Pj>>); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && _Is_min_max_optimization_safe<_It, _Pr> && sized_sentinel_for<_Se, _It>) { if (!_STD is_constant_evaluated()) { @@ -7265,7 +7265,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ auto _Found = _First; if (_First == _Last) { @@ -7314,13 +7314,13 @@ _NODISCARD constexpr _Ty(max)(initializer_list<_Ty> _Ilist, _Pr _Pred) { // return leftmost/largest _STL_ASSERT( _Ilist.size() != 0, "An initializer_list passed to std::max must not be empty. (N4971 [alg.min.max]/13)"); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_min_max_value_optimization_safe) { if (!_Is_constant_evaluated()) { return static_cast<_Ty>(_STD _Max_vectorized(_Ilist.begin(), _Ilist.end())); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ const _Ty* _Res = _STD _Max_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); return *_Res; } @@ -7360,13 +7360,13 @@ namespace ranges { const auto _Last = _Range.end(); _STL_ASSERT(_First != _Last, "An initializer_list passed to std::ranges::max must not be empty. (N4971 [alg.min.max]/13)"); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && _Is_min_max_value_optimization_safe) { if (!_STD is_constant_evaluated()) { return static_cast<_Ty>(_STD _Max_vectorized(_First, _Last)); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ return *_RANGES _Max_element_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); } @@ -7379,7 +7379,7 @@ namespace ranges { auto _ULast = _Uend(_Range); _STL_ASSERT( _UFirst != _ULast, "A range passed to std::ranges::max must not be empty. (N4971 [alg.min.max]/13)"); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && _Is_min_max_value_optimization_safe && sized_sentinel_for) { if (!_STD is_constant_evaluated()) { @@ -7388,7 +7388,7 @@ namespace ranges { return static_cast>(_STD _Max_vectorized(_First_ptr, _Last_ptr)); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ if constexpr (forward_range<_Rng> && _Prefer_iterator_copies) { return static_cast>(*_RANGES _Max_element_unchecked( _STD move(_UFirst), _STD move(_ULast), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj))); @@ -7411,7 +7411,7 @@ namespace ranges { template constexpr _FwdIt _Min_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // find smallest element -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_min_max_optimization_safe<_FwdIt, _Pr>) { if (!_Is_constant_evaluated()) { const auto _First_ptr = _STD _To_address(_First); @@ -7423,7 +7423,7 @@ constexpr _FwdIt _Min_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _FwdIt _Found = _First; if (_First != _Last) { @@ -7475,7 +7475,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_strict_weak_order<_Pr, projected<_It, _Pj>>); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && _Is_min_max_optimization_safe<_It, _Pr> && sized_sentinel_for<_Se, _It>) { if (!_STD is_constant_evaluated()) { @@ -7489,7 +7489,7 @@ namespace ranges { } } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ auto _Found = _First; if (_First == _Last) { @@ -7538,13 +7538,13 @@ _NODISCARD constexpr _Ty(min)(initializer_list<_Ty> _Ilist, _Pr _Pred) { // return leftmost/smallest _STL_ASSERT( _Ilist.size() != 0, "An initializer_list passed to std::min must not be empty. (N4971 [alg.min.max]/5)"); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (_Is_min_max_value_optimization_safe) { if (!_Is_constant_evaluated()) { return static_cast<_Ty>(_STD _Min_vectorized(_Ilist.begin(), _Ilist.end())); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ const _Ty* _Res = _STD _Min_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); return *_Res; } @@ -7578,13 +7578,13 @@ namespace ranges { const auto _Last = _Range.end(); _STL_ASSERT(_First != _Last, "An initializer_list passed to std::ranges::min must not be empty. (N4971 [alg.min.max]/5)"); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && _Is_min_max_value_optimization_safe) { if (!_STD is_constant_evaluated()) { return static_cast<_Ty>(_STD _Min_vectorized(_First, _Last)); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ return *_RANGES _Min_element_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); } @@ -7597,7 +7597,7 @@ namespace ranges { auto _ULast = _Uend(_Range); _STL_ASSERT( _UFirst != _ULast, "A range passed to std::ranges::min must not be empty. (N4971 [alg.min.max]/5)"); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && _Is_min_max_value_optimization_safe && sized_sentinel_for) { if (!_STD is_constant_evaluated()) { @@ -7606,7 +7606,7 @@ namespace ranges { return static_cast>(_STD _Min_vectorized(_First_ptr, _Last_ptr)); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ if constexpr (forward_range<_Rng> && _Prefer_iterator_copies) { return static_cast>(*_RANGES _Min_element_unchecked( _STD move(_UFirst), _STD move(_ULast), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj))); @@ -7687,7 +7687,7 @@ template _CONSTEXPR20 _FwdIt2 _Swap_ranges_unchecked(_FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) { // swap [_First1, _Last1) with [_First2, ...) -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 using _Elem1 = remove_reference_t<_Iter_ref_t<_FwdIt1>>; using _Elem2 = remove_reference_t<_Iter_ref_t<_FwdIt2>>; if constexpr (is_same_v<_Elem1, _Elem2> && _Is_trivially_swappable_v<_Elem1> @@ -7701,7 +7701,7 @@ _CONSTEXPR20 _FwdIt2 _Swap_ranges_unchecked(_FwdIt1 _First1, const _FwdIt1 _Last return _First2 + (_Last1 - _First1); } } -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ for (; _First1 != _Last1; ++_First1, (void) ++_First2) { swap(*_First1, *_First2); // intentional ADL diff --git a/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp b/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp index 5dabfa6499b..0147d030574 100644 --- a/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp +++ b/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp @@ -529,10 +529,10 @@ STATIC_ASSERT(test_equal_memcmp_is_safe_for_types> == magic); STATIC_ASSERT(_Equal_memcmp_is_safe> == magic); -#if _USE_STD_VECTOR_ALGORITHMS +#if _VECTORIZED_FOR_X64_X86 STATIC_ASSERT(_Vector_alg_in_search_is_safe> == magic); STATIC_ASSERT(!_Vector_alg_in_search_is_safe>); -#endif // _USE_STD_VECTOR_ALGORITHMS +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ #endif // _HAS_CXX20 // Test _Std_char_traits_eq diff --git a/tests/std/tests/GH_000431_lex_compare_memcmp_classify/test.compile.pass.cpp b/tests/std/tests/GH_000431_lex_compare_memcmp_classify/test.compile.pass.cpp index 85f43c2201c..261370801b6 100644 --- a/tests/std/tests/GH_000431_lex_compare_memcmp_classify/test.compile.pass.cpp +++ b/tests/std/tests/GH_000431_lex_compare_memcmp_classify/test.compile.pass.cpp @@ -178,7 +178,7 @@ void test_lex_compare_memcmp_classify_for_types() { #endif // _HAS_CXX20 } -constexpr bool vec_alg = _USE_STD_VECTOR_ALGORITHMS; +constexpr bool vec_alg = _VECTORIZED_FOR_X64_X86; template void test_lex_compare_memcmp_classify_for_1byte_integrals() { From 4efcf9de26cacb5c9a956173febfbacdeda1b347 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 07:50:27 -0700 Subject: [PATCH 03/33] Improve comments for vectorization type traits. --- stl/inc/algorithm | 7 +++++-- stl/inc/xutility | 8 ++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 137a35087be..a2d1db679dd 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -385,6 +385,7 @@ _Ty* _Unique_copy_vectorized(const _Ty* const _First, const _Ty* const _Last, _T _STL_INTERNAL_STATIC_ASSERT(false); // Unexpected size } } + // Can we activate the vector algorithms for replace? template constexpr bool _Vector_alg_in_replace_is_safe = _Vector_alg_in_find_is_safe<_Iter, _Ty1> // can search for the value @@ -396,6 +397,7 @@ constexpr bool _Vector_alg_in_ranges_replace_is_safe = _Vector_alg_in_replace_is_safe<_Iter, _Ty1> // can search and replace && _Vector_alg_in_find_is_safe_elem<_Ty2, _Iter_value_t<_Iter>>; // replacement fits +// Can we activate the vector algorithms for search_n? template constexpr bool _Vector_alg_in_search_n_is_safe = _Vector_alg_in_find_is_safe<_Iter, _Ty> && _Is_any_of_v<_Pr, @@ -403,11 +405,12 @@ constexpr bool _Vector_alg_in_search_n_is_safe = _Vector_alg_in_find_is_safe<_It ranges::equal_to, #endif equal_to<>>; -// Can we activate the vector algorithms for unique? + +// Can we activate the vector algorithms for unique and unique_copy? template constexpr bool _Vector_alg_in_unique_is_safe = _Vector_alg_in_search_is_safe<_Iter, _Iter, _Pr>; -// Can we use this output iterator for remove_copy or unique_copy? +// Can we use this output iterator for remove_copy and unique_copy? template constexpr bool _Output_iterator_for_vector_alg_is_safe() { if constexpr (_Iterator_is_contiguous<_Out>) { diff --git a/stl/inc/xutility b/stl/inc/xutility index c290d9ba1be..766e8ff4d45 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -302,6 +302,8 @@ _Ty* _Adjacent_find_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { } // find_first_of vectorization is likely to be a win after this size (in elements) +// (Used with _Find_first_of_vectorized, _Find_first_of_pos_vectorized, _Find_first_not_of_pos_vectorized, +// _Find_last_of_pos_vectorized, and _Find_last_not_of_pos_vectorized.) _INLINE_VAR constexpr ptrdiff_t _Threshold_find_first_of = 16; template @@ -5629,7 +5631,8 @@ constexpr bool _Equal_memcmp_is_safe = template constexpr bool _Is_vector_element_size = _Size == 1 || _Size == 2 || _Size == 4 || _Size == 8; -// Can we activate the vector algorithms for std::search? +// Can we activate the vector algorithms for search, adjacent_find, find_end, find_first_of, and default_searcher? +// (Also used indirectly for unique and unique_copy.) template constexpr bool _Vector_alg_in_search_is_safe = _Equal_memcmp_is_safe<_It1, _It2, _Pr> && _Is_vector_element_size)>; @@ -6191,7 +6194,8 @@ constexpr bool _Vector_alg_in_find_is_safe_elem = // - One of the pointer types is a cv1 U* and the other is a cv2 U*. _Vector_alg_in_find_is_safe_object_pointers<_Ty, _Elem>>; -// Can we activate the vector algorithms for find/count? +// Can we activate the vector algorithms for find, count, remove, remove_copy, and ranges::find_last? +// (Also used indirectly for replace and search_n.) template constexpr bool _Vector_alg_in_find_is_safe = // The iterator must be contiguous so we can get raw pointers. From 11a385eb9a71d731978f3fa80f46052e375b21cf Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 08:33:19 -0700 Subject: [PATCH 04/33] _VECTORIZED_MISMATCH. (note _Lex_compare_memcmp_classify_elements) --- stl/inc/__msvc_string_view.hpp | 4 +-- stl/inc/algorithm | 14 ++++----- stl/inc/xutility | 29 +++++++++++-------- .../test.compile.pass.cpp | 2 +- 4 files changed, 27 insertions(+), 22 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 1e45eae2540..969583f356a 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -360,7 +360,7 @@ struct _WChar_traits : private _Char_traits<_Elem, unsigned short> { _NODISCARD static _CONSTEXPR17 int compare(_In_reads_(_Count) const _Elem* const _First1, _In_reads_(_Count) const _Elem* const _First2, const size_t _Count) noexcept /* strengthened */ { // compare [_First1, _First1 + _Count) with [_First2, ...) -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MISMATCH if (!_STD _Is_constant_evaluated()) { // TRANSITION, GH-2289: Use vectorized algorithms for better performance than __builtin_wmemcmp. const size_t _Pos = _Mismatch_vectorized(_First1, _First2, _Count); @@ -370,7 +370,7 @@ struct _WChar_traits : private _Char_traits<_Elem, unsigned short> { return _First1[_Pos] < _First2[_Pos] ? -1 : +1; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MISMATCH ^^^ if constexpr (is_same_v<_Elem, wchar_t>) { return __builtin_wmemcmp(_First1, _First2, _Count); diff --git a/stl/inc/algorithm b/stl/inc/algorithm index a2d1db679dd..1d740a8c0f9 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -927,7 +927,7 @@ _NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch(_InIt1 _First1, const _InI auto _UFirst1 = _STD _Get_unwrapped(_First1); const auto _ULast1 = _STD _Get_unwrapped(_Last1); auto _UFirst2 = _STD _Get_unwrapped_n(_First2, _STD _Idl_distance<_InIt1>(_UFirst1, _ULast1)); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MISMATCH if constexpr (_Equal_memcmp_is_safe) { if (!_STD _Is_constant_evaluated()) { constexpr size_t _Elem_size = sizeof(_Iter_value_t<_InIt1>); @@ -943,7 +943,7 @@ _NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch(_InIt1 _First1, const _InI return {_First1, _First2}; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MISMATCH ^^^ while (_UFirst1 != _ULast1 && _Pred(*_UFirst1, *_UFirst2)) { ++_UFirst1; ++_UFirst2; @@ -991,7 +991,7 @@ _NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch( const _CT _Count2 = _ULast2 - _UFirst2; const auto _Count = static_cast<_Iter_diff_t<_InIt1>>((_STD min) (_Count1, _Count2)); _ULast1 = _UFirst1 + _Count; -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MISMATCH if constexpr (_Equal_memcmp_is_safe) { if (!_STD _Is_constant_evaluated()) { constexpr size_t _Elem_size = sizeof(_Iter_value_t<_InIt1>); @@ -1007,7 +1007,7 @@ _NODISCARD _CONSTEXPR20 pair<_InIt1, _InIt2> mismatch( return {_First1, _First2}; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MISMATCH ^^^ while (_UFirst1 != _ULast1 && _Pred(*_UFirst1, *_UFirst2)) { ++_UFirst1; ++_UFirst2; @@ -11904,7 +11904,7 @@ namespace ranges { } const size_t _Num = (_STD min) (_Num1, _Num2); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MISMATCH const auto _First1_ptr = _STD to_address(_First1); const auto _First2_ptr = _STD to_address(_First2); const size_t _Pos = _Mismatch_vectorized(_First1_ptr, _First2_ptr, _Num); @@ -11915,10 +11915,10 @@ namespace ranges { } else { return _STD invoke(_Pred, _First1_ptr[_Pos], _First2_ptr[_Pos]); } -#else // ^^^ _VECTORIZED_FOR_X64_X86 / !_VECTORIZED_FOR_X64_X86 vvv +#else // ^^^ _VECTORIZED_MISMATCH / !_VECTORIZED_MISMATCH vvv const int _Ans = _STD _Memcmp_count(_First1, _First2, _Num); return _Memcmp_classification_pred{}(_Ans, 0) || (_Ans == 0 && _Num1 < _Num2); -#endif // ^^^ !_VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ !_VECTORIZED_MISMATCH ^^^ } } diff --git a/stl/inc/xutility b/stl/inc/xutility index 766e8ff4d45..8c756b8c41a 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -199,10 +199,13 @@ __declspec(noalias) uint64_t __stdcall __std_max_8u(const void* _First, const vo __declspec(noalias) float __stdcall __std_max_f(const void* _First, const void* _Last) noexcept; __declspec(noalias) double __stdcall __std_max_d(const void* _First, const void* _Last) noexcept; +#if _VECTORIZED_MISMATCH __declspec(noalias) size_t __stdcall __std_mismatch_1(const void* _First1, const void* _First2, size_t _Count) noexcept; __declspec(noalias) size_t __stdcall __std_mismatch_2(const void* _First1, const void* _First2, size_t _Count) noexcept; __declspec(noalias) size_t __stdcall __std_mismatch_4(const void* _First1, const void* _First2, size_t _Count) noexcept; __declspec(noalias) size_t __stdcall __std_mismatch_8(const void* _First1, const void* _First2, size_t _Count) noexcept; +#endif // ^^^ _VECTORIZED_MISMATCH ^^^ + } // extern "C" #endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ @@ -466,7 +469,9 @@ auto _Max_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#if _VECTORIZED_MISMATCH template size_t _Mismatch_vectorized(const void* const _First1, const void* const _First2, const size_t _Count) noexcept { if constexpr (_Element_size % 8 == 0) { @@ -479,7 +484,7 @@ size_t _Mismatch_vectorized(const void* const _First1, const void* const _First2 return __std_mismatch_1(_First1, _First2, _Count * _Element_size) / _Element_size; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MISMATCH ^^^ template struct _Get_first_parameter; @@ -5793,7 +5798,7 @@ namespace ranges { _NODISCARD constexpr mismatch_result<_It1, _It2> _Mismatch_n( _It1 _First1, _It2 _First2, iter_difference_t<_It1> _Count, _Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) { _STL_INTERNAL_CHECK(_Count >= 0); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MISMATCH if constexpr (_Equal_memcmp_is_safe<_It1, _It2, _Pr> && is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>) { if (!_STD is_constant_evaluated()) { @@ -5806,7 +5811,7 @@ namespace ranges { _First2 + static_cast>(_Pos)}; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MISMATCH ^^^ for (; _Count != 0; ++_First1, (void) ++_First2, --_Count) { if (!_STD invoke(_Pred, _STD invoke(_Proj1, *_First1), _STD invoke(_Proj2, *_First2))) { break; @@ -5905,13 +5910,13 @@ namespace ranges { template constexpr bool _Lex_compare_memcmp_classify_elements = -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MISMATCH is_integral_v<_Elem1> && is_integral_v<_Elem2> && sizeof(_Elem1) == sizeof(_Elem2) && is_unsigned_v<_Elem1> == is_unsigned_v<_Elem2>; -#else // ^^^ _VECTORIZED_FOR_X64_X86 / !_VECTORIZED_FOR_X64_X86 vvv +#else // ^^^ _VECTORIZED_MISMATCH / !_VECTORIZED_MISMATCH vvv conjunction_v<_Is_character_or_bool<_Elem1>, _Is_character_or_bool<_Elem2>, is_unsigned<_Elem1>, is_unsigned<_Elem2>>; -#endif // ^^^ !_VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ !_VECTORIZED_MISMATCH ^^^ #ifdef __cpp_lib_byte template <> @@ -5986,7 +5991,7 @@ _NODISCARD _CONSTEXPR20 bool lexicographical_compare( const auto _Num1 = static_cast(_ULast1 - _UFirst1); const auto _Num2 = static_cast(_ULast2 - _UFirst2); const size_t _Num = (_STD min) (_Num1, _Num2); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MISMATCH const auto _First1_ptr = _STD _To_address(_UFirst1); const auto _First2_ptr = _STD _To_address(_UFirst2); const size_t _Pos = _Mismatch_vectorized(_First1_ptr, _First2_ptr, _Num); @@ -5997,10 +6002,10 @@ _NODISCARD _CONSTEXPR20 bool lexicographical_compare( } else { return _Pred(_First1_ptr[_Pos], _First2_ptr[_Pos]); } -#else // ^^^ _VECTORIZED_FOR_X64_X86 / !_VECTORIZED_FOR_X64_X86 vvv +#else // ^^^ _VECTORIZED_MISMATCH / !_VECTORIZED_MISMATCH vvv const int _Ans = _STD _Memcmp_count(_UFirst1, _UFirst2, _Num); return _Memcmp_pred{}(_Ans, 0) || (_Ans == 0 && _Num1 < _Num2); -#endif // ^^^ !_VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ !_VECTORIZED_MISMATCH ^^^ } } @@ -6111,7 +6116,7 @@ _NODISCARD constexpr auto lexicographical_compare_three_way(const _InIt1 _First1 const auto _Num1 = static_cast(_ULast1 - _UFirst1); const auto _Num2 = static_cast(_ULast2 - _UFirst2); const size_t _Num = (_STD min) (_Num1, _Num2); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MISMATCH const auto _First1_ptr = _STD to_address(_UFirst1); const auto _First2_ptr = _STD to_address(_UFirst2); const size_t _Pos = _Mismatch_vectorized(_First1_ptr, _First2_ptr, _Num); @@ -6125,14 +6130,14 @@ _NODISCARD constexpr auto lexicographical_compare_three_way(const _InIt1 _First1 __assume(_Val1 != _Val2); // avoid one comparison return _Comp(_Val1, _Val2); } -#else // ^^^ _VECTORIZED_FOR_X64_X86 / !_VECTORIZED_FOR_X64_X86 vvv +#else // ^^^ _VECTORIZED_MISMATCH / !_VECTORIZED_MISMATCH vvv const int _Ans = _STD _Memcmp_count(_UFirst1, _UFirst2, _Num); if (_Ans == 0) { return _Num1 <=> _Num2; } else { return _Memcmp_pred{}(_Ans, 0); } -#endif // ^^^ !_VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ !_VECTORIZED_MISMATCH ^^^ } } diff --git a/tests/std/tests/GH_000431_lex_compare_memcmp_classify/test.compile.pass.cpp b/tests/std/tests/GH_000431_lex_compare_memcmp_classify/test.compile.pass.cpp index 261370801b6..ea9da34ae0c 100644 --- a/tests/std/tests/GH_000431_lex_compare_memcmp_classify/test.compile.pass.cpp +++ b/tests/std/tests/GH_000431_lex_compare_memcmp_classify/test.compile.pass.cpp @@ -178,7 +178,7 @@ void test_lex_compare_memcmp_classify_for_types() { #endif // _HAS_CXX20 } -constexpr bool vec_alg = _VECTORIZED_FOR_X64_X86; +constexpr bool vec_alg = _VECTORIZED_MISMATCH; template void test_lex_compare_memcmp_classify_for_1byte_integrals() { From 9c4490b3517cffa3ade4e36b6d8845f253679613 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 08:37:14 -0700 Subject: [PATCH 05/33] _VECTORIZED_IS_SORTED_UNTIL. --- stl/inc/algorithm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 1d740a8c0f9..e5c5e32c35f 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -75,6 +75,7 @@ __declspec(noalias) _Min_max_8u __stdcall __std_minmax_8u(const void* _First, co __declspec(noalias) _Min_max_f __stdcall __std_minmax_f(const void* _First, const void* _Last) noexcept; __declspec(noalias) _Min_max_d __stdcall __std_minmax_d(const void* _First, const void* _Last) noexcept; +#if _VECTORIZED_IS_SORTED_UNTIL const void* __stdcall __std_is_sorted_until_1i(const void* _First, const void* _Last, bool _Greater) noexcept; const void* __stdcall __std_is_sorted_until_1u(const void* _First, const void* _Last, bool _Greater) noexcept; const void* __stdcall __std_is_sorted_until_2i(const void* _First, const void* _Last, bool _Greater) noexcept; @@ -85,6 +86,7 @@ const void* __stdcall __std_is_sorted_until_8i(const void* _First, const void* _ const void* __stdcall __std_is_sorted_until_8u(const void* _First, const void* _Last, bool _Greater) noexcept; const void* __stdcall __std_is_sorted_until_f(const void* _First, const void* _Last, bool _Greater) noexcept; const void* __stdcall __std_is_sorted_until_d(const void* _First, const void* _Last, bool _Greater) noexcept; +#endif // ^^^ _VECTORIZED_IS_SORTED_UNTIL ^^^ __declspec(noalias) bool __stdcall __std_includes_less_1i( const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept; @@ -236,6 +238,7 @@ auto _Minmax_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { } } +#if _VECTORIZED_IS_SORTED_UNTIL template _Ty* _Is_sorted_until_vectorized(_Ty* const _First, _Ty* const _Last, const bool _Greater) noexcept { constexpr bool _Signed = is_signed_v<_Ty>; @@ -272,6 +275,7 @@ _Ty* _Is_sorted_until_vectorized(_Ty* const _First, _Ty* const _Last, const bool _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_IS_SORTED_UNTIL ^^^ template bool _Includes_vectorized( @@ -8483,7 +8487,7 @@ namespace ranges { return _First; } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_IS_SORTED_UNTIL if constexpr (_Is_min_max_iterators_safe<_It> && sized_sentinel_for<_Se, _It> && is_same_v<_Pj, identity>) { constexpr bool _Is_greater = _Is_predicate_greater<_It, _Pr>; if constexpr (_Is_greater || _Is_predicate_less<_It, _Pr>) { @@ -8500,7 +8504,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_IS_SORTED_UNTIL ^^^ for (auto _Prev = _First; ++_First != _Last; ++_Prev) { if (_STD invoke(_Pred, _STD invoke(_Proj, *_First), _STD invoke(_Proj, *_Prev))) { @@ -11651,7 +11655,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt is_sorted_until(const _FwdIt _First, _FwdIt _Last auto _UFirst = _STD _Get_unwrapped(_First); auto _ULast = _STD _Get_unwrapped(_Last); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_IS_SORTED_UNTIL if constexpr (_Is_min_max_iterators_safe) { constexpr bool _Is_greater = _Is_predicate_greater; if constexpr (_Is_greater || _Is_predicate_less) { @@ -11671,7 +11675,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt is_sorted_until(const _FwdIt _First, _FwdIt _Last } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_IS_SORTED_UNTIL ^^^ if (_UFirst != _ULast) { for (auto _UNext = _UFirst; ++_UNext != _ULast; ++_UFirst) { From 44afd8cd83f8f27cff9e1fb343602823cc5c748a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 08:39:55 -0700 Subject: [PATCH 06/33] _VECTORIZED_ROTATE. --- stl/inc/algorithm | 4 ++-- stl/inc/xutility | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index e5c5e32c35f..79a53c24e16 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -5850,7 +5850,7 @@ namespace ranges { } if constexpr (bidirectional_iterator<_It>) { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_ROTATE using _Elem = remove_reference_t>; if constexpr (contiguous_iterator<_It> && sized_sentinel_for<_Se, _It> @@ -5861,7 +5861,7 @@ namespace ranges { return {_First + (_Last - _Mid), _Last}; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_ROTATE ^^^ _RANGES _Reverse_common(_First, _Mid); auto _Final = _RANGES _Get_final_iterator_unwrapped<_It>(_Mid, _STD move(_Last)); diff --git a/stl/inc/xutility b/stl/inc/xutility index 8c756b8c41a..ba90602f03b 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -119,7 +119,9 @@ __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_8(void* _Firs __declspec(noalias) void __cdecl __std_swap_ranges_trivially_swappable_noalias( void* _First1, void* _Last1, void* _First2) noexcept; +#if _VECTORIZED_ROTATE __declspec(noalias) void __stdcall __std_rotate(void* _First, void* _Mid, void* _Last) noexcept; +#endif // ^^^ _VECTORIZED_ROTATE ^^^ __declspec(noalias) size_t __stdcall __std_count_trivial_1( const void* _First, const void* _Last, uint8_t _Val) noexcept; @@ -6733,7 +6735,7 @@ _CONSTEXPR20 _FwdIt rotate(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last) { } if constexpr (_Is_cpp17_random_iter_v<_FwdIt>) { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_ROTATE using _Elem = remove_reference_t<_Iter_ref_t>; if constexpr (conjunction_v>, @@ -6743,7 +6745,7 @@ _CONSTEXPR20 _FwdIt rotate(_FwdIt _First, _FwdIt _Mid, _FwdIt _Last) { return _First + (_Last - _Mid); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_ROTATE ^^^ _STD reverse(_UFirst, _UMid); _STD reverse(_UMid, _ULast); _STD reverse(_UFirst, _ULast); From d58cc6c07cb3fe732cfefdf42c5e105dd0ff330d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 08:43:28 -0700 Subject: [PATCH 07/33] _VECTORIZED_SWAP_RANGES. --- stl/inc/algorithm | 4 ++-- stl/inc/xutility | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 79a53c24e16..f388f172df2 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -4002,7 +4002,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se2, _It2>); _STL_INTERNAL_STATIC_ASSERT(indirectly_swappable<_It1, _It2>); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_SWAP_RANGES using _Elem1 = remove_reference_t>; using _Elem2 = remove_reference_t>; if constexpr (same_as<_Elem1, _Elem2> && _Is_trivially_ranges_swappable_v<_Elem1> // @@ -4035,7 +4035,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_SWAP_RANGES ^^^ for (; _First1 != _Last1 && _First2 != _Last2; ++_First1, (void) ++_First2) { _RANGES iter_swap(_First1, _First2); diff --git a/stl/inc/xutility b/stl/inc/xutility index ba90602f03b..8484fa816d3 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -116,8 +116,11 @@ __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_1(void* _Firs __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_2(void* _First, void* _Last) noexcept; __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_4(void* _First, void* _Last) noexcept; __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_8(void* _First, void* _Last) noexcept; + +#if _VECTORIZED_SWAP_RANGES __declspec(noalias) void __cdecl __std_swap_ranges_trivially_swappable_noalias( void* _First1, void* _Last1, void* _First2) noexcept; +#endif // ^^^ _VECTORIZED_SWAP_RANGES ^^^ #if _VECTORIZED_ROTATE __declspec(noalias) void __stdcall __std_rotate(void* _First, void* _Mid, void* _Last) noexcept; @@ -7698,7 +7701,7 @@ template _CONSTEXPR20 _FwdIt2 _Swap_ranges_unchecked(_FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) { // swap [_First1, _Last1) with [_First2, ...) -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_SWAP_RANGES using _Elem1 = remove_reference_t<_Iter_ref_t<_FwdIt1>>; using _Elem2 = remove_reference_t<_Iter_ref_t<_FwdIt2>>; if constexpr (is_same_v<_Elem1, _Elem2> && _Is_trivially_swappable_v<_Elem1> @@ -7712,7 +7715,7 @@ _CONSTEXPR20 _FwdIt2 _Swap_ranges_unchecked(_FwdIt1 _First1, const _FwdIt1 _Last return _First2 + (_Last1 - _First1); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_SWAP_RANGES ^^^ for (; _First1 != _Last1; ++_First1, (void) ++_First2) { swap(*_First1, *_First2); // intentional ADL From f79f4449faf564a2678b6513765251ca48b0c792 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 08:46:45 -0700 Subject: [PATCH 08/33] _VECTORIZED_REVERSE. --- stl/inc/algorithm | 4 ++-- stl/inc/xutility | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index f388f172df2..a189996f479 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -5639,7 +5639,7 @@ namespace ranges { template requires permutable<_It> constexpr void _Reverse_common(_It _First, _It _Last) { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REVERSE if constexpr (contiguous_iterator<_It>) { using _Elem = remove_reference_t>; constexpr size_t _Nx = sizeof(_Elem); @@ -5653,7 +5653,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_REVERSE ^^^ for (; _First != _Last && _First != --_Last; ++_First) { _RANGES iter_swap(_First, _Last); diff --git a/stl/inc/xutility b/stl/inc/xutility index 8484fa816d3..523aa10dfb4 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -112,10 +112,13 @@ extern "C" { // functions are in native code objects that the compiler cannot analyze. In the absence of the noalias attribute, the // compiler has to assume that the denoted arrays are "globally address taken", and that any later calls to // unanalyzable routines may modify those arrays. + +#if _VECTORIZED_REVERSE __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_1(void* _First, void* _Last) noexcept; __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_2(void* _First, void* _Last) noexcept; __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_4(void* _First, void* _Last) noexcept; __declspec(noalias) void __cdecl __std_reverse_trivially_swappable_8(void* _First, void* _Last) noexcept; +#endif // ^^^ _VECTORIZED_REVERSE ^^^ #if _VECTORIZED_SWAP_RANGES __declspec(noalias) void __cdecl __std_swap_ranges_trivially_swappable_noalias( @@ -225,7 +228,7 @@ _Target _Find_arg_cast(const _Source _Val) noexcept { } } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REVERSE template __declspec(noalias) void _Reverse_vectorized(void* _First, void* _Last) noexcept { if constexpr (_Nx == 1) { @@ -240,7 +243,9 @@ __declspec(noalias) void _Reverse_vectorized(void* _First, void* _Last) noexcept _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_REVERSE ^^^ +#if _VECTORIZED_FOR_X64_X86 template __declspec(noalias) size_t _Count_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -6676,7 +6681,7 @@ _CONSTEXPR20 void reverse(const _BidIt _First, const _BidIt _Last) { // reverse _STD _Adl_verify_range(_First, _Last); auto _UFirst = _STD _Get_unwrapped(_First); auto _ULast = _STD _Get_unwrapped(_Last); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REVERSE using _Elem = remove_reference_t<_Iter_ref_t>; constexpr bool _Allow_vectorization = conjunction_v>, _Is_trivially_swappable<_Elem>, negation>>; @@ -6691,7 +6696,7 @@ _CONSTEXPR20 void reverse(const _BidIt _First, const _BidIt _Last) { // reverse return; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_REVERSE ^^^ for (; _UFirst != _ULast && _UFirst != --_ULast; ++_UFirst) { swap(*_UFirst, *_ULast); // intentional ADL From 681774949e03d7d4e16e1a18799079112c017dee Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 08:49:38 -0700 Subject: [PATCH 09/33] _VECTORIZED_REMOVE. --- stl/inc/algorithm | 4 ++-- stl/inc/xmemory | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index a189996f479..7ef21087a7a 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -5023,7 +5023,7 @@ namespace ranges { return {_STD move(_Next), _STD move(_First)}; } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REMOVE if constexpr (_Vector_alg_in_find_is_safe<_It, _Ty> && sized_sentinel_for<_Se, _It> && is_same_v<_Pj, identity>) { if (!_STD is_constant_evaluated()) { @@ -5039,7 +5039,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_REMOVE ^^^ while (++_First != _Last) { if (_STD invoke(_Proj, *_First) != _Val) { diff --git a/stl/inc/xmemory b/stl/inc/xmemory index d5b0d1dd8c0..c73653f10be 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -31,7 +31,7 @@ _STL_DISABLE_CLANG_WARNINGS #undef msvc #undef no_specializations -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REMOVE extern "C" { void* __stdcall __std_remove_1(void* _First, void* _Last, uint8_t _Val) noexcept; void* __stdcall __std_remove_2(void* _First, void* _Last, uint16_t _Val) noexcept; @@ -56,7 +56,7 @@ _Ty* _Remove_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) n } _STD_END -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_REMOVE ^^^ _STD_BEGIN template @@ -2330,7 +2330,7 @@ _NODISCARD_REMOVE_ALG _CONSTEXPR20 _FwdIt remove(_FwdIt _First, const _FwdIt _La _UFirst = _STD _Find_unchecked(_UFirst, _ULast, _Val); auto _UNext = _UFirst; if (_UFirst != _ULast) { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REMOVE if constexpr (_Vector_alg_in_find_is_safe) { #if _HAS_CXX20 if (!_STD is_constant_evaluated()) @@ -2349,7 +2349,7 @@ _NODISCARD_REMOVE_ALG _CONSTEXPR20 _FwdIt remove(_FwdIt _First, const _FwdIt _La return _First; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_REMOVE ^^^ while (++_UFirst != _ULast) { if (!(*_UFirst == _Val)) { From ad789330d5bd0a52f38ff5a94d3765e42d1c7d55 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 08:53:02 -0700 Subject: [PATCH 10/33] _VECTORIZED_INCLUDES. --- stl/inc/algorithm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 7ef21087a7a..a92912cb918 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -88,6 +88,7 @@ const void* __stdcall __std_is_sorted_until_f(const void* _First, const void* _L const void* __stdcall __std_is_sorted_until_d(const void* _First, const void* _Last, bool _Greater) noexcept; #endif // ^^^ _VECTORIZED_IS_SORTED_UNTIL ^^^ +#if _VECTORIZED_INCLUDES __declspec(noalias) bool __stdcall __std_includes_less_1i( const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept; __declspec(noalias) bool __stdcall __std_includes_less_1u( @@ -104,6 +105,7 @@ __declspec(noalias) bool __stdcall __std_includes_less_8i( const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept; __declspec(noalias) bool __stdcall __std_includes_less_8u( const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept; +#endif // ^^^ _VECTORIZED_INCLUDES ^^^ // TRANSITION, DevCom-10610477 __declspec(noalias) void __stdcall __std_replace_4( @@ -277,6 +279,7 @@ _Ty* _Is_sorted_until_vectorized(_Ty* const _First, _Ty* const _Last, const bool } #endif // ^^^ _VECTORIZED_IS_SORTED_UNTIL ^^^ +#if _VECTORIZED_INCLUDES template bool _Includes_vectorized( const _Ty* const _First1, const _Ty* const _Last1, const _Ty* const _First2, const _Ty* const _Last2) noexcept { @@ -310,6 +313,7 @@ bool _Includes_vectorized( _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_INCLUDES ^^^ template __declspec(noalias) void _Replace_vectorized( @@ -10317,14 +10321,14 @@ _NODISCARD _CONSTEXPR20 bool includes(_InIt1 _First1, _InIt1 _Last1, _InIt2 _Fir return false; } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_INCLUDES if constexpr (_Vector_alg_includes_iterators_safe<_InIt1, _InIt2> && _Is_predicate_less<_InIt1, _Pr>) { if (!_STD _Is_constant_evaluated()) { return _STD _Includes_vectorized(_STD _To_address(_First1), _STD _To_address(_Last1), _STD _To_address(_First2), _STD _To_address(_Last2)); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_INCLUDES ^^^ for (;;) { if (_DEBUG_LT_PRED(_Pred, *_UFirst1, *_UFirst2)) { @@ -10415,7 +10419,7 @@ namespace ranges { return false; } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_INCLUDES if constexpr (_Vector_alg_includes_iterators_safe<_It1, _It2> && _Is_predicate_less<_It1, _Pr> && sized_sentinel_for<_Se1, _It1> && sized_sentinel_for<_Se2, _It2> && is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>) { @@ -10427,7 +10431,7 @@ namespace ranges { return _STD _Includes_vectorized(_First1_ptr, _Last1_ptr, _First2_ptr, _Last2_ptr); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_INCLUDES ^^^ for (;;) { if (_STD invoke(_Pred, _STD invoke(_Proj1, *_First1), _STD invoke(_Proj2, *_First2))) { From 547fd5648a55e8a1104071588213c8285dc0fe6b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 09:12:49 -0700 Subject: [PATCH 11/33] _VECTORIZED_MINMAX. --- stl/inc/algorithm | 39 +++++++++++++++++++++++++++------------ stl/inc/xutility | 31 ++++++++++++++++++------------- 2 files changed, 45 insertions(+), 25 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index a92912cb918..9faf05579f1 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -64,6 +64,7 @@ _Min_max_element_t __stdcall __std_minmax_element_8(const void* _First, const vo _Min_max_element_t __stdcall __std_minmax_element_f(const void* _First, const void* _Last, bool _Unused) noexcept; _Min_max_element_t __stdcall __std_minmax_element_d(const void* _First, const void* _Last, bool _Unused) noexcept; +#if _VECTORIZED_MINMAX __declspec(noalias) _Min_max_1i __stdcall __std_minmax_1i(const void* _First, const void* _Last) noexcept; __declspec(noalias) _Min_max_1u __stdcall __std_minmax_1u(const void* _First, const void* _Last) noexcept; __declspec(noalias) _Min_max_2i __stdcall __std_minmax_2i(const void* _First, const void* _Last) noexcept; @@ -74,6 +75,7 @@ __declspec(noalias) _Min_max_8i __stdcall __std_minmax_8i(const void* _First, co __declspec(noalias) _Min_max_8u __stdcall __std_minmax_8u(const void* _First, const void* _Last) noexcept; __declspec(noalias) _Min_max_f __stdcall __std_minmax_f(const void* _First, const void* _Last) noexcept; __declspec(noalias) _Min_max_d __stdcall __std_minmax_d(const void* _First, const void* _Last) noexcept; +#endif // ^^^ _VECTORIZED_MINMAX ^^^ #if _VECTORIZED_IS_SORTED_UNTIL const void* __stdcall __std_is_sorted_until_1i(const void* _First, const void* _Last, bool _Greater) noexcept; @@ -196,6 +198,7 @@ pair<_Ty*, _Ty*> _Minmax_element_vectorized(_Ty* const _First, _Ty* const _Last) return {const_cast<_Ty*>(static_cast(_Res._Min)), const_cast<_Ty*>(static_cast(_Res._Max))}; } +#if _VECTORIZED_MINMAX template auto _Minmax_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { constexpr bool _Signed = is_signed_v<_Ty>; @@ -239,6 +242,7 @@ auto _Minmax_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_MINMAX ^^^ #if _VECTORIZED_IS_SORTED_UNTIL template @@ -11227,14 +11231,14 @@ _NODISCARD constexpr pair<_Ty, _Ty> minmax(initializer_list<_Ty> _Ilist, _Pr _Pr // return {leftmost/smallest, rightmost/largest} _STL_ASSERT( _Ilist.size() != 0, "An initializer_list passed to std::minmax must not be empty. (N4971 [alg.min.max]/21)"); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX if constexpr (_Is_min_max_value_optimization_safe) { if (!_STD _Is_constant_evaluated()) { const auto _Result = _STD _Minmax_vectorized(_Ilist.begin(), _Ilist.end()); return {static_cast<_Ty>(_Result._Min), static_cast<_Ty>(_Result._Max)}; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX ^^^ pair _Res = _STD _Minmax_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); return pair<_Ty, _Ty>(*_Res.first, *_Res.second); @@ -11287,15 +11291,20 @@ namespace ranges { "An initializer_list passed to std::ranges::minmax must not be empty. (N4971 [alg.min.max]/21)"); #if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity>) { +#if _VECTORIZED_MINMAX if constexpr (_Is_min_max_value_optimization_safe) { if (!_STD is_constant_evaluated()) { const auto _Result = _STD _Minmax_vectorized(_First, _Last); return {static_cast<_Ty>(_Result._Min), static_cast<_Ty>(_Result._Max)}; } - } else if constexpr (_Is_min_max_optimization_safe) { - if (!_STD is_constant_evaluated()) { - const auto _Result = _STD _Minmax_element_vectorized(_First, _Last); - return {*static_cast(_Result.first), *static_cast(_Result.second)}; + } else +#endif // ^^^ _VECTORIZED_MINMAX ^^^ + { + if constexpr (_Is_min_max_optimization_safe) { + if (!_STD is_constant_evaluated()) { + const auto _Result = _STD _Minmax_element_vectorized(_First, _Last); + return {*static_cast(_Result.first), *static_cast(_Result.second)}; + } } } } @@ -11315,6 +11324,7 @@ namespace ranges { using _Vty = range_value_t<_Rng>; #if _VECTORIZED_FOR_X64_X86 if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for) { +#if _VECTORIZED_MINMAX if constexpr (_Is_min_max_value_optimization_safe) { if (!_STD is_constant_evaluated()) { const auto _First_ptr = _STD to_address(_UFirst); @@ -11322,12 +11332,17 @@ namespace ranges { const auto _Result = _STD _Minmax_vectorized(_First_ptr, _Last_ptr); return {static_cast<_Vty>(_Result._Min), static_cast<_Vty>(_Result._Max)}; } - } else if constexpr (_Is_min_max_optimization_safe) { - if (!_STD is_constant_evaluated()) { - const auto _First_ptr = _STD to_address(_UFirst); - const auto _Last_ptr = _First_ptr + static_cast(_ULast - _UFirst); - const auto _Result = _STD _Minmax_element_vectorized(_First_ptr, _Last_ptr); - return {*static_cast(_Result.first), *static_cast(_Result.second)}; + } else +#endif // ^^^ _VECTORIZED_MINMAX ^^^ + { + if constexpr (_Is_min_max_optimization_safe) { + if (!_STD is_constant_evaluated()) { + const auto _First_ptr = _STD to_address(_UFirst); + const auto _Last_ptr = _First_ptr + static_cast(_ULast - _UFirst); + const auto _Result = _STD _Minmax_element_vectorized(_First_ptr, _Last_ptr); + return { + *static_cast(_Result.first), *static_cast(_Result.second)}; + } } } } diff --git a/stl/inc/xutility b/stl/inc/xutility index 523aa10dfb4..8130b23d5ad 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -186,6 +186,7 @@ const void* __stdcall __std_max_element_8(const void* _First, const void* _Last, const void* __stdcall __std_max_element_f(const void* _First, const void* _Last, bool _Unused) noexcept; const void* __stdcall __std_max_element_d(const void* _First, const void* _Last, bool _Unused) noexcept; +#if _VECTORIZED_MINMAX __declspec(noalias) int8_t __stdcall __std_min_1i(const void* _First, const void* _Last) noexcept; __declspec(noalias) uint8_t __stdcall __std_min_1u(const void* _First, const void* _Last) noexcept; __declspec(noalias) int16_t __stdcall __std_min_2i(const void* _First, const void* _Last) noexcept; @@ -196,6 +197,7 @@ __declspec(noalias) int64_t __stdcall __std_min_8i(const void* _First, const voi __declspec(noalias) uint64_t __stdcall __std_min_8u(const void* _First, const void* _Last) noexcept; __declspec(noalias) float __stdcall __std_min_f(const void* _First, const void* _Last) noexcept; __declspec(noalias) double __stdcall __std_min_d(const void* _First, const void* _Last) noexcept; + __declspec(noalias) int8_t __stdcall __std_max_1i(const void* _First, const void* _Last) noexcept; __declspec(noalias) uint8_t __stdcall __std_max_1u(const void* _First, const void* _Last) noexcept; __declspec(noalias) int16_t __stdcall __std_max_2i(const void* _First, const void* _Last) noexcept; @@ -206,6 +208,7 @@ __declspec(noalias) int64_t __stdcall __std_max_8i(const void* _First, const voi __declspec(noalias) uint64_t __stdcall __std_max_8u(const void* _First, const void* _Last) noexcept; __declspec(noalias) float __stdcall __std_max_f(const void* _First, const void* _Last) noexcept; __declspec(noalias) double __stdcall __std_max_d(const void* _First, const void* _Last) noexcept; +#endif // ^^^ _VECTORIZED_MINMAX ^^^ #if _VECTORIZED_MISMATCH __declspec(noalias) size_t __stdcall __std_mismatch_1(const void* _First1, const void* _First2, size_t _Count) noexcept; @@ -393,7 +396,9 @@ _Ty* _Max_element_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#if _VECTORIZED_MINMAX template auto _Min_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { constexpr bool _Signed = is_signed_v<_Ty>; @@ -479,7 +484,7 @@ auto _Max_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX ^^^ #if _VECTORIZED_MISMATCH template @@ -7333,13 +7338,13 @@ _NODISCARD constexpr _Ty(max)(initializer_list<_Ty> _Ilist, _Pr _Pred) { // return leftmost/largest _STL_ASSERT( _Ilist.size() != 0, "An initializer_list passed to std::max must not be empty. (N4971 [alg.min.max]/13)"); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX if constexpr (_Is_min_max_value_optimization_safe) { if (!_Is_constant_evaluated()) { return static_cast<_Ty>(_STD _Max_vectorized(_Ilist.begin(), _Ilist.end())); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX ^^^ const _Ty* _Res = _STD _Max_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); return *_Res; } @@ -7379,13 +7384,13 @@ namespace ranges { const auto _Last = _Range.end(); _STL_ASSERT(_First != _Last, "An initializer_list passed to std::ranges::max must not be empty. (N4971 [alg.min.max]/13)"); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX if constexpr (is_same_v<_Pj, identity> && _Is_min_max_value_optimization_safe) { if (!_STD is_constant_evaluated()) { return static_cast<_Ty>(_STD _Max_vectorized(_First, _Last)); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX ^^^ return *_RANGES _Max_element_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); } @@ -7398,7 +7403,7 @@ namespace ranges { auto _ULast = _Uend(_Range); _STL_ASSERT( _UFirst != _ULast, "A range passed to std::ranges::max must not be empty. (N4971 [alg.min.max]/13)"); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX if constexpr (is_same_v<_Pj, identity> && _Is_min_max_value_optimization_safe && sized_sentinel_for) { if (!_STD is_constant_evaluated()) { @@ -7407,7 +7412,7 @@ namespace ranges { return static_cast>(_STD _Max_vectorized(_First_ptr, _Last_ptr)); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX ^^^ if constexpr (forward_range<_Rng> && _Prefer_iterator_copies) { return static_cast>(*_RANGES _Max_element_unchecked( _STD move(_UFirst), _STD move(_ULast), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj))); @@ -7557,13 +7562,13 @@ _NODISCARD constexpr _Ty(min)(initializer_list<_Ty> _Ilist, _Pr _Pred) { // return leftmost/smallest _STL_ASSERT( _Ilist.size() != 0, "An initializer_list passed to std::min must not be empty. (N4971 [alg.min.max]/5)"); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX if constexpr (_Is_min_max_value_optimization_safe) { if (!_Is_constant_evaluated()) { return static_cast<_Ty>(_STD _Min_vectorized(_Ilist.begin(), _Ilist.end())); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX ^^^ const _Ty* _Res = _STD _Min_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); return *_Res; } @@ -7597,13 +7602,13 @@ namespace ranges { const auto _Last = _Range.end(); _STL_ASSERT(_First != _Last, "An initializer_list passed to std::ranges::min must not be empty. (N4971 [alg.min.max]/5)"); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX if constexpr (is_same_v<_Pj, identity> && _Is_min_max_value_optimization_safe) { if (!_STD is_constant_evaluated()) { return static_cast<_Ty>(_STD _Min_vectorized(_First, _Last)); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX ^^^ return *_RANGES _Min_element_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); } @@ -7616,7 +7621,7 @@ namespace ranges { auto _ULast = _Uend(_Range); _STL_ASSERT( _UFirst != _ULast, "A range passed to std::ranges::min must not be empty. (N4971 [alg.min.max]/5)"); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX if constexpr (is_same_v<_Pj, identity> && _Is_min_max_value_optimization_safe && sized_sentinel_for) { if (!_STD is_constant_evaluated()) { @@ -7625,7 +7630,7 @@ namespace ranges { return static_cast>(_STD _Min_vectorized(_First_ptr, _Last_ptr)); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX ^^^ if constexpr (forward_range<_Rng> && _Prefer_iterator_copies) { return static_cast>(*_RANGES _Min_element_unchecked( _STD move(_UFirst), _STD move(_ULast), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj))); From cbc0361c81714ce5daabdfca159f1eda92ac2db0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 09:25:38 -0700 Subject: [PATCH 12/33] _VECTORIZED_MINMAX_ELEMENT. (note interaction with _VECTORIZED_MINMAX) --- stl/inc/algorithm | 28 ++++++++++++++++++++-------- stl/inc/xutility | 23 +++++++++++++---------- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 9faf05579f1..9280adf7a54 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -57,12 +57,14 @@ __declspec(noalias) void __cdecl __std_reverse_copy_trivially_copyable_4( __declspec(noalias) void __cdecl __std_reverse_copy_trivially_copyable_8( const void* _First, const void* _Last, void* _Dest) noexcept; +#if _VECTORIZED_MINMAX_ELEMENT _Min_max_element_t __stdcall __std_minmax_element_1(const void* _First, const void* _Last, bool _Signed) noexcept; _Min_max_element_t __stdcall __std_minmax_element_2(const void* _First, const void* _Last, bool _Signed) noexcept; _Min_max_element_t __stdcall __std_minmax_element_4(const void* _First, const void* _Last, bool _Signed) noexcept; _Min_max_element_t __stdcall __std_minmax_element_8(const void* _First, const void* _Last, bool _Signed) noexcept; _Min_max_element_t __stdcall __std_minmax_element_f(const void* _First, const void* _Last, bool _Unused) noexcept; _Min_max_element_t __stdcall __std_minmax_element_d(const void* _First, const void* _Last, bool _Unused) noexcept; +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ #if _VECTORIZED_MINMAX __declspec(noalias) _Min_max_1i __stdcall __std_minmax_1i(const void* _First, const void* _Last) noexcept; @@ -173,6 +175,7 @@ __declspec(noalias) void _Reverse_copy_vectorized(const void* _First, const void } } +#if _VECTORIZED_MINMAX_ELEMENT template pair<_Ty*, _Ty*> _Minmax_element_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { constexpr bool _Signed = is_signed_v<_Ty>; @@ -197,6 +200,7 @@ pair<_Ty*, _Ty*> _Minmax_element_vectorized(_Ty* const _First, _Ty* const _Last) return {const_cast<_Ty*>(static_cast(_Res._Min)), const_cast<_Ty*>(static_cast(_Res._Max))}; } +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ #if _VECTORIZED_MINMAX template @@ -11023,7 +11027,7 @@ namespace ranges { template constexpr pair<_FwdIt, _FwdIt> _Minmax_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX_ELEMENT if constexpr (_Is_min_max_optimization_safe<_FwdIt, _Pr>) { if (!_Is_constant_evaluated()) { const auto _First_ptr = _STD _To_address(_First); @@ -11036,7 +11040,7 @@ constexpr pair<_FwdIt, _FwdIt> _Minmax_element_unchecked(_FwdIt _First, _FwdIt _ } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ // find smallest and largest elements pair<_FwdIt, _FwdIt> _Found(_First, _First); @@ -11149,7 +11153,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_strict_weak_order<_Pr, projected<_It, _Pj>>); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX_ELEMENT if constexpr (is_same_v<_Pj, identity> && _Is_min_max_optimization_safe<_It, _Pr> && sized_sentinel_for<_Se, _It>) { if (!_STD is_constant_evaluated()) { @@ -11164,7 +11168,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ min_max_result<_It> _Found{_First, _First}; @@ -11289,7 +11293,8 @@ namespace ranges { const auto _Last = _Range.end(); _STL_ASSERT(_First != _Last, "An initializer_list passed to std::ranges::minmax must not be empty. (N4971 [alg.min.max]/21)"); -#if _VECTORIZED_FOR_X64_X86 + +#if _VECTORIZED_MINMAX || _VECTORIZED_MINMAX_ELEMENT if constexpr (is_same_v<_Pj, identity>) { #if _VECTORIZED_MINMAX if constexpr (_Is_min_max_value_optimization_safe) { @@ -11300,15 +11305,18 @@ namespace ranges { } else #endif // ^^^ _VECTORIZED_MINMAX ^^^ { +#if _VECTORIZED_MINMAX_ELEMENT if constexpr (_Is_min_max_optimization_safe) { if (!_STD is_constant_evaluated()) { const auto _Result = _STD _Minmax_element_vectorized(_First, _Last); return {*static_cast(_Result.first), *static_cast(_Result.second)}; } } +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX || _VECTORIZED_MINMAX_ELEMENT ^^^ + return _Minmax_fwd_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); } @@ -11322,7 +11330,8 @@ namespace ranges { _STL_ASSERT( _UFirst != _ULast, "A range passed to std::ranges::minmax must not be empty. (N4971 [alg.min.max]/21)"); using _Vty = range_value_t<_Rng>; -#if _VECTORIZED_FOR_X64_X86 + +#if _VECTORIZED_MINMAX || _VECTORIZED_MINMAX_ELEMENT if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for) { #if _VECTORIZED_MINMAX if constexpr (_Is_min_max_value_optimization_safe) { @@ -11335,6 +11344,7 @@ namespace ranges { } else #endif // ^^^ _VECTORIZED_MINMAX ^^^ { +#if _VECTORIZED_MINMAX_ELEMENT if constexpr (_Is_min_max_optimization_safe) { if (!_STD is_constant_evaluated()) { const auto _First_ptr = _STD to_address(_UFirst); @@ -11344,9 +11354,11 @@ namespace ranges { *static_cast(_Result.first), *static_cast(_Result.second)}; } } +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX || _VECTORIZED_MINMAX_ELEMENT ^^^ + if constexpr (forward_range<_Rng> && _Prefer_iterator_copies) { return _Minmax_fwd_unchecked( _STD move(_UFirst), _STD move(_ULast), _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); diff --git a/stl/inc/xutility b/stl/inc/xutility index 8130b23d5ad..39a802b2040 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -171,7 +171,7 @@ const void* __stdcall __std_find_end_4( const void* __stdcall __std_find_end_8( const void* _First1, const void* _Last1, const void* _First2, size_t _Count2) noexcept; - +#if _VECTORIZED_MINMAX_ELEMENT const void* __stdcall __std_min_element_1(const void* _First, const void* _Last, bool _Signed) noexcept; const void* __stdcall __std_min_element_2(const void* _First, const void* _Last, bool _Signed) noexcept; const void* __stdcall __std_min_element_4(const void* _First, const void* _Last, bool _Signed) noexcept; @@ -185,6 +185,7 @@ const void* __stdcall __std_max_element_4(const void* _First, const void* _Last, const void* __stdcall __std_max_element_8(const void* _First, const void* _Last, bool _Signed) noexcept; const void* __stdcall __std_max_element_f(const void* _First, const void* _Last, bool _Unused) noexcept; const void* __stdcall __std_max_element_d(const void* _First, const void* _Last, bool _Unused) noexcept; +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ #if _VECTORIZED_MINMAX __declspec(noalias) int8_t __stdcall __std_min_1i(const void* _First, const void* _Last) noexcept; @@ -354,7 +355,9 @@ _Ty1* _Find_end_vectorized( _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#if _VECTORIZED_MINMAX_ELEMENT template _Ty* _Min_element_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { constexpr bool _Signed = is_signed_v<_Ty>; @@ -396,7 +399,7 @@ _Ty* _Max_element_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ #if _VECTORIZED_MINMAX template @@ -7211,7 +7214,7 @@ constexpr bool _Is_min_max_value_optimization_safe = // Activate the vector algo template constexpr _FwdIt _Max_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // find largest element -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX_ELEMENT if constexpr (_Is_min_max_optimization_safe<_FwdIt, _Pr>) { if (!_Is_constant_evaluated()) { const auto _First_ptr = _STD _To_address(_First); @@ -7223,7 +7226,7 @@ constexpr _FwdIt _Max_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ _FwdIt _Found = _First; if (_First != _Last) { @@ -7275,7 +7278,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_strict_weak_order<_Pr, projected<_It, _Pj>>); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX_ELEMENT if constexpr (is_same_v<_Pj, identity> && _Is_min_max_optimization_safe<_It, _Pr> && sized_sentinel_for<_Se, _It>) { if (!_STD is_constant_evaluated()) { @@ -7289,7 +7292,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ auto _Found = _First; if (_First == _Last) { @@ -7435,7 +7438,7 @@ namespace ranges { template constexpr _FwdIt _Min_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // find smallest element -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX_ELEMENT if constexpr (_Is_min_max_optimization_safe<_FwdIt, _Pr>) { if (!_Is_constant_evaluated()) { const auto _First_ptr = _STD _To_address(_First); @@ -7447,7 +7450,7 @@ constexpr _FwdIt _Min_element_unchecked(_FwdIt _First, _FwdIt _Last, _Pr _Pred) } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ _FwdIt _Found = _First; if (_First != _Last) { @@ -7499,7 +7502,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_strict_weak_order<_Pr, projected<_It, _Pj>>); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_MINMAX_ELEMENT if constexpr (is_same_v<_Pj, identity> && _Is_min_max_optimization_safe<_It, _Pr> && sized_sentinel_for<_Se, _It>) { if (!_STD is_constant_evaluated()) { @@ -7513,7 +7516,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_MINMAX_ELEMENT ^^^ auto _Found = _First; if (_First == _Last) { From 465b4c5d1c6bd8bf1c6879559a8306f734e739a8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 09:30:14 -0700 Subject: [PATCH 13/33] _VECTORIZED_COUNT. --- stl/inc/algorithm | 4 ++-- stl/inc/xutility | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 9280adf7a54..92f188eecec 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -841,7 +841,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_binary_predicate, const _Ty*>); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_COUNT if constexpr (is_same_v<_Pj, identity> && _Vector_alg_in_find_is_safe<_It, _Ty> && sized_sentinel_for<_Se, _It>) { if (!_STD is_constant_evaluated()) { @@ -855,7 +855,7 @@ namespace ranges { return static_cast>(_STD _Count_vectorized(_First_ptr, _Last_ptr, _Val)); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_COUNT ^^^ iter_difference_t<_It> _Count = 0; for (; _First != _Last; ++_First) { diff --git a/stl/inc/xutility b/stl/inc/xutility index 39a802b2040..2b63941f475 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -129,6 +129,7 @@ __declspec(noalias) void __cdecl __std_swap_ranges_trivially_swappable_noalias( __declspec(noalias) void __stdcall __std_rotate(void* _First, void* _Mid, void* _Last) noexcept; #endif // ^^^ _VECTORIZED_ROTATE ^^^ +#if _VECTORIZED_COUNT __declspec(noalias) size_t __stdcall __std_count_trivial_1( const void* _First, const void* _Last, uint8_t _Val) noexcept; __declspec(noalias) size_t __stdcall __std_count_trivial_2( @@ -137,6 +138,7 @@ __declspec(noalias) size_t __stdcall __std_count_trivial_4( const void* _First, const void* _Last, uint32_t _Val) noexcept; __declspec(noalias) size_t __stdcall __std_count_trivial_8( const void* _First, const void* _Last, uint64_t _Val) noexcept; +#endif // ^^^ _VECTORIZED_COUNT ^^^ const void* __stdcall __std_find_trivial_1(const void* _First, const void* _Last, uint8_t _Val) noexcept; const void* __stdcall __std_find_trivial_2(const void* _First, const void* _Last, uint16_t _Val) noexcept; @@ -249,7 +251,7 @@ __declspec(noalias) void _Reverse_vectorized(void* _First, void* _Last) noexcept } #endif // ^^^ _VECTORIZED_REVERSE ^^^ -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_COUNT template __declspec(noalias) size_t _Count_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -264,7 +266,9 @@ __declspec(noalias) size_t _Count_vectorized(_Ty* const _First, _Ty* const _Last _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_COUNT ^^^ +#if _VECTORIZED_FOR_X64_X86 template _Ty* _Find_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -6485,7 +6489,7 @@ _NODISCARD _CONSTEXPR20 _Iter_diff_t<_InIt> count(const _InIt _First, const _InI auto _UFirst = _STD _Get_unwrapped(_First); const auto _ULast = _STD _Get_unwrapped(_Last); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_COUNT if constexpr (_Vector_alg_in_find_is_safe) { #if _HAS_CXX20 if (!_STD is_constant_evaluated()) @@ -6499,7 +6503,7 @@ _NODISCARD _CONSTEXPR20 _Iter_diff_t<_InIt> count(const _InIt _First, const _InI _STD _Count_vectorized(_STD _To_address(_UFirst), _STD _To_address(_ULast), _Val)); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_COUNT ^^^ _Iter_diff_t<_InIt> _Count = 0; From a21bbaed8e4a20f24b15f62bd1a265a7937e889f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 09:33:28 -0700 Subject: [PATCH 14/33] _VECTORIZED_SEARCH. --- stl/inc/__msvc_string_view.hpp | 4 ++-- stl/inc/algorithm | 4 ++-- stl/inc/functional | 4 ++-- stl/inc/xutility | 8 ++++++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 969583f356a..819fe18ab24 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -728,7 +728,7 @@ constexpr size_t _Traits_find(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits> return _Start_at; } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_SEARCH if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { const auto _End = _Haystack + _Hay_size; @@ -741,7 +741,7 @@ constexpr size_t _Traits_find(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits> } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_SEARCH ^^^ const auto _Possible_matches_end = _Haystack + (_Hay_size - _Needle_size) + 1; for (auto _Match_try = _Haystack + _Start_at;; ++_Match_try) { diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 92f188eecec..65acae911b4 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -2373,7 +2373,7 @@ _NODISCARD _CONSTEXPR20 _FwdItHaystack search(_FwdItHaystack _First1, _FwdItHays if constexpr (_Is_ranges_random_iter_v<_FwdItHaystack> && _Is_ranges_random_iter_v<_FwdItPat>) { const _Iter_diff_t<_FwdItPat> _Count2 = _ULast2 - _UFirst2; if (_ULast1 - _UFirst1 >= _Count2) { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_SEARCH if constexpr (_Vector_alg_in_search_is_safe) { if (!_STD _Is_constant_evaluated()) { const auto _Ptr1 = _STD _To_address(_UFirst1); @@ -2391,7 +2391,7 @@ _NODISCARD _CONSTEXPR20 _FwdItHaystack search(_FwdItHaystack _First1, _FwdItHays return _Last1; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_SEARCH ^^^ const auto _Last_possible = _ULast1 - static_cast<_Iter_diff_t<_FwdItHaystack>>(_Count2); for (;; ++_UFirst1) { diff --git a/stl/inc/functional b/stl/inc/functional index 20259397b13..0643a4a4aaa 100644 --- a/stl/inc/functional +++ b/stl/inc/functional @@ -2556,7 +2556,7 @@ _CONSTEXPR20 pair<_FwdItHaystack, _FwdItHaystack> _Search_pair_unchecked( _Iter_diff_t<_FwdItHaystack> _Count1 = _Last1 - _First1; _Iter_diff_t<_FwdItPat> _Count2 = _Last2 - _First2; -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_SEARCH if constexpr (_Vector_alg_in_search_is_safe<_FwdItHaystack, _FwdItPat, _Pred_eq>) { if (!_STD _Is_constant_evaluated()) { const auto _Ptr1 = _STD _To_address(_First1); @@ -2577,7 +2577,7 @@ _CONSTEXPR20 pair<_FwdItHaystack, _FwdItHaystack> _Search_pair_unchecked( } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_SEARCH ^^^ for (; _Count2 <= _Count1; ++_First1, (void) --_Count1) { // room for match, try it _FwdItHaystack _Mid1 = _First1; diff --git a/stl/inc/xutility b/stl/inc/xutility index 2b63941f475..93083df763f 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -155,6 +155,7 @@ const void* __stdcall __std_adjacent_find_2(const void* _First, const void* _Las const void* __stdcall __std_adjacent_find_4(const void* _First, const void* _Last) noexcept; const void* __stdcall __std_adjacent_find_8(const void* _First, const void* _Last) noexcept; +#if _VECTORIZED_SEARCH const void* __stdcall __std_search_1( const void* _First1, const void* _Last1, const void* _First2, size_t _Count2) noexcept; const void* __stdcall __std_search_2( @@ -163,6 +164,7 @@ const void* __stdcall __std_search_4( const void* _First1, const void* _Last1, const void* _First2, size_t _Count2) noexcept; const void* __stdcall __std_search_8( const void* _First1, const void* _Last1, const void* _First2, size_t _Count2) noexcept; +#endif // ^^^ _VECTORIZED_SEARCH ^^^ const void* __stdcall __std_find_end_1( const void* _First1, const void* _Last1, const void* _First2, size_t _Count2) noexcept; @@ -327,6 +329,7 @@ _Ty* _Adjacent_find_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { // _Find_last_of_pos_vectorized, and _Find_last_not_of_pos_vectorized.) _INLINE_VAR constexpr ptrdiff_t _Threshold_find_first_of = 16; +#if _VECTORIZED_SEARCH template _Ty1* _Search_vectorized(_Ty1* const _First1, _Ty1* const _Last1, _Ty2* const _First2, const size_t _Count2) noexcept { _STL_INTERNAL_STATIC_ASSERT(sizeof(_Ty1) == sizeof(_Ty2)); @@ -342,6 +345,7 @@ _Ty1* _Search_vectorized(_Ty1* const _First1, _Ty1* const _Last1, _Ty2* const _F _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_SEARCH ^^^ template _Ty1* _Find_end_vectorized( @@ -7088,7 +7092,7 @@ namespace ranges { _STL_INTERNAL_CHECK(_RANGES distance(_First1, _Last1) == _Count1); _STL_INTERNAL_CHECK(_RANGES distance(_First2, _Last2) == _Count2); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_SEARCH if constexpr (_Vector_alg_in_search_is_safe<_It1, _It2, _Pr> && is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>) { if (!_STD is_constant_evaluated()) { @@ -7121,7 +7125,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_SEARCH ^^^ for (; _Count1 >= _Count2; ++_First1, (void) --_Count1) { auto _Match_and_mid1 = _RANGES _Equal_rev_pred(_First1, _First2, _Last2, _Pred, _Proj1, _Proj2); From 649a2fdff8ba79bab85f1099d67b24afd72bf927 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 09:39:49 -0700 Subject: [PATCH 15/33] _VECTORIZED_ADJACENT_FIND. --- stl/inc/algorithm | 4 ++-- stl/inc/xutility | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 65acae911b4..9f3a7957a1a 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -767,7 +767,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt adjacent_find(const _FwdIt _First, _FwdIt _Last, auto _UFirst = _STD _Get_unwrapped(_First); auto _ULast = _STD _Get_unwrapped(_Last); if (_UFirst != _ULast) { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_ADJACENT_FIND if constexpr (_Vector_alg_in_search_is_safe) { if (!_STD _Is_constant_evaluated()) { const auto _First_ptr = _STD _To_address(_UFirst); @@ -783,7 +783,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt adjacent_find(const _FwdIt _First, _FwdIt _Last, return _Last; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_ADJACENT_FIND ^^^ for (auto _UNext = _UFirst; ++_UNext != _ULast; _UFirst = _UNext) { if (_Pred(*_UFirst, *_UNext)) { diff --git a/stl/inc/xutility b/stl/inc/xutility index 93083df763f..682aae18e25 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -150,10 +150,12 @@ const void* __stdcall __std_find_last_trivial_2(const void* _First, const void* const void* __stdcall __std_find_last_trivial_4(const void* _First, const void* _Last, uint32_t _Val) noexcept; const void* __stdcall __std_find_last_trivial_8(const void* _First, const void* _Last, uint64_t _Val) noexcept; +#if _VECTORIZED_ADJACENT_FIND const void* __stdcall __std_adjacent_find_1(const void* _First, const void* _Last) noexcept; const void* __stdcall __std_adjacent_find_2(const void* _First, const void* _Last) noexcept; const void* __stdcall __std_adjacent_find_4(const void* _First, const void* _Last) noexcept; const void* __stdcall __std_adjacent_find_8(const void* _First, const void* _Last) noexcept; +#endif // ^^^ _VECTORIZED_ADJACENT_FIND ^^^ #if _VECTORIZED_SEARCH const void* __stdcall __std_search_1( @@ -309,6 +311,7 @@ _Ty* _Find_last_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val } } +#if _VECTORIZED_ADJACENT_FIND template _Ty* _Adjacent_find_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -323,6 +326,7 @@ _Ty* _Adjacent_find_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_ADJACENT_FIND ^^^ // find_first_of vectorization is likely to be a win after this size (in elements) // (Used with _Find_first_of_vectorized, _Find_first_of_pos_vectorized, _Find_first_not_of_pos_vectorized, @@ -6988,7 +6992,7 @@ namespace ranges { return _First; } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_ADJACENT_FIND if constexpr (_Vector_alg_in_search_is_safe<_It, _It, _Pr> && sized_sentinel_for<_Se, _It> && is_same_v<_Pj, identity>) { if (!_STD is_constant_evaluated()) { @@ -7003,7 +7007,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_ADJACENT_FIND ^^^ for (auto _Next = _First;; ++_First) { if (++_Next == _Last) { From 6747f12a82828820c34f6553596c32c7985826e7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 09:42:58 -0700 Subject: [PATCH 16/33] _VECTORIZED_FIND_FIRST_OF. --- stl/inc/__msvc_string_view.hpp | 17 +++++++++++++---- stl/inc/algorithm | 15 +++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 819fe18ab24..dc6a8ac4358 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -29,6 +29,7 @@ extern "C" { // compiler has to assume that the denoted arrays are "globally address taken", and that any later calls to // unanalyzable routines may modify those arrays. +#if _VECTORIZED_FIND_FIRST_OF __declspec(noalias) size_t __stdcall __std_find_first_of_trivial_pos_1( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; __declspec(noalias) size_t __stdcall __std_find_first_of_trivial_pos_2( @@ -37,6 +38,7 @@ __declspec(noalias) size_t __stdcall __std_find_first_of_trivial_pos_4( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; __declspec(noalias) size_t __stdcall __std_find_first_of_trivial_pos_8( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; +#endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ __declspec(noalias) size_t __stdcall __std_find_last_of_trivial_pos_1( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; @@ -57,10 +59,12 @@ __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_4( __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_8( const void* _First, const void* _Last, uint64_t _Val) noexcept; +#if _VECTORIZED_FIND_FIRST_OF __declspec(noalias) size_t __stdcall __std_find_first_not_of_trivial_pos_1( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; __declspec(noalias) size_t __stdcall __std_find_first_not_of_trivial_pos_2( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; +#endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ __declspec(noalias) size_t __stdcall __std_find_last_not_of_trivial_pos_1( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; @@ -71,6 +75,7 @@ __declspec(noalias) size_t __stdcall __std_find_last_not_of_trivial_pos_2( _STD_BEGIN +#if _VECTORIZED_FIND_FIRST_OF template size_t _Find_first_of_pos_vectorized(const _Ty1* const _Haystack, const size_t _Haystack_length, const _Ty2* const _Needle, const size_t _Needle_length) noexcept { @@ -87,6 +92,7 @@ size_t _Find_first_of_pos_vectorized(const _Ty1* const _Haystack, const size_t _ _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ template size_t _Find_last_of_pos_vectorized(const _Ty1* const _Haystack, const size_t _Haystack_length, @@ -130,6 +136,8 @@ size_t _Find_last_not_ch_pos_vectorized(const _Ty* const _First, const _Ty* cons _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } + +#if _VECTORIZED_FIND_FIRST_OF template size_t _Find_first_not_of_pos_vectorized(const _Ty1* const _Haystack, const size_t _Haystack_length, const _Ty2* const _Needle, const size_t _Needle_length) noexcept { @@ -142,6 +150,7 @@ size_t _Find_first_not_of_pos_vectorized(const _Ty1* const _Haystack, const size _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ template size_t _Find_last_not_of_pos_vectorized(const _Ty1* const _Haystack, const size_t _Haystack_length, @@ -934,7 +943,7 @@ constexpr size_t _Traits_find_first_of(_In_reads_(_Hay_size) const _Traits_ptr_t const auto _Hay_end = _Haystack + _Hay_size; if constexpr (_Is_implementation_handled_char_traits<_Traits>) { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_FIRST_OF if (!_STD _Is_constant_evaluated()) { const size_t _Remaining_size = _Hay_size - _Start_at; if (_Remaining_size + _Needle_size >= _Threshold_find_first_of) { @@ -945,7 +954,7 @@ constexpr size_t _Traits_find_first_of(_In_reads_(_Hay_size) const _Traits_ptr_t return _Pos; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ _String_bitmap _Matches; @@ -1035,7 +1044,7 @@ constexpr size_t _Traits_find_first_not_of(_In_reads_(_Hay_size) const _Traits_p if constexpr (_Is_implementation_handled_char_traits<_Traits>) { using _Elem = typename _Traits::char_type; -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_FIRST_OF if constexpr (sizeof(_Elem) <= 2) { if (!_STD _Is_constant_evaluated()) { const size_t _Remaining_size = _Hay_size - _Start_at; @@ -1048,7 +1057,7 @@ constexpr size_t _Traits_find_first_not_of(_In_reads_(_Hay_size) const _Traits_p } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ _String_bitmap<_Elem> _Matches; if (_Matches._Mark(_Needle, _Needle + _Needle_size)) { diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 9f3a7957a1a..542b36baaa7 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -39,6 +39,8 @@ extern "C" { // functions are in native code objects that the compiler cannot analyze. In the absence of the noalias attribute, the // compiler has to assume that the denoted arrays are "globally address taken", and that any later calls to // unanalyzable routines may modify those arrays. + +#if _VECTORIZED_FIND_FIRST_OF const void* __stdcall __std_find_first_of_trivial_1( const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept; const void* __stdcall __std_find_first_of_trivial_2( @@ -47,6 +49,7 @@ const void* __stdcall __std_find_first_of_trivial_4( const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept; const void* __stdcall __std_find_first_of_trivial_8( const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept; +#endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ __declspec(noalias) void __cdecl __std_reverse_copy_trivially_copyable_1( const void* _First, const void* _Last, void* _Dest) noexcept; @@ -139,6 +142,8 @@ void* __stdcall __std_unique_copy_8(const void* _First, const void* _Last, void* } // extern "C" _STD_BEGIN + +#if _VECTORIZED_FIND_FIRST_OF template _Ty1* _Find_first_of_vectorized( _Ty1* const _First1, _Ty1* const _Last1, _Ty2* const _First2, _Ty2* const _Last2) noexcept { @@ -159,6 +164,7 @@ _Ty1* _Find_first_of_vectorized( _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ template __declspec(noalias) void _Reverse_copy_vectorized(const void* _First, const void* _Last, void* _Dest) noexcept { @@ -3851,7 +3857,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_first_of( } } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_FIRST_OF if constexpr (_Vector_alg_in_search_is_safe) { if (!_STD _Is_constant_evaluated() && _ULast1 - _UFirst1 >= _Threshold_find_first_of) { const auto _First1_ptr = _STD _To_address(_UFirst1); @@ -3867,7 +3873,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_first_of( return _First1; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ for (; _UFirst1 != _ULast1; ++_UFirst1) { for (auto _UMid2 = _UFirst2; _UMid2 != _ULast2; ++_UMid2) { @@ -3955,7 +3961,7 @@ namespace ranges { } } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_FIRST_OF if constexpr (_Vector_alg_in_search_is_safe<_It1, _It2, _Pr> && sized_sentinel_for<_Se1, _It1> && sized_sentinel_for<_Se2, _It2> && is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>) { if (!_STD is_constant_evaluated() && _Last1 - _First1 >= _Threshold_find_first_of) { @@ -3977,7 +3983,8 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ + for (; _First1 != _Last1; ++_First1) { for (auto _Mid2 = _First2; _Mid2 != _Last2; ++_Mid2) { if (_STD invoke(_Pred, _STD invoke(_Proj1, *_First1), _STD invoke(_Proj2, *_Mid2))) { From d410936c858ea1fbd0030fed772b9057b91e76bf Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 10:21:58 -0700 Subject: [PATCH 17/33] _VECTORIZED_FIND_LAST_OF. --- stl/inc/__msvc_string_view.hpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index dc6a8ac4358..428579f1912 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -40,10 +40,12 @@ __declspec(noalias) size_t __stdcall __std_find_first_of_trivial_pos_8( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; #endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ +#if _VECTORIZED_FIND_LAST_OF __declspec(noalias) size_t __stdcall __std_find_last_of_trivial_pos_1( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; __declspec(noalias) size_t __stdcall __std_find_last_of_trivial_pos_2( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; +#endif // ^^^ _VECTORIZED_FIND_LAST_OF ^^^ const void* __stdcall __std_find_not_ch_1(const void* _First, const void* _Last, uint8_t _Val) noexcept; const void* __stdcall __std_find_not_ch_2(const void* _First, const void* _Last, uint16_t _Val) noexcept; @@ -66,10 +68,12 @@ __declspec(noalias) size_t __stdcall __std_find_first_not_of_trivial_pos_2( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; #endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ +#if _VECTORIZED_FIND_LAST_OF __declspec(noalias) size_t __stdcall __std_find_last_not_of_trivial_pos_1( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; __declspec(noalias) size_t __stdcall __std_find_last_not_of_trivial_pos_2( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; +#endif // ^^^ _VECTORIZED_FIND_LAST_OF ^^^ } // extern "C" @@ -94,6 +98,7 @@ size_t _Find_first_of_pos_vectorized(const _Ty1* const _Haystack, const size_t _ } #endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ +#if _VECTORIZED_FIND_LAST_OF template size_t _Find_last_of_pos_vectorized(const _Ty1* const _Haystack, const size_t _Haystack_length, const _Ty2* const _Needle, const size_t _Needle_length) noexcept { @@ -106,6 +111,7 @@ size_t _Find_last_of_pos_vectorized(const _Ty1* const _Haystack, const size_t _H _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FIND_LAST_OF ^^^ template const _Ty* _Find_not_ch_vectorized(const _Ty* const _First, const _Ty* const _Last, const _Ty _Ch) noexcept { @@ -152,6 +158,7 @@ size_t _Find_first_not_of_pos_vectorized(const _Ty1* const _Haystack, const size } #endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ +#if _VECTORIZED_FIND_LAST_OF template size_t _Find_last_not_of_pos_vectorized(const _Ty1* const _Haystack, const size_t _Haystack_length, const _Ty2* const _Needle, const size_t _Needle_length) noexcept { @@ -164,6 +171,7 @@ size_t _Find_last_not_of_pos_vectorized(const _Ty1* const _Haystack, const size_ _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FIND_LAST_OF ^^^ _STD_END @@ -992,7 +1000,7 @@ constexpr size_t _Traits_find_last_of(_In_reads_(_Hay_size) const _Traits_ptr_t< if constexpr (_Is_implementation_handled_char_traits<_Traits>) { using _Elem = typename _Traits::char_type; -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_LAST_OF if constexpr (sizeof(_Elem) <= 2) { if (!_STD _Is_constant_evaluated()) { const size_t _Remaining_size = _Hay_start + 1; @@ -1001,7 +1009,7 @@ constexpr size_t _Traits_find_last_of(_In_reads_(_Hay_size) const _Traits_ptr_t< } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_LAST_OF ^^^ _String_bitmap<_Elem> _Matches; if (_Matches._Mark(_Needle, _Needle + _Needle_size)) { @@ -1126,7 +1134,7 @@ constexpr size_t _Traits_find_last_not_of(_In_reads_(_Hay_size) const _Traits_pt if constexpr (_Is_implementation_handled_char_traits<_Traits>) { using _Elem = typename _Traits::char_type; -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_LAST_OF if constexpr (sizeof(_Elem) <= 2) { if (!_STD _Is_constant_evaluated()) { const size_t _Remaining_size = _Hay_start + 1; @@ -1135,7 +1143,7 @@ constexpr size_t _Traits_find_last_not_of(_In_reads_(_Hay_size) const _Traits_pt } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_LAST_OF ^^^ _String_bitmap<_Elem> _Matches; if (_Matches._Mark(_Needle, _Needle + _Needle_size)) { From b2485ab0f347a20bb7697f7b6d63420958e29203 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 10:28:34 -0700 Subject: [PATCH 18/33] _VECTORIZED_FIND. --- stl/inc/__msvc_string_view.hpp | 12 ++++++++---- stl/inc/xutility | 18 +++++++++++------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 428579f1912..48096bd6a98 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -47,10 +47,12 @@ __declspec(noalias) size_t __stdcall __std_find_last_of_trivial_pos_2( const void* _Haystack, size_t _Haystack_length, const void* _Needle, size_t _Needle_length) noexcept; #endif // ^^^ _VECTORIZED_FIND_LAST_OF ^^^ +#if _VECTORIZED_FIND const void* __stdcall __std_find_not_ch_1(const void* _First, const void* _Last, uint8_t _Val) noexcept; const void* __stdcall __std_find_not_ch_2(const void* _First, const void* _Last, uint16_t _Val) noexcept; const void* __stdcall __std_find_not_ch_4(const void* _First, const void* _Last, uint32_t _Val) noexcept; const void* __stdcall __std_find_not_ch_8(const void* _First, const void* _Last, uint64_t _Val) noexcept; +#endif // ^^^ _VECTORIZED_FIND ^^^ __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_1( const void* _First, const void* _Last, uint8_t _Val) noexcept; @@ -113,6 +115,7 @@ size_t _Find_last_of_pos_vectorized(const _Ty1* const _Haystack, const size_t _H } #endif // ^^^ _VECTORIZED_FIND_LAST_OF ^^^ +#if _VECTORIZED_FIND template const _Ty* _Find_not_ch_vectorized(const _Ty* const _First, const _Ty* const _Last, const _Ty _Ch) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -127,6 +130,7 @@ const _Ty* _Find_not_ch_vectorized(const _Ty* const _First, const _Ty* const _La _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FIND ^^^ template size_t _Find_last_not_ch_pos_vectorized(const _Ty* const _First, const _Ty* const _Last, const _Ty _Ch) noexcept { @@ -781,7 +785,7 @@ constexpr size_t _Traits_find_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_Trai return static_cast(-1); // (npos) no room for match } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { const auto _End = _Haystack + _Hay_size; @@ -794,7 +798,7 @@ constexpr size_t _Traits_find_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_Trai } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND ^^^ const auto _Found_at = _Traits::find(_Haystack + _Start_at, _Hay_size - _Start_at, _Ch); if (_Found_at) { @@ -1099,7 +1103,7 @@ constexpr size_t _Traits_find_not_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_ const auto _End = _Haystack + _Hay_size; -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { const auto _Result = _STD _Find_not_ch_vectorized(_Haystack + _Start_at, _End, _Ch); @@ -1110,7 +1114,7 @@ constexpr size_t _Traits_find_not_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_ } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND ^^^ for (auto _Match_try = _Haystack + _Start_at; _Match_try < _End; ++_Match_try) { if (!_Traits::eq(*_Match_try, _Ch)) { diff --git a/stl/inc/xutility b/stl/inc/xutility index 682aae18e25..69624d6b94f 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -140,10 +140,12 @@ __declspec(noalias) size_t __stdcall __std_count_trivial_8( const void* _First, const void* _Last, uint64_t _Val) noexcept; #endif // ^^^ _VECTORIZED_COUNT ^^^ +#if _VECTORIZED_FIND const void* __stdcall __std_find_trivial_1(const void* _First, const void* _Last, uint8_t _Val) noexcept; const void* __stdcall __std_find_trivial_2(const void* _First, const void* _Last, uint16_t _Val) noexcept; const void* __stdcall __std_find_trivial_4(const void* _First, const void* _Last, uint32_t _Val) noexcept; const void* __stdcall __std_find_trivial_8(const void* _First, const void* _Last, uint64_t _Val) noexcept; +#endif // ^^^ _VECTORIZED_FIND ^^^ const void* __stdcall __std_find_last_trivial_1(const void* _First, const void* _Last, uint8_t _Val) noexcept; const void* __stdcall __std_find_last_trivial_2(const void* _First, const void* _Last, uint16_t _Val) noexcept; @@ -272,7 +274,7 @@ __declspec(noalias) size_t _Count_vectorized(_Ty* const _First, _Ty* const _Last } #endif // ^^^ _VECTORIZED_COUNT ^^^ -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND template _Ty* _Find_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -291,7 +293,9 @@ _Ty* _Find_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) noe _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FIND ^^^ +#if _VECTORIZED_FOR_X64_X86 template _Ty* _Find_last_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -6307,7 +6311,7 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c if (!_STD _Could_compare_equal_to_value_type<_InIt>(_Val)) { return _Last; } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND const auto _First_ptr = _STD _To_address(_First); const auto _Result = _STD _Find_vectorized(_First_ptr, _STD _To_address(_Last), _Val); if constexpr (is_pointer_v<_InIt>) { @@ -6315,7 +6319,7 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c } else { return _First + static_cast<_Iter_diff_t<_InIt>>(_Result - _First_ptr); } -#else // ^^^ _VECTORIZED_FOR_X64_X86 / !_VECTORIZED_FOR_X64_X86 vvv +#else // ^^^ _VECTORIZED_FIND / !_VECTORIZED_FIND vvv if constexpr (sizeof(_Iter_value_t<_InIt>) <= 2) { const auto _First_ptr = _STD _To_address(_First); const auto _Count = static_cast(_Last - _First); @@ -6338,7 +6342,7 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c return _Result ? _First + (_Result - _First_ptr) : _Last; } } -#endif // ^^^ !_VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ !_VECTORIZED_FIND ^^^ } } @@ -6387,7 +6391,7 @@ namespace ranges { if constexpr (_Vector_alg_in_find_is_safe<_It, _Ty> && same_as<_Pj, identity> && (_Elements_are_1_byte ? _Is_sized || same_as<_Se, unreachable_sentinel_t> : _Elements_are_2_bytes ? _Is_sized - : _Is_sized && _VECTORIZED_FOR_X64_X86)) { + : _Is_sized && _VECTORIZED_FIND)) { if (!_STD is_constant_evaluated()) { if (!_STD _Could_compare_equal_to_value_type<_It>(_Val)) { if constexpr (_Is_sized) { @@ -6402,13 +6406,13 @@ namespace ranges { const auto _First_ptr = _STD _To_address(_First); _Ptr_t _Result; -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND if constexpr (_Is_sized) { // Prefer this over memchr()/wmemchr() below for performance const auto _Last_ptr = _First_ptr + static_cast(_Last - _First); _Result = _STD _Find_vectorized(_First_ptr, _Last_ptr, _Val); } else -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND ^^^ { if constexpr (_Elements_are_2_bytes) { _STL_INTERNAL_STATIC_ASSERT(_Is_sized); From 071af154010a49c5fb4ec57ca30c945d69987c4e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 10:31:55 -0700 Subject: [PATCH 19/33] _VECTORIZED_SEARCH_N. --- stl/inc/algorithm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 542b36baaa7..0e188e61713 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -120,10 +120,12 @@ __declspec(noalias) void __stdcall __std_replace_4( __declspec(noalias) void __stdcall __std_replace_8( void* _First, void* _Last, uint64_t _Old_val, uint64_t _New_val) noexcept; +#if _VECTORIZED_SEARCH_N const void* __stdcall __std_search_n_1(const void* _First, const void* _Last, size_t _Count, uint8_t _Value) noexcept; const void* __stdcall __std_search_n_2(const void* _First, const void* _Last, size_t _Count, uint16_t _Value) noexcept; const void* __stdcall __std_search_n_4(const void* _First, const void* _Last, size_t _Count, uint32_t _Value) noexcept; const void* __stdcall __std_search_n_8(const void* _First, const void* _Last, size_t _Count, uint64_t _Value) noexcept; +#endif // ^^^ _VECTORIZED_SEARCH_N ^^^ void* __stdcall __std_remove_copy_1(const void* _First, const void* _Last, void* _Out, uint8_t _Val) noexcept; void* __stdcall __std_remove_copy_2(const void* _First, const void* _Last, void* _Out, uint16_t _Val) noexcept; @@ -343,6 +345,7 @@ __declspec(noalias) void _Replace_vectorized( } } +#if _VECTORIZED_SEARCH_N template _Ty* _Search_n_vectorized(_Ty* const _First, _Ty* const _Last, const size_t _Count, const _TVal _Val) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -361,6 +364,7 @@ _Ty* _Search_n_vectorized(_Ty* const _First, _Ty* const _Last, const size_t _Cou _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_SEARCH_N ^^^ template _Ty* _Unique_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { @@ -2488,7 +2492,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt search_n( auto _UFirst = _STD _Get_unwrapped(_First); const auto _ULast = _STD _Get_unwrapped(_Last); if constexpr (_Is_ranges_random_iter_v<_FwdIt>) { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_SEARCH_N if constexpr (_Vector_alg_in_search_n_is_safe) { if (!_STD _Is_constant_evaluated()) { if (!_STD _Could_compare_equal_to_value_type(_Val)) { @@ -2509,7 +2513,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt search_n( return _Last; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_SEARCH_N ^^^ const auto _Count_diff = static_cast<_Iter_diff_t<_FwdIt>>(_Count); auto _UOld_first = _UFirst; @@ -2683,7 +2687,7 @@ namespace ranges { return {_First, _First}; } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_SEARCH_N if constexpr (_Vector_alg_in_search_n_is_safe<_It, _Ty, _Pr> && is_same_v<_Pj, identity>) { if (!_STD is_constant_evaluated()) { if (!_STD _Could_compare_equal_to_value_type<_It>(_Val)) { @@ -2713,7 +2717,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_SEARCH_N ^^^ auto _Last = _RANGES next(_First, _Count); auto _Mid1 = _First; From 94f5ea631928a86285e708f0ad450061a4bdc91a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 10:34:03 -0700 Subject: [PATCH 20/33] _VECTORIZED_REMOVE_COPY. --- stl/inc/algorithm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 0e188e61713..540a90f50c6 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -127,10 +127,12 @@ const void* __stdcall __std_search_n_4(const void* _First, const void* _Last, si const void* __stdcall __std_search_n_8(const void* _First, const void* _Last, size_t _Count, uint64_t _Value) noexcept; #endif // ^^^ _VECTORIZED_SEARCH_N ^^^ +#if _VECTORIZED_REMOVE_COPY void* __stdcall __std_remove_copy_1(const void* _First, const void* _Last, void* _Out, uint8_t _Val) noexcept; void* __stdcall __std_remove_copy_2(const void* _First, const void* _Last, void* _Out, uint16_t _Val) noexcept; void* __stdcall __std_remove_copy_4(const void* _First, const void* _Last, void* _Out, uint32_t _Val) noexcept; void* __stdcall __std_remove_copy_8(const void* _First, const void* _Last, void* _Out, uint64_t _Val) noexcept; +#endif // ^^^ _VECTORIZED_REMOVE_COPY ^^^ void* __stdcall __std_unique_1(void* _First, void* _Last) noexcept; void* __stdcall __std_unique_2(void* _First, void* _Last) noexcept; @@ -381,6 +383,7 @@ _Ty* _Unique_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { } } +#if _VECTORIZED_REMOVE_COPY template _Ty* _Remove_copy_vectorized( const _Ty* const _First, const _Ty* const _Last, _Ty* const _Dest, const _TVal _Val) noexcept { @@ -396,6 +399,7 @@ _Ty* _Remove_copy_vectorized( _STL_INTERNAL_STATIC_ASSERT(false); // Unexpected size } } +#endif // ^^^ _VECTORIZED_REMOVE_COPY ^^^ template _Ty* _Unique_copy_vectorized(const _Ty* const _First, const _Ty* const _Last, _Ty* const _Dest) noexcept { @@ -4923,7 +4927,7 @@ _CONSTEXPR20 _OutIt remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _ const auto _ULast = _STD _Get_unwrapped(_Last); auto _UDest = _STD _Get_unwrapped_unverified(_Dest); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REMOVE_COPY if constexpr (_Vector_alg_in_find_is_safe && _Output_iterator_for_vector_alg_is_safe()) { if (!_STD _Is_constant_evaluated()) { @@ -4947,7 +4951,7 @@ _CONSTEXPR20 _OutIt remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _ return _Dest; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_REMOVE_COPY ^^^ for (; _UFirst != _ULast; ++_UFirst) { if (!(*_UFirst == _Val)) { @@ -5174,7 +5178,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(indirectly_copyable<_It, _Out>); _STL_INTERNAL_STATIC_ASSERT(indirect_binary_predicate, const _Ty*>); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REMOVE_COPY if constexpr (_Vector_alg_in_find_is_safe<_It, _Ty> && _Output_iterator_for_vector_alg_is_safe<_Out, _It>() && sized_sentinel_for<_Se, _It> && is_same_v<_Pj, identity>) { if (!_STD is_constant_evaluated()) { @@ -5198,7 +5202,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_REMOVE_COPY ^^^ for (; _First != _Last; ++_First) { if (_STD invoke(_Proj, *_First) != _Val) { From d81cf8fdc624d6adb6bfe547b45c5e1d803b4276 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 10:39:01 -0700 Subject: [PATCH 21/33] _VECTORIZED_FIND_LAST. --- stl/inc/__msvc_string_view.hpp | 4 ++-- stl/inc/algorithm | 4 ++-- stl/inc/xutility | 7 ++++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 48096bd6a98..818eebf2297 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -864,7 +864,7 @@ constexpr size_t _Traits_rfind_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_Tra const size_t _Actual_start_at = (_STD min) (_Start_at, _Hay_size - 1); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_LAST if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { const auto _End = _Haystack + _Actual_start_at + 1; @@ -877,7 +877,7 @@ constexpr size_t _Traits_rfind_ch(_In_reads_(_Hay_size) const _Traits_ptr_t<_Tra } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_LAST ^^^ for (auto _Match_try = _Haystack + _Actual_start_at;; --_Match_try) { if (_Traits::eq(*_Match_try, _Ch)) { diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 540a90f50c6..b3201388c01 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -3381,7 +3381,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_binary_predicate, const _Ty*>); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_LAST if constexpr (is_same_v<_Pj, identity> && _Vector_alg_in_find_is_safe<_It, _Ty> && sized_sentinel_for<_Se, _It>) { if (!_STD is_constant_evaluated()) { @@ -3402,7 +3402,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_LAST ^^^ if constexpr (_Bidi_common<_It, _Se>) { for (auto _Result = _Last; _Result != _First;) { diff --git a/stl/inc/xutility b/stl/inc/xutility index 69624d6b94f..e25d9d2ab09 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -147,10 +147,12 @@ const void* __stdcall __std_find_trivial_4(const void* _First, const void* _Last const void* __stdcall __std_find_trivial_8(const void* _First, const void* _Last, uint64_t _Val) noexcept; #endif // ^^^ _VECTORIZED_FIND ^^^ +#if _VECTORIZED_FIND_LAST const void* __stdcall __std_find_last_trivial_1(const void* _First, const void* _Last, uint8_t _Val) noexcept; const void* __stdcall __std_find_last_trivial_2(const void* _First, const void* _Last, uint16_t _Val) noexcept; const void* __stdcall __std_find_last_trivial_4(const void* _First, const void* _Last, uint32_t _Val) noexcept; const void* __stdcall __std_find_last_trivial_8(const void* _First, const void* _Last, uint64_t _Val) noexcept; +#endif // ^^^ _VECTORIZED_FIND_LAST ^^^ #if _VECTORIZED_ADJACENT_FIND const void* __stdcall __std_adjacent_find_1(const void* _First, const void* _Last) noexcept; @@ -295,7 +297,7 @@ _Ty* _Find_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) noe } #endif // ^^^ _VECTORIZED_FIND ^^^ -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_LAST template _Ty* _Find_last_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -314,6 +316,7 @@ _Ty* _Find_last_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FIND_LAST ^^^ #if _VECTORIZED_ADJACENT_FIND template @@ -332,6 +335,8 @@ _Ty* _Adjacent_find_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { } #endif // ^^^ _VECTORIZED_ADJACENT_FIND ^^^ +#if _VECTORIZED_FOR_X64_X86 + // find_first_of vectorization is likely to be a win after this size (in elements) // (Used with _Find_first_of_vectorized, _Find_first_of_pos_vectorized, _Find_first_not_of_pos_vectorized, // _Find_last_of_pos_vectorized, and _Find_last_not_of_pos_vectorized.) From c2a314dea4413bec799da6a62b6e094ada58adc2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 10:43:20 -0700 Subject: [PATCH 22/33] _VECTORIZED_REVERSE_COPY. --- stl/inc/algorithm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index b3201388c01..eb8c615958c 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -51,6 +51,7 @@ const void* __stdcall __std_find_first_of_trivial_8( const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept; #endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ +#if _VECTORIZED_REVERSE_COPY __declspec(noalias) void __cdecl __std_reverse_copy_trivially_copyable_1( const void* _First, const void* _Last, void* _Dest) noexcept; __declspec(noalias) void __cdecl __std_reverse_copy_trivially_copyable_2( @@ -59,6 +60,7 @@ __declspec(noalias) void __cdecl __std_reverse_copy_trivially_copyable_4( const void* _First, const void* _Last, void* _Dest) noexcept; __declspec(noalias) void __cdecl __std_reverse_copy_trivially_copyable_8( const void* _First, const void* _Last, void* _Dest) noexcept; +#endif // ^^^ _VECTORIZED_REVERSE_COPY ^^^ #if _VECTORIZED_MINMAX_ELEMENT _Min_max_element_t __stdcall __std_minmax_element_1(const void* _First, const void* _Last, bool _Signed) noexcept; @@ -170,6 +172,7 @@ _Ty1* _Find_first_of_vectorized( } #endif // ^^^ _VECTORIZED_FIND_FIRST_OF ^^^ +#if _VECTORIZED_REVERSE_COPY template __declspec(noalias) void _Reverse_copy_vectorized(const void* _First, const void* _Last, void* _Dest) noexcept { if constexpr (_Nx == 1) { @@ -184,6 +187,7 @@ __declspec(noalias) void _Reverse_copy_vectorized(const void* _First, const void _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_REVERSE_COPY ^^^ #if _VECTORIZED_MINMAX_ELEMENT template @@ -5726,7 +5730,7 @@ _CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) { auto _ULast = _STD _Get_unwrapped(_Last); auto _UDest = _STD _Get_unwrapped_n(_Dest, _STD _Idl_distance<_BidIt>(_UFirst, _ULast)); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REVERSE_COPY using _Elem = remove_reference_t<_Iter_ref_t>>; using _DestElem = remove_reference_t<_Iter_ref_t>; constexpr bool _Allow_vectorization = conjunction_v, _DestElem>, @@ -5746,7 +5750,7 @@ _CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) { return _Dest; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_REVERSE_COPY ^^^ for (; _UFirst != _ULast; ++_UDest) { *_UDest = *--_ULast; @@ -5815,7 +5819,7 @@ namespace ranges { _STD _Verify_ranges_do_not_overlap(_First, _Last, _Output); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REVERSE_COPY if constexpr (contiguous_iterator<_It> && contiguous_iterator<_Out>) { using _Elem = remove_reference_t>; using _DestElem = remove_reference_t>; @@ -5832,7 +5836,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_REVERSE_COPY ^^^ for (; _First != _Last; ++_Output) { *_Output = *--_Last; From 2e5893936cec0f771c6a8a6e3fdb2b9cc66158b4 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 11:08:09 -0700 Subject: [PATCH 23/33] _VECTORIZED_REPLACE. --- stl/inc/algorithm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index eb8c615958c..4f926c0001f 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -116,11 +116,13 @@ __declspec(noalias) bool __stdcall __std_includes_less_8u( const void* _First1, const void* _Last1, const void* _First2, const void* _Last2) noexcept; #endif // ^^^ _VECTORIZED_INCLUDES ^^^ +#if _VECTORIZED_REPLACE // TRANSITION, DevCom-10610477 __declspec(noalias) void __stdcall __std_replace_4( void* _First, void* _Last, uint32_t _Old_val, uint32_t _New_val) noexcept; __declspec(noalias) void __stdcall __std_replace_8( void* _First, void* _Last, uint64_t _Old_val, uint64_t _New_val) noexcept; +#endif // ^^^ _VECTORIZED_REPLACE ^^^ #if _VECTORIZED_SEARCH_N const void* __stdcall __std_search_n_1(const void* _First, const void* _Last, size_t _Count, uint8_t _Value) noexcept; @@ -337,6 +339,7 @@ bool _Includes_vectorized( } #endif // ^^^ _VECTORIZED_INCLUDES ^^^ +#if _VECTORIZED_REPLACE template __declspec(noalias) void _Replace_vectorized( _Ty* const _First, _Ty* const _Last, const _TVal1 _Old_val, const _TVal2 _New_val) noexcept { @@ -350,6 +353,7 @@ __declspec(noalias) void _Replace_vectorized( _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_REPLACE ^^^ #if _VECTORIZED_SEARCH_N template @@ -4369,7 +4373,7 @@ _CONSTEXPR20 void replace(const _FwdIt _First, const _FwdIt _Last, const _Ty& _O auto _UFirst = _STD _Get_unwrapped(_First); const auto _ULast = _STD _Get_unwrapped(_Last); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REPLACE if constexpr (_Vector_alg_in_replace_is_safe) { #if _HAS_CXX20 if (!_STD is_constant_evaluated()) @@ -4382,7 +4386,7 @@ _CONSTEXPR20 void replace(const _FwdIt _First, const _FwdIt _Last, const _Ty& _O return; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_REPLACE ^^^ for (; _UFirst != _ULast; ++_UFirst) { if (*_UFirst == _Oldval) { @@ -4437,7 +4441,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(indirectly_writable<_It, const _Ty2&>); _STL_INTERNAL_STATIC_ASSERT(indirect_binary_predicate, const _Ty1*>); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_REPLACE if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for<_Se, _It> && _Vector_alg_in_ranges_replace_is_safe<_It, _Ty1, _Ty2>) { if (!_STD is_constant_evaluated()) { @@ -4452,7 +4456,7 @@ namespace ranges { return _First + _Count; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_REPLACE ^^^ for (; _First != _Last; ++_First) { if (_STD invoke(_Proj, *_First) == _Oldval) { From 86f8a909b9439264517b925bfc820ecf071edf6a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 11:11:22 -0700 Subject: [PATCH 24/33] _VECTORIZED_FIND_END. --- stl/inc/__msvc_string_view.hpp | 4 ++-- stl/inc/algorithm | 8 ++++---- stl/inc/xutility | 7 ++++++- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 818eebf2297..c02c49d5a6e 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -823,7 +823,7 @@ constexpr size_t _Traits_rfind(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits const size_t _Actual_start_at = (_STD min) (_Start_at, _Hay_size - _Needle_size); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_END if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { // _Find_end_vectorized takes into account the needle length when locating the search start. @@ -840,7 +840,7 @@ constexpr size_t _Traits_rfind(_In_reads_(_Hay_size) const _Traits_ptr_t<_Traits } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_END ^^^ for (auto _Match_try = _Haystack + _Actual_start_at;; --_Match_try) { if (_Traits::eq(*_Match_try, *_Needle) && _Traits::compare(_Match_try, _Needle, _Needle_size) == 0) { diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 4f926c0001f..9d029ef0e3c 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -3550,7 +3550,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_end( if constexpr (_Is_ranges_random_iter_v<_FwdIt1> && _Is_ranges_random_iter_v<_FwdIt2>) { const _Iter_diff_t<_FwdIt2> _Count2 = _ULast2 - _UFirst2; if (_Count2 > 0 && _Count2 <= _ULast1 - _UFirst1) { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_END if constexpr (_Vector_alg_in_search_is_safe) { if (!_STD _Is_constant_evaluated()) { const auto _Ptr1 = _STD _To_address(_UFirst1); @@ -3568,7 +3568,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt1 find_end( return _First1; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_END ^^^ for (auto _UCandidate = _ULast1 - static_cast<_Iter_diff_t<_FwdIt1>>(_Count2);; --_UCandidate) { if (_STD _Equal_rev_pred_unchecked(_UCandidate, _UFirst2, _ULast2, _STD _Pass_fn(_Pred))) { @@ -3673,7 +3673,7 @@ namespace ranges { if (_Count2 > 0 && _Count2 <= _Count1) { const auto _Count2_as1 = static_cast>(_Count2); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_END if constexpr (_Vector_alg_in_search_is_safe<_It1, _It2, _Pr> && is_same_v<_Pj1, identity> && is_same_v<_Pj2, identity>) { if (!_STD is_constant_evaluated()) { @@ -3700,7 +3700,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_END ^^^ for (auto _Candidate = _First1 + (_Count1 - _Count2_as1);; --_Candidate) { auto _Match_and_mid1 = diff --git a/stl/inc/xutility b/stl/inc/xutility index e25d9d2ab09..fc418aff51e 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -172,6 +172,7 @@ const void* __stdcall __std_search_8( const void* _First1, const void* _Last1, const void* _First2, size_t _Count2) noexcept; #endif // ^^^ _VECTORIZED_SEARCH ^^^ +#if _VECTORIZED_FIND_END const void* __stdcall __std_find_end_1( const void* _First1, const void* _Last1, const void* _First2, size_t _Count2) noexcept; const void* __stdcall __std_find_end_2( @@ -180,6 +181,7 @@ const void* __stdcall __std_find_end_4( const void* _First1, const void* _Last1, const void* _First2, size_t _Count2) noexcept; const void* __stdcall __std_find_end_8( const void* _First1, const void* _Last1, const void* _First2, size_t _Count2) noexcept; +#endif // ^^^ _VECTORIZED_FIND_END ^^^ #if _VECTORIZED_MINMAX_ELEMENT const void* __stdcall __std_min_element_1(const void* _First, const void* _Last, bool _Signed) noexcept; @@ -342,6 +344,8 @@ _Ty* _Adjacent_find_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { // _Find_last_of_pos_vectorized, and _Find_last_not_of_pos_vectorized.) _INLINE_VAR constexpr ptrdiff_t _Threshold_find_first_of = 16; +#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ + #if _VECTORIZED_SEARCH template _Ty1* _Search_vectorized(_Ty1* const _First1, _Ty1* const _Last1, _Ty2* const _First2, const size_t _Count2) noexcept { @@ -360,6 +364,7 @@ _Ty1* _Search_vectorized(_Ty1* const _First1, _Ty1* const _Last1, _Ty2* const _F } #endif // ^^^ _VECTORIZED_SEARCH ^^^ +#if _VECTORIZED_FIND_END template _Ty1* _Find_end_vectorized( _Ty1* const _First1, _Ty1* const _Last1, _Ty2* const _First2, const size_t _Count2) noexcept { @@ -376,7 +381,7 @@ _Ty1* _Find_end_vectorized( _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_END ^^^ #if _VECTORIZED_MINMAX_ELEMENT template From 13f8b502686bdb0ca7325e2df606d54b37fb6ffd Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 11:22:33 -0700 Subject: [PATCH 25/33] _VECTORIZED_FIND_LAST_NOT_OF. --- stl/inc/__msvc_string_view.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index c02c49d5a6e..3b7891804a6 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -54,6 +54,7 @@ const void* __stdcall __std_find_not_ch_4(const void* _First, const void* _Last, const void* __stdcall __std_find_not_ch_8(const void* _First, const void* _Last, uint64_t _Val) noexcept; #endif // ^^^ _VECTORIZED_FIND ^^^ +#if _VECTORIZED_FIND_LAST_NOT_OF __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_1( const void* _First, const void* _Last, uint8_t _Val) noexcept; __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_2( @@ -62,6 +63,7 @@ __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_4( const void* _First, const void* _Last, uint32_t _Val) noexcept; __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_8( const void* _First, const void* _Last, uint64_t _Val) noexcept; +#endif // ^^^ _VECTORIZED_FIND_LAST_NOT_OF ^^^ #if _VECTORIZED_FIND_FIRST_OF __declspec(noalias) size_t __stdcall __std_find_first_not_of_trivial_pos_1( @@ -132,6 +134,7 @@ const _Ty* _Find_not_ch_vectorized(const _Ty* const _First, const _Ty* const _La } #endif // ^^^ _VECTORIZED_FIND ^^^ +#if _VECTORIZED_FIND_LAST_NOT_OF template size_t _Find_last_not_ch_pos_vectorized(const _Ty* const _First, const _Ty* const _Last, const _Ty _Ch) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -146,6 +149,7 @@ size_t _Find_last_not_ch_pos_vectorized(const _Ty* const _First, const _Ty* cons _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } +#endif // ^^^ _VECTORIZED_FIND_LAST_NOT_OF ^^^ #if _VECTORIZED_FIND_FIRST_OF template @@ -1186,13 +1190,13 @@ constexpr size_t _Traits_rfind_not_ch(_In_reads_(_Hay_size) const _Traits_ptr_t< const size_t _Actual_start_at = (_STD min) (_Start_at, _Hay_size - 1); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_FIND_LAST_NOT_OF if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { return _STD _Find_last_not_ch_pos_vectorized(_Haystack, _Haystack + _Actual_start_at + 1, _Ch); } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_LAST_NOT_OF ^^^ for (auto _Match_try = _Haystack + _Actual_start_at;; --_Match_try) { if (!_Traits::eq(*_Match_try, _Ch)) { From cbf48ae7348d8bee2efdf653546a4fc61173d31e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 11:25:36 -0700 Subject: [PATCH 26/33] _VECTORIZED_UNIQUE. --- stl/inc/algorithm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 9d029ef0e3c..41426ba223e 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -138,10 +138,12 @@ void* __stdcall __std_remove_copy_4(const void* _First, const void* _Last, void* void* __stdcall __std_remove_copy_8(const void* _First, const void* _Last, void* _Out, uint64_t _Val) noexcept; #endif // ^^^ _VECTORIZED_REMOVE_COPY ^^^ +#if _VECTORIZED_UNIQUE void* __stdcall __std_unique_1(void* _First, void* _Last) noexcept; void* __stdcall __std_unique_2(void* _First, void* _Last) noexcept; void* __stdcall __std_unique_4(void* _First, void* _Last) noexcept; void* __stdcall __std_unique_8(void* _First, void* _Last) noexcept; +#endif // ^^^ _VECTORIZED_UNIQUE ^^^ void* __stdcall __std_unique_copy_1(const void* _First, const void* _Last, void* _Dest) noexcept; void* __stdcall __std_unique_copy_2(const void* _First, const void* _Last, void* _Dest) noexcept; @@ -376,6 +378,7 @@ _Ty* _Search_n_vectorized(_Ty* const _First, _Ty* const _Last, const size_t _Cou } #endif // ^^^ _VECTORIZED_SEARCH_N ^^^ +#if _VECTORIZED_UNIQUE template _Ty* _Unique_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -390,6 +393,7 @@ _Ty* _Unique_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { _STL_INTERNAL_STATIC_ASSERT(false); // Unexpected size } } +#endif // ^^^ _VECTORIZED_UNIQUE ^^^ #if _VECTORIZED_REMOVE_COPY template @@ -5293,7 +5297,7 @@ _NODISCARD_UNIQUE_ALG _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last, _P auto _UFirst = _STD _Get_unwrapped(_First); const auto _ULast = _STD _Get_unwrapped(_Last); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_UNIQUE if constexpr (_Vector_alg_in_unique_is_safe) { if (!_STD _Is_constant_evaluated()) { const auto _First_ptr = _STD _To_address(_UFirst); @@ -5309,7 +5313,7 @@ _NODISCARD_UNIQUE_ALG _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last, _P return _Last; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_UNIQUE ^^^ if (_UFirst != _ULast) { for (auto _UFirstb = _UFirst; ++_UFirst != _ULast; _UFirstb = _UFirst) { @@ -5387,7 +5391,7 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>); _STL_INTERNAL_STATIC_ASSERT(indirect_equivalence_relation<_Pr, projected<_It, _Pj>>); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_UNIQUE if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for<_Se, _It> && _Vector_alg_in_unique_is_safe<_It, _Pr>) { if (!_STD is_constant_evaluated()) { @@ -5403,7 +5407,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_UNIQUE ^^^ auto _Current = _First; if (_First == _Last) { From 5af3ecc03bb71fdcdd3ba5cac05ef3cda53990e3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 11:28:14 -0700 Subject: [PATCH 27/33] _VECTORIZED_UNIQUE_COPY. --- stl/inc/algorithm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 41426ba223e..73e777f5454 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -145,10 +145,12 @@ void* __stdcall __std_unique_4(void* _First, void* _Last) noexcept; void* __stdcall __std_unique_8(void* _First, void* _Last) noexcept; #endif // ^^^ _VECTORIZED_UNIQUE ^^^ +#if _VECTORIZED_UNIQUE_COPY void* __stdcall __std_unique_copy_1(const void* _First, const void* _Last, void* _Dest) noexcept; void* __stdcall __std_unique_copy_2(const void* _First, const void* _Last, void* _Dest) noexcept; void* __stdcall __std_unique_copy_4(const void* _First, const void* _Last, void* _Dest) noexcept; void* __stdcall __std_unique_copy_8(const void* _First, const void* _Last, void* _Dest) noexcept; +#endif // ^^^ _VECTORIZED_UNIQUE_COPY ^^^ } // extern "C" _STD_BEGIN @@ -413,6 +415,7 @@ _Ty* _Remove_copy_vectorized( } #endif // ^^^ _VECTORIZED_REMOVE_COPY ^^^ +#if _VECTORIZED_UNIQUE_COPY template _Ty* _Unique_copy_vectorized(const _Ty* const _First, const _Ty* const _Last, _Ty* const _Dest) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -427,6 +430,7 @@ _Ty* _Unique_copy_vectorized(const _Ty* const _First, const _Ty* const _Last, _T _STL_INTERNAL_STATIC_ASSERT(false); // Unexpected size } } +#endif // ^^^ _VECTORIZED_UNIQUE_COPY ^^^ // Can we activate the vector algorithms for replace? template @@ -5463,7 +5467,7 @@ _CONSTEXPR20 _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pr auto _UDest = _STD _Get_unwrapped_unverified(_Dest); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_UNIQUE_COPY if constexpr (_Vector_alg_in_unique_is_safe && _Output_iterator_for_vector_alg_is_safe()) { if (!_STD _Is_constant_evaluated()) { @@ -5481,7 +5485,7 @@ _CONSTEXPR20 _OutIt unique_copy(_InIt _First, _InIt _Last, _OutIt _Dest, _Pr _Pr return _Dest; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_UNIQUE_COPY ^^^ if constexpr (_Is_ranges_fwd_iter_v<_InIt>) { // can reread the source for comparison auto _Firstb = _UFirst; @@ -5610,7 +5614,7 @@ namespace ranges { return {_STD move(_First), _STD move(_Output)}; } -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_UNIQUE_COPY if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for<_Se, _It> && _Vector_alg_in_unique_is_safe<_It, _Pr> && _Output_iterator_for_vector_alg_is_safe<_Out, _It>()) { @@ -5629,7 +5633,7 @@ namespace ranges { } } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_UNIQUE_COPY ^^^ if constexpr (_Is_input_with_value_type<_Out, iter_value_t<_It>>) { // Can reread _Output From 741b5b90a9889407c4755013218a25ba1137eca6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 11:39:53 -0700 Subject: [PATCH 28/33] _VECTORIZED_BITSET_TO_STRING. --- stl/inc/bitset | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/stl/inc/bitset b/stl/inc/bitset index 0d1cbca3154..4689bc132ca 100644 --- a/stl/inc/bitset +++ b/stl/inc/bitset @@ -28,10 +28,13 @@ _STL_DISABLE_CLANG_WARNINGS // due to vectorization thresholds. extern "C" { +#if _VECTORIZED_BITSET_TO_STRING __declspec(noalias) void __stdcall __std_bitset_to_string_1( char* _Dest, const void* _Src, size_t _Size_bits, char _Elem0, char _Elem1) noexcept; __declspec(noalias) void __stdcall __std_bitset_to_string_2( wchar_t* _Dest, const void* _Src, size_t _Size_bits, wchar_t _Elem0, wchar_t _Elem1) noexcept; +#endif // ^^^ _VECTORIZED_BITSET_TO_STRING ^^^ + __declspec(noalias) bool __stdcall __std_bitset_from_string_1(void* _Dest, const char* _Src, size_t _Size_bytes, size_t _Size_bits, size_t _Size_chars, char _Elem0, char _Elem1) noexcept; __declspec(noalias) bool __stdcall __std_bitset_from_string_2(void* _Dest, const wchar_t* _Src, size_t _Size_bytes, @@ -516,7 +519,7 @@ public: template _CONSTEXPR23 void _To_string( _Elem* const _Buf, const size_t _Len, const _Elem _Elem0, const _Elem _Elem1) const noexcept { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_BITSET_TO_STRING constexpr size_t _Bitset_to_string_vector_threshold = 32; if constexpr (_Bits >= _Bitset_to_string_vector_threshold && is_integral_v<_Elem> && sizeof(_Elem) <= 2) { if (!_Is_constant_evaluated()) { @@ -532,7 +535,7 @@ public: return; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_BITSET_TO_STRING ^^^ for (size_t _Pos = 0; _Pos < _Len; ++_Pos) { _Buf[_Pos] = _Subscript(_Len - 1 - _Pos) ? _Elem1 : _Elem0; From a19efcd7398ea11fbcf4d5df38e807b41880ef2d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 11:41:12 -0700 Subject: [PATCH 29/33] _VECTORIZED_BITSET_FROM_STRING. --- stl/inc/bitset | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/stl/inc/bitset b/stl/inc/bitset index 4689bc132ca..c7383f6c9c4 100644 --- a/stl/inc/bitset +++ b/stl/inc/bitset @@ -35,10 +35,13 @@ __declspec(noalias) void __stdcall __std_bitset_to_string_2( wchar_t* _Dest, const void* _Src, size_t _Size_bits, wchar_t _Elem0, wchar_t _Elem1) noexcept; #endif // ^^^ _VECTORIZED_BITSET_TO_STRING ^^^ +#if _VECTORIZED_BITSET_FROM_STRING __declspec(noalias) bool __stdcall __std_bitset_from_string_1(void* _Dest, const char* _Src, size_t _Size_bytes, size_t _Size_bits, size_t _Size_chars, char _Elem0, char _Elem1) noexcept; __declspec(noalias) bool __stdcall __std_bitset_from_string_2(void* _Dest, const wchar_t* _Src, size_t _Size_bytes, size_t _Size_bits, size_t _Size_chars, wchar_t _Elem0, wchar_t _Elem1) noexcept; +#endif // ^^^ _VECTORIZED_BITSET_FROM_STRING ^^^ + } // extern "C" #endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ @@ -150,7 +153,7 @@ public: private: template _CONSTEXPR23 void _Construct(const _Elem* const _Ptr, size_t _Count, const _Elem _Elem0, const _Elem _Elem1) { -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_BITSET_FROM_STRING constexpr size_t _Bitset_from_string_vector_threshold = 16; if constexpr (_Bits >= _Bitset_from_string_vector_threshold && _Is_implementation_handled_char_traits<_Traits> && sizeof(_Elem) <= 2) { @@ -173,7 +176,8 @@ private: return; } } -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_BITSET_FROM_STRING ^^^ + if (_Count > _Bits) { for (size_t _Idx = _Bits; _Idx < _Count; ++_Idx) { const auto _Ch = _Ptr[_Idx]; From 834eea413539b29d766408fc86c0a60209b57d59 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 11:57:40 -0700 Subject: [PATCH 30/33] Remove/shrink _VECTORIZED_FOR_X64_X86 regions. --- stl/inc/__msvc_string_view.hpp | 6 ------ stl/inc/algorithm | 8 ++++---- stl/inc/bitset | 4 +--- stl/inc/xutility | 2 -- 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 3b7891804a6..bc043f15af5 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -19,7 +19,6 @@ _STL_DISABLE_CLANG_WARNINGS #pragma push_macro("new") #undef new -#if _VECTORIZED_FOR_X64_X86 extern "C" { // The "noalias" attribute tells the compiler optimizer that pointers going into these hand-vectorized algorithms // won't be stored beyond the lifetime of the function, and that the function will only reference arrays denoted by @@ -181,11 +180,6 @@ size_t _Find_last_not_of_pos_vectorized(const _Ty1* const _Haystack, const size_ } #endif // ^^^ _VECTORIZED_FIND_LAST_OF ^^^ -_STD_END - -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ - -_STD_BEGIN #ifdef __clang__ #define _HAS_MEMCPY_MEMMOVE_INTRINSICS 1 #else // ^^^ use __builtin_memcpy and __builtin_memmove / use workaround vvv diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 73e777f5454..296bdef91f0 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -29,8 +29,6 @@ _STL_DISABLE_CLANG_WARNINGS #undef msvc #undef lifetimebound -#if _VECTORIZED_FOR_X64_X86 - extern "C" { // The "noalias" attribute tells the compiler optimizer that pointers going into these hand-vectorized algorithms // won't be stored beyond the lifetime of the function, and that the function will only reference arrays denoted by @@ -151,6 +149,7 @@ void* __stdcall __std_unique_copy_2(const void* _First, const void* _Last, void* void* __stdcall __std_unique_copy_4(const void* _First, const void* _Last, void* _Dest) noexcept; void* __stdcall __std_unique_copy_8(const void* _First, const void* _Last, void* _Dest) noexcept; #endif // ^^^ _VECTORIZED_UNIQUE_COPY ^^^ + } // extern "C" _STD_BEGIN @@ -432,6 +431,8 @@ _Ty* _Unique_copy_vectorized(const _Ty* const _First, const _Ty* const _Last, _T } #endif // ^^^ _VECTORIZED_UNIQUE_COPY ^^^ +#if _VECTORIZED_FOR_X64_X86 + // Can we activate the vector algorithms for replace? template constexpr bool _Vector_alg_in_replace_is_safe = _Vector_alg_in_find_is_safe<_Iter, _Ty1> // can search for the value @@ -473,10 +474,9 @@ constexpr bool _Vector_alg_includes_iterators_safe = && !_Iterator_is_volatile<_Iter1> && !_Iterator_is_volatile<_Iter2> // Iterators must not be volatile. && is_same_v<_Elem, _Iter_value_t<_Iter2>> // Iterators have the same value type. && disjunction_v, is_pointer<_Elem>>; // Integral or pointer type. -_STD_END + #endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ -_STD_BEGIN #define _REQUIRE_CPP17_MUTABLE_RANDOM_ACCESS_ITERATOR(_Iter) \ static_assert(_Is_cpp17_random_iter_v<_Iter>, \ "This algorithm requires that mutable iterators be Cpp17RandomAccessIterators or stronger.") diff --git a/stl/inc/bitset b/stl/inc/bitset index c7383f6c9c4..13ed3252884 100644 --- a/stl/inc/bitset +++ b/stl/inc/bitset @@ -22,12 +22,11 @@ _STL_DISABLE_CLANG_WARNINGS #define _STD_BITSET_TO_STREAM_STACK_RESERVATION 128 #endif // !defined(_STD_BITSET_TO_STREAM_STACK_RESERVATION) -#if _VECTORIZED_FOR_X64_X86 +extern "C" { // These bitset functions sometimes assume that the bit array has zero padding to a multiple of 2 or 4 bytes. // The assumptions hold true even for the vNext suggestion to use smaller types for small bitsets (see GH-1498) // due to vectorization thresholds. -extern "C" { #if _VECTORIZED_BITSET_TO_STRING __declspec(noalias) void __stdcall __std_bitset_to_string_1( char* _Dest, const void* _Src, size_t _Size_bits, char _Elem0, char _Elem1) noexcept; @@ -43,7 +42,6 @@ __declspec(noalias) bool __stdcall __std_bitset_from_string_2(void* _Dest, const #endif // ^^^ _VECTORIZED_BITSET_FROM_STRING ^^^ } // extern "C" -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _STD_BEGIN template _STD_BITSET_TO_STREAM_STACK_RESERVATION)> diff --git a/stl/inc/xutility b/stl/inc/xutility index fc418aff51e..d144f1df2f7 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -103,7 +103,6 @@ _STL_DISABLE_CLANG_WARNINGS #endif // ^^^ !defined(__clang__) || __clang_major__ < 19 ^^^ #endif // ^^^ !defined(_USE_BUILTIN_IS_TRIVIALLY_EQUALITY_COMPARABLE) ^^^ -#if _VECTORIZED_FOR_X64_X86 extern "C" { // The "noalias" attribute tells the compiler optimizer that pointers going into these hand-vectorized algorithms // won't be stored beyond the lifetime of the function, and that the function will only reference arrays denoted by @@ -231,7 +230,6 @@ __declspec(noalias) size_t __stdcall __std_mismatch_8(const void* _First1, const #endif // ^^^ _VECTORIZED_MISMATCH ^^^ } // extern "C" -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ _STD_BEGIN From a8b60158b10363e86a69030ed01323b169ac44c7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 12:20:33 -0700 Subject: [PATCH 31/33] Guard the helper traits to finish removing _VECTORIZED_FOR_X64_X86. --- stl/inc/algorithm | 14 ++++++++++---- stl/inc/xutility | 11 +++++------ .../test.compile.pass.cpp | 5 +++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 296bdef91f0..e1af3d2818a 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -431,8 +431,7 @@ _Ty* _Unique_copy_vectorized(const _Ty* const _First, const _Ty* const _Last, _T } #endif // ^^^ _VECTORIZED_UNIQUE_COPY ^^^ -#if _VECTORIZED_FOR_X64_X86 - +#if _VECTORIZED_REPLACE // Can we activate the vector algorithms for replace? template constexpr bool _Vector_alg_in_replace_is_safe = _Vector_alg_in_find_is_safe<_Iter, _Ty1> // can search for the value @@ -443,7 +442,9 @@ template constexpr bool _Vector_alg_in_ranges_replace_is_safe = _Vector_alg_in_replace_is_safe<_Iter, _Ty1> // can search and replace && _Vector_alg_in_find_is_safe_elem<_Ty2, _Iter_value_t<_Iter>>; // replacement fits +#endif // ^^^ _VECTORIZED_REPLACE ^^^ +#if _VECTORIZED_SEARCH_N // Can we activate the vector algorithms for search_n? template constexpr bool _Vector_alg_in_search_n_is_safe = _Vector_alg_in_find_is_safe<_Iter, _Ty> @@ -452,11 +453,15 @@ constexpr bool _Vector_alg_in_search_n_is_safe = _Vector_alg_in_find_is_safe<_It ranges::equal_to, #endif equal_to<>>; +#endif // ^^^ _VECTORIZED_SEARCH_N ^^^ +#if _VECTORIZED_UNIQUE || _VECTORIZED_UNIQUE_COPY // Can we activate the vector algorithms for unique and unique_copy? template constexpr bool _Vector_alg_in_unique_is_safe = _Vector_alg_in_search_is_safe<_Iter, _Iter, _Pr>; +#endif // ^^^ _VECTORIZED_UNIQUE || _VECTORIZED_UNIQUE_COPY ^^^ +#if _VECTORIZED_REMOVE_COPY || _VECTORIZED_UNIQUE_COPY // Can we use this output iterator for remove_copy and unique_copy? template constexpr bool _Output_iterator_for_vector_alg_is_safe() { @@ -466,7 +471,9 @@ constexpr bool _Output_iterator_for_vector_alg_is_safe() { return false; } } +#endif // ^^^ _VECTORIZED_REMOVE_COPY || _VECTORIZED_UNIQUE_COPY ^^^ +#if _VECTORIZED_INCLUDES // Can we activate the vector algorithms for includes? template > constexpr bool _Vector_alg_includes_iterators_safe = @@ -474,8 +481,7 @@ constexpr bool _Vector_alg_includes_iterators_safe = && !_Iterator_is_volatile<_Iter1> && !_Iterator_is_volatile<_Iter2> // Iterators must not be volatile. && is_same_v<_Elem, _Iter_value_t<_Iter2>> // Iterators have the same value type. && disjunction_v, is_pointer<_Elem>>; // Integral or pointer type. - -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_INCLUDES ^^^ #define _REQUIRE_CPP17_MUTABLE_RANDOM_ACCESS_ITERATOR(_Iter) \ static_assert(_Is_cpp17_random_iter_v<_Iter>, \ diff --git a/stl/inc/xutility b/stl/inc/xutility index d144f1df2f7..a3ef522dcf6 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -335,14 +335,12 @@ _Ty* _Adjacent_find_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { } #endif // ^^^ _VECTORIZED_ADJACENT_FIND ^^^ -#if _VECTORIZED_FOR_X64_X86 - +#if _VECTORIZED_FIND_FIRST_OF || _VECTORIZED_FIND_LAST_OF // find_first_of vectorization is likely to be a win after this size (in elements) // (Used with _Find_first_of_vectorized, _Find_first_of_pos_vectorized, _Find_first_not_of_pos_vectorized, // _Find_last_of_pos_vectorized, and _Find_last_not_of_pos_vectorized.) _INLINE_VAR constexpr ptrdiff_t _Threshold_find_first_of = 16; - -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _VECTORIZED_FIND_FIRST_OF || _VECTORIZED_FIND_LAST_OF ^^^ #if _VECTORIZED_SEARCH template @@ -5674,7 +5672,8 @@ template constexpr bool _Equal_memcmp_is_safe = _Equal_memcmp_is_safe_helper, remove_const_t<_Iter2>, remove_const_t<_Pr>>; -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_SEARCH || _VECTORIZED_ADJACENT_FIND || _VECTORIZED_FIND_END || _VECTORIZED_FIND_FIRST_OF \ + || _VECTORIZED_UNIQUE || _VECTORIZED_UNIQUE_COPY template constexpr bool _Is_vector_element_size = _Size == 1 || _Size == 2 || _Size == 4 || _Size == 8; @@ -5683,7 +5682,7 @@ constexpr bool _Is_vector_element_size = _Size == 1 || _Size == 2 || _Size == 4 template constexpr bool _Vector_alg_in_search_is_safe = _Equal_memcmp_is_safe<_It1, _It2, _Pr> && _Is_vector_element_size)>; -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _Vector_alg_in_search_is_safe is available ^^^ template _NODISCARD int _Memcmp_count(_CtgIt1 _First1, _CtgIt2 _First2, const size_t _Count) { diff --git a/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp b/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp index 0147d030574..52bcd932c13 100644 --- a/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp +++ b/tests/std/tests/GH_000431_equal_memcmp_is_safe/test.compile.pass.cpp @@ -529,10 +529,11 @@ STATIC_ASSERT(test_equal_memcmp_is_safe_for_types> == magic); STATIC_ASSERT(_Equal_memcmp_is_safe> == magic); -#if _VECTORIZED_FOR_X64_X86 +#if _VECTORIZED_SEARCH || _VECTORIZED_ADJACENT_FIND || _VECTORIZED_FIND_END || _VECTORIZED_FIND_FIRST_OF \ + || _VECTORIZED_UNIQUE || _VECTORIZED_UNIQUE_COPY STATIC_ASSERT(_Vector_alg_in_search_is_safe> == magic); STATIC_ASSERT(!_Vector_alg_in_search_is_safe>); -#endif // ^^^ _VECTORIZED_FOR_X64_X86 ^^^ +#endif // ^^^ _Vector_alg_in_search_is_safe is available ^^^ #endif // _HAS_CXX20 // Test _Std_char_traits_eq From 391b33e9c8490fead85db26b1bc7a87c664ebf89 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 24 Oct 2025 12:51:46 -0700 Subject: [PATCH 32/33] Define the algorithm macros. --- stl/inc/xutility | 48 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index a3ef522dcf6..192a43d6093 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -55,15 +55,10 @@ _STL_DISABLE_CLANG_WARNINGS // _USE_STD_VECTOR_ALGORITHMS is our documented control macro: // https://learn.microsoft.com/en-us/cpp/standard-library/vectorized-stl-algorithms?view=msvc-170 -// In the STL's implementation, we inspect the following architecture-specific detection macros, -// because various algorithms are vectorized for various architectures: -#if defined(_VECTORIZED_FOR_X64_X86) -#error _VECTORIZED_FOR_X64_X86 is not a control macro; define _USE_STD_VECTOR_ALGORITHMS instead. -#elif defined(_VECTORIZED_FOR_X64_X86_ARM64) -#error _VECTORIZED_FOR_X64_X86_ARM64 is not a control macro; define _USE_STD_VECTOR_ALGORITHMS instead. -#elif defined(_VECTORIZED_FOR_X64_X86_ARM64_ARM64EC) -#error _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC is not a control macro; define _USE_STD_VECTOR_ALGORITHMS instead. -#elif !_USE_STD_VECTOR_ALGORITHMS +// In the STL's implementation, we inspect the following detection macros, +// because various algorithms are vectorized for various architectures. + +#if !_USE_STD_VECTOR_ALGORITHMS #define _VECTORIZED_FOR_X64_X86 0 #define _VECTORIZED_FOR_X64_X86_ARM64 0 #define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 0 @@ -71,18 +66,45 @@ _STL_DISABLE_CLANG_WARNINGS #define _VECTORIZED_FOR_X64_X86 0 #define _VECTORIZED_FOR_X64_X86_ARM64 0 #define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 1 -#elif defined(_M_X64) || defined(_M_IX86) -#define _VECTORIZED_FOR_X64_X86 1 -#define _VECTORIZED_FOR_X64_X86_ARM64 1 -#define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 1 #elif defined(_M_ARM64) #define _VECTORIZED_FOR_X64_X86 0 #define _VECTORIZED_FOR_X64_X86_ARM64 1 #define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 1 +#elif defined(_M_X64) || defined(_M_IX86) +#define _VECTORIZED_FOR_X64_X86 1 +#define _VECTORIZED_FOR_X64_X86_ARM64 1 +#define _VECTORIZED_FOR_X64_X86_ARM64_ARM64EC 1 #else // ^^^ known architecture / unknown architecture vvv #error Unknown architecture. #endif // ^^^ unknown architecture ^^^ +#define _VECTORIZED_ADJACENT_FIND _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_BITSET_FROM_STRING _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_BITSET_TO_STRING _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_COUNT _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_FIND _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_FIND_END _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_FIND_FIRST_OF _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_FIND_LAST _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_FIND_LAST_NOT_OF _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_FIND_LAST_OF _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_INCLUDES _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_IS_SORTED_UNTIL _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_MINMAX _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_MINMAX_ELEMENT _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_MISMATCH _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_REMOVE _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_REMOVE_COPY _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_REPLACE _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_REVERSE _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_REVERSE_COPY _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_ROTATE _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_SEARCH _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_SEARCH_N _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_SWAP_RANGES _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_UNIQUE _VECTORIZED_FOR_X64_X86 +#define _VECTORIZED_UNIQUE_COPY _VECTORIZED_FOR_X64_X86 + #ifndef _USE_STD_VECTOR_FLOATING_ALGORITHMS #if _USE_STD_VECTOR_ALGORITHMS && !defined(_M_FP_EXCEPT) #define _USE_STD_VECTOR_FLOATING_ALGORITHMS 1 From c546a4818c91cee7d03fb66a6fb97e69dc8d16d3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 25 Oct 2025 08:18:28 -0700 Subject: [PATCH 33/33] Unify _VECTORIZED_FIND_LAST_NOT_OF into _VECTORIZED_FIND_LAST. _VECTORIZED_FIND_LAST_NOT_OF guarded __std_find_last_not_ch_pos_1 which calls _Finding::_Find_last_pos_impl which calls _Finding::_Find_last_impl _VECTORIZED_FIND_LAST guards __std_find_last_trivial_1 which calls _Finding::_Find_last_impl --- stl/inc/__msvc_string_view.hpp | 12 ++++++------ stl/inc/xutility | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index bc043f15af5..bd8105e0815 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -53,7 +53,7 @@ const void* __stdcall __std_find_not_ch_4(const void* _First, const void* _Last, const void* __stdcall __std_find_not_ch_8(const void* _First, const void* _Last, uint64_t _Val) noexcept; #endif // ^^^ _VECTORIZED_FIND ^^^ -#if _VECTORIZED_FIND_LAST_NOT_OF +#if _VECTORIZED_FIND_LAST __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_1( const void* _First, const void* _Last, uint8_t _Val) noexcept; __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_2( @@ -62,7 +62,7 @@ __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_4( const void* _First, const void* _Last, uint32_t _Val) noexcept; __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_8( const void* _First, const void* _Last, uint64_t _Val) noexcept; -#endif // ^^^ _VECTORIZED_FIND_LAST_NOT_OF ^^^ +#endif // ^^^ _VECTORIZED_FIND_LAST ^^^ #if _VECTORIZED_FIND_FIRST_OF __declspec(noalias) size_t __stdcall __std_find_first_not_of_trivial_pos_1( @@ -133,7 +133,7 @@ const _Ty* _Find_not_ch_vectorized(const _Ty* const _First, const _Ty* const _La } #endif // ^^^ _VECTORIZED_FIND ^^^ -#if _VECTORIZED_FIND_LAST_NOT_OF +#if _VECTORIZED_FIND_LAST template size_t _Find_last_not_ch_pos_vectorized(const _Ty* const _First, const _Ty* const _Last, const _Ty _Ch) noexcept { if constexpr (sizeof(_Ty) == 1) { @@ -148,7 +148,7 @@ size_t _Find_last_not_ch_pos_vectorized(const _Ty* const _First, const _Ty* cons _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size } } -#endif // ^^^ _VECTORIZED_FIND_LAST_NOT_OF ^^^ +#endif // ^^^ _VECTORIZED_FIND_LAST ^^^ #if _VECTORIZED_FIND_FIRST_OF template @@ -1184,13 +1184,13 @@ constexpr size_t _Traits_rfind_not_ch(_In_reads_(_Hay_size) const _Traits_ptr_t< const size_t _Actual_start_at = (_STD min) (_Start_at, _Hay_size - 1); -#if _VECTORIZED_FIND_LAST_NOT_OF +#if _VECTORIZED_FIND_LAST if constexpr (_Is_implementation_handled_char_traits<_Traits>) { if (!_STD _Is_constant_evaluated()) { return _STD _Find_last_not_ch_pos_vectorized(_Haystack, _Haystack + _Actual_start_at + 1, _Ch); } } -#endif // ^^^ _VECTORIZED_FIND_LAST_NOT_OF ^^^ +#endif // ^^^ _VECTORIZED_FIND_LAST ^^^ for (auto _Match_try = _Haystack + _Actual_start_at;; --_Match_try) { if (!_Traits::eq(*_Match_try, _Ch)) { diff --git a/stl/inc/xutility b/stl/inc/xutility index 192a43d6093..da3e663bdec 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -86,7 +86,6 @@ _STL_DISABLE_CLANG_WARNINGS #define _VECTORIZED_FIND_END _VECTORIZED_FOR_X64_X86 #define _VECTORIZED_FIND_FIRST_OF _VECTORIZED_FOR_X64_X86 #define _VECTORIZED_FIND_LAST _VECTORIZED_FOR_X64_X86 -#define _VECTORIZED_FIND_LAST_NOT_OF _VECTORIZED_FOR_X64_X86 #define _VECTORIZED_FIND_LAST_OF _VECTORIZED_FOR_X64_X86 #define _VECTORIZED_INCLUDES _VECTORIZED_FOR_X64_X86 #define _VECTORIZED_IS_SORTED_UNTIL _VECTORIZED_FOR_X64_X86