https://gcc.gnu.org/g:6ad573de4e7dd03ed4edbf2caf1c2cb028b647bf

commit 6ad573de4e7dd03ed4edbf2caf1c2cb028b647bf
Author: Michael Meissner <[email protected]>
Date:   Tue Oct 21 23:47:00 2025 -0400

    Add scalar _Float16 converts.
    
    2025-10-21  Michael Meissner  <[email protected]>
    
    gcc/
    
            * config/rs6000/float16.md (FP16_HW): New mode iterator.
            (VFP16_HW): Likewise.
            (fp16_float_convert): Likewise.
            (extendhf<mode>2): Add support converting between HFmode and other
            floating point scalars if we are on power9 or later.
            (trunc<mode>hf2): Likewise.
            (extend<FP16_HW:mode><fp16_float_convert:mode>): Likewise.
            (trunc<fp16_float_convert:mode><FP16_HW:mode>2): Likewise.
            (float<GPR:mode><FP16_HW:mode>2): Add support converting between 
HFmode
            to and from integers.
            (floatuns<GPR:mode><FP16_HW:mode>2): Likewise.
            (fix_trunc<FP16_HW:mode><GPR:mode>2): Likewise.
            (fixuns_trunc<FP16_HW:mode><GPR:mode>2): Likewise.

Diff:
---
 gcc/config/rs6000/float16.md | 110 +++++++++++++++++++++++++++++++++++++++++++
 gcc/config/rs6000/rs6000.h   |   8 ++++
 2 files changed, 118 insertions(+)

diff --git a/gcc/config/rs6000/float16.md b/gcc/config/rs6000/float16.md
index 4240602f66ea..9e3444111ddc 100644
--- a/gcc/config/rs6000/float16.md
+++ b/gcc/config/rs6000/float16.md
@@ -36,6 +36,15 @@
 (define_mode_attr fp16_vector8 [(BF "v8bf")
                                (HF "v8hf")])
 
+;; Mode iterator for 16-bit floating point modes on machines with
+;; hardware support both as a scalar and as a vector.
+(define_mode_iterator FP16_HW [(HF "TARGET_FLOAT16_HW")])
+
+(define_mode_iterator VFP16_HW [(V8HF "TARGET_FLOAT16_HW")])
+
+;; Mode iterator for floating point modes other than SF/DFmode that we
+;; convert to/from _Float16 (HFmode) via DFmode.
+(define_mode_iterator fp16_float_convert [TF KF IF SD DD TD])
 
 ;; _Float16 and __bfloat16 moves
 (define_expand "mov<mode>"
@@ -126,3 +135,104 @@
 }
   [(set_attr "type" "vecperm")
    (set_attr "prefixed" "*,yes")])
