[libcxx-commits] [libcxx] [libc++] Optimize vector::__move_range for trivially copyable types (PR #207384)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jul 3 06:12:37 PDT 2026


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

>From 39ac08268a6afa5b6bf080d409693f8d595e0f1c Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 3 Jul 2026 13:34:50 +0200
Subject: [PATCH] [libc++] Optimize vector::__move_range for trivially copyable
 types

This is a code size rather than a performance optimization.

For example, the number of instructions in `__insert_with_iter` is
almost cut in half.
---
 libcxx/include/__vector/vector.h | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)

diff --git a/libcxx/include/__vector/vector.h b/libcxx/include/__vector/vector.h
index 2b9508ecafeac..bbace6225fce3 100644
--- a/libcxx/include/__vector/vector.h
+++ b/libcxx/include/__vector/vector.h
@@ -47,6 +47,7 @@
 #include <__ranges/container_compatible_range.h>
 #include <__ranges/from_range.h>
 #include <__split_buffer>
+#include <__string/constexpr_c_functions.h>
 #include <__type_traits/conditional.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/is_allocator.h>
@@ -57,6 +58,7 @@
 #include <__type_traits/is_pointer.h>
 #include <__type_traits/is_same.h>
 #include <__type_traits/is_swappable.h>
+#include <__type_traits/is_trivially_copyable.h>
 #include <__type_traits/is_trivially_relocatable.h>
 #include <__type_traits/type_identity.h>
 #include <__utility/declval.h>
@@ -1120,14 +1122,26 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void
 vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) {
   pointer __old_last  = __layout_.__end_ptr();
   difference_type __n = __old_last - __to;
+#ifndef _LIBCPP_CXX03_LANG
+  if constexpr (__allocator_has_trivial_move_construct_v<allocator_type, value_type> &&
+                is_trivially_copyable<value_type>::value) {
+    if (__libcpp_is_constant_evaluated()) // construct the new trailing objects
+      std::uninitialized_fill_n(__old_last, (__from_e - __from_s) - __n, *__from_s);
+    std::__constexpr_memmove(
+        std::__to_address(__to), std::__to_address(__from_s), __element_count(__from_e - __from_s));
+    __layout_.__set_bound_using_pointer(__to + (__from_e - __from_s));
+  } else
+#endif
   {
-    pointer __i = __from_s + __n;
-    _ConstructTransaction __tx(*this, __from_e - __i);
-    for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, (void)++__pos, __tx.__pos_ = __pos) {
-      __alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__pos), std::move(*__i));
+    {
+      pointer __i = __from_s + __n;
+      _ConstructTransaction __tx(*this, __from_e - __i);
+      for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, (void)++__pos, __tx.__pos_ = __pos) {
+        __alloc_traits::construct(this->__layout_.__alloc(), std::__to_address(__pos), std::move(*__i));
+      }
     }
+    std::move_backward(__from_s, __from_s + __n, __old_last);
   }
-  std::move_backward(__from_s, __from_s + __n, __old_last);
 }
 
 template <class _Tp, class _Allocator>



More information about the libcxx-commits mailing list