diff options
author | Wilco Dijkstra <wdijkstr@arm.com> | 2016-09-28 11:06:41 +0000 |
---|---|---|
committer | Wilco Dijkstra <wilco@gcc.gnu.org> | 2016-09-28 11:06:41 +0000 |
commit | 912d9ec300f1f1262b1ab09798304d0c99ff5778 (patch) | |
tree | 3c170771d3f815d96a6d0ba133a16b9fe28bc717 | |
parent | 1b4be62ad3e153d2e4eda115698cbf33fca09781 (diff) | |
download | gcc-912d9ec300f1f1262b1ab09798304d0c99ff5778.zip gcc-912d9ec300f1f1262b1ab09798304d0c99ff5778.tar.gz gcc-912d9ec300f1f1262b1ab09798304d0c99ff5778.tar.bz2 |
Optimize strchr (s, 0) to s + strlen (s).
Optimize strchr (s, 0) to s + strlen (s). strchr (s, 0) appears a common
idiom for finding the end of a string, however it is not a very efficient
way of doing so. Strlen is a much simpler operation which is significantly
faster (eg. on x86 strlen is 50% faster for strings of 8 bytes and about
twice as fast as strchr on strings of 1KB).
gcc/
* gimple-fold.c (gimple_fold_builtin_strchr):
New function to optimize strchr (s, 0) to strlen.
(gimple_fold_builtin): Add BUILT_IN_STRCHR case.
testsuite/
* gcc.dg/strlenopt-20.c: Update test.
* gcc.dg/strlenopt-21.c: Likewise.
* gcc.dg/strlenopt-22.c: Likewise.
* gcc.dg/strlenopt-22g.c: Likewise.
* gcc.dg/strlenopt-26.c: Likewise.
* gcc.dg/strlenopt-5.c: Likewise.
* gcc.dg/strlenopt-7.c: Likewise.
* gcc.dg/strlenopt-9.c: Likewise.
From-SVN: r240568
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/gimple-fold.c | 51 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-20.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-21.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-22.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-22g.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-26.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-5.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-7.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/strlenopt-9.c | 4 |
11 files changed, 85 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4793646..75eeb63 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-09-28 Wilco Dijkstra <wdijkstr@arm.com> + + PR tree-optimization/61056 + * gimple-fold.c (gimple_fold_builtin_strchr): + New function to optimize strchr (s, 0) to strlen. + (gimple_fold_builtin): Add BUILT_IN_STRCHR case. + 2016-09-27 Robin Dapp <rdapp@linux.vnet.ibm.com> PR tree-optimization/77724 diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 23e4516..f5a5e5d 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -1457,6 +1457,55 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi, return true; } +/* Simplify strchr (str, 0) into str + strlen (str). + In general strlen is significantly faster than strchr + due to being a simpler operation. */ +static bool +gimple_fold_builtin_strchr (gimple_stmt_iterator *gsi) +{ + gimple *stmt = gsi_stmt (*gsi); + tree str = gimple_call_arg (stmt, 0); + tree c = gimple_call_arg (stmt, 1); + location_t loc = gimple_location (stmt); + + if (optimize_function_for_size_p (cfun)) + return false; + + if (!integer_zerop (c) || !gimple_call_lhs (stmt)) + return false; + + tree len; + tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN); + + if (!strlen_fn) + return false; + + /* Create newstr = strlen (str). */ + gimple_seq stmts = NULL; + gimple *new_stmt = gimple_build_call (strlen_fn, 1, str); + gimple_set_location (new_stmt, loc); + if (gimple_in_ssa_p (cfun)) + len = make_ssa_name (size_type_node); + else + len = create_tmp_reg (size_type_node); + gimple_call_set_lhs (new_stmt, len); + gimple_seq_add_stmt_without_update (&stmts, new_stmt); + + /* Create (str p+ strlen (str)). */ + new_stmt = gimple_build_assign (gimple_call_lhs (stmt), + POINTER_PLUS_EXPR, str, len); + gimple_seq_add_stmt_without_update (&stmts, new_stmt); + gsi_replace_with_seq_vops (gsi, stmts); + /* gsi now points at the assignment to the lhs, get a + stmt iterator to the strlen. + ??? We can't use gsi_for_stmt as that doesn't work when the + CFG isn't built yet. */ + gimple_stmt_iterator gsi2 = *gsi; + gsi_prev (&gsi2); + fold_stmt (&gsi2); + return true; +} + /* Simplify a call to the strcat builtin. DST and SRC are the arguments to the call. @@ -2898,6 +2947,8 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi) gimple_call_arg (stmt, 1)); case BUILT_IN_STRNCAT: return gimple_fold_builtin_strncat (gsi); + case BUILT_IN_STRCHR: + return gimple_fold_builtin_strchr (gsi); case BUILT_IN_FPUTS: return gimple_fold_builtin_fputs (gsi, gimple_call_arg (stmt, 0), gimple_call_arg (stmt, 1), false); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3de855f..0642e23 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2016-09-28 Wilco Dijkstra <wdijkstr@arm.com> + + * gcc.dg/strlenopt-20.c: Update test. + * gcc.dg/strlenopt-21.c: Likewise. + * gcc.dg/strlenopt-22.c: Likewise. + * gcc.dg/strlenopt-22g.c: Likewise. + * gcc.dg/strlenopt-26.c: Likewise. + * gcc.dg/strlenopt-5.c: Likewise. + * gcc.dg/strlenopt-7.c: Likewise. + * gcc.dg/strlenopt-9.c: Likewise. + 2016-09-27 Jakub Jelinek <jakub@redhat.com> * g++.dg/cpp1z/feat-cxx1z.C: Add __cpp_capture_star_this test. diff --git a/gcc/testsuite/gcc.dg/strlenopt-20.c b/gcc/testsuite/gcc.dg/strlenopt-20.c index a83e845..7b483ea 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-20.c +++ b/gcc/testsuite/gcc.dg/strlenopt-20.c @@ -86,9 +86,9 @@ main () return 0; } -/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */ /* { dg-final { scan-tree-dump-times "memcpy \\(" 4 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ -/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ diff --git a/gcc/testsuite/gcc.dg/strlenopt-21.c b/gcc/testsuite/gcc.dg/strlenopt-21.c index e22fa9f..05b85a4 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-21.c +++ b/gcc/testsuite/gcc.dg/strlenopt-21.c @@ -57,9 +57,9 @@ main () return 0; } -/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */ /* { dg-final { scan-tree-dump-times "memcpy \\(" 3 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ -/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ diff --git a/gcc/testsuite/gcc.dg/strlenopt-22.c b/gcc/testsuite/gcc.dg/strlenopt-22.c index aa55f5e..b4ef772 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-22.c +++ b/gcc/testsuite/gcc.dg/strlenopt-22.c @@ -31,9 +31,9 @@ main () return 0; } -/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strlen \\(" 4 "strlen" } } */ /* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ -/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ diff --git a/gcc/testsuite/gcc.dg/strlenopt-22g.c b/gcc/testsuite/gcc.dg/strlenopt-22g.c index 3e2f8c46..9c5d020 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-22g.c +++ b/gcc/testsuite/gcc.dg/strlenopt-22g.c @@ -5,9 +5,9 @@ #define USE_GNU #include "strlenopt-22.c" -/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */ /* { dg-final { scan-tree-dump-times "memcpy \\(" 1 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ -/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "stpcpy \\(" 1 "strlen" } } */ diff --git a/gcc/testsuite/gcc.dg/strlenopt-26.c b/gcc/testsuite/gcc.dg/strlenopt-26.c index 4bd54be..da2f465 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-26.c +++ b/gcc/testsuite/gcc.dg/strlenopt-26.c @@ -21,4 +21,5 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ diff --git a/gcc/testsuite/gcc.dg/strlenopt-5.c b/gcc/testsuite/gcc.dg/strlenopt-5.c index 1b006a9..a24aea4 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-5.c +++ b/gcc/testsuite/gcc.dg/strlenopt-5.c @@ -48,9 +48,9 @@ main () return 0; } -/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strlen \\(" 2 "strlen" } } */ /* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ -/* { dg-final { scan-tree-dump-times "strchr \\(" 2 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ diff --git a/gcc/testsuite/gcc.dg/strlenopt-7.c b/gcc/testsuite/gcc.dg/strlenopt-7.c index 3ae1e2c..aa53d7e 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-7.c +++ b/gcc/testsuite/gcc.dg/strlenopt-7.c @@ -40,11 +40,11 @@ main () return 0; } -/* { dg-final { scan-tree-dump-times "strlen \\(" 0 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strlen \\(" 1 "strlen" } } */ /* { dg-final { scan-tree-dump-times "memcpy \\(" 2 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcpy \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ -/* { dg-final { scan-tree-dump-times "strchr \\(" 1 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "\\*r_\[0-9\]* = 0;" 1 "strlen" } } */ /* { dg-final { scan-tree-dump-times "return 3;" 1 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/strlenopt-9.c b/gcc/testsuite/gcc.dg/strlenopt-9.c index f78defe..e8ff102 100644 --- a/gcc/testsuite/gcc.dg/strlenopt-9.c +++ b/gcc/testsuite/gcc.dg/strlenopt-9.c @@ -98,10 +98,10 @@ main () return 0; } -/* { dg-final { scan-tree-dump-times "strlen \\(" 3 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strlen \\(" 5 "strlen" } } */ /* { dg-final { scan-tree-dump-times "memcpy \\(" 6 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcpy \\(" 1 "strlen" } } */ /* { dg-final { scan-tree-dump-times "strcat \\(" 0 "strlen" } } */ -/* { dg-final { scan-tree-dump-times "strchr \\(" 3 "strlen" } } */ +/* { dg-final { scan-tree-dump-times "strchr \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "stpcpy \\(" 0 "strlen" } } */ /* { dg-final { scan-tree-dump-times "return 4;" 1 "optimized" } } */ |