https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84794
Bug ID: 84794 Summary: memcpy between a struct and its first member not eliminated Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- GCC eliminates most calls to memcpy where the first two arguments are guaranteed to be the same. However, it fails to eliminate such calls when one of the arguments points to a struct object and the other to the first member of the same struct object. $ cat z.c && gcc -O2 -S -Wall -Wextra -Wpedantic -Wrestrict -fdump-tree-optimized=/dev/stdout z.c extern void* memcpy (void* restrict, const void* restrict, __SIZE_TYPE__); struct S { union { char a[4], b[4]; }; } s; void f (struct S *p) { if ((void*)p != p->a || (void*)p != p->b) // folded to false (good) __builtin_abort (); // eliminated } void g (struct S *p, unsigned n) { memcpy (p->a, p->b, n); // undefined and eliminated (good) } void h (struct S *p, unsigned n) { memcpy (p, p->b, n); // also undefined but not eliminated } ;; Function f (f, funcdef_no=0, decl_uid=1968, cgraph_uid=0, symbol_order=1) f (struct S * p) { <bb 2> [local count: 1073741825]: return; } z.c: In function ‘g’: z.c:17:3: warning: ‘memcpy’ source argument is the same as destination [-Wrestrict] memcpy (p->a, p->b, n); // -Wrestrict (good) ^~~~~~~~~~~~~~~~~~~~~~ ;; Function g (g, funcdef_no=1, decl_uid=1972, cgraph_uid=1, symbol_order=2) g (struct S * p, unsigned int n) { <bb 2> [local count: 1073741825]: return; } ;; Function h (h, funcdef_no=2, decl_uid=1976, cgraph_uid=2, symbol_order=3) h (struct S * p, unsigned int n) { long unsigned int _1; char[4] * _2; <bb 2> [local count: 1073741825]: _1 = (long unsigned int) n_3(D); _2 = &p_4(D)->D.1965.b; memcpy (p_4(D), _2, _1); [tail call] return; }