From: Richard Biener Date: Wed, 3 Dec 2014 14:08:07 +0000 (+0000) Subject: builtins.c (target_percent_c): Export. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=edd7ae68b0594c496d5751b5ec9817f505efb673;p=gcc.git builtins.c (target_percent_c): Export. 2014-12-03 Richard Biener * builtins.c (target_percent_c): Export. (fold_builtin_fprintf): Move to gimple-fold.c. (fold_builtin_2): Do not fold fprintf functions. (fold_builtin_3): Likewise. (fold_builtin_4): Remove. (fold_builtin_n): Do not call fold_builtin_4. * builtins.h (target_percent_c): Declare. * gimple-fold.c (gimple_fold_builtin_fprintf): Move from builtins.c and gimplify. (gimple_fold_builtin): Fold fprintf, fprintf_unlocked, vfprintf, fprintf_chk and vfprintf_chk here. From-SVN: r218317 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 610606494cd..aa6175eb50c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2014-12-03 Richard Biener + + * builtins.c (target_percent_c): Export. + (fold_builtin_fprintf): Move to gimple-fold.c. + (fold_builtin_2): Do not fold fprintf functions. + (fold_builtin_3): Likewise. + (fold_builtin_4): Remove. + (fold_builtin_n): Do not call fold_builtin_4. + * builtins.h (target_percent_c): Declare. + * gimple-fold.c (gimple_fold_builtin_fprintf): Move from + builtins.c and gimplify. + (gimple_fold_builtin): Fold fprintf, fprintf_unlocked, vfprintf, + fprintf_chk and vfprintf_chk here. + 2014-12-03 Martin Jambor PR ipa/64153 diff --git a/gcc/builtins.c b/gcc/builtins.c index 236f9207ede..beb4c05bfbb 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -195,7 +195,6 @@ 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_4 (location_t, tree, tree, tree, tree, tree, bool); static tree fold_builtin_varargs (location_t, tree, tree*, int, bool); static tree fold_builtin_strpbrk (location_t, tree, tree, tree); @@ -213,14 +212,12 @@ static void maybe_emit_sprintf_chk_warning (tree, enum built_in_function); static void maybe_emit_free_warning (tree); static tree fold_builtin_object_size (tree, tree); static tree fold_builtin_printf (location_t, tree, tree, tree, bool, enum built_in_function); -static tree fold_builtin_fprintf (location_t, tree, tree, tree, tree, bool, - enum built_in_function); static unsigned HOST_WIDE_INT target_newline; unsigned HOST_WIDE_INT target_percent; static unsigned HOST_WIDE_INT target_c; static unsigned HOST_WIDE_INT target_s; -static char target_percent_c[3]; +char target_percent_c[3]; char target_percent_s[3]; static char target_percent_s_newline[4]; static tree do_mpfr_arg1 (tree, tree, int (*)(mpfr_ptr, mpfr_srcptr, mp_rnd_t), @@ -10481,12 +10478,6 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore) arg1, NULL_TREE, ignore, fcode); break; - case BUILT_IN_FPRINTF: - case BUILT_IN_FPRINTF_UNLOCKED: - case BUILT_IN_VFPRINTF: - return fold_builtin_fprintf (loc, fndecl, arg0, arg1, NULL_TREE, - ignore, fcode); - case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE: return fold_builtin_atomic_always_lock_free (arg0, arg1); @@ -10548,21 +10539,6 @@ fold_builtin_3 (location_t loc, tree fndecl, return fold_builtin_printf (loc, fndecl, arg1, arg2, ignore, fcode); break; - case BUILT_IN_FPRINTF: - case BUILT_IN_FPRINTF_UNLOCKED: - case BUILT_IN_VFPRINTF: - return fold_builtin_fprintf (loc, fndecl, arg0, arg1, arg2, - ignore, fcode); - - case BUILT_IN_FPRINTF_CHK: - case BUILT_IN_VFPRINTF_CHK: - if (!validate_arg (arg1, INTEGER_TYPE) - || TREE_SIDE_EFFECTS (arg1)) - return NULL_TREE; - else - return fold_builtin_fprintf (loc, fndecl, arg0, arg2, NULL_TREE, - ignore, fcode); - case BUILT_IN_EXPECT: return fold_builtin_expect (loc, arg0, arg1, arg2); @@ -10595,35 +10571,6 @@ fold_builtin_3 (location_t loc, tree fndecl, return NULL_TREE; } -/* Fold a call to built-in function FNDECL with 4 arguments, ARG0, ARG1, - ARG2, and ARG3. IGNORE is true if the result of the function call is - ignored. This function returns NULL_TREE if no simplification was - possible. */ - -static tree -fold_builtin_4 (location_t loc, tree fndecl, - tree arg0, tree arg1, tree arg2, tree arg3, bool ignore) -{ - enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); - - switch (fcode) - { - case BUILT_IN_FPRINTF_CHK: - case BUILT_IN_VFPRINTF_CHK: - if (!validate_arg (arg1, INTEGER_TYPE) - || TREE_SIDE_EFFECTS (arg1)) - return NULL_TREE; - else - return fold_builtin_fprintf (loc, fndecl, arg0, arg2, arg3, - ignore, fcode); - break; - - default: - break; - } - return NULL_TREE; -} - /* Fold a call to built-in function FNDECL. ARGS is an array of NARGS arguments. IGNORE is true if the result of the function call is ignored. This function returns NULL_TREE if no @@ -10648,10 +10595,6 @@ fold_builtin_n (location_t loc, tree fndecl, tree *args, int nargs, bool ignore) case 3: ret = fold_builtin_3 (loc, fndecl, args[0], args[1], args[2], ignore); break; - case 4: - ret = fold_builtin_4 (loc, fndecl, args[0], args[1], args[2], args[3], - ignore); - break; default: ret = fold_builtin_varargs (loc, fndecl, args, nargs, ignore); break; @@ -11977,105 +11920,6 @@ fold_builtin_printf (location_t loc, tree fndecl, tree fmt, return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call); } -/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins. - FP, FMT, and ARG are the arguments to the call. We don't fold calls with - more than 3 arguments, and ARG may be null in the 2-argument case. - - Return NULL_TREE if no simplification was possible, otherwise return the - simplified form of the call as a tree. FCODE is the BUILT_IN_* - code of the function to be simplified. */ - -static tree -fold_builtin_fprintf (location_t loc, tree fndecl, tree fp, - tree fmt, tree arg, bool ignore, - enum built_in_function fcode) -{ - tree fn_fputc, fn_fputs, call = NULL_TREE; - const char *fmt_str = NULL; - - /* If the return value is used, don't do the transformation. */ - if (! ignore) - return NULL_TREE; - - /* Verify the required arguments in the original call. */ - if (!validate_arg (fp, POINTER_TYPE)) - return NULL_TREE; - if (!validate_arg (fmt, POINTER_TYPE)) - return NULL_TREE; - - /* Check whether the format is a literal string constant. */ - fmt_str = c_getstr (fmt); - if (fmt_str == NULL) - return NULL_TREE; - - if (fcode == BUILT_IN_FPRINTF_UNLOCKED) - { - /* If we're using an unlocked function, assume the other - unlocked functions exist explicitly. */ - fn_fputc = builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED); - fn_fputs = builtin_decl_explicit (BUILT_IN_FPUTS_UNLOCKED); - } - else - { - fn_fputc = builtin_decl_implicit (BUILT_IN_FPUTC); - fn_fputs = builtin_decl_implicit (BUILT_IN_FPUTS); - } - - if (!init_target_chars ()) - return NULL_TREE; - - /* If the format doesn't contain % args or %%, use strcpy. */ - if (strchr (fmt_str, target_percent) == NULL) - { - if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK - && arg) - return NULL_TREE; - - /* If the format specifier was "", fprintf does nothing. */ - if (fmt_str[0] == '\0') - { - /* If FP has side-effects, just wait until gimplification is - done. */ - if (TREE_SIDE_EFFECTS (fp)) - return NULL_TREE; - - return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), 0); - } - - /* When "string" doesn't contain %, replace all cases of - fprintf (fp, string) with fputs (string, fp). The fputs - builtin will take care of special cases like length == 1. */ - if (fn_fputs) - call = build_call_expr_loc (loc, fn_fputs, 2, fmt, fp); - } - - /* The other optimizations can be done only on the non-va_list variants. */ - else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK) - return NULL_TREE; - - /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */ - else if (strcmp (fmt_str, target_percent_s) == 0) - { - if (!arg || !validate_arg (arg, POINTER_TYPE)) - return NULL_TREE; - if (fn_fputs) - call = build_call_expr_loc (loc, fn_fputs, 2, arg, fp); - } - - /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */ - else if (strcmp (fmt_str, target_percent_c) == 0) - { - if (!arg || !validate_arg (arg, INTEGER_TYPE)) - return NULL_TREE; - if (fn_fputc) - call = build_call_expr_loc (loc, fn_fputc, 2, arg, fp); - } - - if (!call) - return NULL_TREE; - return fold_convert_loc (loc, TREE_TYPE (TREE_TYPE (fndecl)), call); -} - /* Initialize format string characters in the target charset. */ bool diff --git a/gcc/builtins.h b/gcc/builtins.h index 93d45cb6983..c857c94063c 100644 --- a/gcc/builtins.h +++ b/gcc/builtins.h @@ -91,5 +91,6 @@ extern const char *c_getstr (tree); extern bool init_target_chars (void); extern unsigned HOST_WIDE_INT target_percent; extern char target_percent_s[3]; +extern char target_percent_c[3]; #endif diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index bdc6088ec0e..3f1a11f6d4b 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2453,6 +2453,108 @@ gimple_fold_builtin_snprintf (gimple_stmt_iterator *gsi) return false; } +/* Fold a call to the {,v}fprintf{,_unlocked} and __{,v}printf_chk builtins. + FP, FMT, and ARG are the arguments to the call. We don't fold calls with + more than 3 arguments, and ARG may be null in the 2-argument case. + + Return NULL_TREE if no simplification was possible, otherwise return the + simplified form of the call as a tree. FCODE is the BUILT_IN_* + code of the function to be simplified. */ + +static bool +gimple_fold_builtin_fprintf (gimple_stmt_iterator *gsi, + tree fp, tree fmt, tree arg, + enum built_in_function fcode) +{ + gcall *stmt = as_a (gsi_stmt (*gsi)); + tree fn_fputc, fn_fputs; + const char *fmt_str = NULL; + + /* If the return value is used, don't do the transformation. */ + if (gimple_call_lhs (stmt) != NULL_TREE) + return false; + + /* Check whether the format is a literal string constant. */ + fmt_str = c_getstr (fmt); + if (fmt_str == NULL) + return false; + + if (fcode == BUILT_IN_FPRINTF_UNLOCKED) + { + /* If we're using an unlocked function, assume the other + unlocked functions exist explicitly. */ + fn_fputc = builtin_decl_explicit (BUILT_IN_FPUTC_UNLOCKED); + fn_fputs = builtin_decl_explicit (BUILT_IN_FPUTS_UNLOCKED); + } + else + { + fn_fputc = builtin_decl_implicit (BUILT_IN_FPUTC); + fn_fputs = builtin_decl_implicit (BUILT_IN_FPUTS); + } + + if (!init_target_chars ()) + return false; + + /* If the format doesn't contain % args or %%, use strcpy. */ + if (strchr (fmt_str, target_percent) == NULL) + { + if (fcode != BUILT_IN_VFPRINTF && fcode != BUILT_IN_VFPRINTF_CHK + && arg) + return false; + + /* If the format specifier was "", fprintf does nothing. */ + if (fmt_str[0] == '\0') + { + replace_call_with_value (gsi, NULL_TREE); + return true; + } + + /* When "string" doesn't contain %, replace all cases of + fprintf (fp, string) with fputs (string, fp). The fputs + builtin will take care of special cases like length == 1. */ + if (fn_fputs) + { + gcall *repl = gimple_build_call (fn_fputs, 2, fmt, fp); + replace_call_with_call_and_fold (gsi, repl); + return true; + } + } + + /* The other optimizations can be done only on the non-va_list variants. */ + else if (fcode == BUILT_IN_VFPRINTF || fcode == BUILT_IN_VFPRINTF_CHK) + return false; + + /* If the format specifier was "%s", call __builtin_fputs (arg, fp). */ + else if (strcmp (fmt_str, target_percent_s) == 0) + { + if (!arg || ! POINTER_TYPE_P (TREE_TYPE (arg))) + return false; + if (fn_fputs) + { + gcall *repl = gimple_build_call (fn_fputs, 2, arg, fp); + replace_call_with_call_and_fold (gsi, repl); + return true; + } + } + + /* If the format specifier was "%c", call __builtin_fputc (arg, fp). */ + else if (strcmp (fmt_str, target_percent_c) == 0) + { + if (!arg + || ! useless_type_conversion_p (integer_type_node, TREE_TYPE (arg))) + return false; + if (fn_fputc) + { + gcall *repl = gimple_build_call (fn_fputc, 2, arg, fp); + replace_call_with_call_and_fold (gsi, repl); + return true; + } + } + + return false; +} + + /* Fold a call to __builtin_strlen with known length LEN. */ @@ -2483,7 +2585,9 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi) if (avoid_folding_inline_builtin (callee)) return false; - switch (DECL_FUNCTION_CODE (callee)) + unsigned n = gimple_call_num_args (stmt); + enum built_in_function fcode = DECL_FUNCTION_CODE (callee); + switch (fcode) { case BUILT_IN_BZERO: return gimple_fold_builtin_memset (gsi, integer_zero_node, @@ -2506,7 +2610,7 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi) gimple_call_arg (stmt, 1), 3); case BUILT_IN_SPRINTF_CHK: case BUILT_IN_VSPRINTF_CHK: - return gimple_fold_builtin_sprintf_chk (gsi, DECL_FUNCTION_CODE (callee)); + return gimple_fold_builtin_sprintf_chk (gsi, fcode); case BUILT_IN_STRCAT_CHK: return gimple_fold_builtin_strcat_chk (gsi); case BUILT_IN_STRNCAT_CHK: @@ -2540,14 +2644,14 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi) gimple_call_arg (stmt, 1), gimple_call_arg (stmt, 2), gimple_call_arg (stmt, 3), - DECL_FUNCTION_CODE (callee)); + fcode); case BUILT_IN_STRCPY_CHK: case BUILT_IN_STPCPY_CHK: return gimple_fold_builtin_stxcpy_chk (gsi, gimple_call_arg (stmt, 0), gimple_call_arg (stmt, 1), gimple_call_arg (stmt, 2), - DECL_FUNCTION_CODE (callee)); + fcode); case BUILT_IN_STRNCPY_CHK: case BUILT_IN_STPNCPY_CHK: return gimple_fold_builtin_stxncpy_chk (gsi, @@ -2555,15 +2659,37 @@ gimple_fold_builtin (gimple_stmt_iterator *gsi) gimple_call_arg (stmt, 1), gimple_call_arg (stmt, 2), gimple_call_arg (stmt, 3), - DECL_FUNCTION_CODE (callee)); + fcode); case BUILT_IN_SNPRINTF_CHK: case BUILT_IN_VSNPRINTF_CHK: - return gimple_fold_builtin_snprintf_chk (gsi, - DECL_FUNCTION_CODE (callee)); + return gimple_fold_builtin_snprintf_chk (gsi, fcode); case BUILT_IN_SNPRINTF: return gimple_fold_builtin_snprintf (gsi); case BUILT_IN_SPRINTF: return gimple_fold_builtin_sprintf (gsi); + case BUILT_IN_FPRINTF: + case BUILT_IN_FPRINTF_UNLOCKED: + case BUILT_IN_VFPRINTF: + if (n == 2 || n == 3) + return gimple_fold_builtin_fprintf (gsi, + gimple_call_arg (stmt, 0), + gimple_call_arg (stmt, 1), + n == 3 + ? gimple_call_arg (stmt, 2) + : NULL_TREE, + fcode); + break; + case BUILT_IN_FPRINTF_CHK: + case BUILT_IN_VFPRINTF_CHK: + if (n == 3 || n == 4) + return gimple_fold_builtin_fprintf (gsi, + gimple_call_arg (stmt, 0), + gimple_call_arg (stmt, 2), + n == 4 + ? gimple_call_arg (stmt, 3) + : NULL_TREE, + fcode); + break; default:; }