[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