On Thu, May 16, 2013 at 03:38:47PM +0200, Jakub Jelinek wrote: > Please add here a comment what it does and why, that if si->length > is non-zero constant, we know that the character at that spot is > not '\0' and when storing non-'\0' to that location, we can't affect > size of any strings at all. Therefore we do the gsi_next + return false > to signal caller that it shouldn't invalidate anything. > > Ok with that change, thanks.
Thanks, this what I'll commit later today if no objections. 2013-05-16 Marek Polacek <pola...@redhat.com> * tree-ssa-strlen.c (handle_char_store): Don't invalidate cached length when doing non-zero store. * gcc.dg/strlenopt-25.c: New test. --- gcc/tree-ssa-strlen.c.mp 2013-05-15 14:11:20.079707492 +0200 +++ gcc/tree-ssa-strlen.c 2013-05-16 16:03:50.373504796 +0200 @@ -1717,6 +1717,27 @@ handle_char_store (gimple_stmt_iterator si->endptr = ssaname; si->dont_invalidate = true; } + /* If si->length is non-zero constant, we aren't overwriting '\0', + and if we aren't storing '\0', we know that the length of the + string remains the same. In that case we move to the next + gimple statement and return to signal the caller that it shouldn't + invalidate anything. + + This is benefical for cases like: + + char p[] = "foobar"; + size_t len = strlen (p); + p[0] = 'X' + size_t len2 = strlen (p); + + where we should be able to optimize away the second strlen call. */ + else if (si != NULL && si->length != NULL_TREE + && TREE_CODE (si->length) == INTEGER_CST + && integer_nonzerop (gimple_assign_rhs1 (stmt))) + { + gsi_next (gsi); + return false; + } } else if (idx == 0 && initializer_zerop (gimple_assign_rhs1 (stmt))) { --- gcc/testsuite/gcc.dg/strlenopt-25.c.mp 2013-05-15 17:15:18.702118637 +0200 +++ gcc/testsuite/gcc.dg/strlenopt-25.c 2013-05-15 18:26:27.881030317 +0200 @@ -0,0 +1,18 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-strlen" } */ + +#include "strlenopt.h" + +int +main () +{ + char p[] = "foobar"; + int len, len2; + len = strlen (p); + p[0] = 'O'; + len2 = strlen (p); + return len - len2; +} + +/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */ +/* { dg-final { cleanup-tree-dump "strlen" } } */ Marek