diff --git a/libcxx/include/__algorithm/swap_ranges.h b/libcxx/include/__algorithm/swap_ranges.h index 54b453b72360e0..e3f62e371da9ea 100644 --- a/libcxx/include/__algorithm/swap_ranges.h +++ b/libcxx/include/__algorithm/swap_ranges.h @@ -40,6 +40,48 @@ __swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator1, _ForwardIterator2> __swap_ranges(_ForwardIterator1 __first1, _Sentinel1 __last1, _ForwardIterator2 __first2) { +#if _LIBCPP_STD_VER >= 26 + if ! consteval { + using _V1Type = iterator_traits<_ForwardIterator1>::value_type; + using _V2Type = iterator_traits<_ForwardIterator2>::value_type; + if constexpr(__libcpp_is_contiguous_iterator<_ForwardIterator1>::value && + __libcpp_is_contiguous_iterator<_ForwardIterator2>::value && + is_same_v<_V1Type, _V2Type> && is_replaceable_v<_V1Type>) { + size_t __distance = distance(__first1, __last1); + if (__distance == 1) { + using std::swap; + swap(*__first1, *__first2); + } + else if (__distance > 0) { + size_t __numBytes = __distance * sizeof(_V1Type); + byte *__aptr = reinterpret_cast (addressof(*__first1)); + byte *__bptr = reinterpret_cast (addressof(*__first2)); + + size_t __size = __numBytes < 512 ? __numBytes : 512; + size_t __chunk = __numBytes / __size; + size_t __rem = __numBytes % __size; + + char __buffer[__size]; + if (__chunk > 0) { + for (std::size_t __n = 0; __n < __chunk; __n++, __aptr += __size, __bptr += __size) { + __builtin_memcpy(__buffer, __aptr, __size); + __builtin_memcpy(__aptr, __bptr, __size); + __builtin_memcpy(__bptr, __buffer, __size); + } + } + + if (__rem > 0) { + __builtin_memcpy(__buffer, __aptr, __rem); + __builtin_memcpy(__aptr, __bptr, __rem); + __builtin_memcpy(__bptr, __buffer, __rem); + } + } + return pair<_ForwardIterator1, _ForwardIterator2>(__first1 + __distance, __first2 + __distance); + } + } +#endif + +// else not replaceable, not contiguous, or constexpr while (__first1 != __last1) { _IterOps<_AlgPolicy>::iter_swap(__first1, __first2); ++__first1;