https://gcc.gnu.org/g:69705411b1cae2c6e96877b1a60fd90601087905

commit 69705411b1cae2c6e96877b1a60fd90601087905
Author: Michael Meissner <[email protected]>
Date:   Thu Sep 3 22:26:02 2026 -0400

    Don't return HFmode/BFmode as SFmode.
    
    2026-09-03  Michael Meissner  <[email protected]>
    
    gcc/
    
            * config/rs6000/rs6000-call.cc (rs6000_promote_function_mode): Only
            convert HFmode/BFmode to SFmode, but don't change return value at
            present.
            (rs6000_promote_function_mode_convert): Add unsignedp argument.
            * config/rs6000/rs6000-internal.h
            (rs6000_promote_function_mode_convert): Update calling sequence.
            * config/rs6000/rs6000.cc (rs6000_function_value): Undo last change.
            * doc/tm.texi: Regenerate.
            * doc/tm.texi.in (TARGET_PROMOTE_FUNCTION_MODE_CONVERT): Update 
calling
            sequence.
            * expr.cc (expand_expr_real_1): Update call to
            promote_function_mode_convert.
            * target.def (PROMOTE_FUNCTION_MODE_CONVERT): Update calling 
sequence.
            * targhooks.cc (default_promote_function_mode_convert): Likewise.
            * targhooks.h (default_promote_function_mode_convert): Likewise.

Diff:
---
 gcc/config/rs6000/rs6000-call.cc    | 13 ++++++-------
 gcc/config/rs6000/rs6000-internal.h |  2 +-
 gcc/config/rs6000/rs6000.cc         |  3 ---
 gcc/doc/tm.texi                     |  5 +++--
 gcc/expr.cc                         | 16 +++++++++++-----
 gcc/target.def                      |  6 ++++--
 gcc/targhooks.cc                    |  7 ++++---
 gcc/targhooks.h                     |  2 +-
 8 files changed, 30 insertions(+), 24 deletions(-)

diff --git a/gcc/config/rs6000/rs6000-call.cc b/gcc/config/rs6000/rs6000-call.cc
index 2c7d864f495b..9460d4fb49ac 100644
--- a/gcc/config/rs6000/rs6000-call.cc
+++ b/gcc/config/rs6000/rs6000-call.cc
@@ -721,9 +721,9 @@ machine_mode
 rs6000_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
                              machine_mode mode,
                              int *punsignedp ATTRIBUTE_UNUSED,
-                             const_tree, int for_return ATTRIBUTE_UNUSED)
+                             const_tree, int for_return)
 {
-  if (FP16_SCALAR_MODE_P (mode))
+  if (FP16_SCALAR_MODE_P (mode) && !for_return)
     return SFmode;
 
   if (GET_MODE_CLASS (mode) == MODE_INT
@@ -738,12 +738,11 @@ rs6000_promote_function_mode (const_tree type 
ATTRIBUTE_UNUSED,
 rtx
 rs6000_promote_function_mode_convert (machine_mode new_mode,
                                      machine_mode old_mode,
-                                     rtx decl_rtl)
+                                     rtx decl_rtl,
+                                     int unsignedp)
 {
-  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);
+  if (FP16_SCALAR_MODE_P (new_mode) || FP16_SCALAR_MODE_P (old_mode))
+    return convert_to_mode (new_mode, decl_rtl, unsignedp);
 
   return NULL_RTX;
 }
diff --git a/gcc/config/rs6000/rs6000-internal.h 
b/gcc/config/rs6000/rs6000-internal.h
index 7e5b40b73db6..dc8bde7cebb9 100644
--- a/gcc/config/rs6000/rs6000-internal.h
+++ b/gcc/config/rs6000/rs6000-internal.h
@@ -151,7 +151,7 @@ extern machine_mode rs6000_promote_function_mode 
(const_tree type ATTRIBUTE_UNUS
                                                  const_tree, int);
 extern rtx rs6000_promote_function_mode_convert (machine_mode new_mode,
                                                 machine_mode old_mode,
-                                                rtx decl_rtl);
+                                                rtx decl_rtl, int unsignedp);
 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 9ee451d8912e..7f2b8b71d159 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -24426,9 +24426,6 @@ 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 68721b73d2ce..fd875ed24a5c 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -1110,11 +1110,12 @@ 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
+@deftypefn {Target Hook} rtx TARGET_PROMOTE_FUNCTION_MODE_CONVERT 
(machine_mode @var{new_mode}, machine_mode @var{old_mode}, rtx @var{decl_rtl}, 
int @var{unsignedp})
+If @code{PROMOTE_FUNCTION_MODE} returns a 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 argument @var{UNSIGNEDP} is non-0 if the type is unsigned.
 
 The default is to not do a conversion.
 @end deftypefn
diff --git a/gcc/expr.cc b/gcc/expr.cc
index ab0d6af870de..4a38c4a97c36 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -11878,11 +11878,17 @@ expand_expr_real_1 (tree exp, rtx target, 
machine_mode tmode,
          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);
+         if (pmode != mode)
+           {
+             rtx cvt
+               = targetm.calls.promote_function_mode_convert (pmode,
+                                                              mode,
+                                                              decl_rtl,
+                                                              unsignedp);
+
+             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
diff --git a/gcc/target.def b/gcc/target.def
index 884862096154..54158aa51c7e 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -4932,13 +4932,15 @@ if you would like to apply the same rules given by 
@code{PROMOTE_MODE}.",
 
 DEFHOOK
 (promote_function_mode_convert,
- "If @code{PROMOTE_FUNCTION_MODE} returns mode (@code{@var{NEW_MODE}}) which\n\
+ "If @code{PROMOTE_FUNCTION_MODE} returns a 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\
+The argument @var{UNSIGNEDP} is non-0 if the type is unsigned.\n\
 \n\
 The default is to not do a conversion.",
- rtx, (machine_mode new_mode, machine_mode old_mode, rtx decl_rtl),
+ rtx, (machine_mode new_mode, machine_mode old_mode, rtx decl_rtl,
+       int unsignedp),
  default_promote_function_mode_convert)
 
 DEFHOOK
diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
index 9ec801e79df9..068c97bfdf46 100644
--- a/gcc/targhooks.cc
+++ b/gcc/targhooks.cc
@@ -153,9 +153,10 @@ default_promote_function_mode (const_tree type 
ATTRIBUTE_UNUSED,
 }
 
 rtx
-default_promot_function_mode_convert (machine_mode new_mode ATTRIBUTE_UNUSED,
-                                     machine_mode old_mode ATTRIBUTE_UNUSED,
-                                     rtx decl_rtx ATTRIBUTE_UNUSED)
+default_promote_function_mode_convert (machine_mode new_mode ATTRIBUTE_UNUSED,
+                                      machine_mode old_mode ATTRIBUTE_UNUSED,
+                                      rtx decl_rtx ATTRIBUTE_UNUSED,
+                                      int unsignedp ATTRIBUTE_UNUSED)
 {
   return NULL_RTX;
 }
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 204f7f7e0be8..70feec79ceba 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -32,7 +32,7 @@ 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);
+                                                 rtx, int);
 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

Reply via email to