[libcxx-commits] [libcxx] [libc++] Use char_traits::copy while inserting when possible (PR #97201)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Jun 30 02:51:29 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Nikolas Klauser (philnik777)
<details>
<summary>Changes</summary>
This reduces the number of asm lines from 707 to 519 for this snippet:
```c++
auto test(std::string& str, const char* begin, const char* end) {
str.insert(str.begin(), begin, end);
}
```
While that's not a performance metric, I've never seen a use of `memcpy` result in a performance regression for any realistic usage.
---
Full diff: https://github.com/llvm/llvm-project/pull/97201.diff
1 Files Affected:
- (modified) libcxx/include/string (+23-13)
``````````diff
diff --git a/libcxx/include/string b/libcxx/include/string
index 9a52ab6aef41e..d2fb206d7132a 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1830,6 +1830,22 @@ private:
template <class _Iterator, class _Sentinel>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel(_Iterator __first, _Sentinel __last);
+ template <class _ForwardIter, class _Sent>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static value_type*
+ __copy_range(_ForwardIter __first, _Sent __last, value_type* __dest) {
+#ifndef _LIBCPP_CXX03_LANG
+ if constexpr (__libcpp_is_contiguous_iterator<_ForwardIter>::value &&
+ is_same<value_type, __iter_value_type<_ForwardIter>>::value && is_same<_ForwardIter, _Sent>::value) {
+ traits_type::copy(__dest, std::__to_address(__first), __last - __first);
+ return __dest + (__last - __first);
+ }
+#endif
+
+ for (; __first != __last; ++__first)
+ traits_type::assign(*__dest++, *__first);
+ return __dest;
+ }
+
template <class _ForwardIterator, class _Sentinel>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 iterator
__insert_from_safe_copy(size_type __n, size_type __ip, _ForwardIterator __first, _Sentinel __last) {
@@ -1849,8 +1865,7 @@ private:
__sz += __n;
__set_size(__sz);
traits_type::assign(__p[__sz], value_type());
- for (__p += __ip; __first != __last; ++__p, ++__first)
- traits_type::assign(*__p, *__first);
+ __copy_range(__first, __last, __p + __ip);
return begin() + __ip;
}
@@ -2361,9 +2376,8 @@ basic_string<_CharT, _Traits, _Allocator>::__init_with_size(_InputIterator __fir
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
try {
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
- for (; __first != __last; ++__first, (void)++__p)
- traits_type::assign(*__p, *__first);
- traits_type::assign(*__p, value_type());
+ auto __end = __copy_range(__first, __last, std::__to_address(__p));
+ traits_type::assign(*__end, value_type());
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
} catch (...) {
if (__is_long())
@@ -2684,10 +2698,8 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_trivial(_Iterator __first, _
__annotate_increase(__n);
} else if (__n > __old_size)
__annotate_increase(__n - __old_size);
- pointer __p = __get_pointer();
- for (; __first != __last; ++__p, (void)++__first)
- traits_type::assign(*__p, *__first);
- traits_type::assign(*__p, value_type());
+ auto __end = __copy_range(__first, __last, std::__to_address(__get_pointer()));
+ traits_type::assign(*__end, value_type());
__set_size(__n);
if (__n < __old_size)
__annotate_shrink(__old_size);
@@ -2829,10 +2841,8 @@ basic_string<_CharT, _Traits, _Allocator>::append(_ForwardIterator __first, _For
if (__cap - __sz < __n)
__grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0);
__annotate_increase(__n);
- pointer __p = __get_pointer() + __sz;
- for (; __first != __last; ++__p, (void)++__first)
- traits_type::assign(*__p, *__first);
- traits_type::assign(*__p, value_type());
+ auto __end = __copy_range(__first, __last, std::__to_address(__get_pointer() + __sz));
+ traits_type::assign(*__end, value_type());
__set_size(__sz + __n);
} else {
const basic_string __temp(__first, __last, __alloc());
``````````
</details>
https://github.com/llvm/llvm-project/pull/97201
More information about the libcxx-commits
mailing list