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

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Sep 14 03:22:01 PDT 2026


Author: Nikolas Klauser
Date: 2026-09-14T12:21:57+02:00
New Revision: d873afedebd0726700ba7f42a5d6e54dba288557

URL: https://github.com/llvm/llvm-project/commit/d873afedebd0726700ba7f42a5d6e54dba288557
DIFF: https://github.com/llvm/llvm-project/commit/d873afedebd0726700ba7f42a5d6e54dba288557.diff

LOG: [libc++] Optimize string copy construction (#222021)

We know that the string size provided to `__init_copy_ctor_external` is
less than or equal to `max_size()`, so we don't need to do that check
again. Removing that check allows the compiler to ShrinkWrap the small
size path and also removes some unnecessary work in the allocating path.

Added: 
    libcxx/include/__utility/assume.h

Modified: 
    libcxx/include/CMakeLists.txt
    libcxx/include/__assert
    libcxx/include/module.modulemap.in
    libcxx/include/string
    libcxx/test/libcxx/assertions/single_expression.pass.cpp

Removed: 
    


################################################################################
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