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
This commit is contained in:
Wilco Dijkstra 2016-09-28 11:06:41 +00:00 committed by Wilco Dijkstra
parent 1b4be62ad3
commit 912d9ec300
11 changed files with 85 additions and 15 deletions

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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