diff options
author | Roger Sayle <roger@nextmovesoftware.com> | 2022-07-04 16:45:47 +0100 |
---|---|---|
committer | Roger Sayle <roger@nextmovesoftware.com> | 2022-07-04 16:45:47 +0100 |
commit | ac4c8f53b0f735be17aa020796602de2299da1c5 (patch) | |
tree | cc3b7b25905f59d4ab62635cd2b5dfc0925f04e1 /gcc/calls.cc | |
parent | fc968115a742d9e4674d9725ce9c2106b91b6ead (diff) | |
download | gcc-ac4c8f53b0f735be17aa020796602de2299da1c5.zip gcc-ac4c8f53b0f735be17aa020796602de2299da1c5.tar.gz gcc-ac4c8f53b0f735be17aa020796602de2299da1c5.tar.bz2 |
middle-end: Support ABIs that pass FP values as wider integers.
Sorry for the long delay getting back to this, but after deeper
investigation, it turns out that Jeff Law's tingling spider senses
that the original patch wasn't updating everywhere that was required
were spot on. Although my nvptx testing showed no problems with -O2,
compiling the same tests with -O0 found several additional assertion
ICEs (exactly where he'd predicted they'd be).
Here's a revised patch that updates five locations (up from the
previous two). Finding any remaining locations (if any) might be
easier once folks are able to test things on their targets. This
also implements Jeff's suggestion to factor the common code into
helper routines.
2022-07-04 Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
PR target/104489
* calls.cc (precompute_register_parameters): Allow promotion
of floating point values to be passed in wider integer modes
by calling new convert_float_to_wider_int.
(expand_call): Allow floating point results to be returned in
wider integer modes by calling new convert wider_int_to_float.
* cfgexpand.cc (expand_value_return): Allow backends to promote
a scalar floating point return value to a wider integer mode
by calling new convert_float_to_wider_int.
* expr.cc (convert_float_to_wider_int): New function.
(convert_wider_int_to_float): Likewise.
(expand_expr_real_1) <expand_decl_rtl>: Allow backends to promote
scalar FP PARM_DECLs to wider integer modes, by calling new
convert_wider_int_to_float.
* expr.h (convert_modes): Name arguments for improved documentation.
(convert_float_to_wider_int): Prototype new function here.
(convert_wider_int_to_float): Likewise.
* function.cc (assign_parm_setup_stack): Allow floating point
values to be passed on the stack as wider integer modes by
calling new convert_wider_int_to_float.
Diffstat (limited to 'gcc/calls.cc')
-rw-r--r-- | gcc/calls.cc | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/gcc/calls.cc b/gcc/calls.cc index f4e1299..7f3cf5f 100644 --- a/gcc/calls.cc +++ b/gcc/calls.cc @@ -992,11 +992,21 @@ precompute_register_parameters (int num_actuals, struct arg_data *args, /* If we are to promote the function arg to a wider mode, do it now. */ - if (args[i].mode != TYPE_MODE (TREE_TYPE (args[i].tree_value))) - args[i].value - = convert_modes (args[i].mode, - TYPE_MODE (TREE_TYPE (args[i].tree_value)), - args[i].value, args[i].unsignedp); + machine_mode old_mode = TYPE_MODE (TREE_TYPE (args[i].tree_value)); + + /* Some ABIs require scalar floating point modes to be returned + in a wider scalar integer mode. We need to explicitly + reinterpret to an integer mode of the correct precision + before extending to the desired result. */ + if (SCALAR_INT_MODE_P (args[i].mode) + && SCALAR_FLOAT_MODE_P (old_mode) + && known_gt (GET_MODE_SIZE (args[i].mode), + GET_MODE_SIZE (old_mode))) + args[i].value = convert_float_to_wider_int (args[i].mode, old_mode, + args[i].value); + else if (args[i].mode != old_mode) + args[i].value = convert_modes (args[i].mode, old_mode, + args[i].value, args[i].unsignedp); /* If the value is a non-legitimate constant, force it into a pseudo now. TLS symbols sometimes need a call to resolve. */ @@ -3825,18 +3835,24 @@ expand_call (tree exp, rtx target, int ignore) { tree type = rettype; int unsignedp = TYPE_UNSIGNED (type); + machine_mode ret_mode = TYPE_MODE (type); machine_mode pmode; /* Ensure we promote as expected, and get the new unsignedness. */ - pmode = promote_function_mode (type, TYPE_MODE (type), &unsignedp, + pmode = promote_function_mode (type, ret_mode, &unsignedp, funtype, 1); gcc_assert (GET_MODE (target) == pmode); - poly_uint64 offset = subreg_lowpart_offset (TYPE_MODE (type), - GET_MODE (target)); - target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset); - SUBREG_PROMOTED_VAR_P (target) = 1; - SUBREG_PROMOTED_SET (target, unsignedp); + if (SCALAR_INT_MODE_P (pmode) + && SCALAR_FLOAT_MODE_P (ret_mode) + && known_gt (GET_MODE_SIZE (pmode), GET_MODE_SIZE (ret_mode))) + target = convert_wider_int_to_float (ret_mode, pmode, target); + else + { + target = gen_lowpart_SUBREG (ret_mode, target); + SUBREG_PROMOTED_VAR_P (target) = 1; + SUBREG_PROMOTED_SET (target, unsignedp); + } } /* If size of args is variable or this was a constructor call for a stack |