From fbea7a282bc2eaee6df3f238d67a2f16da86b36b Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 15 Aug 2024 22:15:20 +0300 Subject: [PATCH 1/8] Use wmemchr --- stl/inc/xutility | 47 ++++++++++++++++++++++++++--------- stl/src/vector_algorithms.cpp | 4 +-- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 110178e1416..0b062b8adda 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -6009,17 +6009,31 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c return _First + (_Result - _First_ptr); } #else // ^^^ _USE_STD_VECTOR_ALGORITHMS / !_USE_STD_VECTOR_ALGORITHMS vvv - if constexpr (sizeof(_Iter_value_t<_InIt>) == 1) { + if constexpr (sizeof(_Iter_value_t<_InIt>) == 1 || sizeof(_Iter_value_t<_InIt>) == 2) { const auto _First_ptr = _STD _To_address(_First); - const auto _Result = static_cast>*>( - _CSTD memchr(_First_ptr, static_cast(_Val), static_cast(_Last - _First))); + const auto _Size = static_cast(_Last - _First); + + using _Result_t = remove_reference_t<_Iter_ref_t<_InIt>>*; + _Result_t _Result; + + if constexpr (sizeof(_Iter_value_t<_InIt>) == 1) { + _Result = static_cast<_Result_t>(_CSTD memchr(_First_ptr, static_cast(_Val), _Size)); + } else { + _STL_INTERNAL_STATIC_ASSERT(sizeof(_Iter_value_t<_InIt>) == 2); + + using _Src_type = + conditional_t>>, const wchar_t*, wchar_t*>; + + _Result = reinterpret_cast<_Result_t>( + _CSTD wmemchr(reinterpret_cast<_Src_type>(_First_ptr), static_cast(_Val), _Size)); + } + if constexpr (is_pointer_v<_InIt>) { return _Result ? _Result : _Last; } else { return _Result ? _First + (_Result - _First_ptr) : _Last; } } - // TRANSITION, DevCom-1614562: not trying wmemchr #endif // ^^^ !_USE_STD_VECTOR_ALGORITHMS ^^^ } } @@ -6062,14 +6076,12 @@ namespace ranges { template _Se, class _Ty, class _Pj = identity> requires indirect_binary_predicate, const _Ty*> _NODISCARD constexpr _It _Find_unchecked(_It _First, const _Se _Last, const _Ty& _Val, _Pj _Proj = {}) { - // TRANSITION, DevCom-1614562: not trying wmemchr - // Only single-byte elements are suitable for unsized optimization - constexpr bool _Single_byte_elements = sizeof(_Iter_value_t<_It>) == 1; - constexpr bool _Is_sized = sized_sentinel_for<_Se, _It>; + constexpr bool _1_or_2_bytes_elements = sizeof(_Iter_value_t<_It>) <= 2; + constexpr bool _Is_sized = sized_sentinel_for<_Se, _It>; if constexpr (_Vector_alg_in_find_is_safe<_It, _Ty> - && (_Single_byte_elements ? _Is_sized || same_as<_Se, unreachable_sentinel_t> - : _Is_sized && _USE_STD_VECTOR_ALGORITHMS) + && (_1_or_2_bytes_elements ? _Is_sized || same_as<_Se, unreachable_sentinel_t> + : _Is_sized && _USE_STD_VECTOR_ALGORITHMS) && same_as<_Pj, identity>) { if (!_STD is_constant_evaluated()) { if (!_STD _Could_compare_equal_to_value_type<_It>(_Val)) { @@ -6093,7 +6105,7 @@ namespace ranges { } else #endif // ^^^ _USE_STD_VECTOR_ALGORITHMS ^^^ { - _STL_INTERNAL_STATIC_ASSERT(_Single_byte_elements); + _STL_INTERNAL_STATIC_ASSERT(_1_or_2_bytes_elements); size_t _Count; if constexpr (_Is_sized) { _Count = static_cast(_Last - _First); @@ -6101,7 +6113,18 @@ namespace ranges { _Count = SIZE_MAX; } - _Result = static_cast<_Ptr_t>(_CSTD memchr(_First_ptr, static_cast(_Val), _Count)); + if constexpr (sizeof(_Iter_value_t<_It>) == 1) { + _Result = + static_cast<_Ptr_t>(_CSTD memchr(_First_ptr, static_cast(_Val), _Count)); + } else { + _STL_INTERNAL_STATIC_ASSERT(sizeof(_Iter_value_t<_It>) == 2); + + using _Src_type = + conditional_t>>, const wchar_t*, wchar_t*>; + + _Result = reinterpret_cast<_Ptr_t>( + _CSTD wmemchr(reinterpret_cast<_Src_type>(_First_ptr), static_cast(_Val), _Count)); + } if constexpr (_Is_sized) { if (_Result == nullptr) { diff --git a/stl/src/vector_algorithms.cpp b/stl/src/vector_algorithms.cpp index 44cca169203..45015d20cd6 100644 --- a/stl/src/vector_algorithms.cpp +++ b/stl/src/vector_algorithms.cpp @@ -9,6 +9,7 @@ #include <__msvc_minmax.hpp> #include #include +#include #include #ifndef _M_ARM64EC @@ -3271,8 +3272,7 @@ const void* __stdcall __std_find_trivial_unsized_1(const void* const _First, con // TRANSITION, ABI: preserved for binary compatibility const void* __stdcall __std_find_trivial_unsized_2(const void* const _First, const uint16_t _Val) noexcept { - // TRANSITION, DevCom-1614562: not trying wmemchr - return __std_find_trivial_unsized_impl(_First, _Val); + return wmemchr(static_cast(_First), static_cast(_Val), SIZE_MAX); } // TRANSITION, ABI: preserved for binary compatibility From b6ffa6e519d74330a832da2c81151a9b2102a711 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 15 Aug 2024 22:39:27 +0300 Subject: [PATCH 2/8] missing include --- stl/inc/xutility | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/xutility b/stl/inc/xutility index 0b062b8adda..7d9e72fd206 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -12,6 +12,7 @@ #include #include #include +#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) From 6a451f9e00ac3499aba7127b324fb283d348ce88 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 17 Aug 2024 13:34:49 +0300 Subject: [PATCH 3/8] Simplify 1 or 2 check --- stl/inc/xutility | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 7d9e72fd206..9793d1ab90c 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -6010,7 +6010,7 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c return _First + (_Result - _First_ptr); } #else // ^^^ _USE_STD_VECTOR_ALGORITHMS / !_USE_STD_VECTOR_ALGORITHMS vvv - if constexpr (sizeof(_Iter_value_t<_InIt>) == 1 || sizeof(_Iter_value_t<_InIt>) == 2) { + if constexpr (sizeof(_Iter_value_t<_InIt>) <= 2) { const auto _First_ptr = _STD _To_address(_First); const auto _Size = static_cast(_Last - _First); From 5ddb5234b8800ea4724bc82cb6230987ed90ad01 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sun, 18 Aug 2024 11:51:26 +0300 Subject: [PATCH 4/8] Count uniformly --- stl/inc/xutility | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 9793d1ab90c..3b0815ae78d 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -6012,21 +6012,21 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c #else // ^^^ _USE_STD_VECTOR_ALGORITHMS / !_USE_STD_VECTOR_ALGORITHMS vvv if constexpr (sizeof(_Iter_value_t<_InIt>) <= 2) { const auto _First_ptr = _STD _To_address(_First); - const auto _Size = static_cast(_Last - _First); + const auto _Count = static_cast(_Last - _First); - using _Result_t = remove_reference_t<_Iter_ref_t<_InIt>>*; - _Result_t _Result; + using _Ptr_t = remove_reference_t<_Iter_ref_t<_InIt>>*; + _Ptr_t _Result; if constexpr (sizeof(_Iter_value_t<_InIt>) == 1) { - _Result = static_cast<_Result_t>(_CSTD memchr(_First_ptr, static_cast(_Val), _Size)); + _Result = static_cast<_Ptr_t>(_CSTD memchr(_First_ptr, static_cast(_Val), _Count)); } else { _STL_INTERNAL_STATIC_ASSERT(sizeof(_Iter_value_t<_InIt>) == 2); using _Src_type = conditional_t>>, const wchar_t*, wchar_t*>; - _Result = reinterpret_cast<_Result_t>( - _CSTD wmemchr(reinterpret_cast<_Src_type>(_First_ptr), static_cast(_Val), _Size)); + _Result = reinterpret_cast<_Ptr_t>( + _CSTD wmemchr(reinterpret_cast<_Src_type>(_First_ptr), static_cast(_Val), _Count)); } if constexpr (is_pointer_v<_InIt>) { From 7863bda659b9a3d953b2dd25cb7819ef77a3bcf5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 23 Aug 2024 14:48:08 -0700 Subject: [PATCH 5/8] `` => `` --- stl/inc/xutility | 2 +- stl/src/vector_algorithms.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 3b0815ae78d..90b1be31564 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -12,7 +12,7 @@ #include #include #include -#include +#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) diff --git a/stl/src/vector_algorithms.cpp b/stl/src/vector_algorithms.cpp index 45015d20cd6..63456d6f1c6 100644 --- a/stl/src/vector_algorithms.cpp +++ b/stl/src/vector_algorithms.cpp @@ -9,7 +9,7 @@ #include <__msvc_minmax.hpp> #include #include -#include +#include #include #ifndef _M_ARM64EC From 446767b63ebe1a4b2759bf7ca11efc7f921cab22 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 23 Aug 2024 14:54:44 -0700 Subject: [PATCH 6/8] `_1_or_2_bytes_elements` => `_Elements_are_1_or_2_bytes` --- stl/inc/xutility | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 90b1be31564..b17d7a6dfac 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -6077,12 +6077,12 @@ namespace ranges { template _Se, class _Ty, class _Pj = identity> requires indirect_binary_predicate, const _Ty*> _NODISCARD constexpr _It _Find_unchecked(_It _First, const _Se _Last, const _Ty& _Val, _Pj _Proj = {}) { - constexpr bool _1_or_2_bytes_elements = sizeof(_Iter_value_t<_It>) <= 2; - constexpr bool _Is_sized = sized_sentinel_for<_Se, _It>; + constexpr bool _Elements_are_1_or_2_bytes = sizeof(_Iter_value_t<_It>) <= 2; + constexpr bool _Is_sized = sized_sentinel_for<_Se, _It>; if constexpr (_Vector_alg_in_find_is_safe<_It, _Ty> - && (_1_or_2_bytes_elements ? _Is_sized || same_as<_Se, unreachable_sentinel_t> - : _Is_sized && _USE_STD_VECTOR_ALGORITHMS) + && (_Elements_are_1_or_2_bytes ? _Is_sized || same_as<_Se, unreachable_sentinel_t> + : _Is_sized && _USE_STD_VECTOR_ALGORITHMS) && same_as<_Pj, identity>) { if (!_STD is_constant_evaluated()) { if (!_STD _Could_compare_equal_to_value_type<_It>(_Val)) { @@ -6106,7 +6106,7 @@ namespace ranges { } else #endif // ^^^ _USE_STD_VECTOR_ALGORITHMS ^^^ { - _STL_INTERNAL_STATIC_ASSERT(_1_or_2_bytes_elements); + _STL_INTERNAL_STATIC_ASSERT(_Elements_are_1_or_2_bytes); size_t _Count; if constexpr (_Is_sized) { _Count = static_cast(_Last - _First); From d35f89b433626b5816d2476f1556d0cbbc084bd2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 23 Aug 2024 14:57:28 -0700 Subject: [PATCH 7/8] Update comment. --- stl/inc/xutility | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index b17d7a6dfac..87265aa9294 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -6100,7 +6100,7 @@ namespace ranges { _Ptr_t _Result; #if _USE_STD_VECTOR_ALGORITHMS if constexpr (_Is_sized) { - // When _Is_sized && _Single_byte_elements, prefer this over memchr() for performance + // When _Is_sized && _Elements_are_1_or_2_bytes, prefer this over memchr()/wmemchr() for performance const auto _Last_ptr = _First_ptr + (_Last - _First); _Result = _STD _Find_vectorized(_First_ptr, _Last_ptr, _Val); } else From a9fa4e7f176e62a9a99ea5ea530dfe9228240773 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 23 Aug 2024 15:17:48 -0700 Subject: [PATCH 8/8] Simplify `const wchar_t*` / `wchar_t*` casting. --- stl/inc/xutility | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 87265aa9294..8182ef7b846 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -6021,12 +6021,8 @@ _NODISCARD _CONSTEXPR20 _InIt _Find_unchecked(_InIt _First, const _InIt _Last, c _Result = static_cast<_Ptr_t>(_CSTD memchr(_First_ptr, static_cast(_Val), _Count)); } else { _STL_INTERNAL_STATIC_ASSERT(sizeof(_Iter_value_t<_InIt>) == 2); - - using _Src_type = - conditional_t>>, const wchar_t*, wchar_t*>; - - _Result = reinterpret_cast<_Ptr_t>( - _CSTD wmemchr(reinterpret_cast<_Src_type>(_First_ptr), static_cast(_Val), _Count)); + _Result = reinterpret_cast<_Ptr_t>(const_cast(_CSTD wmemchr( + reinterpret_cast(_First_ptr), static_cast(_Val), _Count))); } if constexpr (is_pointer_v<_InIt>) { @@ -6119,12 +6115,8 @@ namespace ranges { static_cast<_Ptr_t>(_CSTD memchr(_First_ptr, static_cast(_Val), _Count)); } else { _STL_INTERNAL_STATIC_ASSERT(sizeof(_Iter_value_t<_It>) == 2); - - using _Src_type = - conditional_t>>, const wchar_t*, wchar_t*>; - - _Result = reinterpret_cast<_Ptr_t>( - _CSTD wmemchr(reinterpret_cast<_Src_type>(_First_ptr), static_cast(_Val), _Count)); + _Result = reinterpret_cast<_Ptr_t>(const_cast(_CSTD wmemchr( + reinterpret_cast(_First_ptr), static_cast(_Val), _Count))); } if constexpr (_Is_sized) {