Add tree-ssa-strlen optimization.

From-SVN: r199006
This commit is contained in:
Marek Polacek 2013-05-17 09:32:01 +00:00 committed by Marek Polacek
parent 68119618f7
commit 5b115c1f2b
4 changed files with 81 additions and 1 deletions

View File

@ -1,3 +1,12 @@
2013-05-17 Marek Polacek <polacek@redhat.com>
* tree-ssa-strlen.c (handle_char_store): Don't invalidate
cached length when doing non-zero store of storing '\0' to
'\0'.
* gcc.dg/strlenopt-25.c: New test.
* gcc.dg/strlenopt-26.c: Likewise.
2013-05-17 Jakub Jelinek <jakub@redhat.com>
* tree-vect-patterns.c (vect_recog_rotate_pattern): For

View File

@ -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" } } */

View File

@ -0,0 +1,25 @@
/* { dg-do run } */
/* { dg-options "-O2 -fdump-tree-strlen" } */
#include "strlenopt.h"
__attribute__((noinline, noclone)) size_t
fn1 (char *p, const char *r)
{
size_t len1 = strlen (r);
char *q = strchr (p, '\0');
*q = '\0';
return len1 - strlen (r); // This strlen should be optimized into len1.
}
int
main (void)
{
char p[] = "foobar";
const char *volatile q = "xyzzy";
fn1 (p, q);
return 0;
}
/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */
/* { dg-final { cleanup-tree-dump "strlen" } } */

View File

@ -1694,7 +1694,8 @@ handle_char_store (gimple_stmt_iterator *gsi)
else
{
si->writable = true;
si->dont_invalidate = true;
gsi_next (gsi);
return false;
}
}
else
@ -1717,6 +1718,33 @@ handle_char_store (gimple_stmt_iterator *gsi)
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 and any other zero terminated string in memory 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[20];
void foo (char *q)
{
strcpy (p, "foobar");
size_t len = strlen (p); // This can be optimized into 6
size_t len2 = strlen (q); // This has to be computed
p[0] = 'X';
size_t len3 = strlen (p); // This can be optimized into 6
size_t len4 = strlen (q); // This can be optimized into len2
bar (len, len2, len3, len4);
}
*/
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)))
{