diff options
author | bonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-08-01 22:03:34 +0000 |
---|---|---|
committer | bonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-08-01 22:03:34 +0000 |
commit | 3b2411a88d1a0a07e7c93da834ec7719792d351f (patch) | |
tree | f0eeae6aa04e1213f78c59803b4a875d6b3602cd | |
parent | 1684855694a44db9229a0c991221e727904ca960 (diff) | |
download | gcc-3b2411a88d1a0a07e7c93da834ec7719792d351f.tar.gz |
2009-04-17 Paolo Bonzini <bonzini@gnu.org>
* expr.c (store_constructor): Use promote_decl_mode. Remove
now write-only variable unsignedp.
(expand_expr_real_1): Use promote_decl_mode.
* expr.h (promote_function_mode, promote_decl_mode): New.
(promote_mode): Remove last argument.
* function.c (assign_temp): Drop last argument of promote_mode.
(assign_parm_find_data_types): Use promote_function_mode.
(assign_parm_setup_reg): Likewise.
(expand_function_end): Use promote_function_mode.
* calls.c (initialize_argument_information): Use promote_function_mode.
(precompute_arguments): Use promote_mode instead of checking if
only PROMOTE_FUNCTION_MODE is defined.
(expand_call): When making sibcall decisions, use promote_function_mode.
Below, remove an if for targetm.calls.promote_function_return and
and use promote_function_mode.
(emit_library_call_value_1): Use promote_function_mode, fix bug
where promote_mode was passed FOR_CALL == 0 for a return value in an
assertion.
* cfgexpand.c (expand_one_register_var): Use promote_decl_mode.
* explow.c (promote_function_mode, promote_decl_mode): New.
(promote_mode): Keep only the FOR_CALL == 0 case.
* combine.c (setup_incoming_promotion): Remove test of
promote_function_args. Use promote_function_mode.
* stmt.c (expand_value_return): Use promote_decl_mode.
(expand_decl): Use promote_decl_mode.
* expr.c (store_constructor): Use promote_decl_mode. Remove
now write-only variable unsignedp.
(expand_expr_real_1): Use promote_decl_mode.
* expr.h (promote_function_mode, promote_decl_mode): New.
(promote_mode): Remove last argument.
* function.c (assign_temp): Drop last argument of promote_mode.
(assign_parm_find_data_types): Use promote_function_mode.
(assign_parm_setup_reg): Likewise.
(expand_function_end): Use promote_function_mode.
* calls.c (initialize_argument_information): Use promote_function_mode.
(precompute_arguments): Use promote_mode instead of checking if
only PROMOTE_FUNCTION_MODE is defined.
(expand_call): When making sibcall decisions, use promote_function_mode.
Below, remove an if for targetm.calls.promote_function_return and
and use promote_function_mode.
(emit_library_call_value_1): Use promote_function_mode, fix bug
where promote_mode was passed FOR_CALL == 0 for a return value in an
assertion.
* cfgexpand.c (expand_one_register_var): Use promote_decl_mode.
* explow.c (promote_function_mode, promote_decl_mode): New.
(promote_mode): Keep only the FOR_CALL == 0 case.
* combine.c (setup_incoming_promotion): Remove test of
promote_function_args. Use promote_function_mode.
* stmt.c (expand_value_return): Use promote_decl_mode.
(expand_decl): Use promote_decl_mode.
* explow.c (promote_function_mode): Just call the target hook.
* targhooks.c (default_promote_function_mode,
default_promote_function_mode_always_promote): New.
* targhooks.h (default_promote_function_mode,
default_promote_function_mode_always_promote): Declare.
* target.h (promote_function_args, promote_function_return): Remove.
(promote_function_mode): New.
* target-def.h (TARGET_PROMOTE_FUNCTION_ARGS,
TARGET_PROMOTE_FUNCTION_RETURN): Remove.
(TARGET_PROMOTE_FUNCTION_MODE): New.
(TARGET_CALLS): Adjust.
* system.h (TARGET_PROMOTE_FUNCTION_ARGS,
TARGET_PROMOTE_FUNCTION_RETURN, PROMOTE_FUNCTION_MODE): Poison.
* config/s390/s390.h (PROMOTE_FUNCTION_MODE): Move...
* config/s390/s390.c (s390_promote_function_mode): ... here,
with pointer handling.
(TARGET_PROMOTE_FUNCTION_MODE): Define.
(TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove.
* config/sparc/sparc.h (PROMOTE_FUNCTION_MODE): Move...
* config/sparc/sparc.c (sparc_promote_function_mode): ... here,
with pointer handling.
(TARGET_PROMOTE_FUNCTION_MODE): Define.
(TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove.
* config/sh/sh-protos.h (sh_promote_function_mode): New.
* config/sh/sh.c (sh_promote_function_mode): New.
(TARGET_PROMOTE_FUNCTION_MODE): Define.
(TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove.
* config/cris/cris.h (PROMOTE_FUNCTION_MODE): Move...
* config/cris/cris.c (cris_promote_function_mode): ... here.
(TARGET_PROMOTE_FUNCTION_MODE): Define.
(TARGET_PROMOTE_FUNCTION_ARGS): Remove.
* config/mmix/mmix.h (PROMOTE_FUNCTION_MODE): Move...
* config/mmix/mmix.c (mmix_promote_function_mode): ... here.
(TARGET_PROMOTE_FUNCTION_MODE): Define.
(TARGET_PROMOTE_FUNCTION_ARGS): Remove.
* config/arm/arm.h (PROMOTE_FUNCTION_MODE): Move...
* config/arm/arm.c (arm_promote_function_mode): ... here, without complex
type handling.
(TARGET_PROMOTE_FUNCTION_MODE): Define.
(TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove.
* config/pa/pa.c (pa_promote_function_mode): New.
(TARGET_PROMOTE_FUNCTION_MODE): Define.
(TARGET_PROMOTE_FUNCTION_RETURN): Remove.
* config/alpha/alpha.c (TARGET_PROMOTE_FUNCTION_ARGS,
TARGET_PROMOTE_FUNCTION_RETURN): Remove.
(TARGET_PROMOTE_FUNCTION_MODE): Define equivalently.
* config/xtensa/xtensa.c: Likewise.
* config/stormy16/stormy16.c: Likewise.
* config/iq2000/iq2000.c: Likewise.
* config/rs6000/rs6000.c: Likewise.
* config/picochip/picochip.c: Likewise.
* config/arc/arc.c: Likewise.
* config/mcore/mcore.c: Likewise.
* config/score/score.c: Likewise.
* config/mips/mips.c: Likewise.
* config/bfin/bfin.c: Likewise.
* config/ia64/ia64.c: Likewise (disabled though).
* config/frv/frv.h: Remove pointless remark.
* doc/tm.texi (PROMOTE_FUNCTION_MODE,
TARGET_PROMOTE_FUNCTION_ARGS,
TARGET_PROMOTE_FUNCTION_RETURN): Consolidate into...
(TARGET_PROMOTE_FUNCTION_MODE): ... this.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@150336 138bc75d-0d04-0410-961f-82ee72b054a4
48 files changed, 541 insertions, 343 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2d3a15fefce..b75113fb8c1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,130 @@ +2009-04-17 Paolo Bonzini <bonzini@gnu.org> + + * expr.c (store_constructor): Use promote_decl_mode. Remove + now write-only variable unsignedp. + (expand_expr_real_1): Use promote_decl_mode. + * expr.h (promote_function_mode, promote_decl_mode): New. + (promote_mode): Remove last argument. + * function.c (assign_temp): Drop last argument of promote_mode. + (assign_parm_find_data_types): Use promote_function_mode. + (assign_parm_setup_reg): Likewise. + (expand_function_end): Use promote_function_mode. + * calls.c (initialize_argument_information): Use promote_function_mode. + (precompute_arguments): Use promote_mode instead of checking if + only PROMOTE_FUNCTION_MODE is defined. + (expand_call): When making sibcall decisions, use promote_function_mode. + Below, remove an if for targetm.calls.promote_function_return and + and use promote_function_mode. + (emit_library_call_value_1): Use promote_function_mode, fix bug + where promote_mode was passed FOR_CALL == 0 for a return value in an + assertion. + * cfgexpand.c (expand_one_register_var): Use promote_decl_mode. + * explow.c (promote_function_mode, promote_decl_mode): New. + (promote_mode): Keep only the FOR_CALL == 0 case. + * combine.c (setup_incoming_promotion): Remove test of + promote_function_args. Use promote_function_mode. + * stmt.c (expand_value_return): Use promote_decl_mode. + (expand_decl): Use promote_decl_mode. + + * expr.c (store_constructor): Use promote_decl_mode. Remove + now write-only variable unsignedp. + (expand_expr_real_1): Use promote_decl_mode. + * expr.h (promote_function_mode, promote_decl_mode): New. + (promote_mode): Remove last argument. + * function.c (assign_temp): Drop last argument of promote_mode. + (assign_parm_find_data_types): Use promote_function_mode. + (assign_parm_setup_reg): Likewise. + (expand_function_end): Use promote_function_mode. + * calls.c (initialize_argument_information): Use promote_function_mode. + (precompute_arguments): Use promote_mode instead of checking if + only PROMOTE_FUNCTION_MODE is defined. + (expand_call): When making sibcall decisions, use promote_function_mode. + Below, remove an if for targetm.calls.promote_function_return and + and use promote_function_mode. + (emit_library_call_value_1): Use promote_function_mode, fix bug + where promote_mode was passed FOR_CALL == 0 for a return value in an + assertion. + * cfgexpand.c (expand_one_register_var): Use promote_decl_mode. + * explow.c (promote_function_mode, promote_decl_mode): New. + (promote_mode): Keep only the FOR_CALL == 0 case. + * combine.c (setup_incoming_promotion): Remove test of + promote_function_args. Use promote_function_mode. + * stmt.c (expand_value_return): Use promote_decl_mode. + (expand_decl): Use promote_decl_mode. + + * explow.c (promote_function_mode): Just call the target hook. + * targhooks.c (default_promote_function_mode, + default_promote_function_mode_always_promote): New. + * targhooks.h (default_promote_function_mode, + default_promote_function_mode_always_promote): Declare. + * target.h (promote_function_args, promote_function_return): Remove. + (promote_function_mode): New. + * target-def.h (TARGET_PROMOTE_FUNCTION_ARGS, + TARGET_PROMOTE_FUNCTION_RETURN): Remove. + (TARGET_PROMOTE_FUNCTION_MODE): New. + (TARGET_CALLS): Adjust. + * system.h (TARGET_PROMOTE_FUNCTION_ARGS, + TARGET_PROMOTE_FUNCTION_RETURN, PROMOTE_FUNCTION_MODE): Poison. + + * config/s390/s390.h (PROMOTE_FUNCTION_MODE): Move... + * config/s390/s390.c (s390_promote_function_mode): ... here, + with pointer handling. + (TARGET_PROMOTE_FUNCTION_MODE): Define. + (TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove. + + * config/sparc/sparc.h (PROMOTE_FUNCTION_MODE): Move... + * config/sparc/sparc.c (sparc_promote_function_mode): ... here, + with pointer handling. + (TARGET_PROMOTE_FUNCTION_MODE): Define. + (TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove. + + * config/sh/sh-protos.h (sh_promote_function_mode): New. + * config/sh/sh.c (sh_promote_function_mode): New. + (TARGET_PROMOTE_FUNCTION_MODE): Define. + (TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove. + + * config/cris/cris.h (PROMOTE_FUNCTION_MODE): Move... + * config/cris/cris.c (cris_promote_function_mode): ... here. + (TARGET_PROMOTE_FUNCTION_MODE): Define. + (TARGET_PROMOTE_FUNCTION_ARGS): Remove. + + * config/mmix/mmix.h (PROMOTE_FUNCTION_MODE): Move... + * config/mmix/mmix.c (mmix_promote_function_mode): ... here. + (TARGET_PROMOTE_FUNCTION_MODE): Define. + (TARGET_PROMOTE_FUNCTION_ARGS): Remove. + + * config/arm/arm.h (PROMOTE_FUNCTION_MODE): Move... + * config/arm/arm.c (arm_promote_function_mode): ... here, without complex + type handling. + (TARGET_PROMOTE_FUNCTION_MODE): Define. + (TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN): Remove. + + * config/pa/pa.c (pa_promote_function_mode): New. + (TARGET_PROMOTE_FUNCTION_MODE): Define. + (TARGET_PROMOTE_FUNCTION_RETURN): Remove. + + * config/alpha/alpha.c (TARGET_PROMOTE_FUNCTION_ARGS, + TARGET_PROMOTE_FUNCTION_RETURN): Remove. + (TARGET_PROMOTE_FUNCTION_MODE): Define equivalently. + * config/xtensa/xtensa.c: Likewise. + * config/stormy16/stormy16.c: Likewise. + * config/iq2000/iq2000.c: Likewise. + * config/rs6000/rs6000.c: Likewise. + * config/picochip/picochip.c: Likewise. + * config/arc/arc.c: Likewise. + * config/mcore/mcore.c: Likewise. + * config/score/score.c: Likewise. + * config/mips/mips.c: Likewise. + * config/bfin/bfin.c: Likewise. + * config/ia64/ia64.c: Likewise (disabled though). + + * config/frv/frv.h: Remove pointless remark. + + * doc/tm.texi (PROMOTE_FUNCTION_MODE, + TARGET_PROMOTE_FUNCTION_ARGS, + TARGET_PROMOTE_FUNCTION_RETURN): Consolidate into... + (TARGET_PROMOTE_FUNCTION_MODE): ... this. + 2009-08-01 Sebastian Pop <sebastian.pop@amd.com> * doc/invoke.texi (-fgraphite-force-parallel): Renamed diff --git a/gcc/calls.c b/gcc/calls.c index bac4f8bb5d9..6d186c581c3 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1122,13 +1122,9 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED, } } - mode = TYPE_MODE (type); unsignedp = TYPE_UNSIGNED (type); - - if (targetm.calls.promote_function_args (fndecl - ? TREE_TYPE (fndecl) - : fntype)) - mode = promote_mode (type, mode, &unsignedp, 1); + mode = promote_function_mode (type, TYPE_MODE (type), &unsignedp, + fndecl ? TREE_TYPE (fndecl) : fntype, 0); args[i].unsignedp = unsignedp; args[i].mode = mode; @@ -1308,29 +1304,33 @@ precompute_arguments (int num_actuals, struct arg_data *args) for (i = 0; i < num_actuals; i++) { + tree type; enum machine_mode mode; if (TREE_CODE (args[i].tree_value) != CALL_EXPR) continue; /* If this is an addressable type, we cannot pre-evaluate it. */ - gcc_assert (!TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value))); + type = TREE_TYPE (args[i].tree_value); + gcc_assert (!TREE_ADDRESSABLE (type)); args[i].initial_value = args[i].value = expand_normal (args[i].tree_value); - mode = TYPE_MODE (TREE_TYPE (args[i].tree_value)); + mode = TYPE_MODE (type); if (mode != args[i].mode) { + int unsignedp = args[i].unsignedp; args[i].value = convert_modes (args[i].mode, mode, args[i].value, args[i].unsignedp); -#if defined(PROMOTE_FUNCTION_MODE) && !defined(PROMOTE_MODE) + /* CSE will replace this only if it contains args[i].value pseudo, so convert it down to the declared mode using a SUBREG. */ if (REG_P (args[i].value) - && GET_MODE_CLASS (args[i].mode) == MODE_INT) + && GET_MODE_CLASS (args[i].mode) == MODE_INT + && promote_mode (type, mode, &unsignedp) != args[i].mode) { args[i].initial_value = gen_lowpart_SUBREG (mode, args[i].value); @@ -1338,7 +1338,6 @@ precompute_arguments (int num_actuals, struct arg_data *args) SUBREG_PROMOTED_UNSIGNED_SET (args[i].initial_value, args[i].unsignedp); } -#endif } } } @@ -2346,17 +2345,17 @@ expand_call (tree exp, rtx target, int ignore) tree caller_res = DECL_RESULT (current_function_decl); caller_unsignedp = TYPE_UNSIGNED (TREE_TYPE (caller_res)); - caller_mode = caller_promoted_mode = DECL_MODE (caller_res); + caller_mode = DECL_MODE (caller_res); callee_unsignedp = TYPE_UNSIGNED (TREE_TYPE (funtype)); - callee_mode = callee_promoted_mode = TYPE_MODE (TREE_TYPE (funtype)); - if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl))) - caller_promoted_mode - = promote_mode (TREE_TYPE (caller_res), caller_mode, - &caller_unsignedp, 1); - if (targetm.calls.promote_function_return (funtype)) - callee_promoted_mode - = promote_mode (TREE_TYPE (funtype), callee_mode, - &callee_unsignedp, 1); + callee_mode = TYPE_MODE (TREE_TYPE (funtype)); + caller_promoted_mode + = promote_function_mode (TREE_TYPE (caller_res), caller_mode, + &caller_unsignedp, + TREE_TYPE (current_function_decl), 1); + callee_promoted_mode + = promote_function_mode (TREE_TYPE (caller_res), callee_mode, + &callee_unsignedp, + TREE_TYPE (funtype), 1); if (caller_mode != VOIDmode && (caller_promoted_mode != callee_promoted_mode || ((caller_mode != caller_promoted_mode @@ -3030,38 +3029,37 @@ expand_call (tree exp, rtx target, int ignore) else target = copy_to_reg (avoid_likely_spilled_reg (valreg)); - if (targetm.calls.promote_function_return(funtype)) + /* If we promoted this return value, make the proper SUBREG. + TARGET might be const0_rtx here, so be careful. */ + if (REG_P (target) + && TYPE_MODE (TREE_TYPE (exp)) != BLKmode + && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp))) { - /* If we promoted this return value, make the proper SUBREG. - TARGET might be const0_rtx here, so be careful. */ - if (REG_P (target) - && TYPE_MODE (TREE_TYPE (exp)) != BLKmode - && GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp))) + tree type = TREE_TYPE (exp); + int unsignedp = TYPE_UNSIGNED (type); + int offset = 0; + enum machine_mode pmode; + + /* Ensure we promote as expected, and get the new unsignedness. */ + pmode = promote_function_mode (type, TYPE_MODE (type), &unsignedp, + funtype, 1); + gcc_assert (GET_MODE (target) == pmode); + + if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN) + && (GET_MODE_SIZE (GET_MODE (target)) + > GET_MODE_SIZE (TYPE_MODE (type)))) { - tree type = TREE_TYPE (exp); - int unsignedp = TYPE_UNSIGNED (type); - int offset = 0; - enum machine_mode pmode; - - pmode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1); - /* If we don't promote as expected, something is wrong. */ - gcc_assert (GET_MODE (target) == pmode); - - if ((WORDS_BIG_ENDIAN || BYTES_BIG_ENDIAN) - && (GET_MODE_SIZE (GET_MODE (target)) - > GET_MODE_SIZE (TYPE_MODE (type)))) - { - offset = GET_MODE_SIZE (GET_MODE (target)) - - GET_MODE_SIZE (TYPE_MODE (type)); - if (! BYTES_BIG_ENDIAN) - offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD; - else if (! WORDS_BIG_ENDIAN) - offset %= UNITS_PER_WORD; - } - target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset); - SUBREG_PROMOTED_VAR_P (target) = 1; - SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp); + offset = GET_MODE_SIZE (GET_MODE (target)) + - GET_MODE_SIZE (TYPE_MODE (type)); + if (! BYTES_BIG_ENDIAN) + offset = (offset / UNITS_PER_WORD) * UNITS_PER_WORD; + else if (! WORDS_BIG_ENDIAN) + offset %= UNITS_PER_WORD; } + + target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset); + SUBREG_PROMOTED_VAR_P (target) = 1; + SUBREG_PROMOTED_UNSIGNED_SET (target, unsignedp); } /* If size of args is variable or this was a constructor call for a stack @@ -3876,15 +3874,14 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value, } else { - /* Convert to the proper mode if PROMOTE_MODE has been active. */ + /* Convert to the proper mode if a promotion has been active. */ if (GET_MODE (valreg) != outmode) { int unsignedp = TYPE_UNSIGNED (tfom); - gcc_assert (targetm.calls.promote_function_return (tfom)); - gcc_assert (promote_mode (tfom, outmode, &unsignedp, 0) + gcc_assert (promote_function_mode (tfom, outmode, &unsignedp, + fndecl ? TREE_TYPE (fndecl) : fntype, 1) == GET_MODE (valreg)); - valreg = convert_modes (outmode, GET_MODE (valreg), valreg, 0); } diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index c172c96a580..07d6dd30974 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1202,9 +1202,7 @@ expand_one_register_var (tree var) { tree decl = SSAVAR (var); tree type = TREE_TYPE (decl); - int unsignedp = TYPE_UNSIGNED (type); - enum machine_mode reg_mode - = promote_mode (type, DECL_MODE (decl), &unsignedp, 0); + enum machine_mode reg_mode = promote_decl_mode (decl, NULL); rtx x = gen_reg_rtx (reg_mode); set_rtl (var, x); diff --git a/gcc/combine.c b/gcc/combine.c index 3f39bc3b286..6a0e6ec5c93 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1333,9 +1333,6 @@ setup_incoming_promotions (rtx first) tree arg; bool strictly_local = false; - if (!targetm.calls.promote_function_args (TREE_TYPE (cfun->decl))) - return; - for (arg = DECL_ARGUMENTS (current_function_decl); arg; arg = TREE_CHAIN (arg)) { @@ -1365,7 +1362,8 @@ setup_incoming_promotions (rtx first) /* The mode and signedness of the argument as it is actually passed, after any TARGET_PROMOTE_FUNCTION_ARGS-driven ABI promotions. */ - mode3 = promote_mode (DECL_ARG_TYPE (arg), mode2, &uns3, 1); + mode3 = promote_function_mode (DECL_ARG_TYPE (arg), mode2, &uns3, + TREE_TYPE (cfun->decl), 0); /* The mode of the register in which the argument is being passed. */ mode4 = GET_MODE (reg); diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index a9f5fba7ca5..f250e14a0c2 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -10818,10 +10818,8 @@ alpha_init_libfuncs (void) #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG alpha_reorg -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false #undef TARGET_RETURN_IN_MEMORY diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 66709c7f31c..f53c8988b4f 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -133,10 +133,8 @@ static const struct attribute_spec arc_attribute_table[] = #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST arc_address_cost -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 3be2126be3d..83db0ec1cda 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -125,6 +125,8 @@ static int arm_adjust_cost (rtx, rtx, rtx, int); static int count_insns_for_constant (HOST_WIDE_INT, int); static int arm_get_strip_length (int); static bool arm_function_ok_for_sibcall (tree, tree); +static enum machine_mode arm_promote_function_mode (const_tree, enum machine_mode, + int *, const_tree, int); static void arm_internal_label (FILE *, const char *, unsigned long); static void arm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree); @@ -329,10 +331,8 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_INIT_LIBFUNCS #define TARGET_INIT_LIBFUNCS arm_init_libfuncs -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE arm_promote_function_mode #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES arm_promote_prototypes #undef TARGET_PASS_BY_REFERENCE @@ -3072,7 +3072,7 @@ arm_canonicalize_comparison (enum rtx_code code, enum machine_mode mode, /* Define how to find the value returned by a function. */ rtx -arm_function_value(const_tree type, const_tree func ATTRIBUTE_UNUSED) +arm_function_value(const_tree type, const_tree func) { enum machine_mode mode; int unsignedp ATTRIBUTE_UNUSED; @@ -3081,7 +3081,7 @@ arm_function_value(const_tree type, const_tree func ATTRIBUTE_UNUSED) mode = TYPE_MODE (type); /* Promote integer types. */ if (INTEGRAL_TYPE_P (type)) - PROMOTE_FUNCTION_MODE (mode, unsignedp, type); + mode = arm_promote_function_mode (type, mode, &unsignedp, func, 1); /* Promotes small structs returned in a register to full-word size for big-endian AAPCS. */ @@ -19094,6 +19094,19 @@ arm_promote_prototypes (const_tree t ATTRIBUTE_UNUSED) return !TARGET_AAPCS_BASED; } +static enum machine_mode +arm_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, + enum machine_mode mode, + int *punsignedp ATTRIBUTE_UNUSED, + const_tree fntype ATTRIBUTE_UNUSED, + int for_return ATTRIBUTE_UNUSED) +{ + if (GET_MODE_CLASS (mode) == MODE_INT + && GET_MODE_SIZE (mode) < 4) + return SImode; + + return mode; +} /* AAPCS based ABIs use short enums by default. */ diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 58ced2e7e51..082b5fabc3a 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -501,11 +501,6 @@ extern int arm_arch_hwdiv; (MODE) = SImode; \ } -#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE) \ - if (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < 4) \ - (MODE) = SImode; - /* Define this if most significant bit is lowest numbered in instructions that operate on numbered bit-fields. */ #define BITS_BIG_ENDIAN 0 diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 4f213062a4f..13887480d1f 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -6296,12 +6296,8 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, #undef TARGET_SCHED_ISSUE_RATE #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate -#undef TARGET_PROMOTE_PROTOTYPES -#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #undef TARGET_ARG_PARTIAL_BYTES #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index 66fc05d0f6e..a9fe9dee52f 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -85,6 +85,9 @@ static int in_code = 0; /* Fix for reg_overlap_mentioned_p. */ static int cris_reg_overlap_mentioned_p (rtx, rtx); +static enum machine_mode cris_promote_function_mode (const_tree, enum machine_mode, + int *, const_tree, int); + static void cris_print_base (rtx, FILE *); static void cris_print_index (rtx, FILE *); @@ -166,8 +169,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION; #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST cris_address_cost -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE cris_promote_function_mode + #undef TARGET_STRUCT_VALUE_RTX #define TARGET_STRUCT_VALUE_RTX cris_struct_value_rtx #undef TARGET_SETUP_INCOMING_VARARGS @@ -3753,6 +3757,25 @@ cris_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED, || CRIS_FUNCTION_ARG_SIZE (mode, type) > 8); } +/* A combination of defining TARGET_PROMOTE_FUNCTION_MODE, promoting arguments + and *not* defining TARGET_PROMOTE_PROTOTYPES or PROMOTE_MODE gives the + best code size and speed for gcc, ipps and products in gcc-2.7.2. */ + +enum machine_mode +cris_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, + enum machine_mode mode, + int *punsignedp ATTRIBUTE_UNUSED, + const_tree fntype ATTRIBUTE_UNUSED, + int for_return) +{ + /* Defining PROMOTE_FUNCTION_RETURN in gcc-2.7.2 uncovered bug 981110 (even + when modifying FUNCTION_VALUE to return the promoted mode). Maybe + pointless as of now, but let's keep the old behavior. */ + if (for_return) + return mode; + return CRIS_PROMOTED_MODE (mode, *punsignedp, type); +} + static int cris_arg_partial_bytes (CUMULATIVE_ARGS *ca, enum machine_mode mode, diff --git a/gcc/config/cris/cris.h b/gcc/config/cris/cris.h index 920e354417e..39291079662 100644 --- a/gcc/config/cris/cris.h +++ b/gcc/config/cris/cris.h @@ -352,24 +352,10 @@ extern int target_flags; #define UNITS_PER_WORD 4 -/* A combination of defining PROMOTE_FUNCTION_MODE, - TARGET_PROMOTE_FUNCTION_ARGS that always returns true - and *not* defining TARGET_PROMOTE_PROTOTYPES or PROMOTE_MODE gives the - best code size and speed for gcc, ipps and products in gcc-2.7.2. */ #define CRIS_PROMOTED_MODE(MODE, UNSIGNEDP, TYPE) \ (GET_MODE_CLASS (MODE) == MODE_INT && GET_MODE_SIZE (MODE) < 4) \ ? SImode : MODE -#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE) \ - (MODE) = CRIS_PROMOTED_MODE (MODE, UNSIGNEDP, TYPE) - -/* Defining PROMOTE_FUNCTION_RETURN in gcc-2.7.2 uncovers bug 981110 (even - if defining FUNCTION_VALUE with MODE as PROMOTED_MODE ;-) - - FIXME: Report this when cris.h is part of GCC, so others can easily - see the problem. Maybe check other systems that define - TARGET_PROMOTE_FUNCTION_RETURN that always returns true. */ - /* We will be using prototype promotion, so they will be 32 bit. */ #define PARM_BOUNDARY 32 diff --git a/gcc/config/frv/frv.h b/gcc/config/frv/frv.h index 483ed77e9f7..dfb3fb8eeb1 100644 --- a/gcc/config/frv/frv.h +++ b/gcc/config/frv/frv.h @@ -1764,10 +1764,6 @@ typedef struct frv_stack { (Actually, on most machines, scalar values are returned in the same place regardless of mode). - If `TARGET_PROMOTE_FUNCTION_RETURN' is defined to return true, you - must apply the same promotion rules specified in `PROMOTE_MODE' if - VALTYPE is a scalar type. - If the precise function being called is known, FUNC is a tree node (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer. This makes it possible to use a different value-returning convention for specific diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index b2e950e52b8..71acdab0bb9 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -459,14 +459,8 @@ static const struct attribute_spec ia64_attribute_table[] = /* ??? ABI doesn't allow us to define this. */ #if 0 -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true -#endif - -/* ??? ABI doesn't allow us to define this. */ -#if 0 -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #endif /* ??? Investigate. */ diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c index b99043efa99..ff0c868aaf2 100644 --- a/gcc/config/iq2000/iq2000.c +++ b/gcc/config/iq2000/iq2000.c @@ -189,10 +189,8 @@ static bool iq2000_legitimate_address_p (enum machine_mode, rtx, bool); #undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS #define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true @@ -2186,15 +2184,14 @@ iq2000_select_section (tree decl, int reloc ATTRIBUTE_UNUSED, FUNC. */ rtx -iq2000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) +iq2000_function_value (const_tree valtype, const_tree func) { int reg = GP_RETURN; enum machine_mode mode = TYPE_MODE (valtype); int unsignedp = TYPE_UNSIGNED (valtype); - /* Since we define TARGET_PROMOTE_FUNCTION_RETURN that returns true, - we must promote the mode just as PROMOTE_MODE does. */ - mode = promote_mode (valtype, mode, &unsignedp, 1); + /* Since we promote return types, we must promote the mode here too. */ + mode = promote_function_mode (valtype, mode, &unsignedp, func, 1); return gen_rtx_REG (mode, reg); } diff --git a/gcc/config/mcore/mcore.c b/gcc/config/mcore/mcore.c index 3b0adef1074..170b4b00de6 100644 --- a/gcc/config/mcore/mcore.c +++ b/gcc/config/mcore/mcore.c @@ -192,10 +192,8 @@ static const struct attribute_spec mcore_attribute_table[] = #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG mcore_reorg -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true @@ -2730,14 +2728,15 @@ handle_structs_in_regs (enum machine_mode mode, const_tree type, int reg) } rtx -mcore_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) +mcore_function_value (const_tree valtype, const_tree func) { enum machine_mode mode; int unsigned_p; mode = TYPE_MODE (valtype); - mode = promote_mode (valtype, mode, &unsigned_p, 1); + /* Since we promote return types, we must promote the mode here too. */ + mode = promote_function_mode (valtype, mode, &unsignedp, func, 1); return handle_structs_in_regs (mode, valtype, FIRST_RET_REG); } diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index d5d6eeea8d5..222cb8942f9 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -279,7 +279,7 @@ extern void mips_expand_prologue (void); extern void mips_expand_before_return (void); extern void mips_expand_epilogue (bool); extern bool mips_can_use_return_insn (void); -extern rtx mips_function_value (const_tree, enum machine_mode); +extern rtx mips_function_value (const_tree, const_tree, enum machine_mode); extern bool mips_cannot_change_mode_class (enum machine_mode, enum machine_mode, enum reg_class); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 4a10fb47244..083b253faf0 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -4976,7 +4976,7 @@ mips_return_fpr_pair (enum machine_mode mode, VALTYPE is null and MODE is the mode of the return value. */ rtx -mips_function_value (const_tree valtype, enum machine_mode mode) +mips_function_value (const_tree valtype, const_tree func, enum machine_mode mode) { if (valtype) { @@ -4986,9 +4986,9 @@ mips_function_value (const_tree valtype, enum machine_mode mode) mode = TYPE_MODE (valtype); unsigned_p = TYPE_UNSIGNED (valtype); - /* Since TARGET_PROMOTE_FUNCTION_RETURN unconditionally returns true, - we must promote the mode just as PROMOTE_MODE does. */ - mode = promote_mode (valtype, mode, &unsigned_p, 1); + /* Since TARGET_PROMOTE_FUNCTION_MODE unconditionally promotes, + return values, promote the mode here too. */ + mode = promote_function_mode (valtype, mode, &unsigned_p, func, 1); /* Handle structures whose fields are returned in $f0/$f2. */ switch (mips_fpr_return_fields (valtype, fields)) @@ -14851,10 +14851,8 @@ mips_final_postscan_insn (FILE *file, rtx insn, rtx *opvec, int noperands) #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR mips_gimplify_va_arg_expr -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index a3ab2f8bb8f..8515ce10408 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -2204,10 +2204,10 @@ enum reg_class #define FP_ARG_LAST (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1) #define LIBCALL_VALUE(MODE) \ - mips_function_value (NULL_TREE, MODE) + mips_function_value (NULL_TREE, NULL_TREE, MODE) #define FUNCTION_VALUE(VALTYPE, FUNC) \ - mips_function_value (VALTYPE, VOIDmode) + mips_function_value (VALTYPE, FUNC, VOIDmode) /* 1 if N is a possible register number for a function value. On the MIPS, R2 R3 and F0 F2 are the only register thus used. diff --git a/gcc/config/mmix/mmix.c b/gcc/config/mmix/mmix.c index 67b1b2323b5..9e94279b85a 100644 --- a/gcc/config/mmix/mmix.c +++ b/gcc/config/mmix/mmix.c @@ -135,6 +135,9 @@ static void mmix_file_start (void); static void mmix_file_end (void); static bool mmix_rtx_costs (rtx, int, int, int *, bool); static rtx mmix_struct_value_rtx (tree, int); +static enum machine_mode mmix_promote_function_mode (const_tree, + enum machine_mode, + int *, const_tree, int); static bool mmix_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, const_tree, bool); static bool mmix_frame_pointer_required (void); @@ -188,14 +191,9 @@ static bool mmix_frame_pointer_required (void); #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG mmix_reorg -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#if 0 -/* Apparently not doing TRT if int < register-size. FIXME: Perhaps - FUNCTION_VALUE and LIBCALL_VALUE needs tweaking as some ports say. */ -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true -#endif +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE mmix_promote_function_mode + #undef TARGET_STRUCT_VALUE_RTX #define TARGET_STRUCT_VALUE_RTX mmix_struct_value_rtx @@ -2692,6 +2690,28 @@ mmix_intval (rtx x) fatal_insn ("MMIX Internal: This is not a constant:", x); } +/* Worker function for TARGET_PROMOTE_FUNCTION_MODE. */ + +enum machine_mode +mmix_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, + enum machine_mode mode, + int *punsignedp ATTRIBUTE_UNUSED, + const_tree fntype ATTRIBUTE_UNUSED, + int for_return) +{ + /* Apparently not doing TRT if int < register-size. FIXME: Perhaps + FUNCTION_VALUE and LIBCALL_VALUE needs tweaking as some ports say. */ + if (for_return) + return mode; + + /* Promotion of modes currently generates slow code, extending before + operation, so we do it only for arguments. */ + if (GET_MODE_CLASS (mode) == MODE_INT + && GET_MODE_SIZE (mode) < 8) + return DImode; + else + return mode; +} /* Worker function for TARGET_STRUCT_VALUE_RTX. */ static rtx diff --git a/gcc/config/mmix/mmix.h b/gcc/config/mmix/mmix.h index 72e35680ef5..41466545e21 100644 --- a/gcc/config/mmix/mmix.h +++ b/gcc/config/mmix/mmix.h @@ -182,23 +182,6 @@ extern int target_flags; #define FLOAT_WORDS_BIG_ENDIAN 1 #define UNITS_PER_WORD 8 -/* FIXME: Promotion of modes currently generates slow code, extending - before every operation. */ -/* I'm a little bit undecided about this one. It might be beneficial to - promote all operations. */ - -#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE) \ - do { \ - if (GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < 8) \ - { \ - (MODE) = DImode; \ - /* Do the following some time later, \ - scrutinizing differences. */ \ - if (0) (UNSIGNEDP) = 0; \ - } \ - } while (0) - /* We need to align everything to 64 bits that can affect the alignment of other types. Since address N is interpreted in MMIX as (N modulo access_size), we must align. */ diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 8e8db865e2b..bbd09f522e0 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -285,8 +285,8 @@ static size_t n_deferred_plabels = 0; #define TARGET_INIT_LIBFUNCS pa_hpux_init_libfuncs #endif -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE pa_promote_function_mode #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true @@ -9187,11 +9187,25 @@ insn_refs_are_delayed (rtx insn) && get_attr_type (insn) == TYPE_MILLI)); } +/* Promote the return value, but not the arguments. */ + +enum machine_mode +pa_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, + enum machine_mode mode, + int *punsignedp ATTRIBUTE_UNUSED, + const_tree fntype ATTRIBUTE_UNUSED, + int for_return) +{ + if (!for_return) + return mode; + return promote_mode (mode, punsignedp, type); +} + /* On the HP-PA the value is found in register(s) 28(-29), unless the mode is SF or DF. Then the value is returned in fr4 (32). - This must perform the same promotions as PROMOTE_MODE, else - TARGET_PROMOTE_FUNCTION_RETURN will not work correctly. + This must perform the same promotions as PROMOTE_MODE, else promoting + return values in TARGET_PROMOTE_FUNCTION_MODE will not work correctly. Small structures must be returned in a PARALLEL on PA64 in order to match the HP Compiler ABI. */ diff --git a/gcc/config/picochip/picochip.c b/gcc/config/picochip/picochip.c index 358ef71e36b..ecec1f7121e 100644 --- a/gcc/config/picochip/picochip.c +++ b/gcc/config/picochip/picochip.c @@ -254,10 +254,8 @@ static char picochip_get_vliw_alu_id (void); #undef TARGET_ARG_PARTIAL_BYTES #define TARGET_ARG_PARTIAL_BYTES picochip_arg_partial_bytes -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true @@ -4144,7 +4142,7 @@ warn_of_byte_access (void) } rtx -picochip_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED, +picochip_function_value (const_tree valtype, const_tree func, bool outgoing ATTRIBUTE_UNUSED) { enum machine_mode mode = TYPE_MODE (valtype); @@ -4152,7 +4150,7 @@ picochip_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED, /* Since we define PROMOTE_FUNCTION_RETURN, we must promote the mode just as PROMOTE_MODE does. */ - mode = promote_mode (valtype, mode, &unsignedp, 1); + mode = promote_function_mode (valtype, mode, &unsignedp, func, 1); return gen_rtx_REG (mode, 0); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 25cacc46e91..8c0feb55057 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1347,10 +1347,8 @@ static const struct attribute_spec rs6000_attribute_table[] = /* On rs6000, function arguments are promoted, as are function return values. */ -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY rs6000_return_in_memory diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 2329138cf1f..8b9ad5aedb5 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -125,6 +125,6 @@ extern void s390_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int); #ifdef RTX_CODE extern rtx s390_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int); -extern rtx s390_function_value (const_tree, enum machine_mode); +extern rtx s390_function_value (const_tree, const_tree, enum machine_mode); #endif /* RTX_CODE */ #endif /* TREE_CODE */ diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index f5b2fa73d1f..25203ab52b6 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -8343,17 +8343,36 @@ s390_return_in_memory (const_tree type, const_tree fundecl ATTRIBUTE_UNUSED) return true; } +/* Function arguments and return values are promoted to word size. */ + +static enum machine_mode +s390_promote_function_mode (const_tree type, enum machine_mode mode, + int *punsignedp, + const_tree fntype ATTRIBUTE_UNUSED, + int for_return ATTRIBUTE_UNUSED) +{ + if (INTEGRAL_MODE_P (mode) + && GET_MODE_SIZE (mode) < UNITS_PER_WORD) + { + if (POINTER_TYPE_P (type)) + *punsignedp = POINTERS_EXTEND_UNSIGNED; + return Pmode; + } + + return mode; +} + /* Define where to return a (scalar) value of type TYPE. If TYPE is null, define where to return a (scalar) value of mode MODE from a libcall. */ rtx -s390_function_value (const_tree type, enum machine_mode mode) +s390_function_value (const_tree type, const_tree fn, enum machine_mode mode) { if (type) { int unsignedp = TYPE_UNSIGNED (type); - mode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1); + mode = promote_function_mode (type, TYPE_MODE (type), &unsignedp, fn, 1); } gcc_assert (GET_MODE_CLASS (mode) == MODE_INT || SCALAR_FLOAT_MODE_P (mode)); @@ -9998,10 +10017,8 @@ s390_reorg (void) #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR s390_gimplify_va_arg -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE s390_promote_function_mode #undef TARGET_PASS_BY_REFERENCE #define TARGET_PASS_BY_REFERENCE s390_pass_by_reference diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index f34b7f22567..4772367eee5 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -216,13 +216,6 @@ extern int s390_arch_flags; #endif #define MAX_BITS_PER_WORD 64 -/* Function arguments and return values are promoted to word size. */ -#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE) \ -if (INTEGRAL_MODE_P (MODE) && \ - GET_MODE_SIZE (MODE) < UNITS_PER_WORD) { \ - (MODE) = Pmode; \ - } - /* Allocation boundary (in *bits*) for storing arguments in argument list. */ #define PARM_BOUNDARY (TARGET_64BIT ? 64 : 32) @@ -697,10 +690,10 @@ CUMULATIVE_ARGS; /* Scalar return values. */ #define FUNCTION_VALUE(VALTYPE, FUNC) \ - s390_function_value ((VALTYPE), VOIDmode) + s390_function_value ((VALTYPE), (FUNC), VOIDmode) #define LIBCALL_VALUE(MODE) \ - s390_function_value (NULL, (MODE)) + s390_function_value (NULL, NULL, (MODE)) /* Only gpr 2 and fpr 0 are ever used as return registers. */ #define FUNCTION_VALUE_REGNO_P(N) ((N) == 2 || (N) == 16) diff --git a/gcc/config/score/score.c b/gcc/config/score/score.c index b75f3cfaebf..0241383fc86 100644 --- a/gcc/config/score/score.c +++ b/gcc/config/score/score.c @@ -89,11 +89,8 @@ #undef TARGET_ASM_OUTPUT_MI_THUNK #define TARGET_ASM_OUTPUT_MI_THUNK score_output_mi_thunk -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true - -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true diff --git a/gcc/config/score/score3.c b/gcc/config/score/score3.c index 4258d29e525..385620d33d6 100644 --- a/gcc/config/score/score3.c +++ b/gcc/config/score/score3.c @@ -859,15 +859,14 @@ score3_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, VALTYPE is the return type and MODE is VOIDmode. For libcalls, VALTYPE is null and MODE is the mode of the return value. */ rtx -score3_function_value (tree valtype, tree func ATTRIBUTE_UNUSED, - enum machine_mode mode) +score3_function_value (tree valtype, tree func, enum machine_mode mode) { if (valtype) { int unsignedp; mode = TYPE_MODE (valtype); unsignedp = TYPE_UNSIGNED (valtype); - mode = promote_mode (valtype, mode, &unsignedp, 1); + mode = promote_function_mode (valtype, mode, &unsignedp, func, 1); } return gen_rtx_REG (mode, RT_REGNUM); } diff --git a/gcc/config/score/score7.c b/gcc/config/score/score7.c index 9ab6ebd3004..368ac03a3ba 100644 --- a/gcc/config/score/score7.c +++ b/gcc/config/score/score7.c @@ -850,15 +850,14 @@ score7_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, VALTYPE is the return type and MODE is VOIDmode. For libcalls, VALTYPE is null and MODE is the mode of the return value. */ rtx -score7_function_value (tree valtype, tree func ATTRIBUTE_UNUSED, - enum machine_mode mode) +score7_function_value (tree valtype, tree func, enum machine_mode mode) { if (valtype) { int unsignedp; mode = TYPE_MODE (valtype); unsignedp = TYPE_UNSIGNED (valtype); - mode = promote_mode (valtype, mode, &unsignedp, 1); + mode = promote_function_mode (valtype, mode, &unsignedp, func, 1); } return gen_rtx_REG (mode, RT_REGNUM); } diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index 35cd73021b9..dec662b197e 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -166,6 +166,8 @@ extern int sh_pass_in_reg_p (CUMULATIVE_ARGS *, enum machine_mode, tree); extern void sh_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, signed int, enum machine_mode); extern bool sh_promote_prototypes (const_tree); extern rtx sh_dwarf_register_span (rtx); +extern enum machine_mode sh_promote_function_mode (const_tree, enum machine_mode, + int *, const_tree, int); extern rtx replace_n_hard_rtx (rtx, rtx *, int , int); extern int shmedia_cleanup_truncate (rtx *, void *); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 5b555f83e1a..9c919d0a774 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -438,9 +438,7 @@ static const struct attribute_spec sh_attribute_table[] = #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES sh_promote_prototypes #undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS sh_promote_prototypes -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN sh_promote_prototypes +#define TARGET_PROMOTE_FUNCTION_ARGS sh_promote_function_mode #undef TARGET_STRUCT_VALUE_RTX #define TARGET_STRUCT_VALUE_RTX sh_struct_value_rtx @@ -7896,6 +7894,16 @@ sh_dwarf_register_span (rtx reg) DBX_REGISTER_NUMBER (regno)))); } +enum machine_mode +sh_promote_function_mode (const_tree type, enum machine_mode mode, + int *punsignedp, const_tree funtype, int for_return) +{ + if (sh_promote_prototypes (funtype)) + return promote_mode (type, machine_mode, punsignedp); + else + return mode; +} + bool sh_promote_prototypes (const_tree type) { diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index baba1d98057..52cbe703458 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -404,6 +404,8 @@ static int get_some_local_dynamic_name_1 (rtx *, void *); static bool sparc_rtx_costs (rtx, int, int, int *, bool); static bool sparc_promote_prototypes (const_tree); static rtx sparc_struct_value_rtx (tree, int); +static enum machine_mode sparc_promote_function_mode (const_tree, enum machine_mode, + int *, const_tree, int); static bool sparc_return_in_memory (const_tree, const_tree); static bool sparc_strict_argument_naming (CUMULATIVE_ARGS *); static void sparc_va_start (tree, rtx); @@ -524,17 +526,8 @@ static bool fpu_option_set = false; #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST hook_int_rtx_bool_0 -/* This is only needed for TARGET_ARCH64, but since PROMOTE_FUNCTION_MODE is a - no-op for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime - test for this value. */ -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true - -/* This is only needed for TARGET_ARCH64, but since PROMOTE_FUNCTION_MODE is a - no-op for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime - test for this value. */ -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE sparc_promote_function_mode #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES sparc_promote_prototypes @@ -4642,6 +4635,36 @@ sparc_promote_prototypes (const_tree fntype ATTRIBUTE_UNUSED) return TARGET_ARCH32 ? true : false; } +/* Handle promotion of pointer and integer arguments. */ + +static enum machine_mode +sparc_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, + enum machine_mode mode, + int *punsignedp ATTRIBUTE_UNUSED, + const_tree fntype ATTRIBUTE_UNUSED, + int for_return ATTRIBUTE_UNUSED) +{ + if (POINTER_TYPE_P (type)) + { + *punsignedp = POINTERS_EXTEND_UNSIGNED; + return Pmode; + } + + /* For TARGET_ARCH64 we need this, as we don't have instructions + for arithmetic operations which do zero/sign extension at the same time, + so without this we end up with a srl/sra after every assignment to an + user variable, which means very very bad code. */ + + if (TARGET_ARCH64 + && GET_MODE_CLASS (mode) == MODE_INT + && GET_MODE_SIZE (mode) < UNITS_PER_WORD) + return word_mode; + + return mode; +} + + + /* Handle the TARGET_STRICT_ARGUMENT_NAMING target hook. */ static bool @@ -5784,7 +5807,8 @@ function_value (const_tree type, enum machine_mode mode, int incoming_p) mclass = MODE_INT; } - /* This must match PROMOTE_FUNCTION_MODE. */ + /* This must match sparc_promote_function_mode. + ??? Maybe 32-bit pointers should actually remain in Pmode? */ else if (mclass == MODE_INT && GET_MODE_SIZE (mode) < UNITS_PER_WORD) mode = word_mode; } diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h index 31c74095f75..3b713611f84 100644 --- a/gcc/config/sparc/sparc.h +++ b/gcc/config/sparc/sparc.h @@ -636,16 +636,6 @@ extern struct sparc_cpu_select sparc_select[]; if ptr_mode and Pmode are the same. */ #define POINTERS_EXTEND_UNSIGNED 1 -/* For TARGET_ARCH64 we need this, as we don't have instructions - for arithmetic operations which do zero/sign extension at the same time, - so without this we end up with a srl/sra after every assignment to an - user variable, which means very very bad code. */ -#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE) \ -if (TARGET_ARCH64 \ - && GET_MODE_CLASS (MODE) == MODE_INT \ - && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \ - (MODE) = word_mode; - /* Allocation boundary (in *bits*) for storing arguments in argument list. */ #define PARM_BOUNDARY (TARGET_ARCH64 ? 64 : 32) diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c index 2e646f98d4c..06b96c7b8ce 100644 --- a/gcc/config/stormy16/stormy16.c +++ b/gcc/config/stormy16/stormy16.c @@ -2640,10 +2640,8 @@ xstormy16_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) #undef TARGET_GIMPLIFY_VA_ARG_EXPR #define TARGET_GIMPLIFY_VA_ARG_EXPR xstormy16_gimplify_va_arg_expr -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 38f300aeef7..77ba2d9d017 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -185,10 +185,8 @@ static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = #undef TARGET_EXPAND_BUILTIN_VA_START #define TARGET_EXPAND_BUILTIN_VA_START xtensa_va_start -#undef TARGET_PROMOTE_FUNCTION_ARGS -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true -#undef TARGET_PROMOTE_FUNCTION_RETURN -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote #undef TARGET_PROMOTE_PROTOTYPES #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h index a9987c7609f..84d320bc95b 100644 --- a/gcc/config/xtensa/xtensa.h +++ b/gcc/config/xtensa/xtensa.h @@ -582,7 +582,7 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER]; /* Define how to find the value returned by a library function assuming the value has mode MODE. Because we have defined - TARGET_PROMOTE_FUNCTION_RETURN that returns true, we have to + TARGET_PROMOTE_FUNCTION_MODE to promote everything, we have to perform the same promotions as PROMOTE_MODE. */ #define XTENSA_LIBCALL_VALUE(MODE, OUTGOINGP) \ gen_rtx_REG ((GET_MODE_CLASS (MODE) == MODE_INT \ diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 8157714e1f6..bb4f61b9e83 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1039,27 +1039,20 @@ sign-extend the result to 64 bits. On such machines, set Do not define this macro if it would never modify @var{m}. @end defmac -@defmac PROMOTE_FUNCTION_MODE -Like @code{PROMOTE_MODE}, but is applied to outgoing function arguments or -function return values, as specified by @code{TARGET_PROMOTE_FUNCTION_ARGS} -and @code{TARGET_PROMOTE_FUNCTION_RETURN}, respectively. - -The default is @code{PROMOTE_MODE}. -@end defmac - -@deftypefn {Target Hook} bool TARGET_PROMOTE_FUNCTION_ARGS (tree @var{fntype}) -This target hook should return @code{true} if the promotion described by -@code{PROMOTE_FUNCTION_MODE} should be done for outgoing function -arguments. -@end deftypefn - -@deftypefn {Target Hook} bool TARGET_PROMOTE_FUNCTION_RETURN (tree @var{fntype}) -This target hook should return @code{true} if the promotion described by -@code{PROMOTE_FUNCTION_MODE} should be done for the return value of -functions. - -If this target hook returns @code{true}, @code{TARGET_FUNCTION_VALUE} -must perform the same promotions done by @code{PROMOTE_FUNCTION_MODE}. +@deftypefn {Target Hook} enum machine_mode TARGET_PROMOTE_FUNCTION_MODE (tree @var{type}, enum machine_mode @var{mode}, int *@var{punsignedp}, tree @var{funtype}, int @var{for_return}) +Like @code{PROMOTE_MODE}, but it is applied to outgoing function arguments or +function return values. The target hook should return the new mode +and possibly change @code{*@var{punsignedp}} if the promotion should +change signedness. This function is called only for scalar @emph{or +pointer} types. + +The default is to not promote arguments and return values. You can +also define the hook to @code{default_promote_function_mode_always_promote} +if you would like to apply the same rules given by @code{PROMOTE_MODE}. + +@var{for_return} allows to distinguish the promotion of arguments and +return values. If this target hook promotes return values, +@code{TARGET_FUNCTION_VALUE} must perform the same promotions done here. @end deftypefn @defmac PARM_BOUNDARY diff --git a/gcc/explow.c b/gcc/explow.c index 198df220fbd..0a2616436e3 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -749,63 +749,96 @@ copy_to_suggested_reg (rtx x, rtx target, enum machine_mode mode) return temp; } -/* Return the mode to use to store a scalar of TYPE and MODE. +/* Return the mode to use to pass or return a scalar of TYPE and MODE. PUNSIGNEDP points to the signedness of the type and may be adjusted to show what signedness to use on extension operations. - FOR_CALL is nonzero if this call is promoting args for a call. */ + FOR_RETURN is nonzero if the caller is promoting the return value + of FNDECL, else it is for promoting args. */ -#if defined(PROMOTE_MODE) && !defined(PROMOTE_FUNCTION_MODE) -#define PROMOTE_FUNCTION_MODE PROMOTE_MODE -#endif +enum machine_mode +promote_function_mode (const_tree type, enum machine_mode mode, int *punsignedp, + const_tree funtype, int for_return) +{ + gcc_assert (GET_MODE_CLASS (mode) != MODE_COMPLEX_INT); + switch (TREE_CODE (type)) + { + case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: + case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE: + case POINTER_TYPE: case REFERENCE_TYPE: + return targetm.calls.promote_function_mode (type, mode, punsignedp, funtype, + for_return); + + default: + return mode; + } +} +/* Return the mode to use to store a scalar of TYPE and MODE. + PUNSIGNEDP points to the signedness of the type and may be adjusted + to show what signedness to use on extension operations. */ enum machine_mode -promote_mode (const_tree type, enum machine_mode mode, int *punsignedp, - int for_call ATTRIBUTE_UNUSED) +promote_mode (const_tree type, enum machine_mode mode, int *punsignedp) { + /* FIXME: this is the same logic that was there until GCC 4.4, but we + probably want to test POINTERS_EXTEND_UNSIGNED even if PROMOTE_MODE + is not defined. The affected targets are M32C, S390, SPARC. */ +#ifdef PROMOTE_MODE const enum tree_code code = TREE_CODE (type); int unsignedp = *punsignedp; -#ifndef PROMOTE_MODE - if (! for_call) - return mode; -#endif - switch (code) { -#ifdef PROMOTE_FUNCTION_MODE case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE: -#ifdef PROMOTE_MODE - if (for_call) - { -#endif - PROMOTE_FUNCTION_MODE (mode, unsignedp, type); -#ifdef PROMOTE_MODE - } - else - { - PROMOTE_MODE (mode, unsignedp, type); - } -#endif + PROMOTE_MODE (mode, unsignedp, type); + *punsignedp = unsignedp; + return mode; break; -#endif #ifdef POINTERS_EXTEND_UNSIGNED case REFERENCE_TYPE: case POINTER_TYPE: - mode = Pmode; - unsignedp = POINTERS_EXTEND_UNSIGNED; + *punsignedp = POINTERS_EXTEND_UNSIGNED; + return Pmode; break; #endif default: - break; + return mode; } - - *punsignedp = unsignedp; +#else return mode; +#endif } + + +/* Use one of promote_mode or promote_function_mode to find the promoted + mode of DECL. If PUNSIGNEDP is not NULL, store there the unsignedness + of DECL after promotion. */ + +enum machine_mode +promote_decl_mode (const_tree decl, int *punsignedp) +{ + tree type = TREE_TYPE (decl); + int unsignedp = TYPE_UNSIGNED (type); + enum machine_mode mode = DECL_MODE (decl); + enum machine_mode pmode; + + if (TREE_CODE (decl) == RESULT_DECL) + pmode = promote_function_mode (type, mode, &unsignedp, + TREE_TYPE (current_function_decl), 1); + else if (TREE_CODE (decl) == PARM_DECL) + pmode = promote_function_mode (type, mode, &unsignedp, + TREE_TYPE (current_function_decl), 0); + else + pmode = promote_mode (type, mode, &unsignedp); + + if (punsignedp) + *punsignedp = unsignedp; + return pmode; +} + /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes). This pops when ADJUST is positive. ADJUST need not be constant. */ diff --git a/gcc/expr.c b/gcc/expr.c index aafa1aaca4a..08c747ecffb 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -5435,13 +5435,11 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) enum machine_mode mode; HOST_WIDE_INT bitsize; HOST_WIDE_INT bitpos; - int unsignedp; rtx xtarget = target; if (cleared && initializer_zerop (value)) continue; - unsignedp = TYPE_UNSIGNED (elttype); mode = TYPE_MODE (elttype); if (mode == BLKmode) bitsize = (host_integerp (TYPE_SIZE (elttype), 1) @@ -5497,14 +5495,10 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size) tree exit_cond; expand_normal (hi_index); - unsignedp = TYPE_UNSIGNED (domain); index = build_decl (EXPR_LOCATION (exp), VAR_DECL, NULL_TREE, domain); - - index_r - = gen_reg_rtx (promote_mode (domain, DECL_MODE (index), - &unsignedp, 0)); + index_r = gen_reg_rtx (promote_decl_mode (index, NULL)); SET_DECL_RTL (index, index_r); store_expr (lo_index, index_r, 0, false); @@ -7429,9 +7423,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, /* Get the signedness used for this variable. Ensure we get the same mode we got when the variable was declared. */ - pmode = promote_mode (type, DECL_MODE (exp), &unsignedp, - (TREE_CODE (exp) == RESULT_DECL - || TREE_CODE (exp) == PARM_DECL) ? 1 : 0); + pmode = promote_decl_mode (exp, &unsignedp); gcc_assert (GET_MODE (decl_rtl) == pmode); temp = gen_lowpart_SUBREG (mode, decl_rtl); diff --git a/gcc/expr.h b/gcc/expr.h index caf965e9412..8e23aecb4b9 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -719,8 +719,17 @@ extern rtx force_reg (enum machine_mode, rtx); /* Return given rtx, copied into a new temp reg if it was in memory. */ extern rtx force_not_mem (rtx); +/* Return mode and signedness to use when an argument or result in the + given mode is promoted. */ +extern enum machine_mode promote_function_mode (const_tree, enum machine_mode, int *, + const_tree, int); + +/* Return mode and signedness to use when an object in the given mode + is promoted. */ +extern enum machine_mode promote_mode (const_tree, enum machine_mode, int *); + /* Return mode and signedness to use when object is promoted. */ -extern enum machine_mode promote_mode (const_tree, enum machine_mode, int *, int); +enum machine_mode promote_decl_mode (const_tree, int *); /* Remove some bytes from the stack. An rtx says how many. */ extern void adjust_stack (rtx); diff --git a/gcc/function.c b/gcc/function.c index e31c12ada35..2294b971547 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -922,7 +922,7 @@ assign_temp (tree type_or_decl, int keep, int memory_required, #ifdef PROMOTE_MODE if (! dont_promote) - mode = promote_mode (type, mode, &unsignedp, 0); + mode = promote_mode (type, mode, &unsignedp); #endif return gen_reg_rtx (mode); @@ -2167,6 +2167,7 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm, { tree nominal_type, passed_type; enum machine_mode nominal_mode, passed_mode, promoted_mode; + int unsignedp; memset (data, 0, sizeof (*data)); @@ -2219,13 +2220,9 @@ assign_parm_find_data_types (struct assign_parm_data_all *all, tree parm, } /* Find mode as it is passed by the ABI. */ - promoted_mode = passed_mode; - if (targetm.calls.promote_function_args (TREE_TYPE (current_function_decl))) - { - int unsignedp = TYPE_UNSIGNED (passed_type); - promoted_mode = promote_mode (passed_type, promoted_mode, - &unsignedp, 1); - } + unsignedp = TYPE_UNSIGNED (passed_type); + promoted_mode = promote_function_mode (passed_type, passed_mode, &unsignedp, + TREE_TYPE (current_function_decl), 0); egress: data->nominal_type = nominal_type; @@ -2778,7 +2775,8 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm, /* This is not really promoting for a call. However we need to be consistent with assign_parm_find_data_types and expand_expr_real_1. */ promoted_nominal_mode - = promote_mode (data->nominal_type, data->nominal_mode, &unsignedp, 1); + = promote_function_mode (data->nominal_type, data->nominal_mode, &unsignedp, + TREE_TYPE (current_function_decl), 0); parmreg = gen_reg_rtx (promoted_nominal_mode); @@ -4722,10 +4720,9 @@ expand_function_end (void) else if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl)) { int unsignedp = TYPE_UNSIGNED (TREE_TYPE (decl_result)); - - if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl))) - promote_mode (TREE_TYPE (decl_result), GET_MODE (decl_rtl), - &unsignedp, 1); + promote_function_mode (TREE_TYPE (decl_result), + GET_MODE (decl_rtl), &unsignedp, + TREE_TYPE (current_function_decl), 1); convert_move (real_decl_rtl, decl_rtl, unsignedp); } diff --git a/gcc/stmt.c b/gcc/stmt.c index d544080a3c1..29bcf870fba 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -1514,23 +1514,22 @@ expand_value_return (rtx val) /* Copy the value to the return location unless it's already there. */ - rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl)); + tree decl = DECL_RESULT (current_function_decl); + rtx return_reg = DECL_RTL (decl); if (return_reg != val) { - tree type = TREE_TYPE (DECL_RESULT (current_function_decl)); - if (targetm.calls.promote_function_return (TREE_TYPE (current_function_decl))) - { - int unsignedp = TYPE_UNSIGNED (type); - enum machine_mode old_mode - = DECL_MODE (DECL_RESULT (current_function_decl)); - enum machine_mode mode - = promote_mode (type, old_mode, &unsignedp, 1); - - if (mode != old_mode) - val = convert_modes (mode, old_mode, val, unsignedp); - } + int unsignedp; + enum machine_mode old_mode = DECL_MODE (decl); + enum machine_mode mode = promote_decl_mode (decl, &unsignedp); + + if (mode != old_mode) + val = convert_modes (mode, old_mode, val, unsignedp); + if (GET_CODE (return_reg) == PARALLEL) - emit_group_load (return_reg, val, type, int_size_in_bytes (type)); + { + tree type = TREE_TYPE (decl); + emit_group_load (return_reg, val, type, int_size_in_bytes (type)); + } else emit_move_insn (return_reg, val); } @@ -1848,9 +1847,7 @@ expand_decl (tree decl) else if (use_register_for_decl (decl)) { /* Automatic variable that can go in a register. */ - int unsignedp = TYPE_UNSIGNED (type); - enum machine_mode reg_mode - = promote_mode (type, DECL_MODE (decl), &unsignedp, 0); + enum machine_mode reg_mode = promote_decl_mode (decl, NULL); SET_DECL_RTL (decl, gen_reg_rtx (reg_mode)); diff --git a/gcc/system.h b/gcc/system.h index 7a9ca816693..5d47f2e1839 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -684,7 +684,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN; DIVDI3_LIBCALL UDIVSI3_LIBCALL UDIVDI3_LIBCALL MODSI3_LIBCALL \ MODDI3_LIBCALL UMODSI3_LIBCALL UMODDI3_LIBCALL BUILD_VA_LIST_TYPE \ PRETEND_OUTGOING_VARARGS_NAMED STRUCT_VALUE_INCOMING_REGNUM \ - ASM_OUTPUT_SECTION_NAME PROMOTE_FUNCTION_ARGS \ + ASM_OUTPUT_SECTION_NAME PROMOTE_FUNCTION_ARGS PROMOTE_FUNCTION_MODE \ STRUCT_VALUE_INCOMING STRICT_ARGUMENT_NAMING \ PROMOTE_FUNCTION_RETURN PROMOTE_PROTOTYPES STRUCT_VALUE_REGNUM \ SETUP_INCOMING_VARARGS EXPAND_BUILTIN_SAVEREGS \ @@ -754,7 +754,8 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN; LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS \ LANG_HOOKS_PUSHLEVEL LANG_HOOKS_SET_BLOCK \ LANG_HOOKS_MAYBE_BUILD_CLEANUP LANG_HOOKS_UPDATE_DECL_AFTER_SAVING \ - LANG_HOOKS_POPLEVEL LANG_HOOKS_TRUTHVALUE_CONVERSION + LANG_HOOKS_POPLEVEL LANG_HOOKS_TRUTHVALUE_CONVERSION \ + TARGET_PROMOTE_FUNCTION_ARGS TARGET_PROMOTE_FUNCTION_RETURN /* Miscellaneous macros that are no longer used. */ #pragma GCC poison USE_MAPPED_LOCATION diff --git a/gcc/target-def.h b/gcc/target-def.h index 54060f5395c..26464ed4472 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -574,8 +574,7 @@ #define TARGET_ARM_EABI_UNWINDER false -#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_false -#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_false +#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_false #define TARGET_STRUCT_VALUE_RTX hook_rtx_tree_int_null @@ -605,8 +604,7 @@ #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS hook_bool_void_true #define TARGET_CALLS { \ - TARGET_PROMOTE_FUNCTION_ARGS, \ - TARGET_PROMOTE_FUNCTION_RETURN, \ + TARGET_PROMOTE_FUNCTION_MODE, \ TARGET_PROMOTE_PROTOTYPES, \ TARGET_STRUCT_VALUE_RTX, \ TARGET_RETURN_IN_MEMORY, \ diff --git a/gcc/target.h b/gcc/target.h index bd107179498..27fd77b7779 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -832,8 +832,11 @@ struct gcc_target /* Functions relating to calls - argument passing, returns, etc. */ struct calls { - bool (*promote_function_args) (const_tree fntype); - bool (*promote_function_return) (const_tree fntype); + enum machine_mode (*promote_function_mode) (const_tree type, + enum machine_mode mode, + int *punsignedp, + const_tree fntype, + int for_return); bool (*promote_prototypes) (const_tree fntype); rtx (*struct_value_rtx) (tree fndecl, int incoming); bool (*return_in_memory) (const_tree type, const_tree fndecl); diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 7d5a09233c7..8c3c2ab1e24 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -113,6 +113,27 @@ default_unspec_may_trap_p (const_rtx x, unsigned flags) } enum machine_mode +default_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, + enum machine_mode mode, + int *punsignedp ATTRIBUTE_UNUSED, + const_tree funtype ATTRIBUTE_UNUSED, + int for_return ATTRIBUTE_UNUSED) +{ + return mode; +} + +enum machine_mode +default_promote_function_mode_always_promote (const_tree type, + enum machine_mode mode, + int *punsignedp, + const_tree funtype ATTRIBUTE_UNUSED, + int for_return ATTRIBUTE_UNUSED) +{ + return promote_mode (type, mode, punsignedp); +} + + +enum machine_mode default_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2) { if (m1 == m2) diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 839f1c32360..5564a7983cf 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -24,6 +24,10 @@ extern void default_external_libcall (rtx); extern rtx default_legitimize_address (rtx, rtx, enum machine_mode); extern int default_unspec_may_trap_p (const_rtx, unsigned); +extern enum machine_mode default_promote_function_mode (const_tree, enum machine_mode, + int *, const_tree, int); +extern enum machine_mode default_promote_function_mode_always_promote + (const_tree, enum machine_mode, int *, const_tree, int); extern enum machine_mode default_cc_modes_compatible (enum machine_mode, enum machine_mode); diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c index 696c7259eed..420ee8099b4 100644 --- a/gcc/tree-outof-ssa.c +++ b/gcc/tree-outof-ssa.c @@ -566,9 +566,8 @@ get_temp_reg (tree name) { tree var = TREE_CODE (name) == SSA_NAME ? SSA_NAME_VAR (name) : name; tree type = TREE_TYPE (var); - int unsignedp = TYPE_UNSIGNED (type); - enum machine_mode reg_mode - = promote_mode (type, DECL_MODE (var), &unsignedp, 0); + int unsignedp; + enum machine_mode reg_mode = promote_decl_mode (var, &unsignedp); rtx x = gen_reg_rtx (reg_mode); if (POINTER_TYPE_P (type)) mark_reg_pointer (x, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (var)))); |