Recent improvements to the strlen pass introduced the assumption that when the length of a string has been recorded by the pass the length is necessarily constant. Bug 83896 shows that this assumption is not always true, and that GCC fails with an ICE when it doesn't hold. To avoid the ICE the attached patch removes the assumption.
x86_64-linux bootstrap successful, regression test in progress. Martin
PR tree-optimization/83896 - ice in get_string_len on a call to strlen with non-constant length gcc/ChangeLog: PR tree-optimization/83896 * tree-ssa-strlen.c (get_string_len): Avoid assuming length is constant. gcc/testsuite/ChangeLog: PR tree-optimization/83896 * gcc.dg/strlenopt-43.c: New test. Index: gcc/tree-ssa-strlen.c =================================================================== --- gcc/tree-ssa-strlen.c (revision 256752) +++ gcc/tree-ssa-strlen.c (working copy) @@ -2772,7 +2772,9 @@ handle_pointer_plus (gimple_stmt_iterator *gsi) } } -/* Check if RHS is string_cst possibly wrapped by mem_ref. */ +/* If RHS, either directly or indirectly, refers to a string of constant + length, return it. Otherwise return a negative value. */ + static int get_string_len (tree rhs) { @@ -2789,7 +2791,8 @@ get_string_len (tree rhs) if (idx > 0) { strinfo *si = get_strinfo (idx); - if (si && si->full_string_p) + if (si && si->full_string_p + && TREE_CODE (si->nonzero_chars) == INTEGER_CST) return tree_to_shwi (si->nonzero_chars); } } Index: gcc/testsuite/gcc.dg/strlenopt-43.c =================================================================== --- gcc/testsuite/gcc.dg/strlenopt-43.c (nonexistent) +++ gcc/testsuite/gcc.dg/strlenopt-43.c (working copy) @@ -0,0 +1,13 @@ +/* PR tree-optimization/83896 - ice in get_string_len on a call to strlen + with non-constant length + { dg-do compile } + { dg-options "-O2 -Wall" } */ + +extern char a[5]; +extern char b[]; + +void f (void) +{ + if (__builtin_strlen (b) != 4) + __builtin_memcpy (a, b, sizeof a); +}