[libcxx-commits] [PATCH] D147741: [libc++, std::vector] call the optimized version of __uninitialized_allocator_copy for trivial types

Aditya Kumar via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu Apr 20 15:27:45 PDT 2023


hiraditya updated this revision to Diff 515506.
hiraditya retitled this revision from "[libc++] unwrap iterator parameters to __uninitialized_allocator_copy before calling std::copy" to "[libc++, std::vector] call the optimized version of __uninitialized_allocator_copy for trivial types".
hiraditya edited the summary of this revision.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D147741/new/

https://reviews.llvm.org/D147741

Files:
  libcxx/include/__memory/uninitialized_algorithms.h
  libcxx/include/vector


Index: libcxx/include/vector
===================================================================
--- libcxx/include/vector
+++ libcxx/include/vector
@@ -310,7 +310,10 @@
 #include <__type_traits/is_allocator.h>
 #include <__type_traits/is_constructible.h>
 #include <__type_traits/is_nothrow_move_assignable.h>
+#include <__type_traits/is_trivially_copy_assignable.h>
+#include <__type_traits/is_trivially_copy_constructible.h>
 #include <__type_traits/noexcept_move_assign_container.h>
+#include <__type_traits/remove_const.h>
 #include <__type_traits/type_identity.h>
 #include <__utility/exception_guard.h>
 #include <__utility/forward.h>
@@ -1028,7 +1031,19 @@
 vector<_Tp, _Allocator>::__construct_at_end(_ForwardIterator __first, _ForwardIterator __last, size_type __n)
 {
   _ConstructTransaction __tx(*this, __n);
+#if _LIBCPP_STD_VER >= 17
+    using _RawType = __remove_const_t<_Tp>;
+    if constexpr(is_trivially_copy_constructible<_RawType>::value && is_trivially_copy_assignable<_RawType>::value &&
+              __allocator_has_trivial_copy_construct<_Allocator, _RawType>::value &&
+              is_same<pointer, _ForwardIterator>::value &&
+              is_same<std::allocator<_Tp>, _Allocator>::value)
+      __tx.__pos_ = std::__uninitialized_allocator_copy_opt(__alloc(), __first, __last, __tx.__pos_);
+    else
+      __tx.__pos_ = std::__uninitialized_allocator_copy(__alloc(), __first, __last, __tx.__pos_);
+
+#else
   __tx.__pos_ = std::__uninitialized_allocator_copy(__alloc(), __first, __last, __tx.__pos_);
+#endif
 }
 
 //  Default constructs __n objects starting at __end_
Index: libcxx/include/__memory/uninitialized_algorithms.h
===================================================================
--- libcxx/include/__memory/uninitialized_algorithms.h
+++ libcxx/include/__memory/uninitialized_algorithms.h
@@ -586,6 +586,50 @@
   }
 }
 
+template <class _Alloc,
+          class _Type,
+          class _RawType = __remove_const_t<_Type>,
+          __enable_if_t<
+              // using _RawType because of the allocator<T const> extension
+              is_trivially_copy_constructible<_RawType>::value && is_trivially_copy_assignable<_RawType>::value &&
+              __allocator_has_trivial_copy_construct<_Alloc, _RawType>::value>* = nullptr>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Type*
+__uninitialized_allocator_copy_opt(_Alloc&, const _Type* __first1, const _Type* __last1, _Type* __first2) {
+  // TODO: Remove the const_cast once we drop support for std::allocator<T const>
+  if (__libcpp_is_constant_evaluated()) {
+    while (__first1 != __last1) {
+      std::__construct_at(std::__to_address(__first2), *__first1);
+      ++__first1;
+      ++__first2;
+    }
+    return __first2;
+  } else {
+    return std::copy(__first1, __last1, const_cast<_RawType*>(__first2));
+  }
+}
+
+template <class _Alloc,
+          class _Type,
+          class _RawType = __remove_const_t<_Type>,
+          __enable_if_t<
+              // using _RawType because of the allocator<T const> extension
+              is_trivially_copy_constructible<_RawType>::value && is_trivially_copy_assignable<_RawType>::value &&
+              __allocator_has_trivial_copy_construct<_Alloc, _RawType>::value>* = nullptr>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Type*
+__uninitialized_allocator_copy_opt(_Alloc&, _Type* __first1, _Type* __last1, _Type* __first2) {
+  // TODO: Remove the const_cast once we drop support for std::allocator<T const>
+  if (__libcpp_is_constant_evaluated()) {
+    while (__first1 != __last1) {
+      std::__construct_at(std::__to_address(__first2), *__first1);
+      ++__first1;
+      ++__first2;
+    }
+    return __first2;
+  } else {
+    return std::copy(__first1, __last1, const_cast<_RawType*>(__first2));
+  }
+}
+
 // Move-construct the elements [__first1, __last1) into [__first2, __first2 + N)
 // if the move constructor is noexcept, where N is distance(__first1, __last1).
 //


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D147741.515506.patch
Type: text/x-patch
Size: 3979 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20230420/803f13e4/attachment-0001.bin>


More information about the libcxx-commits mailing list