[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