https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82912
Bug ID: 82912 Summary: missing strlen optimization for stpncpy with constant string and bound 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 can figure out the length of the string created by the call to strncpy() in f0() but it doesn't do the same for stpncpy() in f2() or f3(). Using stpncpy() the way f2() and f3() do is idiomatic and often preferred because it is assumed to be more efficient than the equivalent sequence involving strncpy(). See also pr82911 for a similar missed optimization opportunity involving strncpy(). $ cat c.c && gcc -O2 -S -Wall -Wextra -fdump-tree-optimized=/dev/stdout c.c void f0 (char *d) { __builtin_strncpy (d, "123", 2); d[2] = 0; if (__builtin_strlen (d) != 2) // eliminated, good __builtin_abort (); } void f2 (char *d) { *__builtin_stpncpy (d, "123", 2) = 0; if (__builtin_strlen (d) != 2) // not eliminated but should be __builtin_abort (); } void f3 (char *d, _Bool b) { *__builtin_stpncpy (d, b ? "123" : "1234", 2) = 0; if (__builtin_strlen (d) != 2) // not eliminated but could be __builtin_abort (); } ;; Function f0 (f0, funcdef_no=0, decl_uid=1887, cgraph_uid=0, symbol_order=0) f0 (char * d) { <bb 2> [local count: 10000]: __builtin_memcpy (d_3(D), "123", 2); MEM[(char *)d_3(D) + 2B] = 0; return; } ;; Function f2 (f2, funcdef_no=1, decl_uid=1890, cgraph_uid=1, symbol_order=1) f2 (char * d) { char * _1; long unsigned int _2; <bb 2> [local count: 10000]: _1 = __builtin_stpncpy (d_4(D), "123", 2); *_1 = 0; _2 = __builtin_strlen (d_4(D)); if (_2 != 2) goto <bb 3>; [0.04%] else goto <bb 4>; [99.96%] <bb 3> [count: 0]: __builtin_abort (); <bb 4> [local count: 9996]: return; } ;; Function f3 (f3, funcdef_no=2, decl_uid=1894, cgraph_uid=2, symbol_order=2) f3 (char * d, _Bool b) { char * _1; long unsigned int _2; const char * iftmp.0_3; <bb 2> [local count: 10000]: if (b_4(D) != 0) goto <bb 4>; [50.00%] else goto <bb 3>; [50.00%] <bb 3> [local count: 5000]: <bb 4> [local count: 10000]: # iftmp.0_3 = PHI <"123"(2), "1234"(3)> _1 = __builtin_stpncpy (d_6(D), iftmp.0_3, 2); *_1 = 0; _2 = __builtin_strlen (d_6(D)); if (_2 != 2) goto <bb 5>; [0.04%] else goto <bb 6>; [99.96%] <bb 5> [count: 0]: __builtin_abort (); <bb 6> [local count: 9996]: return; }