https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114821

--- Comment #2 from Jan Hubicka <hubicka at gcc dot gnu.org> ---
What I am shooting for is to optimize it later in loop distribution. We can
recognize memcpy loop if we can figure out that source and destination memory
are different.

We can help here with restrict, but I was bit lost in how to get them done.

This seems to do the trick, but for some reason I get memmove

diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h
b/libstdc++-v3/include/bits/stl_uninitialized.h
index 7f84da31578..1a6223ea892 100644
--- a/libstdc++-v3/include/bits/stl_uninitialized.h
+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
@@ -1130,7 +1130,58 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
       return __result + __count;
     }
+
+  template <typename _Tp, typename _Allocator>
+    _GLIBCXX20_CONSTEXPR
+    inline __enable_if_t<std::__is_bitwise_relocatable<_Tp>::value, _Tp*>
+    __relocate_a(_Tp * __restrict __first, _Tp *__last,
+                _Tp * __restrict __result, _Allocator& __alloc) noexcept
+    {
+      ptrdiff_t __count = __last - __first;
+      if (__count > 0)
+       {
+#ifdef __cpp_lib_is_constant_evaluated
+         if (std::is_constant_evaluated())
+           {
+             for (; __first != __last; ++__first, (void)++__result)
+               {
+                 // manually inline relocate_object_a to not lose restrict
qualifiers
+                 typedef std::allocator_traits<_Allocator> __traits;
+                 __traits::construct(__alloc, __result, std::move(*__first));
+                 __traits::destroy(__alloc, std::__addressof(*__first));
+               }
+             return __result;
+           }
 #endif
+         __builtin_memcpy(__result, __first, __count * sizeof(_Tp));
+       }
+      return __result + __count;
+    }
+#endif
+
+  template <typename _Tp, typename _Allocator>
+    _GLIBCXX20_CONSTEXPR
+#if _GLIBCXX_HOSTED
+    inline __enable_if_t<!std::__is_bitwise_relocatable<_Tp>::value, _Tp*>
+#else
+    inline _Tp *
+#endif
+    __relocate_a(_Tp * __restrict __first, _Tp *__last,
+                _Tp * __restrict __result, _Allocator& __alloc)
+    noexcept(noexcept(std::allocator_traits<_Allocator>::construct(__alloc,
+                        __result, std::move(*__first)))
+            && noexcept(std::allocator_traits<_Allocator>::destroy(
+                           __alloc, std::__addressof(*__first))))
+    {
+      for (; __first != __last; ++__first, (void)++__result)
+       {
+         // manually inline relocate_object_a to not lose restrict qualifiers
+         typedef std::allocator_traits<_Allocator> __traits;
+         __traits::construct(__alloc, __result, std::move(*__first));
+         __traits::destroy(__alloc, std::__addressof(*__first));
+       }
+      return __result;
+    }

   template <typename _InputIterator, typename _ForwardIterator,
            typename _Allocator>

Reply via email to