https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77889
Bug ID: 77889 Summary: missing optimization on strlen(p + offset) with a bounded offset Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- While testing my patch for bug 77608 I noticed another case of the same limitation, this one in the tree-ssa-strlen pass. The test case below shows that while (with my patch) __builtin_object_size is able to compute the range the smallest sizes of the string that p points to (i.e., either 2 or 3 bytes), __builtin_strlen is not able to compute the range of lengths of the string that p points to, even though the range of the offsets into the string is available via the get_range_info function. (The test cases uses _Bool only to constrain the range to small bounds; the problem is general and not specific to a particular type of the offset variable.) $ cat rng.c && /build/gcc-77608/gcc/xgcc -B /build/gcc-77608/gcc -O2 -S -Wall -Wextra -Wpedantic -fdump-tree-vrp=/dev/stdout rng.c void f (_Bool i) { const char *p = "abc"; p += i; unsigned long n = __builtin_strlen (p); if (n < 2 || 3 < n) __builtin_abort (); } void g (_Bool i) { const char *p = "ab"; p += i; unsigned long n = __builtin_object_size (p, 2); if (n < 2 || 3 < n) __builtin_abort (); } ;; Function f (f, funcdef_no=0, decl_uid=1791, cgraph_uid=0, symbol_order=0) ;; 1 loops found ;; ;; Loop 0 ;; header 0, latch 1 ;; depth 0, outer -1 ;; nodes: 0 1 2 3 4 ;; 2 succs { 3 4 } ;; 3 succs { } ;; 4 succs { 1 } Value ranges after VRP: _1: [0, 1] _2: [0, +INF] i_3(D): VARYING p_4: VARYING n_6: VARYING f (_Bool i) { long unsigned int n; const char * p; sizetype _1; long unsigned int _2; <bb 2>: _1 = (sizetype) i_3(D); p_4 = "abc" + _1; n_6 = __builtin_strlen (p_4); _2 = n_6 + 18446744073709551614; if (_2 > 1) goto <bb 3>; else goto <bb 4>; <bb 3>: __builtin_abort (); <bb 4>: return; } ;; Function f (f, funcdef_no=0, decl_uid=1791, cgraph_uid=0, symbol_order=0) ;; 1 loops found ;; ;; Loop 0 ;; header 0, latch 1 ;; depth 0, outer -1 ;; nodes: 0 1 2 3 4 ;; 2 succs { 3 4 } ;; 3 succs { } ;; 4 succs { 1 } Value ranges after VRP: _1: [0, 1] _2: [0, +INF] i_3(D): VARYING p_4: VARYING n_6: VARYING f (_Bool i) { long unsigned int n; const char * p; sizetype _1; long unsigned int _2; <bb 2>: _1 = (sizetype) i_3(D); p_4 = "abc" + _1; n_6 = __builtin_strlen (p_4); _2 = n_6 + 18446744073709551614; if (_2 > 1) goto <bb 3>; else goto <bb 4>; <bb 3>: __builtin_abort (); <bb 4>: return; } ;; Function g (g, funcdef_no=1, decl_uid=1796, cgraph_uid=1, symbol_order=1) ;; 1 loops found ;; ;; Loop 0 ;; header 0, latch 1 ;; depth 0, outer -1 ;; nodes: 0 1 2 ;; 2 succs { 1 } Value ranges after VRP: _1: [0, 1] i_3(D): VARYING p_4: VARYING n_6: VARYING g (_Bool i) { long unsigned int n; const char * p; sizetype _1; <bb 2>: _1 = (sizetype) i_3(D); p_4 = "ab" + _1; n_6 = __builtin_object_size (p_4, 2); return; } ;; Function g (g, funcdef_no=1, decl_uid=1796, cgraph_uid=1, symbol_order=1) ;; 1 loops found ;; ;; Loop 0 ;; header 0, latch 1 ;; depth 0, outer -1 ;; nodes: 0 1 2 ;; 2 succs { 1 } Value ranges after VRP: g (_Bool i) { long unsigned int n; const char * p; <bb 2>: return; }