diff --git a/libcxx/include/__iterator/iterator_traits.h b/libcxx/include/__iterator/iterator_traits.h --- a/libcxx/include/__iterator/iterator_traits.h +++ b/libcxx/include/__iterator/iterator_traits.h @@ -474,10 +474,10 @@ __has_iterator_category_convertible_to<_Tp, input_iterator_tag>::value && !__has_iterator_category_convertible_to<_Tp, forward_iterator_tag>::value> {}; -#if _LIBCPP_STD_VER >= 17 template using __iter_value_type = typename iterator_traits<_InputIterator>::value_type; +#if _LIBCPP_STD_VER >= 17 template using __iter_key_type = remove_const_t::value_type::first_type>; diff --git a/libcxx/include/__memory/uninitialized_algorithms.h b/libcxx/include/__memory/uninitialized_algorithms.h --- a/libcxx/include/__memory/uninitialized_algorithms.h +++ b/libcxx/include/__memory/uninitialized_algorithms.h @@ -32,12 +32,133 @@ } }; +namespace __uninitialized_algorithms { + +template +_ForwardIterator __next(_ForwardIterator __iter, _Sentinel __sentinel) { + while (__iter != __sentinel) { + ++__iter; + } + return __iter; +} + +template +_ForwardIterator __next_n(_ForwardIterator __iter, _Size __n) { + while (__n > 0) { + ++__iter; + --__n; + } + return __iter; +} + +// TODO(varconst): support contiguous iterators. +template +struct __can_use_memset_fill { + static const bool __value = is_pointer<_OutputIterator>::value + && is_scalar<_ValueType>::value + && (sizeof(_ValueType) == 1 || is_same<_ValueType, bool>::value) + && !is_volatile<_ValueType>::value; +}; + +// TODO(varconst): support contiguous iterators. +template +struct __can_use_memset_zero { + static const bool __value = is_pointer<_OutputIterator>::value + && is_trivial<_ValueType>::value + && !is_volatile<_ValueType>::value; +}; + +template +struct __are_bitwise_compatible { + static const bool __value = sizeof(_From) == sizeof(_To) + && ((is_integral<_From>::value && is_integral<_To>::value) + || (is_floating_point<_From>::value && is_floating_point<_To>::value)); +}; + +template +struct __can_memcpy_between { + static const bool __value = (is_same<_From, _To>::value && is_trivial<_From>::value) + || __are_bitwise_compatible<_From, _To>::__value; +}; + +// TODO(varconst): support contiguous iterators. +template +struct __can_use_memcpy { + static const bool __value = is_pointer<_InputIterator>::value + && is_pointer<_OutputIterator>::value + && __can_memcpy_between<_From, _To>::__value + && !is_volatile<_From>::value + && !is_volatile<_To>::value; +}; + +template +bool __is_represented_as_zero(const _Tp& __x) { +#ifndef _LIBCPP_CXX03_LANG + _Tp __all_zeroes{}; +#else + _Tp __all_zeroes; + _VSTD::memset(_VSTD::addressof(__all_zeroes), 0, sizeof(__all_zeroes)); +#endif + + return _VSTD::memcmp(_VSTD::addressof(__x), _VSTD::addressof(__all_zeroes), sizeof(_Tp)) == 0; +} + +template <> +inline bool __is_represented_as_zero(const nullptr_t&) { + return true; +} + +#if _LIBCPP_STD_VER > 11 + +template +constexpr bool __can_use_memset_fill_v = __can_use_memset_fill<_ValueType, _OutputIterator>::__value; + +template +constexpr bool __can_use_memset_zero_v = __can_use_memset_zero<_ValueType, _OutputIterator>::__value; + +template +constexpr bool __can_use_memcpy_v = __can_use_memcpy<_From, _To, _InputIterator, _OutputIterator>::__value; + +#endif + +// TODO(varconst): use `std::to_address` to support contiguous iterators. +template +_Pointer __memset_fill(_Pointer __first, _Size __n, _ValueType __x) { + _VSTD::memset(__first, static_cast(__x), sizeof(_ValueType) * __n); + return __first + __n; +} + +// TODO(varconst): use `std::to_address` to support contiguous iterators. +template +_Pointer __memset_zero(_Pointer __first, _Size __n) { + _VSTD::memset(__first, 0, sizeof(_ValueType) * __n); + return __first + __n; +} + +// TODO(varconst): use `std::to_address` to support contiguous iterators. +template +pair<_InputPtr, _OutputPtr> __memcpy(_InputPtr __ifirst, _Size __isize, _OutputPtr __ofirst, _Size __osize) { + _Size __smaller_size = __isize < __osize ? __isize : __osize; + _VSTD::memcpy(__ofirst, __ifirst, __smaller_size * sizeof(_ValueType)); + + return make_pair(__ifirst + __smaller_size, __ofirst + __smaller_size); +} + +} // namespace __uninitialized_algorithms + // uninitialized_copy template inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_copy(_InputIterator __ifirst, _Sentinel1 __ilast, _ForwardIterator __ofirst, _Sentinel2 __olast) { +#ifndef _LIBCPP_CXX03_LANG + if constexpr (__uninitialized_algorithms::__can_use_memcpy<__iter_value_type<_InputIterator>, _ValueType, + _InputIterator, _ForwardIterator>::__value) { + return __uninitialized_algorithms::__memcpy<_ValueType>(__ifirst, __ilast - __ifirst, __ofirst, __olast - __ofirst); + } +#endif + _ForwardIterator __idx = __ofirst; #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -51,7 +172,7 @@ } #endif - return pair<_InputIterator, _ForwardIterator>(_VSTD::move(__ifirst), _VSTD::move(__idx)); + return make_pair(_VSTD::move(__ifirst), _VSTD::move(__idx)); } template @@ -69,6 +190,13 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_copy_n(_InputIterator __ifirst, _Size __n, _ForwardIterator __ofirst, _Sentinel __olast) { +#ifndef _LIBCPP_CXX03_LANG + if constexpr (__uninitialized_algorithms::__can_use_memcpy<__iter_value_type<_InputIterator>, _ValueType, + _InputIterator, _ForwardIterator>::__value) { + return __uninitialized_algorithms::__memcpy<_ValueType>(__ifirst, __n, __ofirst, __olast - __ofirst); + } +#endif + _ForwardIterator __idx = __ofirst; #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -82,7 +210,7 @@ } #endif - return pair<_InputIterator, _ForwardIterator>(_VSTD::move(__ifirst), _VSTD::move(__idx)); + return make_pair(_VSTD::move(__ifirst), _VSTD::move(__idx)); } template @@ -100,6 +228,16 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_fill(_ForwardIterator __first, _Sentinel __last, const _Tp& __x) { +#ifndef _LIBCPP_CXX03_LANG + if constexpr (__uninitialized_algorithms::__can_use_memset_fill<_ValueType, _ForwardIterator>::__value) { + return __uninitialized_algorithms::__memset_fill(__first, __last - __first, __x); + } else if constexpr (__uninitialized_algorithms::__can_use_memset_zero<_ValueType, _ForwardIterator>::__value) { + if (__uninitialized_algorithms::__is_represented_as_zero(__x)) { + return __uninitialized_algorithms::__memset_zero<_ValueType>(__first, __last - __first); + } + } +#endif + _ForwardIterator __idx = __first; #ifndef _LIBCPP_NO_EXCEPTIONS try @@ -133,6 +271,16 @@ inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) { +#ifndef _LIBCPP_CXX03_LANG + if constexpr (__uninitialized_algorithms::__can_use_memset_fill<_ValueType, _ForwardIterator>::__value) { + return __uninitialized_algorithms::__memset_fill(__first, __n, __x); + } else if constexpr (__uninitialized_algorithms::__can_use_memset_zero<_ValueType, _ForwardIterator>::__value) { + if (__uninitialized_algorithms::__is_represented_as_zero(__x)) { + return __uninitialized_algorithms::__memset_zero<_ValueType>(__first, __n); + } + } +#endif + _ForwardIterator __idx = __first; #ifndef _LIBCPP_NO_EXCEPTIONS try @@ -167,6 +315,10 @@ template inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct(_ForwardIterator __first, _Sentinel __last) { + if constexpr (is_trivially_default_constructible_v<_ValueType>) { + return __uninitialized_algorithms::__next(__first, __last); + } + auto __idx = __first; #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -196,6 +348,10 @@ template inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) { + if constexpr (is_trivially_default_constructible_v<_ValueType>) { + return __uninitialized_algorithms::__next_n(__first, __n); + } + auto __idx = __first; #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -224,6 +380,10 @@ template inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct(_ForwardIterator __first, _Sentinel __last) { + if constexpr (__uninitialized_algorithms::__can_use_memset_zero_v<_ValueType, _ForwardIterator>) { + return __uninitialized_algorithms::__memset_zero<_ValueType>(__first, __last - __first); + } + auto __idx = __first; #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -253,6 +413,10 @@ template inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator __uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) { + if constexpr (__uninitialized_algorithms::__can_use_memset_zero_v<_ValueType, _ForwardIterator>) { + return __uninitialized_algorithms::__memset_zero<_ValueType>(__first, __n); + } + auto __idx = __first; #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -283,6 +447,11 @@ inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move(_InputIterator __ifirst, _Sentinel1 __ilast, _ForwardIterator __ofirst, _Sentinel2 __olast, _IterMove __iter_move) { + if constexpr (__uninitialized_algorithms::__can_use_memcpy_v<__iter_value_type<_InputIterator>, _ValueType, + _InputIterator, _ForwardIterator>) { + return __uninitialized_algorithms::__memcpy<_ValueType>(__ifirst, __ilast - __ifirst, __ofirst, __olast - __ofirst); + } + auto __idx = __ofirst; #ifndef _LIBCPP_NO_EXCEPTIONS try { @@ -316,7 +485,12 @@ template inline _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _ForwardIterator> __uninitialized_move_n(_InputIterator __ifirst, _Size __n, - _ForwardIterator __ofirst, _Sentinel __olast, _IterMove __iter_move) { + _ForwardIterator __ofirst, _Sentinel __olast, _IterMove __iter_move) { + if constexpr (__uninitialized_algorithms::__can_use_memcpy_v<__iter_value_type<_InputIterator>, _ValueType, + _InputIterator, _ForwardIterator>) { + return __uninitialized_algorithms::__memcpy<_ValueType>(__ifirst, __n, __ofirst, __olast - __ofirst); + } + auto __idx = __ofirst; #ifndef _LIBCPP_NO_EXCEPTIONS try { diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -1206,7 +1206,6 @@ // is_compound -// >= 11 because in C++03 nullptr isn't actually nullptr #if __has_keyword(__is_compound) && !defined(_LIBCPP_CXX03_LANG) template