https://gcc.gnu.org/g:248debee952f142be94dbd335b3de753f4a0e59a
commit 248debee952f142be94dbd335b3de753f4a0e59a Author: Michael Meissner <[email protected]> Date: Wed Oct 22 17:06:24 2025 -0400 Add scalar _Float16 converts. 2025-10-22 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 20286a63fbf1..5343f0c730cc 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" "veclogical,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) \
