[libcxx-commits] [libcxx] [libc++] Optimize string copy construction (PR #222021)
via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Sep 9 07:01:09 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Nikolas Klauser (philnik777)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/222021.diff
6 Files Affected:
- (modified) libcxx/include/CMakeLists.txt (+1)
- (modified) libcxx/include/__assert (-11)
- (added) libcxx/include/__utility/assume.h (+32)
- (modified) libcxx/include/module.modulemap.in (+1)
- (modified) libcxx/include/string (+5)
- (modified) libcxx/test/libcxx/assertions/single_expression.pass.cpp (+1-8)
``````````diff
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index d8fbc3462b02b..529ed15c73072 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -961,6 +961,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..2d0fb84499539
--- /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 _LIBCPP_CONSTEXPR 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 45f98a7b6b9e5..2060196b6d4c4 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..e16fa28fc5522 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,10 @@ 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) {
+# ifndef _LIBCPP_CXX03_LANG
+ if constexpr (__alloc_traits::is_always_equal::value)
+ std::__assume(__sz <= max_size());
+# endif
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;
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/222021
More information about the libcxx-commits
mailing list