summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2014-01-20 18:18:21 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2014-01-20 18:18:21 +0000
commitb65555c1ab475f6a3757b4ecb1a5970e66bde20b (patch)
tree840adcd5d5e2cbfaf6b57c07e9227d984e6650a1
parent98fbe28d1ea9be47419a759a1e3c0653309f44fb (diff)
downloadgcc-b65555c1ab475f6a3757b4ecb1a5970e66bde20b.tar.gz
PR middle-end/59860
* tree.h (fold_builtin_strcat): New prototype. * builtins.c (fold_builtin_strcat): No longer static. Add len argument, if non-NULL, don't call c_strlen. Optimize directly into __builtin_memcpy instead of __builtin_strcpy. (fold_builtin_2): Adjust fold_builtin_strcat caller. * gimple-fold.c (gimple_fold_builtin): Handle BUILT_IN_STRCAT. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@206848 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/builtins.c23
-rw-r--r--gcc/gimple-fold.c8
-rw-r--r--gcc/tree.h1
4 files changed, 33 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a199b8da959..a57bffec83c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2014-01-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/59860
+ * tree.h (fold_builtin_strcat): New prototype.
+ * builtins.c (fold_builtin_strcat): No longer static. Add len
+ argument, if non-NULL, don't call c_strlen. Optimize
+ directly into __builtin_memcpy instead of __builtin_strcpy.
+ (fold_builtin_2): Adjust fold_builtin_strcat caller.
+ * gimple-fold.c (gimple_fold_builtin): Handle BUILT_IN_STRCAT.
+
2014-01-20 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.c (ix86_avoid_lea_for_addr): Return false
diff --git a/gcc/builtins.c b/gcc/builtins.c
index c597e44e58c..d2ea606260b 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -191,7 +191,6 @@ static tree fold_builtin_varargs (location_t, tree, tree, bool);
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_strcat (location_t, tree, tree);
static tree fold_builtin_strncat (location_t, tree, tree, tree);
static tree fold_builtin_strspn (location_t, tree, tree);
static tree fold_builtin_strcspn (location_t, tree, tree);
@@ -10787,7 +10786,7 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
return fold_builtin_strstr (loc, arg0, arg1, type);
case BUILT_IN_STRCAT:
- return fold_builtin_strcat (loc, arg0, arg1);
+ return fold_builtin_strcat (loc, arg0, arg1, NULL_TREE);
case BUILT_IN_STRSPN:
return fold_builtin_strspn (loc, arg0, arg1);
@@ -11736,8 +11735,9 @@ fold_builtin_strpbrk (location_t loc, tree s1, tree s2, tree type)
COMPOUND_EXPR in the chain will contain the tree for the simplified
form of the builtin function call. */
-static tree
-fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
+tree
+fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src,
+ tree len)
{
if (!validate_arg (dst, POINTER_TYPE)
|| !validate_arg (src, POINTER_TYPE))
@@ -11755,14 +11755,15 @@ fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
/* See if we can store by pieces into (dst + strlen(dst)). */
tree newdst, call;
tree strlen_fn = builtin_decl_implicit (BUILT_IN_STRLEN);
- tree strcpy_fn = builtin_decl_implicit (BUILT_IN_STRCPY);
+ tree memcpy_fn = builtin_decl_implicit (BUILT_IN_MEMCPY);
- if (!strlen_fn || !strcpy_fn)
+ if (!strlen_fn || !memcpy_fn)
return NULL_TREE;
/* If the length of the source string isn't computable don't
- split strcat into strlen and strcpy. */
- tree len = c_strlen (src, 1);
+ split strcat into strlen and memcpy. */
+ if (! len)
+ len = c_strlen (src, 1);
if (! len || TREE_SIDE_EFFECTS (len))
return NULL_TREE;
@@ -11776,7 +11777,11 @@ fold_builtin_strcat (location_t loc ATTRIBUTE_UNUSED, tree dst, tree src)
newdst = fold_build_pointer_plus_loc (loc, dst, newdst);
newdst = builtin_save_expr (newdst);
- call = build_call_expr_loc (loc, strcpy_fn, 2, newdst, src);
+ len = fold_convert_loc (loc, size_type_node, len);
+ len = size_binop_loc (loc, PLUS_EXPR, len,
+ build_int_cst (size_type_node, 1));
+
+ call = build_call_expr_loc (loc, memcpy_fn, 3, newdst, src, len);
return build2 (COMPOUND_EXPR, TREE_TYPE (dst), call, dst);
}
return NULL_TREE;
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index bace6f892d2..569b49225b6 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -921,6 +921,7 @@ gimple_fold_builtin (gimple stmt)
break;
case BUILT_IN_STRCPY:
case BUILT_IN_STRNCPY:
+ case BUILT_IN_STRCAT:
arg_idx = 1;
type = 0;
break;
@@ -996,6 +997,13 @@ gimple_fold_builtin (gimple stmt)
val[1]);
break;
+ case BUILT_IN_STRCAT:
+ if (val[1] && is_gimple_val (val[1]) && nargs == 2)
+ result = fold_builtin_strcat (loc, gimple_call_arg (stmt, 0),
+ gimple_call_arg (stmt, 1),
+ val[1]);
+ break;
+
case BUILT_IN_FPUTS:
if (nargs == 2)
result = fold_builtin_fputs (loc, gimple_call_arg (stmt, 0),
diff --git a/gcc/tree.h b/gcc/tree.h
index e22e53c152f..e918ec54d24 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4527,6 +4527,7 @@ extern tree fold_call_expr (location_t, tree, bool);
extern tree fold_builtin_fputs (location_t, tree, tree, bool, bool, tree);
extern tree fold_builtin_strcpy (location_t, tree, tree, tree, tree);
extern tree fold_builtin_strncpy (location_t, tree, tree, tree, tree, tree);
+extern tree fold_builtin_strcat (location_t, tree, tree, tree);
extern tree fold_builtin_memory_chk (location_t, tree, tree, tree, tree, tree, tree, bool,
enum built_in_function);
extern tree fold_builtin_stxcpy_chk (location_t, tree, tree, tree, tree, tree, bool,