[libcxx-commits] [libcxx] [libc++] Optimize basic_string::operator=(const value_type*) (PR #227622)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Tue Oct 6 04:47:42 PDT 2026


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

>From 1c12c66b867926285c9cbc53fc4a7c00d27b50da Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 30 Sep 2026 11:27:47 +0200
Subject: [PATCH] [libc++] Optimize basic_string::operator=(const value_type*)

---
 .../include/__string/extern_template_lists.h  |  1 -
 libcxx/include/string                         | 40 ++++++++++---------
 2 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/libcxx/include/__string/extern_template_lists.h b/libcxx/include/__string/extern_template_lists.h
index dcd538c97247c..f189d41643160 100644
--- a/libcxx/include/__string/extern_template_lists.h
+++ b/libcxx/include/__string/extern_template_lists.h
@@ -84,7 +84,6 @@
   _LIBCPP_STRING_COMMON_EXTERN_TEMPLATE_LIST(Func, CharT)                                                              \
   Func(void basic_string<CharT>::__init_copy_ctor_external(const value_type*, size_type))                              \
   Func(basic_string<CharT>& basic_string<CharT>::__assign_external(const value_type*, size_type))                      \
-  Func(basic_string<CharT>& basic_string<CharT>::__assign_external(const value_type*))                                 \
   Func(void basic_string<CharT>::__assign_no_alias<false>(const value_type*, size_type))                               \
   Func(void basic_string<CharT>::__assign_no_alias<true>(const value_type*, size_type))                                \
   Func(void basic_string<CharT>::__erase_external_with_move(size_type, size_type))
diff --git a/libcxx/include/string b/libcxx/include/string
index a27f9344916d1..bd21d7e74d90c 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -2370,12 +2370,12 @@ private:
       size_type __n_add,
       const value_type* __p_new_stuff);
 
-  // __assign_no_alias is invoked for assignment operations where we
-  // have proof that the input does not alias the current instance.
-  // For example, operator=(basic_string) performs a 'self' check.
-  // The string has to be null terminated at __n.
+  // This function can be called if it is known that
+  // - __n <= max_size() or __s is from an allocator of the same family, and
+  // - __s is null terminated at __n.
+  // __s may point into *this.
   template <bool __is_short>
-  _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void __assign_no_alias(const value_type* __s, size_type __n);
+  _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void __assign_ntcts(const value_type* __s, size_type __n);
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __erase_to_end(size_type __pos) {
     _LIBCPP_ASSERT_INTERNAL(__pos <= capacity(), "Trying to erase at position outside the strings capacity!");
@@ -2437,7 +2437,6 @@ private:
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __move_assign_alloc(basic_string&, false_type) _NOEXCEPT {}
 
-  _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_external(const value_type* __s);
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string& __assign_external(const value_type* __s, size_type __n);
 
   // Assigns the value in __s, guaranteed to be __n < __min_cap in length.
@@ -2729,7 +2728,7 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_without_replace(
 template <class _CharT, class _Traits, class _Allocator>
 template <bool __is_short>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void
-basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* __s, size_type __n) {
+basic_string<_CharT, _Traits, _Allocator>::__assign_ntcts(const value_type* __s, size_type __n) {
   _LIBCPP_ASSERT_INTERNAL(_Traits::eq(__s[__n], value_type()), "`__s` should be null-terminated at __s[__n]");
 
   const auto __cap = __is_short ? static_cast<size_type>(__min_cap) : __get_long_cap();
@@ -2764,7 +2763,7 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_no_alias(const value_type* _
     __p = __get_long_pointer();
     __set_long_size(__n);
   }
-  traits_type::copy(std::__to_address(__p), __s, __n + 1);
+  traits_type::move(std::__to_address(__p), __s, __n + 1);
 }
 
 template <class _CharT, class _Traits, class _Allocator>
@@ -2843,12 +2842,12 @@ basic_string<_CharT, _Traits, _Allocator>::operator=(const basic_string& __str)
   __copy_assign_alloc(__str);
 
   if (__is_long()) {
-    __assign_no_alias<false>(__str.data(), __str.size());
-    return *this;
+     __assign_ntcts<false>(__str.data(), __str.size());
+     return *this;
   }
 
   if (__str.__is_long()) {
-    __assign_no_alias<true>(__str.data(), __str.size());
+    __assign_ntcts<true>(__str.data(), __str.size());
     return *this;
   }
 
@@ -2966,19 +2965,22 @@ basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, siz
   return assign(__str.data() + __pos, std::min(__n, __sz - __pos));
 }
 
-template <class _CharT, class _Traits, class _Allocator>
-_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>&
-basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s) {
-  return __assign_external(__s, traits_type::length(__s));
-}
-
 template <class _CharT, class _Traits, class _Allocator>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>&
 basic_string<_CharT, _Traits, _Allocator>::assign(const value_type* __s) {
   _LIBCPP_ASSERT_NON_NULL(__s != nullptr, "string::assign received nullptr");
-  if (auto __len = traits_type::length(__s); __builtin_constant_p(__len) && __fits_in_sso(__len))
+  auto __len = traits_type::length(__s);
+  if (__fits_in_sso(__len))
     return __assign_short(__s, __len);
-  return __assign_external(__s);
+
+  if (__len > max_size())
+    __throw_length_error();
+  if (__is_long())
+    __assign_ntcts<false>(__s, __len);
+  else
+    __assign_ntcts<true>(__s, __len);
+
+  return *this;
 }
 // append
 



More information about the libcxx-commits mailing list