From e80cc4854a9d1aa0ab3293c2717e5937bf6dcd94 Mon Sep 17 00:00:00 2001 From: rguenth Date: Mon, 8 Dec 2014 09:20:35 +0000 Subject: [PATCH] 2014-12-08 Richard Biener * builtins.c (fold_builtin_0): Remove unused ignore parameter. (fold_builtin_1): Likewise. (fold_builtin_3): Likewise. (fold_builtin_varargs): Likewise. (fold_builtin_2): Likewise. Do not fold stpcpy here. (fold_builtin_n): Adjust. (fold_builtin_stpcpy): Move to gimple-fold.c. (gimple_fold_builtin_stpcpy): Moved and gimplified from builtins.c. (gimple_fold_builtin): Fold stpcpy here. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@218477 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 12 +++++++ gcc/builtins.c | 101 ++++++++++++------------------------------------------ gcc/gimple-fold.c | 66 +++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 80 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 760f5fc3a0a..f17774fe3ff 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2014-12-08 Richard Biener + + * builtins.c (fold_builtin_0): Remove unused ignore parameter. + (fold_builtin_1): Likewise. + (fold_builtin_3): Likewise. + (fold_builtin_varargs): Likewise. + (fold_builtin_2): Likewise. Do not fold stpcpy here. + (fold_builtin_n): Adjust. + (fold_builtin_stpcpy): Move to gimple-fold.c. + (gimple_fold_builtin_stpcpy): Moved and gimplified from builtins.c. + (gimple_fold_builtin): Fold stpcpy here. + 2014-12-07 Trevor Saunders * symtab.c (symtab_node::verify): Check for section attribute before diff --git a/gcc/builtins.c b/gcc/builtins.c index 257d001bfbf..7cbac60851c 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -191,11 +191,11 @@ static tree fold_builtin_fabs (location_t, tree, tree); static tree fold_builtin_abs (location_t, tree, tree); static tree fold_builtin_unordered_cmp (location_t, tree, tree, tree, enum tree_code, enum tree_code); -static tree fold_builtin_0 (location_t, tree, bool); -static tree fold_builtin_1 (location_t, tree, tree, bool); -static tree fold_builtin_2 (location_t, tree, tree, tree, bool); -static tree fold_builtin_3 (location_t, tree, tree, tree, tree, bool); -static tree fold_builtin_varargs (location_t, tree, tree*, int, bool); +static tree fold_builtin_0 (location_t, tree); +static tree fold_builtin_1 (location_t, tree, tree); +static tree fold_builtin_2 (location_t, tree, tree, tree); +static tree fold_builtin_3 (location_t, tree, tree, tree, tree); +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); @@ -8657,47 +8657,6 @@ fold_builtin_exponent (location_t loc, tree fndecl, tree arg, return NULL_TREE; } -/* Fold function call to builtin stpcpy with arguments DEST and SRC. - Return NULL_TREE if no simplification can be made. */ - -static tree -fold_builtin_stpcpy (location_t loc, tree fndecl, tree dest, tree src) -{ - tree fn, len, lenp1, call, type; - - if (!validate_arg (dest, POINTER_TYPE) - || !validate_arg (src, POINTER_TYPE)) - return NULL_TREE; - - len = c_strlen (src, 1); - if (!len - || TREE_CODE (len) != INTEGER_CST) - return NULL_TREE; - - if (optimize_function_for_size_p (cfun) - /* If length is zero it's small enough. */ - && !integer_zerop (len)) - return NULL_TREE; - - fn = builtin_decl_implicit (BUILT_IN_MEMCPY); - if (!fn) - return NULL_TREE; - - lenp1 = size_binop_loc (loc, PLUS_EXPR, - fold_convert_loc (loc, size_type_node, len), - build_int_cst (size_type_node, 1)); - /* We use dest twice in building our expression. Save it from - multiple expansions. */ - dest = builtin_save_expr (dest); - call = build_call_expr_loc (loc, fn, 3, dest, src, lenp1); - - type = TREE_TYPE (TREE_TYPE (fndecl)); - dest = fold_build_pointer_plus_loc (loc, dest, len); - dest = fold_convert_loc (loc, type, dest); - dest = omit_one_operand_loc (loc, type, dest, call); - return dest; -} - /* Fold function call to builtin memchr. ARG1, ARG2 and LEN are the arguments to the call, and TYPE is its return type. Return NULL_TREE if no simplification can be made. */ @@ -9857,11 +9816,10 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode, } /* Fold a call to built-in function FNDECL with 0 arguments. - IGNORE is true if the result of the function call is ignored. This - function returns NULL_TREE if no simplification was possible. */ + This function returns NULL_TREE if no simplification was possible. */ static tree -fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED) +fold_builtin_0 (location_t loc, tree fndecl) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); @@ -9886,11 +9844,10 @@ fold_builtin_0 (location_t loc, tree fndecl, bool ignore ATTRIBUTE_UNUSED) } /* Fold a call to built-in function FNDECL with 1 argument, ARG0. - IGNORE is true if the result of the function call is ignored. This - function returns NULL_TREE if no simplification was possible. */ + This function returns NULL_TREE if no simplification was possible. */ static tree -fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool) +fold_builtin_1 (location_t loc, tree fndecl, tree arg0) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); @@ -10301,11 +10258,10 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool) } /* Fold a call to built-in function FNDECL with 2 arguments, ARG0 and ARG1. - IGNORE is true if the result of the function call is ignored. This - function returns NULL_TREE if no simplification was possible. */ + This function returns NULL_TREE if no simplification was possible. */ static tree -fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore) +fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); @@ -10392,19 +10348,6 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore) case BUILT_IN_RINDEX: return fold_builtin_strrchr (loc, arg0, arg1, type); - case BUILT_IN_STPCPY: - if (ignore) - { - tree fn = builtin_decl_implicit (BUILT_IN_STRCPY); - if (!fn) - break; - - return build_call_expr_loc (loc, fn, 2, arg0, arg1); - } - else - return fold_builtin_stpcpy (loc, fndecl, arg0, arg1); - break; - case BUILT_IN_STRCMP: return fold_builtin_strcmp (loc, arg0, arg1); @@ -10469,12 +10412,12 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore) } /* Fold a call to built-in function FNDECL with 3 arguments, ARG0, ARG1, - and ARG2. IGNORE is true if the result of the function call is ignored. + and ARG2. This function returns NULL_TREE if no simplification was possible. */ static tree fold_builtin_3 (location_t loc, tree fndecl, - tree arg0, tree arg1, tree arg2, bool) + tree arg0, tree arg1, tree arg2) { tree type = TREE_TYPE (TREE_TYPE (fndecl)); enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); @@ -10543,26 +10486,26 @@ fold_builtin_3 (location_t loc, tree fndecl, simplification was possible. */ tree -fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore) +fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool) { tree ret = NULL_TREE; switch (nargs) { case 0: - ret = fold_builtin_0 (loc, fndecl, ignore); + ret = fold_builtin_0 (loc, fndecl); break; case 1: - ret = fold_builtin_1 (loc, fndecl, args[0], ignore); + ret = fold_builtin_1 (loc, fndecl, args[0]); break; case 2: - ret = fold_builtin_2 (loc, fndecl, args[0], args[1], ignore); + ret = fold_builtin_2 (loc, fndecl, args[0], args[1]); break; case 3: - ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore); + ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2]); break; default: - ret = fold_builtin_varargs (loc, fndecl, args, nargs, ignore); + ret = fold_builtin_varargs (loc, fndecl, args, nargs); break; } if (ret) @@ -11656,12 +11599,10 @@ fold_builtin_object_size (tree ptr, tree ost) need special handling; we need to store the arguments in a convenient data structure before attempting any folding. Fortunately there are only a few builtins that fall into this category. FNDECL is the - function, EXP is the CALL_EXPR for the call, and IGNORE is true if the - result of the function call is ignored. */ + function, EXP is the CALL_EXPR for the call. */ static tree -fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs, - bool ignore ATTRIBUTE_UNUSED) +fold_builtin_varargs (location_t loc, tree fndecl, tree *args, int nargs) { enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); tree ret = NULL_TREE; diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index f22281ac206..e71e0954f6c 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2052,6 +2052,70 @@ gimple_fold_builtin_stxncpy_chk (gimple_stmt_iterator *gsi, return true; } +/* Fold function call to builtin stpcpy with arguments DEST and SRC. + Return NULL_TREE if no simplification can be made. */ + +static bool +gimple_fold_builtin_stpcpy (gimple_stmt_iterator *gsi) +{ + gcall *stmt = as_a (gsi_stmt (*gsi)); + location_t loc = gimple_location (stmt); + tree dest = gimple_call_arg (stmt, 0); + tree src = gimple_call_arg (stmt, 1); + tree fn, len, lenp1; + + /* If the result is unused, replace stpcpy with strcpy. */ + if (gimple_call_lhs (stmt) == NULL_TREE) + { + tree fn = builtin_decl_implicit (BUILT_IN_STRCPY); + if (!fn) + return false; + gimple_call_set_fndecl (stmt, fn); + fold_stmt (gsi); + return true; + } + + len = c_strlen (src, 1); + if (!len + || TREE_CODE (len) != INTEGER_CST) + return false; + + if (optimize_function_for_size_p (cfun) + /* If length is zero it's small enough. */ + && !integer_zerop (len)) + return false; + + /* If the source has a known length replace stpcpy with memcpy. */ + fn = builtin_decl_implicit (BUILT_IN_MEMCPY); + if (!fn) + return false; + + gimple_seq stmts = NULL; + tree tem = gimple_convert (&stmts, loc, size_type_node, len); + lenp1 = gimple_build (&stmts, loc, PLUS_EXPR, size_type_node, + tem, build_int_cst (size_type_node, 1)); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + gcall *repl = gimple_build_call (fn, 3, dest, src, lenp1); + gimple_set_vuse (repl, gimple_vuse (stmt)); + gimple_set_vdef (repl, gimple_vdef (stmt)); + if (gimple_vdef (repl) + && TREE_CODE (gimple_vdef (repl)) == SSA_NAME) + SSA_NAME_DEF_STMT (gimple_vdef (repl)) = repl; + gsi_insert_before (gsi, repl, GSI_SAME_STMT); + /* Replace the result with dest + len. */ + stmts = NULL; + tem = gimple_convert (&stmts, loc, sizetype, len); + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); + gassign *ret = gimple_build_assign (gimple_call_lhs (stmt), + POINTER_PLUS_EXPR, dest, tem); + gsi_replace (gsi, ret, true); + /* Finally fold the memcpy call. */ + gimple_stmt_iterator gsi2 = *gsi; + gsi_prev (&gsi2); + fold_stmt (&gsi2); + return true; +} + /* Fold a call EXP to {,v}snprintf having NARGS passed as ARGS. Return NULL_TREE if a normal call should be emitted rather than expanding the function inline. FCODE is either BUILT_IN_SNPRINTF_CHK or @@ -2849,6 +2913,8 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi) gimple_call_arg (stmt, 2), gimple_call_arg (stmt, 3), fcode); + case BUILT_IN_STPCPY: + return gimple_fold_builtin_stpcpy (gsi); case BUILT_IN_STRCPY_CHK: case BUILT_IN_STPCPY_CHK: return gimple_fold_builtin_stxcpy_chk (gsi, -- 2.11.4.GIT