aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.cc
diff options
context:
space:
mode:
authorRoger Sayle <roger@nextmovesoftware.com>2022-07-04 16:45:47 +0100
committerRoger Sayle <roger@nextmovesoftware.com>2022-07-04 16:45:47 +0100
commitac4c8f53b0f735be17aa020796602de2299da1c5 (patch)
treecc3b7b25905f59d4ab62635cd2b5dfc0925f04e1 /gcc/expr.cc
parentfc968115a742d9e4674d9725ce9c2106b91b6ead (diff)
downloadgcc-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/expr.cc')
-rw-r--r--gcc/expr.cc35
1 files changed, 35 insertions, 0 deletions
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 53af027..6229737 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -776,6 +776,32 @@ convert_modes (machine_mode mode, machine_mode oldmode, rtx x, int unsignedp)
convert_move (temp, x, unsignedp);
return temp;
}
+
+/* Variant of convert_modes for ABI parameter passing/return.
+ Return an rtx for a value that would result from converting X from
+ a floating point mode FMODE to wider integer mode MODE. */
+
+rtx
+convert_float_to_wider_int (machine_mode mode, machine_mode fmode, rtx x)
+{
+ gcc_assert (SCALAR_INT_MODE_P (mode) && SCALAR_FLOAT_MODE_P (fmode));
+ scalar_int_mode tmp_mode = int_mode_for_mode (fmode).require ();
+ rtx tmp = force_reg (tmp_mode, gen_lowpart (tmp_mode, x));
+ return convert_modes (mode, tmp_mode, tmp, 1);
+}
+
+/* Variant of convert_modes for ABI parameter passing/return.
+ Return an rtx for a value that would result from converting X from
+ an integer mode IMODE to a narrower floating point mode MODE. */
+
+rtx
+convert_wider_int_to_float (machine_mode mode, machine_mode imode, rtx x)
+{
+ gcc_assert (SCALAR_FLOAT_MODE_P (mode) && SCALAR_INT_MODE_P (imode));
+ scalar_int_mode tmp_mode = int_mode_for_mode (mode).require ();
+ rtx tmp = force_reg (tmp_mode, gen_lowpart (tmp_mode, x));
+ return gen_lowpart_SUBREG (mode, tmp);
+}
/* Return the largest alignment we can use for doing a move (or store)
of MAX_PIECES. ALIGN is the largest alignment we could use. */
@@ -10771,6 +10797,15 @@ 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);
+ /* 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
+ using a SUBREG to reinterpret as a floating point value. */
+ if (SCALAR_FLOAT_MODE_P (mode)
+ && SCALAR_INT_MODE_P (pmode)
+ && known_lt (GET_MODE_SIZE (mode), GET_MODE_SIZE (pmode)))
+ return convert_wider_int_to_float (mode, pmode, decl_rtl);
+
temp = gen_lowpart_SUBREG (mode, decl_rtl);
SUBREG_PROMOTED_VAR_P (temp) = 1;
SUBREG_PROMOTED_SET (temp, unsignedp);