[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