From d1f993dded3e29abad2ab8ebbf0305eb2221ee5f Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 12 Oct 2024 19:33:46 +0300 Subject: [PATCH 1/3] Auto-vectorize minmax --- stl/inc/__msvc_minmax.hpp | 55 ---------- stl/inc/algorithm | 196 +++++++++++++--------------------- stl/inc/xutility | 158 +++++++++------------------ stl/src/vector_algorithms.cpp | 55 ++++++++++ 4 files changed, 182 insertions(+), 282 deletions(-) diff --git a/stl/inc/__msvc_minmax.hpp b/stl/inc/__msvc_minmax.hpp index 7dce57945c2..a739ec55ba0 100644 --- a/stl/inc/__msvc_minmax.hpp +++ b/stl/inc/__msvc_minmax.hpp @@ -21,61 +21,6 @@ struct _Min_max_element_t { const void* _Min; const void* _Max; }; - -struct _Min_max_1i { - int8_t _Min; - int8_t _Max; -}; - -struct _Min_max_1u { - uint8_t _Min; - uint8_t _Max; -}; - -struct _Min_max_2i { - int16_t _Min; - int16_t _Max; -}; - -struct _Min_max_2u { - uint16_t _Min; - uint16_t _Max; -}; - -struct _Min_max_4i { - int32_t _Min; - int32_t _Max; -}; - -struct _Min_max_4u { - uint32_t _Min; - uint32_t _Max; -}; - -struct _Min_max_8i { - int64_t _Min; - int64_t _Max; -}; - -struct _Min_max_8u { - uint64_t _Min; - uint64_t _Max; -}; - -struct _Min_max_f { - float _Min; - float _Max; -}; - -struct _Min_max_d { - double _Min; - double _Max; -}; - -struct _Min_max_p { - void* _Min; - void* _Max; -}; } // extern "C" #pragma pop_macro("new") diff --git a/stl/inc/algorithm b/stl/inc/algorithm index c16afa7d042..36502b7cd58 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -59,17 +59,6 @@ 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; -__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; -__declspec(noalias) _Min_max_2u __stdcall __std_minmax_2u(const void* _First, const void* _Last) noexcept; -__declspec(noalias) _Min_max_4i __stdcall __std_minmax_4i(const void* _First, const void* _Last) noexcept; -__declspec(noalias) _Min_max_4u __stdcall __std_minmax_4u(const void* _First, const void* _Last) noexcept; -__declspec(noalias) _Min_max_8i __stdcall __std_minmax_8i(const void* _First, const void* _Last) noexcept; -__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; - // TRANSITION, DevCom-10610477 __declspec(noalias) void __stdcall __std_replace_4( void* _First, void* _Last, uint32_t _Old_val, uint32_t _New_val) noexcept; @@ -118,50 +107,6 @@ 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))}; } -template -auto _Minmax_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { - constexpr bool _Signed = is_signed_v<_Ty>; - - if constexpr (is_pointer_v<_Ty>) { -#ifdef _WIN64 - const auto _Result = ::__std_minmax_8u(_First, _Last); -#else - const auto _Result = ::__std_minmax_4u(_First, _Last); -#endif - return _Min_max_p{reinterpret_cast(_Result._Min), reinterpret_cast(_Result._Max)}; - } else if constexpr (is_same_v, float>) { - return ::__std_minmax_f(_First, _Last); - } else if constexpr (_Is_any_of_v, double, long double>) { - return ::__std_minmax_d(_First, _Last); - } else if constexpr (sizeof(_Ty) == 1) { - if constexpr (_Signed) { - return ::__std_minmax_1i(_First, _Last); - } else { - return ::__std_minmax_1u(_First, _Last); - } - } else if constexpr (sizeof(_Ty) == 2) { - if constexpr (_Signed) { - return ::__std_minmax_2i(_First, _Last); - } else { - return ::__std_minmax_2u(_First, _Last); - } - } else if constexpr (sizeof(_Ty) == 4) { - if constexpr (_Signed) { - return ::__std_minmax_4i(_First, _Last); - } else { - return ::__std_minmax_4u(_First, _Last); - } - } else if constexpr (sizeof(_Ty) == 8) { - if constexpr (_Signed) { - return ::__std_minmax_8i(_First, _Last); - } else { - return ::__std_minmax_8u(_First, _Last); - } - } else { - _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size - } -} - template _Ty* _Find_last_vectorized(_Ty* const _First, _Ty* const _Last, const _TVal _Val) noexcept { if constexpr (is_pointer_v<_TVal> || is_null_pointer_v<_TVal>) { @@ -10184,22 +10129,38 @@ _NODISCARD constexpr pair minmax( return {_Left, _Right}; } +template +constexpr _Rx _Minmax(const _Ty* _First, const _Ty* const _Last) { + // Vectorization-friendly minmax + // Performs more comparisons than standard requires, but it it not observable + _Ty _Min_val = *_First; + _Ty _Max_val = *_First; + + for (++_First; _First != _Last; ++_First) { + if (_Min_val < *_First) { + _Min_val = *_First; + } + + if (_Max_val <= *_First) { + _Max_val = *_First; + } + } + + return _Rx{_Min_val, _Max_val}; +} + _EXPORT_STD template _NODISCARD constexpr pair<_Ty, _Ty> minmax(initializer_list<_Ty> _Ilist, _Pr _Pred) { // 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 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)}; - } + return _STD _Minmax>(_Ilist.begin(), _Ilist.end()); + } else { + pair _Res = + _STD _Minmax_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); + return pair<_Ty, _Ty>(*_Res.first, *_Res.second); } -#endif // _USE_STD_VECTOR_ALGORITHMS - pair _Res = - _STD _Minmax_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); - return pair<_Ty, _Ty>(*_Res.first, *_Res.second); } _EXPORT_STD template @@ -10247,22 +10208,20 @@ 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 constexpr (is_same_v<_Pj, identity> && _Is_min_max_value_optimization_safe) { + return _STD _Minmax>(_First, _Last); + } else { #if _USE_STD_VECTOR_ALGORITHMS - if constexpr (is_same_v<_Pj, identity>) { - 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 constexpr (is_same_v<_Pj, identity> && _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 // _USE_STD_VECTOR_ALGORITHMS - return _Minmax_fwd_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); + return _Minmax_fwd_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); + } } template ; + if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for + && _Is_min_max_value_optimization_safe) { + const auto _First_ptr = _STD to_address(_UFirst); + const auto _Last_ptr = _First_ptr + (_ULast - _UFirst); + return _STD _Minmax>>(_First_ptr, _Last_ptr); + } else { #if _USE_STD_VECTOR_ALGORITHMS - if constexpr (is_same_v<_Pj, identity> && sized_sentinel_for) { - if constexpr (_Is_min_max_value_optimization_safe) { - if (!_STD is_constant_evaluated()) { - const auto _First_ptr = _STD to_address(_UFirst); - const auto _Last_ptr = _First_ptr + (_ULast - _UFirst); - 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 constexpr (is_same_v<_Pj, identity> && sized_sentinel_for + && _Is_min_max_optimization_safe) { if (!_STD is_constant_evaluated()) { const auto _First_ptr = _STD to_address(_UFirst); const auto _Last_ptr = _First_ptr + (_ULast - _UFirst); @@ -10292,52 +10250,52 @@ namespace ranges { return {*static_cast(_Result.first), *static_cast(_Result.second)}; } } - } #endif // _USE_STD_VECTOR_ALGORITHMS - 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)); - } else { - // This initialization is correct, similar to the N4950 [dcl.init.aggr]/6 example - minmax_result<_Vty> _Found = {static_cast<_Vty>(*_UFirst), _Found.min}; - if (_UFirst == _ULast) { - return _Found; - } - - while (++_UFirst != _ULast) { // process one or two elements - _Vty _Prev(*_UFirst); - if (++_UFirst == _ULast) { // process last element - if (_STD invoke(_Pred, _STD invoke(_Proj, _Prev), _STD invoke(_Proj, _Found.min))) { - _Found.min = _STD move(_Prev); - } else if (!_STD invoke(_Pred, _STD invoke(_Proj, _Prev), _STD invoke(_Proj, _Found.max))) { - _Found.max = _STD move(_Prev); - } - - break; + 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)); + } else { + // This initialization is correct, similar to the N4950 [dcl.init.aggr]/6 example + minmax_result<_Vty> _Found = {static_cast<_Vty>(*_UFirst), _Found.min}; + if (_UFirst == _ULast) { + return _Found; } - // process next two elements - if (_STD invoke(_Pred, _STD invoke(_Proj, *_UFirst), _STD invoke(_Proj, _Prev))) { - // test _UFirst for new smallest - if (_STD invoke(_Pred, _STD invoke(_Proj, *_UFirst), _STD invoke(_Proj, _Found.min))) { - _Found.min = *_UFirst; - } + while (++_UFirst != _ULast) { // process one or two elements + _Vty _Prev(*_UFirst); + if (++_UFirst == _ULast) { // process last element + if (_STD invoke(_Pred, _STD invoke(_Proj, _Prev), _STD invoke(_Proj, _Found.min))) { + _Found.min = _STD move(_Prev); + } else if (!_STD invoke(_Pred, _STD invoke(_Proj, _Prev), _STD invoke(_Proj, _Found.max))) { + _Found.max = _STD move(_Prev); + } - if (!_STD invoke(_Pred, _STD invoke(_Proj, _Prev), _STD invoke(_Proj, _Found.max))) { - _Found.max = _STD move(_Prev); - } - } else { // test _Prev for new smallest - if (_STD invoke(_Pred, _STD invoke(_Proj, _Prev), _STD invoke(_Proj, _Found.min))) { - _Found.min = _STD move(_Prev); + break; } - if (!_STD invoke(_Pred, _STD invoke(_Proj, *_UFirst), _STD invoke(_Proj, _Found.max))) { - _Found.max = *_UFirst; + // process next two elements + if (_STD invoke(_Pred, _STD invoke(_Proj, *_UFirst), _STD invoke(_Proj, _Prev))) { + // test _UFirst for new smallest + if (_STD invoke(_Pred, _STD invoke(_Proj, *_UFirst), _STD invoke(_Proj, _Found.min))) { + _Found.min = *_UFirst; + } + + if (!_STD invoke(_Pred, _STD invoke(_Proj, _Prev), _STD invoke(_Proj, _Found.max))) { + _Found.max = _STD move(_Prev); + } + } else { // test _Prev for new smallest + if (_STD invoke(_Pred, _STD invoke(_Proj, _Prev), _STD invoke(_Proj, _Found.min))) { + _Found.min = _STD move(_Prev); + } + + if (!_STD invoke(_Pred, _STD invoke(_Proj, *_UFirst), _STD invoke(_Proj, _Found.max))) { + _Found.max = *_UFirst; + } } } - } - return _Found; + return _Found; + } } } diff --git a/stl/inc/xutility b/stl/inc/xutility index 206b23557d1..637e531b7a6 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -121,27 +121,6 @@ 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; -__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; -__declspec(noalias) uint16_t __stdcall __std_min_2u(const void* _First, const void* _Last) noexcept; -__declspec(noalias) int32_t __stdcall __std_min_4i(const void* _First, const void* _Last) noexcept; -__declspec(noalias) uint32_t __stdcall __std_min_4u(const void* _First, const void* _Last) noexcept; -__declspec(noalias) int64_t __stdcall __std_min_8i(const void* _First, const void* _Last) noexcept; -__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; -__declspec(noalias) uint16_t __stdcall __std_max_2u(const void* _First, const void* _Last) noexcept; -__declspec(noalias) int32_t __stdcall __std_max_4i(const void* _First, const void* _Last) noexcept; -__declspec(noalias) uint32_t __stdcall __std_max_4u(const void* _First, const void* _Last) noexcept; -__declspec(noalias) int64_t __stdcall __std_max_8i(const void* _First, const void* _Last) noexcept; -__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; - __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; @@ -333,49 +312,6 @@ auto _Min_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { } } -template -auto _Max_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { - constexpr bool _Signed = is_signed_v<_Ty>; - - if constexpr (is_pointer_v<_Ty>) { -#ifdef _WIN64 - return reinterpret_cast(::__std_max_8u(_First, _Last)); -#else - return reinterpret_cast(::__std_max_4u(_First, _Last)); -#endif - } else if constexpr (is_same_v, float>) { - return ::__std_max_f(_First, _Last); - } else if constexpr (_Is_any_of_v, double, long double>) { - return ::__std_max_d(_First, _Last); - } else if constexpr (sizeof(_Ty) == 1) { - if constexpr (_Signed) { - return ::__std_max_1i(_First, _Last); - } else { - return ::__std_max_1u(_First, _Last); - } - } else if constexpr (sizeof(_Ty) == 2) { - if constexpr (_Signed) { - return ::__std_max_2i(_First, _Last); - } else { - return ::__std_max_2u(_First, _Last); - } - } else if constexpr (sizeof(_Ty) == 4) { - if constexpr (_Signed) { - return ::__std_max_4i(_First, _Last); - } else { - return ::__std_max_4u(_First, _Last); - } - } else if constexpr (sizeof(_Ty) == 8) { - if constexpr (_Signed) { - return ::__std_max_8i(_First, _Last); - } else { - return ::__std_max_8u(_First, _Last); - } - } else { - _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size - } -} - template inline size_t // TRANSITION, GH-4496 _Mismatch_vectorized(const void* const _First1, const void* const _First2, const size_t _Count) noexcept { @@ -7030,20 +6966,31 @@ namespace ranges { #endif // _HAS_CXX20 #endif // _HAS_CXX17 +template +constexpr _Ty _Max(const _Ty* _First, const _Ty* const _Last) { + // Vectorization-friendly maximum valiue + _Ty _Max_val = *_First; + + for (++_First; _First != _Last; ++_First) { + if (_Max_val < *_First) { + _Max_val = *_First; + } + } + + return _Max_val; +} + _EXPORT_STD template _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 constexpr (_Is_min_max_value_optimization_safe) { - if (!_Is_constant_evaluated()) { - return static_cast<_Ty>(_STD _Max_vectorized(_Ilist.begin(), _Ilist.end())); - } + return _STD _Max(_Ilist.begin(), _Ilist.end()); + } else { + const _Ty* _Res = _STD _Max_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); + return *_Res; } -#endif // _USE_STD_VECTOR_ALGORITHMS - const _Ty* _Res = _STD _Max_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); - return *_Res; } _EXPORT_STD template @@ -7081,14 +7028,11 @@ 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 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)); - } + return _STD _Max(_First, _Last); + } else { + return *_RANGES _Max_element_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); } -#endif // _USE_STD_VECTOR_ALGORITHMS - return *_RANGES _Max_element_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); } template && _Is_min_max_value_optimization_safe && sized_sentinel_for) { - if (!_STD is_constant_evaluated()) { - const auto _First_ptr = _STD to_address(_UFirst); - const auto _Last_ptr = _First_ptr + (_ULast - _UFirst); - return static_cast>(_STD _Max_vectorized(_First_ptr, _Last_ptr)); - } - } -#endif // _USE_STD_VECTOR_ALGORITHMS - if constexpr (forward_range<_Rng> && _Prefer_iterator_copies) { + const auto _First_ptr = _STD to_address(_UFirst); + const auto _Last_ptr = _First_ptr + (_ULast - _UFirst); + return static_cast>(_STD _Max(_First_ptr, _Last_ptr)); + } else 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))); } else { @@ -7254,20 +7193,31 @@ namespace ranges { #endif // _HAS_CXX20 #endif // _HAS_CXX17 +template +constexpr _Ty _Min(const _Ty* _First, const _Ty* const _Last) { + // Vectorization-friendly minimum valiue + _Ty _Min_val = *_First; + + for (++_First; _First != _Last; ++_First) { + if (*_First < _Min_val) { + _Min_val = *_First; + } + } + + return _Min_val; +} + _EXPORT_STD template _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 constexpr (_Is_min_max_value_optimization_safe) { - if (!_Is_constant_evaluated()) { - return static_cast<_Ty>(_STD _Min_vectorized(_Ilist.begin(), _Ilist.end())); - } + return _STD _Min(_Ilist.begin(), _Ilist.end()); + } else { + const _Ty* _Res = _STD _Min_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); + return *_Res; } -#endif // _USE_STD_VECTOR_ALGORITHMS - const _Ty* _Res = _STD _Min_element_unchecked(_Ilist.begin(), _Ilist.end(), _STD _Pass_fn(_Pred)); - return *_Res; } _EXPORT_STD template @@ -7299,14 +7249,11 @@ 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 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)); - } + return static_cast<_Ty>(_STD _Min(_First, _Last)); + } else { + return *_RANGES _Min_element_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); } -#endif // _USE_STD_VECTOR_ALGORITHMS - return *_RANGES _Min_element_unchecked(_First, _Last, _STD _Pass_fn(_Pred), _STD _Pass_fn(_Proj)); } template && _Is_min_max_value_optimization_safe && sized_sentinel_for) { - if (!_STD is_constant_evaluated()) { - const auto _First_ptr = _STD to_address(_UFirst); - const auto _Last_ptr = _First_ptr + (_ULast - _UFirst); - return static_cast>(_STD _Min_vectorized(_First_ptr, _Last_ptr)); - } - } -#endif // _USE_STD_VECTOR_ALGORITHMS - if constexpr (forward_range<_Rng> && _Prefer_iterator_copies) { + const auto _First_ptr = _STD to_address(_UFirst); + const auto _Last_ptr = _First_ptr + (_ULast - _UFirst); + return static_cast>(_STD _Min(_First_ptr, _Last_ptr)); + } else 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))); } else { diff --git a/stl/src/vector_algorithms.cpp b/stl/src/vector_algorithms.cpp index cd25f40064b..c2092c7bf72 100644 --- a/stl/src/vector_algorithms.cpp +++ b/stl/src/vector_algorithms.cpp @@ -488,6 +488,61 @@ __declspec(noalias) void __cdecl __std_reverse_copy_trivially_copyable_8( static_cast(_Dest)); } +struct _Min_max_1i { + int8_t _Min; + int8_t _Max; +}; + +struct _Min_max_1u { + uint8_t _Min; + uint8_t _Max; +}; + +struct _Min_max_2i { + int16_t _Min; + int16_t _Max; +}; + +struct _Min_max_2u { + uint16_t _Min; + uint16_t _Max; +}; + +struct _Min_max_4i { + int32_t _Min; + int32_t _Max; +}; + +struct _Min_max_4u { + uint32_t _Min; + uint32_t _Max; +}; + +struct _Min_max_8i { + int64_t _Min; + int64_t _Max; +}; + +struct _Min_max_8u { + uint64_t _Min; + uint64_t _Max; +}; + +struct _Min_max_f { + float _Min; + float _Max; +}; + +struct _Min_max_d { + double _Min; + double _Max; +}; + +struct _Min_max_p { + void* _Min; + void* _Max; +}; + } // extern "C" namespace { From 53da2459cf2252ffcb854fe6ae252b2e9917d877 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 12 Oct 2024 20:09:12 +0300 Subject: [PATCH 2/3] min --- stl/inc/algorithm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 36502b7cd58..22d1be37098 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -10137,7 +10137,7 @@ constexpr _Rx _Minmax(const _Ty* _First, const _Ty* const _Last) { _Ty _Max_val = *_First; for (++_First; _First != _Last; ++_First) { - if (_Min_val < *_First) { + if (*_First < _Min_val) { _Min_val = *_First; } From a40764ee3a36627e4520fa865ffc1621d280e133 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 12 Oct 2024 20:29:03 +0300 Subject: [PATCH 3/3] remove more --- stl/inc/xutility | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 637e531b7a6..febda5813c2 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -269,49 +269,6 @@ _Ty* _Max_element_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { } } -template -auto _Min_vectorized(_Ty* const _First, _Ty* const _Last) noexcept { - constexpr bool _Signed = is_signed_v<_Ty>; - - if constexpr (is_pointer_v<_Ty>) { -#ifdef _WIN64 - return reinterpret_cast(::__std_min_8u(_First, _Last)); -#else - return reinterpret_cast(::__std_min_4u(_First, _Last)); -#endif - } else if constexpr (is_same_v, float>) { - return ::__std_min_f(_First, _Last); - } else if constexpr (_Is_any_of_v, double, long double>) { - return ::__std_min_d(_First, _Last); - } else if constexpr (sizeof(_Ty) == 1) { - if constexpr (_Signed) { - return ::__std_min_1i(_First, _Last); - } else { - return ::__std_min_1u(_First, _Last); - } - } else if constexpr (sizeof(_Ty) == 2) { - if constexpr (_Signed) { - return ::__std_min_2i(_First, _Last); - } else { - return ::__std_min_2u(_First, _Last); - } - } else if constexpr (sizeof(_Ty) == 4) { - if constexpr (_Signed) { - return ::__std_min_4i(_First, _Last); - } else { - return ::__std_min_4u(_First, _Last); - } - } else if constexpr (sizeof(_Ty) == 8) { - if constexpr (_Signed) { - return ::__std_min_8i(_First, _Last); - } else { - return ::__std_min_8u(_First, _Last); - } - } else { - _STL_INTERNAL_STATIC_ASSERT(false); // unexpected size - } -} - template inline size_t // TRANSITION, GH-4496 _Mismatch_vectorized(const void* const _First1, const void* const _First2, const size_t _Count) noexcept {