https://gcc.gnu.org/g:51e7b464b1d61138f2aad4e0984b99e044f4dab0
commit 51e7b464b1d61138f2aad4e0984b99e044f4dab0 Author: Michael Meissner <[email protected]> Date: Thu Sep 3 21:30:14 2026 -0400 Pass/return HFmode and BFmode as SFmode. 2026-09-03 Michael Meissner <[email protected]> gcc/ * config/rs6000/rs6000-call.cc (rs6000_promote_function_mode): Pass and return BFmode and HFmode as SFmode. * config/rs6000/rs6000-internal.h (rs6000_promote_function_mode_convert): New declaration. * config/rs6000/rs6000.cc (TARGET_PROMOTE_FUNCTION_MODE_CONVERT): Override default. (rs6000_function_value): Return BFmode/HFmode as SFmode. * doc/tm.texi: Regenerate. * doc/tm.texi.in: (TARGET_PROMOTE_FUNCTION_MODE_CONVERT): New hook. * expr.cc (expand_expr_real_1): Add support for doing a conversion if the argument is passed as a different mode instead of doing a SUBREG. * target.def (promote_function_mode_convert): Add a new target hook to possibly do a real conversion if a function argument is passed ass a different mode. * targhooks.cc (default_promot_function_mode_convert): Likewise. * targhooks.h (default_promot_function_mode_convert): Likewise. Diff: --- gcc/config/rs6000/rs6000-call.cc | 18 ++++++++++++++++++ gcc/config/rs6000/rs6000-internal.h | 3 +++ gcc/config/rs6000/rs6000.cc | 6 ++++++ gcc/doc/tm.texi | 9 +++++++++ gcc/doc/tm.texi.in | 2 ++ gcc/expr.cc | 15 ++++++++++++--- gcc/target.def | 11 +++++++++++ gcc/targhooks.cc | 8 ++++++++ gcc/targhooks.h | 2 ++ 9 files changed, 71 insertions(+), 3 deletions(-) diff --git a/gcc/config/rs6000/rs6000-call.cc b/gcc/config/rs6000/rs6000-call.cc index 1abb7843f10a..2c7d864f495b 100644 --- a/gcc/config/rs6000/rs6000-call.cc +++ b/gcc/config/rs6000/rs6000-call.cc @@ -723,6 +723,9 @@ rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, int *punsignedp ATTRIBUTE_UNUSED, const_tree, int for_return ATTRIBUTE_UNUSED) { + if (FP16_SCALAR_MODE_P (mode)) + return SFmode; + if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) < (TARGET_32BIT ? 4 : 8)) mode = TARGET_32BIT ? SImode : DImode; @@ -730,6 +733,21 @@ rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, return mode; } +/* Convert 16-bit floating arguments and return values to SFmode. */ + +rtx +rs6000_promote_function_mode_convert (machine_mode new_mode, + machine_mode old_mode, + rtx decl_rtl) +{ + if (new_mode != old_mode + && (FP16_SCALAR_MODE_P (new_mode) + || FP16_SCALAR_MODE_P (old_mode))) + return convert_to_mode (new_mode, decl_rtl, 0); + + return NULL_RTX; +} + /* Return true if TYPE must be passed on the stack and not in registers. */ bool diff --git a/gcc/config/rs6000/rs6000-internal.h b/gcc/config/rs6000/rs6000-internal.h index bb1e85cf9be5..7e5b40b73db6 100644 --- a/gcc/config/rs6000/rs6000-internal.h +++ b/gcc/config/rs6000/rs6000-internal.h @@ -149,6 +149,9 @@ extern machine_mode rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUS machine_mode mode, int *punsignedp ATTRIBUTE_UNUSED, const_tree, int); +extern rtx rs6000_promote_function_mode_convert (machine_mode new_mode, + machine_mode old_mode, + rtx decl_rtl); extern bool rs6000_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED); extern bool rs6000_return_in_msb (const_tree valtype); diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 8efd0e7c9991..9ee451d8912e 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -1513,6 +1513,9 @@ static const scoped_attribute_specs *const rs6000_attribute_table[] = #undef TARGET_PROMOTE_FUNCTION_MODE #define TARGET_PROMOTE_FUNCTION_MODE rs6000_promote_function_mode +#undef TARGET_PROMOTE_FUNCTION_MODE_CONVERT +#define TARGET_PROMOTE_FUNCTION_MODE_CONVERT rs6000_promote_function_mode_convert + #undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE rs6000_override_options_after_change @@ -24423,6 +24426,9 @@ rs6000_function_value (const_tree valtype, else regno = GP_ARG_RETURN; + if (FP16_SCALAR_MODE_P (mode)) + mode = SFmode; + return gen_rtx_REG (mode, regno); } diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index a319634ea4db..68721b73d2ce 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1110,6 +1110,15 @@ 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}. @end deftypefn +@deftypefn {Target Hook} rtx TARGET_PROMOTE_FUNCTION_MODE_CONVERT (machine_mode @var{new_mode}, machine_mode @var{old_mode}, rtx @var{decl_rtl}) +If @code{PROMOTE_FUNCTION_MODE} returns mode (@code{@var{NEW_MODE}}) which +is a different mode for the function argument or return value +(@code{@var{OLD_MODE}}) for @var{DECL_RTL}, either return @code{NULL_RTX} to +use @code{SUBREG} to pass the value untranslated, or return a conversion rtl. + +The default is to not do a conversion. +@end deftypefn + @defmac PARM_BOUNDARY Normal alignment required for function parameters on the stack, in bits. All stack parameters receive at least this much alignment diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index dbc090360da3..86b216850df6 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -987,6 +987,8 @@ applied. @hook TARGET_PROMOTE_FUNCTION_MODE +@hook TARGET_PROMOTE_FUNCTION_MODE_CONVERT + @defmac PARM_BOUNDARY Normal alignment required for function parameters on the stack, in bits. All stack parameters receive at least this much alignment diff --git a/gcc/expr.cc b/gcc/expr.cc index 3d99be8472f8..ab0d6af870de 100644 --- a/gcc/expr.cc +++ b/gcc/expr.cc @@ -11852,9 +11852,11 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, /* If the mode of DECL_RTL does not match that of the decl, there are two cases: we are dealing with a BLKmode value that is returned in a register, or we are dealing with - a promoted value. In the latter case, return a SUBREG - of the wanted mode, but mark it so that we know that it - was already extended. */ + a promoted value. + + In the latter case, either do a regular conversion or return a SUBREG + of the wanted mode, but mark it so that we know that it was already + extended. */ if (REG_P (decl_rtl) && dmode != BLKmode && GET_MODE (decl_rtl) != dmode) @@ -11875,6 +11877,13 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, pmode = promote_ssa_mode (ssa_name, &unsignedp); gcc_assert (GET_MODE (decl_rtl) == pmode); + /* Convert the value if the target wants it converted. */ + rtx cvt = targetm.calls.promote_function_mode_convert (pmode, mode, + decl_rtl); + + if (cvt) + return EXTEND_BITINT (cvt); + /* Some ABIs require scalar floating point modes to be passed in a wider scalar integer mode. We need to explicitly truncate to an integer mode of the correct precision before diff --git a/gcc/target.def b/gcc/target.def index 66c20a9c9d2a..884862096154 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -4930,6 +4930,17 @@ if you would like to apply the same rules given by @code{PROMOTE_MODE}.", const_tree funtype, int for_return), default_promote_function_mode) +DEFHOOK +(promote_function_mode_convert, + "If @code{PROMOTE_FUNCTION_MODE} returns mode (@code{@var{NEW_MODE}}) which\n\ +is a different mode for the function argument or return value\n\ +(@code{@var{OLD_MODE}}) for @var{DECL_RTL}, either return @code{NULL_RTX} to\n\ +use @code{SUBREG} to pass the value untranslated, or return a conversion rtl.\n\ +\n\ +The default is to not do a conversion.", + rtx, (machine_mode new_mode, machine_mode old_mode, rtx decl_rtl), + default_promote_function_mode_convert) + DEFHOOK (promote_prototypes, "This target hook returns @code{true} if an argument declared in a\n\ diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc index 388f696c8aa1..9ec801e79df9 100644 --- a/gcc/targhooks.cc +++ b/gcc/targhooks.cc @@ -152,6 +152,14 @@ default_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, return mode; } +rtx +default_promot_function_mode_convert (machine_mode new_mode ATTRIBUTE_UNUSED, + machine_mode old_mode ATTRIBUTE_UNUSED, + rtx decl_rtx ATTRIBUTE_UNUSED) +{ + return NULL_RTX; +} + machine_mode default_promote_function_mode_always_promote (const_tree type, machine_mode mode, diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 86de6ef8a699..204f7f7e0be8 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -31,6 +31,8 @@ extern bool default_const_not_ok_for_debug_p (rtx); extern int default_unspec_may_trap_p (const_rtx, unsigned); extern machine_mode default_promote_function_mode (const_tree, machine_mode, int *, const_tree, int); +extern rtx default_promote_function_mode_convert (machine_mode, machine_mode, + rtx); extern machine_mode default_promote_function_mode_always_promote (const_tree, machine_mode, int *, const_tree, int); extern machine_mode default_promote_function_mode_sign_extend
