aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorWilco Dijkstra <wdijkstr@arm.com>2016-10-05 12:31:05 +0000
committerWilco Dijkstra <wilco@gcc.gnu.org>2016-10-05 12:31:05 +0000
commit71dea1dd60888030f3130f16933becdf597538ab (patch)
tree2e5b327406e5695e411f9f03cf0000a0eb1aafa8 /gcc
parent92805612f4e0cdd33e10282eaf2cc0369bca3293 (diff)
downloadgcc-71dea1dd60888030f3130f16933becdf597538ab.zip
gcc-71dea1dd60888030f3130f16933becdf597538ab.tar.gz
gcc-71dea1dd60888030f3130f16933becdf597538ab.tar.bz2
Move all existing strchr and strrchr folding from builtins.c to gimple-fold.c.
gcc/ * builtins.c (fold_builtin_strchr): Remove function. (fold_builtin_strrchr): Likewise. (fold_builtin2): Remove strchr, index, strrchr, rindex cases. * gimple-fold.c (target_char_cst_p): New function. (gimple_fold_builtin_strchr) Add more foldings. (gimple_fold_builtin): Add index, strrchr, rindex cases. From-SVN: r240782
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/builtins.c128
-rw-r--r--gcc/gimple-fold.c69
3 files changed, 70 insertions, 136 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4fcd8f5..81e4235 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2016-10-05 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * builtins.c (fold_builtin_strchr): Remove function.
+ (fold_builtin_strrchr): Likewise.
+ (fold_builtin2): Remove strchr, index, strrchr, rindex cases.
+ * gimple-fold.c (target_char_cst_p): New function.
+ (gimple_fold_builtin_strchr) Add more foldings.
+ (gimple_fold_builtin): Add index, strrchr, rindex cases.
+
2016-10-05 Richard Biener <rguenther@suse.de>
PR middle-end/77863
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 35cb109..facecd3 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -148,7 +148,6 @@ static tree rewrite_call_expr (location_t, tree, int, tree, int, ...);
static bool validate_arg (const_tree, enum tree_code code);
static rtx expand_builtin_fabs (tree, rtx, rtx);
static rtx expand_builtin_signbit (tree, rtx);
-static tree fold_builtin_strchr (location_t, tree, tree, tree);
static tree fold_builtin_memchr (location_t, tree, tree, tree, tree);
static tree fold_builtin_memcmp (location_t, tree, tree, tree);
static tree fold_builtin_strcmp (location_t, tree, tree);
@@ -168,7 +167,6 @@ static tree fold_builtin_varargs (location_t, tree, tree*, int);
static tree fold_builtin_strpbrk (location_t, tree, tree, tree);
static tree fold_builtin_strstr (location_t, tree, tree, tree);
-static tree fold_builtin_strrchr (location_t, tree, tree, tree);
static tree fold_builtin_strspn (location_t, tree, tree);
static tree fold_builtin_strcspn (location_t, tree, tree);
@@ -8395,14 +8393,6 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1)
case BUILT_IN_STRCSPN:
return fold_builtin_strcspn (loc, arg0, arg1);
- case BUILT_IN_STRCHR:
- case BUILT_IN_INDEX:
- return fold_builtin_strchr (loc, arg0, arg1, type);
-
- case BUILT_IN_STRRCHR:
- case BUILT_IN_RINDEX:
- return fold_builtin_strrchr (loc, arg0, arg1, type);
-
case BUILT_IN_STRCMP:
return fold_builtin_strcmp (loc, arg0, arg1);
@@ -8895,124 +8885,6 @@ fold_builtin_strstr (location_t loc, tree s1, tree s2, tree type)
}
}
-/* Simplify a call to the strchr builtin. S1 and S2 are the arguments to
- the call, and TYPE is its return type.
-
- Return NULL_TREE if no simplification was possible, otherwise return the
- simplified form of the call as a tree.
-
- The simplified form may be a constant or other expression which
- computes the same value, but in a more efficient manner (including
- calls to other builtin functions).
-
- The call may contain arguments which need to be evaluated, but
- which are not useful to determine the result of the call. In
- this case we return a chain of COMPOUND_EXPRs. The LHS of each
- COMPOUND_EXPR will be an argument which must be evaluated.
- COMPOUND_EXPRs are chained through their RHS. The RHS of the last
- COMPOUND_EXPR in the chain will contain the tree for the simplified
- form of the builtin function call. */
-
-static tree
-fold_builtin_strchr (location_t loc, tree s1, tree s2, tree type)
-{
- if (!validate_arg (s1, POINTER_TYPE)
- || !validate_arg (s2, INTEGER_TYPE))
- return NULL_TREE;
- else
- {
- const char *p1;
-
- if (TREE_CODE (s2) != INTEGER_CST)
- return NULL_TREE;
-
- p1 = c_getstr (s1);
- if (p1 != NULL)
- {
- char c;
- const char *r;
- tree tem;
-
- if (target_char_cast (s2, &c))
- return NULL_TREE;
-
- r = strchr (p1, c);
-
- if (r == NULL)
- return build_int_cst (TREE_TYPE (s1), 0);
-
- /* Return an offset into the constant string argument. */
- tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
- return fold_convert_loc (loc, type, tem);
- }
- return NULL_TREE;
- }
-}
-
-/* Simplify a call to the strrchr builtin. S1 and S2 are the arguments to
- the call, and TYPE is its return type.
-
- Return NULL_TREE if no simplification was possible, otherwise return the
- simplified form of the call as a tree.
-
- The simplified form may be a constant or other expression which
- computes the same value, but in a more efficient manner (including
- calls to other builtin functions).
-
- The call may contain arguments which need to be evaluated, but
- which are not useful to determine the result of the call. In
- this case we return a chain of COMPOUND_EXPRs. The LHS of each
- COMPOUND_EXPR will be an argument which must be evaluated.
- COMPOUND_EXPRs are chained through their RHS. The RHS of the last
- COMPOUND_EXPR in the chain will contain the tree for the simplified
- form of the builtin function call. */
-
-static tree
-fold_builtin_strrchr (location_t loc, tree s1, tree s2, tree type)
-{
- if (!validate_arg (s1, POINTER_TYPE)
- || !validate_arg (s2, INTEGER_TYPE))
- return NULL_TREE;
- else
- {
- tree fn;
- const char *p1;
-
- if (TREE_CODE (s2) != INTEGER_CST)
- return NULL_TREE;
-
- p1 = c_getstr (s1);
- if (p1 != NULL)
- {
- char c;
- const char *r;
- tree tem;
-
- if (target_char_cast (s2, &c))
- return NULL_TREE;
-
- r = strrchr (p1, c);
-
- if (r == NULL)
- return build_int_cst (TREE_TYPE (s1), 0);
-
- /* Return an offset into the constant string argument. */
- tem = fold_build_pointer_plus_hwi_loc (loc, s1, r - p1);
- return fold_convert_loc (loc, type, tem);
- }
-
- if (! integer_zerop (s2))
- return NULL_TREE;
-
- fn = builtin_decl_implicit (BUILT_IN_STRCHR);
- if (!fn)
- return NULL_TREE;
-
- /* Transform strrchr(s1, '\0') to strchr(s1, '\0'). */
- return build_call_expr_loc (loc, fn, 2, s1, s2);
- }
-}
-
/* Simplify a call to the strpbrk builtin. S1 and S2 are the arguments
to the call, and TYPE is its return type.
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 1aae845..59c4cb8 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -57,6 +57,20 @@ along with GCC; see the file COPYING3. If not see
#include "tree-cfg.h"
+/* Return true if T is a constant and the value cast to a target char
+ can be represented by a host char.
+ Store the casted char constant in *P if so. */
+
+static bool
+target_char_cst_p (tree t, char *p)
+{
+ if (!tree_fits_uhwi_p (t) || CHAR_TYPE_SIZE != HOST_BITS_PER_CHAR)
+ return false;
+
+ *p = (char)tree_to_uhwi (t);
+ return true;
+}
+
/* Return true when DECL can be referenced from current unit.
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
We can get declarations that are not possible to reference for various
@@ -1457,23 +1471,61 @@ gimple_fold_builtin_strncpy (gimple_stmt_iterator *gsi,
return true;
}
-/* Simplify strchr (str, 0) into str + strlen (str).
+/* Fold function call to builtin strchr or strrchr.
+ If both arguments are constant, evaluate and fold the result,
+ otherwise simplify str(r)chr (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_fold_builtin_strchr (gimple_stmt_iterator *gsi, bool is_strrchr)
{
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);
+ const char *p;
+ char ch;
- if (optimize_function_for_size_p (cfun))
+ if (!gimple_call_lhs (stmt))
return false;
- if (!integer_zerop (c) || !gimple_call_lhs (stmt))
+ if ((p = c_getstr (str)) && target_char_cst_p (c, &ch))
+ {
+ const char *p1 = is_strrchr ? strrchr (p, ch) : strchr (p, ch);
+
+ if (p1 == NULL)
+ {
+ replace_call_with_value (gsi, integer_zero_node);
+ return true;
+ }
+
+ tree len = build_int_cst (size_type_node, p1 - p);
+ gimple_seq stmts = NULL;
+ gimple *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);
+ return true;
+ }
+
+ if (!integer_zerop (c))
return false;
+ /* Transform strrchr (s, 0) to strchr (s, 0) when optimizing for size. */
+ if (optimize_function_for_size_p (cfun))
+ {
+ tree strchr_fn = builtin_decl_implicit (BUILT_IN_STRCHR);
+
+ if (is_strrchr && strchr_fn)
+ {
+ gimple *repl = gimple_build_call (strchr_fn, 2, str, c);
+ replace_call_with_call_and_fold (gsi, repl);
+ return true;
+ }
+
+ return false;
+ }
+
tree len;
tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN);
@@ -2947,11 +2999,12 @@ 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_INDEX:
case BUILT_IN_STRCHR:
- if (gimple_fold_builtin_strchr (gsi))
- return true;
- /* Perform additional folding in builtin.c. */
- break;
+ return gimple_fold_builtin_strchr (gsi, false);
+ case BUILT_IN_RINDEX:
+ case BUILT_IN_STRRCHR:
+ return gimple_fold_builtin_strchr (gsi, true);
case BUILT_IN_FPUTS:
return gimple_fold_builtin_fputs (gsi, gimple_call_arg (stmt, 0),
gimple_call_arg (stmt, 1), false);