https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80937
Bug ID: 80937 Summary: redundant bcopy/memcpy/strcpy to a non-local object not eliminated Product: gcc Version: 7.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 redundant calls to bcopy and memcpy involving the same local variable but doesn't eliminate redundant calls to the same two functions when the target is the same global variable, or a pointer to some unknown variable. It does, however, eliminate calls to bzero and memset regardless of whether of the storage duration of the target object. This seems like a missed optimization opportunity. $ cat t.c && gcc -O2 -S -Wall -Wextra -fdump-tree-optimized=/dev/stdout t.c void sink (void*); char a[33]; void memcpy_global (const void *s) { __builtin_memcpy (a, s, sizeof a); __builtin_memcpy (a, s, sizeof a); sink (a); } void bcopy_global (const void *s) { __builtin_bcopy (s, a, sizeof a); __builtin_bcopy (s, a, sizeof a); sink (a); } void memset_global (void) { __builtin_memset (a, 0, sizeof a); __builtin_memset (a, 0, sizeof a); sink (a); } void bzero_global (void) { __builtin_memset (a, 0, sizeof a); __builtin_memset (a, 0, sizeof a); sink (a); } void memcpy_local (const void *s) { char a[33]; __builtin_memcpy (a, s, sizeof a); __builtin_memcpy (a, s, sizeof a); sink (a); } void bcopy_local (const void *s) { char a[33]; __builtin_bcopy (s, a, sizeof a); __builtin_bcopy (s, a, sizeof a); sink (a); } void memset_local (void) { char a[33]; __builtin_memset (a, 0, sizeof a); __builtin_memset (a, 0, sizeof a); sink (a); } void bzero_local (void) { char a[33]; __builtin_memset (a, 0, sizeof a); __builtin_memset (a, 0, sizeof a); sink (a); } ;; Function memcpy_global (memcpy_global, funcdef_no=0, decl_uid=1796, cgraph_uid=0, symbol_order=1) memcpy_global (const void * s) { <bb 2> [100.00%]: MEM[(char * {ref-all})&a] = MEM[(char * {ref-all})s_2(D)]; MEM[(char * {ref-all})&a] = MEM[(char * {ref-all})s_2(D)]; sink (&a); [tail call] return; } ;; Function bcopy_global (bcopy_global, funcdef_no=1, decl_uid=1799, cgraph_uid=1, symbol_order=2) bcopy_global (const void * s) { <bb 2> [100.00%]: __builtin_bcopy (s_2(D), &a, 33); __builtin_bcopy (s_2(D), &a, 33); sink (&a); [tail call] return; } ;; Function memset_global (memset_global, funcdef_no=2, decl_uid=1802, cgraph_uid=2, symbol_order=3) memset_global () { <bb 2> [100.00%]: __builtin_memset (&a, 0, 33); sink (&a); [tail call] return; } ;; Function bzero_global (bzero_global, funcdef_no=9, decl_uid=1805, cgraph_uid=3, symbol_order=4) bzero_global () { <bb 2> [100.00%]: memset_global (); [tail call] return; } ;; Function memcpy_local (memcpy_local, funcdef_no=4, decl_uid=1808, cgraph_uid=4, symbol_order=5) memcpy_local (const void * s) { char a[33]; <bb 2> [100.00%]: MEM[(char * {ref-all})&a] = MEM[(char * {ref-all})s_2(D)]; sink (&a); a ={v} {CLOBBER}; return; } ;; Function bcopy_local (bcopy_local, funcdef_no=11, decl_uid=1812, cgraph_uid=5, symbol_order=6) bcopy_local (const void * s) { <bb 2> [100.00%]: memcpy_local (s_2(D)); [tail call] return; } ;; Function memset_local (memset_local, funcdef_no=6, decl_uid=1816, cgraph_uid=6, symbol_order=7) memset_local () { char a[33]; <bb 2> [100.00%]: __builtin_memset (&a, 0, 33); sink (&a); a ={v} {CLOBBER}; return; } ;; Function bzero_local (bzero_local, funcdef_no=13, decl_uid=1820, cgraph_uid=7, symbol_order=8) bzero_local () { <bb 2> [100.00%]: memset_local (); [tail call] return; }