aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilco Dijkstra <wdijkstr@arm.com>2016-09-28 11:06:41 +0000
committerWilco Dijkstra <wilco@gcc.gnu.org>2016-09-28 11:06:41 +0000
commit912d9ec300f1f1262b1ab09798304d0c99ff5778 (patch)
tree3c170771d3f815d96a6d0ba133a16b9fe28bc717
parent1b4be62ad3e153d2e4eda115698cbf33fca09781 (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/gimple-fold.c51
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-20.c4
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-21.c4
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-22.c4
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-22g.c4
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-26.c3
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-5.c4
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-7.c4
-rw-r--r--gcc/testsuite/gcc.dg/strlenopt-9.c4
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" } } */