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

            Bug ID: 121946
           Summary: [missing optimization] std::vector does not use memcpy
                    for the trivially copyable/destructible type
           Product: gcc
           Version: 15.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dmitriy.ovdienko at gmail dot com
  Target Milestone: ---

I have a class which is trivially copyable, moveable and destructible. It is
pretty much similar to the `int` type. 

#include <vector>

template<typename T, T EmptyValue>
struct my_optional
{
    T value_ {EmptyValue};

    my_optional() = default;
    my_optional(T value) : value_(value) {}
};

void foo_my_optional(std::vector<my_optional<int, -1>>& v)
{
    v.push_back(1);
}

void foo_int(std::vector<int>& v)
{
    v.push_back(1);
}


My goal is to implement it in such way, so it follows the zero-overhead
principle. In fact, when I compare the assembly generated for the
std::vector<int>, there is a difference. 

For the std::vector<int> I see compiler uses memcpy during the reallocation
while for the std::vector<my_optional> it does not. Instead, it generates some
loop.

It seems the issue is std::uninitialized_copy function. For some reason in
order to use memcpy it requires the class to be trivially_constructible:

      if constexpr (!__is_trivially_constructible(_ValT, decltype(*__first)))
        return std::__do_uninit_copy(__first, __last, __result);
      else if constexpr (__memcpyable<_Dest, _Src>::__value)
        {
          ptrdiff_t __n = __last - __first;
          if (__n > 0) [[__likely__]]
            {
              using _ValT = typename remove_pointer<_Src>::type;
              __builtin_memcpy(std::__niter_base(__result),
                               std::__niter_base(__first),
                               __n * sizeof(_ValT));
              __result += __n;
            }
          return __result;
        }

... while from my perspective it is enough to be trivially destructible and
trivially copyable/moveable.

Link to the godbolt.org: https://godbolt.org/z/cx9PqfqGv

Reply via email to