https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92155
Bug ID: 92155 Summary: strlen(a) not folded after memset(a, 0, sizeof a) Product: gcc Version: 9.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: --- Now that GCC unrolls memset-like loops with small numbers of iterations (pr91975) and transforms some of them into MEM_REF, the strlen pass can also determine the lengths of zeroed-out arrays to be zero. This can be seen in function f below. But GCC doesn't yet transform memset calls into the equivalent MEM_REFs, and the strlen pass for some reason can't figure out that the length of an array that's been zeroed-out by memset is also zero. This missed optimization can be seen in function g below. $ cat z.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout z.c extern char a4[4]; extern char b4[4]; void f (void) { for (int i = 0; i != sizeof a4; ++i) a4[i] = 0; for (int i = 0; i != sizeof b4; ++i) b4[i] = 0; if (__builtin_strlen (a4) != __builtin_strlen (b4)) __builtin_abort (); } void g (void) { __builtin_memset (a4, 0, sizeof a4); __builtin_memset (b4, 0, sizeof b4); if (__builtin_strlen (a4) != __builtin_strlen (b4)) __builtin_abort (); } ;; Function f (f, funcdef_no=0, decl_uid=1932, cgraph_uid=1, symbol_order=0) f () { <bb 2> [local count: 214748369]: MEM <unsigned int> [(char *)&a4] = 0; MEM <unsigned int> [(char *)&b4] = 0; return; } ;; Function g (g, funcdef_no=1, decl_uid=1943, cgraph_uid=2, symbol_order=1) g () { long unsigned int _1; long unsigned int _2; <bb 2> [local count: 1073741824]: __builtin_memset (&a4, 0, 4); __builtin_memset (&b4, 0, 4); _1 = __builtin_strlen (&a4); _2 = __builtin_strlen (&b4); if (_1 != _2) goto <bb 3>; [0.00%] else goto <bb 4>; [100.00%] <bb 3> [count: 0]: __builtin_abort (); <bb 4> [local count: 1073741824]: return; }