@@ -29,6 +29,15 @@ extern "C" {
2929// compiler has to assume that the denoted arrays are "globally address taken", and that any later calls to
3030// unanalyzable routines may modify those arrays.
3131
32+ __declspec (noalias) size_t __stdcall __std_find_first_of_trivial_pos_1(
33+ const void * _Haystack, size_t _Haystack_length, const void * _Needle, size_t _Needle_length) noexcept ;
34+ __declspec (noalias) size_t __stdcall __std_find_first_of_trivial_pos_2(
35+ const void * _Haystack, size_t _Haystack_length, const void * _Needle, size_t _Needle_length) noexcept ;
36+ __declspec (noalias) size_t __stdcall __std_find_first_of_trivial_pos_4(
37+ const void * _Haystack, size_t _Haystack_length, const void * _Needle, size_t _Needle_length) noexcept ;
38+ __declspec (noalias) size_t __stdcall __std_find_first_of_trivial_pos_8(
39+ const void * _Haystack, size_t _Haystack_length, const void * _Needle, size_t _Needle_length) noexcept ;
40+
3241__declspec (noalias) size_t __stdcall __std_find_last_of_trivial_pos_1(
3342 const void * _Haystack, size_t _Haystack_length, const void * _Needle, size_t _Needle_length) noexcept ;
3443__declspec (noalias) size_t __stdcall __std_find_last_of_trivial_pos_2(
@@ -38,6 +47,23 @@ __declspec(noalias) size_t __stdcall __std_find_last_of_trivial_pos_2(
3847
3948_STD_BEGIN
4049
50+ template <class _Ty1 , class _Ty2 >
51+ size_t _Find_first_of_pos_vectorized (const _Ty1* const _Haystack, const size_t _Haystack_length,
52+ const _Ty2* const _Needle, const size_t _Needle_length) noexcept {
53+ _STL_INTERNAL_STATIC_ASSERT (sizeof (_Ty1) == sizeof (_Ty2));
54+ if constexpr (sizeof (_Ty1) == 1 ) {
55+ return ::__std_find_first_of_trivial_pos_1 (_Haystack, _Haystack_length, _Needle, _Needle_length);
56+ } else if constexpr (sizeof (_Ty1) == 2 ) {
57+ return ::__std_find_first_of_trivial_pos_2 (_Haystack, _Haystack_length, _Needle, _Needle_length);
58+ } else if constexpr (sizeof (_Ty1) == 4 ) {
59+ return ::__std_find_first_of_trivial_pos_4 (_Haystack, _Haystack_length, _Needle, _Needle_length);
60+ } else if constexpr (sizeof (_Ty1) == 8 ) {
61+ return ::__std_find_first_of_trivial_pos_8 (_Haystack, _Haystack_length, _Needle, _Needle_length);
62+ } else {
63+ _STL_INTERNAL_STATIC_ASSERT (false ); // unexpected size
64+ }
65+ }
66+
4167template <class _Ty1 , class _Ty2 >
4268size_t _Find_last_of_pos_vectorized (const _Ty1* const _Haystack, const size_t _Haystack_length,
4369 const _Ty2* const _Needle, const size_t _Needle_length) noexcept {
@@ -834,48 +860,31 @@ constexpr size_t _Traits_find_first_of(_In_reads_(_Hay_size) const _Traits_ptr_t
834860 const auto _Hay_end = _Haystack + _Hay_size;
835861
836862 if constexpr (_Is_implementation_handled_char_traits<_Traits>) {
837- if (!_STD _Is_constant_evaluated ()) {
838- using _Elem = typename _Traits::char_type;
839-
840863#if _USE_STD_VECTOR_ALGORITHMS
841- const bool _Try_vectorize = _Hay_size - _Start_at > _Threshold_find_first_of;
842-
843- // Additional condition for when the vectorization outperforms the table lookup
844- constexpr size_t _Find_first_of_bitmap_threshold = sizeof (_Elem) == 1 ? 48 : sizeof (_Elem) == 8 ? 8 : 16 ;
845-
846- const bool _Use_bitmap = !_Try_vectorize || _Needle_size > _Find_first_of_bitmap_threshold;
847- #else // ^^^ _USE_STD_VECTOR_ALGORITHMS / !_USE_STD_VECTOR_ALGORITHMS vvv
848- const bool _Use_bitmap = true ;
849- #endif // ^^^ !_USE_STD_VECTOR_ALGORITHMS ^^^
850-
851- if (_Use_bitmap) {
852- _String_bitmap<_Elem> _Matches;
853-
854- if (_Matches._Mark (_Needle, _Needle + _Needle_size)) {
855- for (auto _Match_try = _Hay_start; _Match_try < _Hay_end; ++_Match_try) {
856- if (_Matches._Match (*_Match_try)) {
857- return static_cast <size_t >(_Match_try - _Haystack); // found a match
858- }
859- }
860- return static_cast <size_t >(-1 ); // no match
864+ if (!_STD _Is_constant_evaluated ()) {
865+ const size_t _Remaining_size = _Hay_size - _Start_at;
866+ if (_Remaining_size + _Needle_size >= _Threshold_find_first_of) {
867+ size_t _Pos = _Find_first_of_pos_vectorized (_Hay_start, _Remaining_size, _Needle, _Needle_size);
868+ if (_Pos != static_cast <size_t >(-1 )) {
869+ _Pos += _Start_at;
861870 }
862-
863- // couldn't put one of the characters into the bitmap, fall back to vectorized or serial algorithms
871+ return _Pos;
864872 }
873+ }
874+ #endif // _USE_STD_VECTOR_ALGORITHMS
865875
866- #if _USE_STD_VECTOR_ALGORITHMS
867- if (_Try_vectorize) {
868- const _Traits_ptr_t<_Traits> _Found =
869- _STD _Find_first_of_vectorized (_Hay_start, _Hay_end, _Needle, _Needle + _Needle_size);
870-
871- if (_Found != _Hay_end) {
872- return static_cast <size_t >(_Found - _Haystack); // found a match
873- } else {
874- return static_cast <size_t >(-1 ); // no match
876+ _String_bitmap<typename _Traits::char_type> _Matches;
877+
878+ if (_Matches._Mark (_Needle, _Needle + _Needle_size)) {
879+ for (auto _Match_try = _Hay_start; _Match_try < _Hay_end; ++_Match_try) {
880+ if (_Matches._Match (*_Match_try)) {
881+ return static_cast <size_t >(_Match_try - _Haystack); // found a match
875882 }
876883 }
877- # endif // _USE_STD_VECTOR_ALGORITHMS
884+ return static_cast < size_t >(- 1 ); // no match
878885 }
886+
887+ // couldn't put one of the characters into the bitmap, fall back to serial algorithm
879888 }
880889
881890 for (auto _Match_try = _Hay_start; _Match_try < _Hay_end; ++_Match_try) {
@@ -899,47 +908,32 @@ constexpr size_t _Traits_find_last_of(_In_reads_(_Hay_size) const _Traits_ptr_t<
899908 const auto _Hay_start = (_STD min)(_Start_at, _Hay_size - 1 );
900909
901910 if constexpr (_Is_implementation_handled_char_traits<_Traits>) {
902- if (!_STD _Is_constant_evaluated ()) {
903- using _Elem = typename _Traits::char_type;
904-
905- bool _Use_bitmap = true ;
911+ using _Elem = typename _Traits::char_type;
906912#if _USE_STD_VECTOR_ALGORITHMS
907- bool _Try_vectorize = false ;
908-
909- if constexpr (sizeof (_Elem) <= 2 ) {
910- _Try_vectorize = _Hay_start + 1 > _Threshold_find_first_of;
911- // Additional condition for when the vectorization outperforms the table lookup
912- constexpr size_t _Find_last_of_bitmap_threshold = sizeof (_Elem) == 1 ? 48 : 8 ;
913-
914- _Use_bitmap = !_Try_vectorize || _Needle_size > _Find_last_of_bitmap_threshold;
913+ if constexpr (sizeof (_Elem) <= 2 ) {
914+ if (!_STD _Is_constant_evaluated ()) {
915+ const size_t _Remaining_size = _Hay_start + 1 ;
916+ if (_Remaining_size + _Needle_size >= _Threshold_find_first_of) { // same threshold for first/last
917+ return _Find_last_of_pos_vectorized (_Haystack, _Remaining_size, _Needle, _Needle_size);
918+ }
915919 }
920+ }
916921#endif // _USE_STD_VECTOR_ALGORITHMS
917922
918- if (_Use_bitmap) {
919- _String_bitmap<_Elem> _Matches;
920- if (_Matches._Mark (_Needle, _Needle + _Needle_size)) {
921- for (auto _Match_try = _Haystack + _Hay_start;; --_Match_try) {
922- if (_Matches._Match (*_Match_try)) {
923- return static_cast <size_t >(_Match_try - _Haystack); // found a match
924- }
925-
926- if (_Match_try == _Haystack) {
927- return static_cast <size_t >(-1 ); // at beginning, no more chance for match
928- }
929- }
923+ _String_bitmap<_Elem> _Matches;
924+ if (_Matches._Mark (_Needle, _Needle + _Needle_size)) {
925+ for (auto _Match_try = _Haystack + _Hay_start;; --_Match_try) {
926+ if (_Matches._Match (*_Match_try)) {
927+ return static_cast <size_t >(_Match_try - _Haystack); // found a match
930928 }
931929
932- // couldn't put one of the characters into the bitmap, fall back to vectorized or serial algorithms
933- }
934-
935- #if _USE_STD_VECTOR_ALGORITHMS
936- if constexpr (sizeof (_Elem) <= 2 ) {
937- if (_Try_vectorize) {
938- return _STD _Find_last_of_pos_vectorized (_Haystack, _Hay_start + 1 , _Needle, _Needle_size);
930+ if (_Match_try == _Haystack) {
931+ return static_cast <size_t >(-1 ); // at beginning, no more chance for match
939932 }
940933 }
941- #endif // _USE_STD_VECTOR_ALGORITHMS
942934 }
935+
936+ // couldn't put one of the characters into the bitmap, fall back to serial algorithm
943937 }
944938
945939 for (auto _Match_try = _Haystack + _Hay_start;; --_Match_try) {
0 commit comments