https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92128
Bug ID: 92128 Summary: fold more non-constant strlen relational expressions 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: --- With pr91996 resolved GCC can make use of strlen range information in some contexts but not in others. The test for pr91996 only enabled on a subset of those where GCC is known to be able to do this, but even for those it is specially crafted to exercise only the contexts where the optimization was implemented. On other targets (e.g., arm-*-*), or even on others such as aarch64-*-* where the test passes, other similar test cases fail. This is because the solution for pr91996 was only put in place for multi-byte assignments via MEM_REF but not also for calls to memcpy. $ cat c.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout c.c typedef __SIZE_TYPE__ size_t; void f (char *d, const char *s) { if (__builtin_strlen (s) < 5) return; __builtin_memcpy (d, s, 16); // when size is a small power of two size_t n1 = __builtin_strlen (d); if (n1 < 5) // this is folded to false __builtin_abort (); } void g (char *d, const char *s) { if (__builtin_strlen (s) < 5) return; __builtin_memcpy (d, s, 32); // with larger power of two or non-power-of-two sizes size_t n1 = __builtin_strlen (d); if (n1 < 5) // this is not folded __builtin_abort (); } ;; Function f (f, funcdef_no=0, decl_uid=1932, cgraph_uid=1, symbol_order=0) Removing basic block 5 f (char * d, const char * s) { long unsigned int _1; __int128 unsigned _5; <bb 2> [local count: 1073741824]: _1 = __builtin_strlen (s_4(D)); if (_1 <= 4) goto <bb 4>; [34.00%] else goto <bb 3>; [66.00%] <bb 3> [local count: 708669605]: _5 = MEM <__int128 unsigned> [(char * {ref-all})s_4(D)]; MEM <__int128 unsigned> [(char * {ref-all})d_6(D)] = _5; <bb 4> [local count: 1073741829]: return; } ;; Function g (g, funcdef_no=1, decl_uid=1937, cgraph_uid=2, symbol_order=1) Removing basic block 6 Removing basic block 7 g (char * d, const char * s) { size_t n1; long unsigned int _1; <bb 2> [local count: 1073741824]: _1 = __builtin_strlen (s_4(D)); if (_1 <= 4) goto <bb 5>; [51.12%] else goto <bb 3>; [48.88%] <bb 3> [local count: 524845004]: __builtin_memcpy (d_5(D), s_4(D), 32); n1_7 = __builtin_strlen (d_5(D)); if (n1_7 <= 4) goto <bb 4>; [0.00%] else goto <bb 5>; [100.00%] <bb 4> [count: 0]: __builtin_abort (); <bb 5> [local count: 1073741828]: return; }