+
+
+
+;; Convert IEEE 16-bit floating point to/from other floating point modes.
+
+(define_insn "extendhf<mode>2"
+  [(set (match_operand:SFDF 0 "vsx_register_operand" "=wa")
+       (float_extend:SFDF
+        (match_operand:HF 1 "vsx_register_operand" "wa")))]
+  "TARGET_FLOAT16_HW"
+  "xscvhpdp %x0,%x1"
+  [(set_attr "type" "fpsimple")])
+
+(define_insn "trunc<mode>hf2"
+  [(set (match_operand:HF 0 "vsx_register_operand" "=wa")
+       (float_truncate:HF
+        (match_operand:SFDF 1 "vsx_register_operand" "wa")))]
+  "TARGET_FLOAT16_HW"
+  "xscvdphp %x0,%x1"
+  [(set_attr "type" "fpsimple")])
+
+
+;; Convert between HFmode and 128-bit binary floating point and
+;; decimal floating point types.  We use convert_move since some of the
+;; types might not have valid RTX expanders.  We use DFmode as the
+;; intermediate conversion destination.
+
+(define_expand "extend<FP16_HW:mode><fp16_float_convert:mode>2"
+  [(set (match_operand:fp16_float_convert 0 "vsx_register_operand")
+       (float_extend:fp16_float_convert
+        (match_operand:FP16_HW 1 "vsx_register_operand")))]
+  ""
+{
+  rtx df_tmp = gen_reg_rtx (DFmode);
+  emit_insn (gen_extend<FP16_HW:mode>df2 (df_tmp, operands[1]));
+  convert_move (operands[0], df_tmp, 0);
+  DONE;
+})
+
+(define_expand "trunc<fp16_float_convert:mode><FP16_HW:mode>2"
+  [(set (match_operand:FP16_HW 0 "vsx_register_operand")
+       (float_truncate:FP16_HW
+        (match_operand:fp16_float_convert 1 "vsx_register_operand")))]
+  ""
+{
+  rtx df_tmp = gen_reg_rtx (DFmode);
+
+  convert_move (df_tmp, operands[1], 0);
+  emit_insn (gen_truncdf<FP16_HW:mode>2 (operands[0], df_tmp));
+  DONE;
+})
+
+;; Convert integers to 16-bit floating point modes.
+(define_expand "float<GPR:mode><FP16_HW:mode>2"
+  [(set (match_operand:FP16_HW 0 "vsx_register_operand")
+       (float:FP16_HW
+        (match_operand:GPR 1 "nonimmediate_operand")))]
+  ""
+{
+  rtx df_tmp = gen_reg_rtx (DFmode);
+  emit_insn (gen_float<GPR:mode>df2 (df_tmp, operands[1]));
+  emit_insn (gen_truncdf<FP16_HW:mode>2 (operands[0], df_tmp));
+  DONE;
+})
+
+(define_expand "floatuns<GPR:mode><FP16_HW:mode>2"
+  [(set (match_operand:FP16_HW 0 "vsx_register_operand")
+       (unsigned_float:FP16_HW
+        (match_operand:GPR 1 "nonimmediate_operand")))]
+  ""
+{
+  rtx df_tmp = gen_reg_rtx (DFmode);
+  emit_insn (gen_floatuns<GPR:mode>df2 (df_tmp, operands[1]));
+  emit_insn (gen_truncdf<FP16_HW:mode>2 (operands[0], df_tmp));
+  DONE;
+})
+
+;; Convert 16-bit floating point modes to integers
+(define_expand "fix_trunc<FP16_HW:mode><GPR:mode>2"
+  [(set (match_operand:GPR 0 "vsx_register_operand")
+       (fix:GPR
+        (match_operand:FP16_HW 1 "vsx_register_operand")))]
+  ""
+{
+  rtx df_tmp = gen_reg_rtx (DFmode);
+  emit_insn (gen_extend<FP16_HW:mode>df2 (df_tmp, operands[1]));
+  emit_insn (gen_fix_truncdf<GPR:mode>2 (operands[0], df_tmp));
+  DONE;
+})
+
+(define_expand "fixuns_trunc<FP16_HW:mode><GPR:mode>2"
+  [(set (match_operand:GPR 0 "vsx_register_operand")
+       (unsigned_fix:GPR
+        (match_operand:FP16_HW 1 "vsx_register_operand")))]
+  ""
+{
+  rtx df_tmp = gen_reg_rtx (DFmode);
+  emit_insn (gen_extend<FP16_HW:mode>df2 (df_tmp, operands[1]));
+  emit_insn (gen_fixuns_truncdf<GPR:mode>2 (operands[0], df_tmp));
+  DONE;
+})
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 0249219bbbc9..eb60573ae4bd 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -343,11 +343,19 @@ extern const char *host_detect_local_cpu (int argc, const 
char **argv);
    || ((MODE) == TDmode)                                               \
    || (!TARGET_FLOAT128_TYPE && FLOAT128_IEEE_P (MODE)))
 
+/* Do we have conversion support in hardware for the 16-bit floating point?  */
+#define TARGET_FLOAT16_HW      (TARGET_FLOAT16 && TARGET_POWER9)
+
 /* Is this a valid 16-bit scalar floating point mode?  */
 #define FP16_SCALAR_MODE_P(MODE)                                       \
   (((MODE) == HFmode && TARGET_FLOAT16)                                        
\
    || ((MODE) == BFmode && TARGET_BFLOAT16))
 
+/* Is this a valid 16-bit scalar floating point mode that has hardware
+   conversions?  */
+#define FP16_HW_SCALAR_MODE_P(MODE)                                    \
+  ((MODE) == HFmode && TARGET_FLOAT16_HW)
+
 /* Is this a valid 16-bit vector floating point mode?  */
 #define FP16_VECTOR_MODE_P(MODE)                                       \
   (((MODE) == V8HFmode && TARGET_FLOAT16)                              \

Reply via email to