https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81704
Bug ID: 81704 Summary: strncpy folding defeats strlen optimization 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: --- Similar to bug 81703, when a call to strncpy() copies an initial sequence from a string of known length without NUL-terminating the result, the gimple_fold_builtin_strncpy function transforms the call into a direct memory access. When the copy is immediately followed by setting the last element of the destination to NUL the transformation then prevents a subsequent strlen optimization that could otherwise take place (bug 81433 tracks the strncpy optimization that's missing from tree-ssa-strlen). As a result, examples like the one in the test case below are not optimized into optimal code. As in bug 81703, I think the way to solve this is to defer the folding until after the tree-ssa-strlen pass has run, similarly to how bug 77671 has been handled. $ cat a.c && gcc -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-optimized=/dev/stdout a.c tree-optimized=/dev/stdout a.c unsigned f (void) { char d[8]; __builtin_strcpy (d, "0123456"); return __builtin_strlen (d); } unsigned g (void) { char d[8]; __builtin_strncpy (d, "01234567", sizeof d); d[sizeof d - 1] = '\0'; return __builtin_strlen (d); } ;; Function f (f, funcdef_no=0, decl_uid=1815, cgraph_uid=0, symbol_order=0) f () { <bb 2> [100.00%] [count: INV]: return 7; } ;; Function g (g, funcdef_no=1, decl_uid=1819, cgraph_uid=1, symbol_order=1) g () { char d[8]; long unsigned int _1; unsigned int _5; <bb 2> [100.00%] [count: INV]: MEM[(char * {ref-all})&d] = MEM[(char * {ref-all})"01234567"]; d[7] = 0; _1 = __builtin_strlen (&d); _5 = (unsigned int) _1; d ={v} {CLOBBER}; return _5; }