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 + + 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 * 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,