[Bug c++/93528] New: Object copy not optimized out for most sizes in strict aliasing memcpy pattern

andrey.vihrov at gmail dot com gcc-bugzilla@gcc.gnu.org
Fri Jan 31 19:08:00 GMT 2020


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

            Bug ID: 93528
           Summary: Object copy not optimized out for most sizes in strict
                    aliasing memcpy pattern
           Product: gcc
           Version: 9.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: andrey.vihrov at gmail dot com
  Target Milestone: ---
              Host: x86_64-pc-linux-gnu
            Target: x86_64-pc-linux-gnu

Consider the following code (a common pattern to avoid strict aliasing
violations):

    struct X
    {
        char arr[10];
    };

    void foo(void *p)
    {
        X x;

        memcpy(&x, p, sizeof(x));
        x.arr[0] = 42;
        memcpy(p, &x, sizeof(x));
    }

When the array is 1, 2, 4, 8 or 16 elements long, memcpy() is optimized out
with -O2. Output for x86-64 Linux:

    _Z3fooPv:
      movb $42, (%rdi)
      ret

For other struct sizes, copies are performed nonetheless. Depending on the
array size either an inline implementation or a call to memcpy() is inserted.
For the above case, on x86-64 Linux GCC generates

    _Z3fooPv:
      movq (%rdi), %rax
      movq %rax, -10(%rsp)
      movb $42, -10(%rsp)
      movq -10(%rsp), %rax
      movq %rax, (%rdi)
      ret

It seems that the field types and the layout of the struct don't matter, and
the optimization is conditional on object size only. For example,

    struct Y
    {
        int a, b, c;
    };

is affected as well.

As a variant, the problem also appears with a plain array instead of a struct:

    void bar(void *p)
    {
        int arr[3];

        memcpy(arr, p, sizeof(arr));
        arr[0] = 42;
        memcpy(p, arr, sizeof(arr));
    }

gives

    _Z3barPv:
      movq (%rdi), %rax
      movq %rax, -12(%rsp)
      movl $42, -12(%rsp)
      movq -12(%rsp), %rax
      movq %rax, (%rdi)
      ret


More information about the Gcc-bugs mailing list