[libcxx-commits] [libcxx] [libc++] Use char_traits::copy while inserting when possible (PR #97201)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jul 16 06:58:36 PDT 2024


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/97201

>From 0413757f7a96198218586d479ac4a4d62b67bf69 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sun, 30 Jun 2024 11:43:22 +0200
Subject: [PATCH] [libc++] Use char_traits::copy while inserting when possible

---
 libcxx/include/string | 31 ++++++++++++++++++++++---------
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index 9a52ab6aef41e..ea2292441abf1 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1830,6 +1830,23 @@ private:
   template <class _Iterator, class _Sentinel>
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel(_Iterator __first, _Sentinel __last);
 
+  // Copy [__first, __last) into [__dest, __dest + (__last - __first)). Assumes that the range don't overlap.
+  template <class _ForwardIter, class _Sent>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static value_type*
+  __copy_non_overlapping_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 +1866,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_non_overlapping_range(__first, __last, __p + __ip);
 
     return begin() + __ip;
   }
@@ -2361,9 +2377,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_non_overlapping_range(__first, __last, std::__to_address(__p));
+    traits_type::assign(*__end, value_type());
 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   } catch (...) {
     if (__is_long())
@@ -2829,10 +2844,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_non_overlapping_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());



More information about the libcxx-commits mailing list