diff options
author | Marek Polacek <polacek@redhat.com> | 2013-05-17 09:32:01 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2013-05-17 09:32:01 +0000 |
commit | 5b115c1f2bb402931e06e2979df006e607d5c6f4 (patch) | |
tree | 37045e2b3b3747a97aa02b2f03011ed1fee86477 | |
parent | 68119618f7a027c1c0205319fc9d315169e6d60f (diff) | |
download | gcc-5b115c1f2bb402931e06e2979df006e607d5c6f4.zip gcc-5b115c1f2bb402931e06e2979df006e607d5c6f4.tar.gz gcc-5b115c1f2bb402931e06e2979df006e607d5c6f4.tar.bz2 |
Add tree-ssa-strlen optimization.
From-SVN: r199006
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-25.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-26.c | 25 | ||||
-rw-r--r-- | gcc/tree-ssa-strlen.c | 30 |
4 files changed, 81 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0394c0e..7bb4e28 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/testsuite/gcc.dg/strlenopt-25.c b/gcc/testsuite/gcc.dg/strlenopt-25.c new file mode 100644 index 0000000..4862156 --- /dev/null +++ b/gcc/testsuite/gcc.dg/strlenopt-25.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.dg/strlenopt-26.c b/gcc/testsuite/gcc.dg/strlenopt-26.c new file mode 100644 index 0000000..089355e --- /dev/null +++ b/gcc/testsuite/gcc.dg/strlenopt-26.c @@ -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" } } */ diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 5ab3764..c0f9ccd 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -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))) { |