[libcxx-commits] [libcxx] [libc++] Optimize string copy construction (PR #222021)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Fri Sep 11 02:40:25 PDT 2026


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

>From 7b44cd787ecb7566c8ec8da1ef35fbcef3ae115f Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 8 Sep 2026 16:56:52 +0200
Subject: [PATCH] [libc++] Optimize string copy construction

---
 libcxx/include/CMakeLists.txt                 |  1 +
 libcxx/include/__assert                       | 11 -------
 libcxx/include/__utility/assume.h             | 32 +++++++++++++++++++
 libcxx/include/module.modulemap.in            |  1 +
 libcxx/include/string                         |  3 ++
 .../assertions/single_expression.pass.cpp     |  9 +-----
 6 files changed, 38 insertions(+), 19 deletions(-)
 create mode 100644 libcxx/include/__utility/assume.h

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 113d4fde7ca59..bc11bda33724b 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -962,6 +962,7 @@ set(files
   __undef_macros
   __utility/as_const.h
   __utility/as_lvalue.h
+  __utility/assume.h
   __utility/auto_cast.h
   __utility/cmp.h
   __utility/constant_wrapper.h
diff --git a/libcxx/include/__assert b/libcxx/include/__assert
index 2ecd310553e71..84b1614dde49d 100644
--- a/libcxx/include/__assert
+++ b/libcxx/include/__assert
@@ -23,17 +23,6 @@
        : _LIBCPP_ASSERTION_HANDLER(__FILE_NAME__ ":" _LIBCPP_TOSTRING(                                                 \
              __LINE__) ": libc++ Hardening assertion " _LIBCPP_TOSTRING(expression) " failed: " message "\n"))
 
-// WARNING: __builtin_assume can currently inhibit optimizations. Only add assumptions with a clear
-// optimization intent. See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a
-// discussion.
-#if __has_builtin(__builtin_assume)
-#  define _LIBCPP_ASSUME(expression)                                                                                   \
-    (_LIBCPP_DIAGNOSTIC_PUSH _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wassume")                                              \
-         __builtin_assume(static_cast<bool>(expression)) _LIBCPP_DIAGNOSTIC_POP)
-#else
-#  define _LIBCPP_ASSUME(expression) ((void)0)
-#endif
-
 // clang-format off
 // Fast hardening mode checks.
 
diff --git a/libcxx/include/__utility/assume.h b/libcxx/include/__utility/assume.h
new file mode 100644
index 0000000000000..72a5efbca7b50
--- /dev/null
+++ b/libcxx/include/__utility/assume.h
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___UTILITY_ASSUME_H
+#define _LIBCPP___UTILITY_ASSUME_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// WARNING: [[assume]] can currently inhibit optimizations. Only add assumptions with a clear optimization intent.
+// See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a discussion.
+
+_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 void __assume(bool __cond) { [[__assume__(__cond)]]; }
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___UTILITY_ASSUME_H
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index d22a9ce36d02c..214020750e1af 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2256,6 +2256,7 @@ module std {
   module utility {
     module as_const                        { header "__utility/as_const.h" }
     module as_lvalue                       { header "__utility/as_lvalue.h" }
+    module assume                          { header "__utility/assume.h" }
     module auto_cast                       {
       header "__utility/auto_cast.h"
       export std_core.type_traits.decay // the macro expansion uses that trait
diff --git a/libcxx/include/string b/libcxx/include/string
index 8b0b648d2c655..c485038312d99 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -644,6 +644,7 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
 #  include <__type_traits/is_trivially_copyable.h>
 #  include <__type_traits/remove_cv.h>
 #  include <__type_traits/remove_cvref.h>
+#  include <__utility/assume.h>
 #  include <__utility/default_three_way_comparator.h>
 #  include <__utility/exception_guard.h>
 #  include <__utility/exchange.h>
@@ -2596,6 +2597,8 @@ basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_ty
 template <class _CharT, class _Traits, class _Allocator>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE void
 basic_string<_CharT, _Traits, _Allocator>::__init_copy_ctor_external(const value_type* __s, size_type __sz) {
+  if _LIBCPP_CONSTEXPR (__alloc_traits::is_always_equal::value)
+    std::__assume(__sz <= max_size());
   pointer __p = __init_internal_buffer(__sz);
   traits_type::copy(std::__to_address(__p), __s, __sz + 1);
 }
diff --git a/libcxx/test/libcxx/assertions/single_expression.pass.cpp b/libcxx/test/libcxx/assertions/single_expression.pass.cpp
index 13253e4cb6ef5..ac1c55f99b4ef 100644
--- a/libcxx/test/libcxx/assertions/single_expression.pass.cpp
+++ b/libcxx/test/libcxx/assertions/single_expression.pass.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-// Make sure that `_LIBCPP_ASSERT` and `_LIBCPP_ASSUME` are each a single expression.
+// Make sure that `_LIBCPP_ASSERT` is a single expression.
 // This is useful so we can use them  in places that require an expression, such as
 // in a constructor initializer list.
 
@@ -19,14 +19,7 @@ void f() {
   return _LIBCPP_ASSERT(true, "message");
 }
 
-void g() {
-  int i = (_LIBCPP_ASSUME(true), 3);
-  assert(i == 3);
-  return _LIBCPP_ASSUME(true);
-}
-
 int main(int, char**) {
   f();
-  g();
   return 0;
 }



More information about the libcxx-commits mailing list