std::uninitialized_move{,_n} delegates to the corresponding
std::uninitialized_copy() variant after wrapping with a move
iterator, but the std::uninitialized_copy() doesn't unwrap the
move iterator, therefore losing the memcpy optimization if the
iterators were just pointers.
Fix this by unwrapping the move iterator using __miter_base().
We remove operator-() in testsuite_greedy_ops.h; otherwise it breaks
the range size computation.
libstdc++v3/Changelog:
PR libstdc++/121789
* include/bits/stl_uninitialized.h (uninitialized_copy):
Unwrap move iterators
* testsuite/20_util/specialized_algorithms/uninitialized_move/121789.cc:
New test.
* testsuite/util/testsuite_greedy_ops.h (greedy_ops): Comment
out operator-(T, T).
#if __cplusplus >= 201103L
using _Dest = decltype(std::__niter_base(__result));
- using _Src = decltype(std::__niter_base(__first));
+ using _Src = decltype(std::__miter_base(std::__niter_base(__first)));
using _ValT = typename iterator_traits<_ForwardIterator>::value_type;
#if __glibcxx_raw_memory_algorithms >= 202411L // >= C++26
{
using _ValT = typename remove_pointer<_Src>::type;
__builtin_memcpy(std::__niter_base(__result),
- std::__niter_base(__first),
+ std::__miter_base(std::__niter_base(__first)),
__n * sizeof(_ValT));
__result += __n;
}
--- /dev/null
+// { dg-options "-O1 -fdump-tree-optimized" }
+// { dg-do compile { target c++17 } }
+// { dg-final { scan-tree-dump "memcpy" "optimized" } }
+
+// PR libstdc++/121789
+// std::uninitialized_move_n() and friends don't optimize to memcpy
+
+#include <memory>
+
+struct T { int x; };
+
+void f(T* src, T* dst, unsigned n)
+{
+ std::uninitialized_move(src, src + n, dst);
+}
+
+void g(T* src, T* dst, unsigned n)
+{
+ std::uninitialized_move_n(src, n, dst);
+}
X operator>=(T, T)
{ return X(); }
+ /*
template<typename T>
X operator-(T, T)
{ return X(); }
- /*
+
template<typename T>
T operator+(std::size_t, T)
{ return T(); }