@@ -2751,6 +2751,96 @@ namespace {
2751
2751
}
2752
2752
}
2753
2753
2754
+ template <class _Traits , class _Ty >
2755
+ const void * __stdcall __std_adjacent_find_impl (const void * _First, const void * const _Last) noexcept {
2756
+ if (_First == _Last) {
2757
+ return _Last;
2758
+ }
2759
+
2760
+ #ifndef _M_ARM64EC
2761
+ const size_t _Size_bytes = _Byte_length (_First, _Last) - sizeof (_Ty);
2762
+
2763
+ if (const size_t _Avx_size = _Size_bytes & ~size_t {0x1F }; _Avx_size != 0 && _Use_avx2 ()) {
2764
+ _Zeroupper_on_exit _Guard; // TRANSITION, DevCom-10331414
2765
+
2766
+ const void * _Stop_at = _First;
2767
+ _Advance_bytes (_Stop_at, _Avx_size);
2768
+
2769
+ do {
2770
+ const void * _Next = _First;
2771
+ _Advance_bytes (_Next, sizeof (_Ty));
2772
+
2773
+ const __m256i _Data = _mm256_loadu_si256 (static_cast <const __m256i*>(_First));
2774
+ const __m256i _Comparand = _mm256_loadu_si256 (static_cast <const __m256i*>(_Next));
2775
+ const int _Bingo = _mm256_movemask_epi8 (_Traits::_Cmp_avx (_Data, _Comparand));
2776
+
2777
+ if (_Bingo != 0 ) {
2778
+ const unsigned long _Offset = _tzcnt_u32 (_Bingo);
2779
+ _Advance_bytes (_First, _Offset);
2780
+ return _First;
2781
+ }
2782
+
2783
+ _Advance_bytes (_First, 32 );
2784
+ } while (_First != _Stop_at);
2785
+
2786
+ if (const size_t _Avx_tail_size = _Size_bytes & 0x1C ; _Avx_tail_size != 0 ) {
2787
+ const void * _Next = _First;
2788
+ _Advance_bytes (_Next, sizeof (_Ty));
2789
+
2790
+ const __m256i _Tail_mask = _Avx2_tail_mask_32 (_Avx_tail_size >> 2 );
2791
+ const __m256i _Data = _mm256_maskload_epi32 (static_cast <const int *>(_First), _Tail_mask);
2792
+ const __m256i _Comparand = _mm256_maskload_epi32 (static_cast <const int *>(_Next), _Tail_mask);
2793
+ const int _Bingo =
2794
+ _mm256_movemask_epi8 (_mm256_and_si256 (_Traits::_Cmp_avx (_Data, _Comparand), _Tail_mask));
2795
+
2796
+ if (_Bingo != 0 ) {
2797
+ const unsigned long _Offset = _tzcnt_u32 (_Bingo);
2798
+ _Advance_bytes (_First, _Offset);
2799
+ return _First;
2800
+ }
2801
+
2802
+ _Advance_bytes (_First, _Avx_tail_size);
2803
+ }
2804
+
2805
+ if constexpr (sizeof (_Ty) >= 4 ) {
2806
+ return _Last;
2807
+ }
2808
+ } else if (const size_t _Sse_size = _Size_bytes & ~size_t {0xF }; _Sse_size != 0 && _Use_sse42 ()) {
2809
+ const void * _Stop_at = _First;
2810
+ _Advance_bytes (_Stop_at, _Sse_size);
2811
+
2812
+ do {
2813
+ const void * _Next = _First;
2814
+ _Advance_bytes (_Next, sizeof (_Ty));
2815
+
2816
+ const __m128i _Data = _mm_loadu_si128 (static_cast <const __m128i*>(_First));
2817
+ const __m128i _Comparand = _mm_loadu_si128 (static_cast <const __m128i*>(_Next));
2818
+ const int _Bingo = _mm_movemask_epi8 (_Traits::_Cmp_sse (_Data, _Comparand));
2819
+
2820
+ if (_Bingo != 0 ) {
2821
+ unsigned long _Offset;
2822
+ // CodeQL [SM02313] _Offset is always initialized: we just tested `if (_Bingo != 0)`.
2823
+ _BitScanForward (&_Offset, _Bingo);
2824
+ _Advance_bytes (_First, _Offset);
2825
+ return _First;
2826
+ }
2827
+
2828
+ _Advance_bytes (_First, 16 );
2829
+ } while (_First != _Stop_at);
2830
+ }
2831
+ #endif // !_M_ARM64EC
2832
+
2833
+ auto _Ptr = static_cast <const _Ty*>(_First);
2834
+ auto _Next = _Ptr + 1 ;
2835
+ for (; _Next != _Last; ++_Ptr, ++_Next) {
2836
+ if (*_Ptr == *_Next) {
2837
+ return _Ptr;
2838
+ }
2839
+ }
2840
+
2841
+ return _Last;
2842
+ }
2843
+
2754
2844
struct _Count_traits_8 : _Find_traits_8 {
2755
2845
#ifndef _M_ARM64EC
2756
2846
static __m256i _Sub_avx (const __m256i _Lhs, const __m256i _Rhs) noexcept {
@@ -4788,6 +4878,22 @@ __declspec(noalias) size_t __stdcall __std_find_last_not_ch_pos_8(
4788
4878
return __std_find_last_pos<_Find_traits_8, _Find_one_predicate::_Not_equal>(_First, _Last, _Val);
4789
4879
}
4790
4880
4881
+ const void * __stdcall __std_adjacent_find_1 (const void * const _First, const void * const _Last) noexcept {
4882
+ return __std_adjacent_find_impl<_Find_traits_1, uint8_t >(_First, _Last);
4883
+ }
4884
+
4885
+ const void * __stdcall __std_adjacent_find_2 (const void * const _First, const void * const _Last) noexcept {
4886
+ return __std_adjacent_find_impl<_Find_traits_2, uint16_t >(_First, _Last);
4887
+ }
4888
+
4889
+ const void * __stdcall __std_adjacent_find_4 (const void * const _First, const void * const _Last) noexcept {
4890
+ return __std_adjacent_find_impl<_Find_traits_4, uint32_t >(_First, _Last);
4891
+ }
4892
+
4893
+ const void * __stdcall __std_adjacent_find_8 (const void * const _First, const void * const _Last) noexcept {
4894
+ return __std_adjacent_find_impl<_Find_traits_8, uint64_t >(_First, _Last);
4895
+ }
4896
+
4791
4897
__declspec (noalias) size_t __stdcall __std_count_trivial_1(
4792
4898
const void * const _First, const void * const _Last, const uint8_t _Val) noexcept {
4793
4899
return __std_count_trivial_impl<_Count_traits_1>(_First, _Last, _Val);
0 commit comments