https://gcc.gnu.org/g:9ac046eaeb483cd449c9a91035209728dd5ceac1
commit 9ac046eaeb483cd449c9a91035209728dd5ceac1 Author: Michael Meissner <[email protected]> Date: Wed Sep 30 15:10:37 2026 -0400 Add conversions between 128-bit integers and 16-bit floating point This patch adds various 16-bit floating point tests. 2026-09-30 Michael Meissner <[email protected]> * config/rs6000/float16.md (floatti<mode>2): New insn to convert between 128-bit integers and 16-bit floating point. (floatunsti<mode>2): Likewise. (fix_trunc<mode>ti2): Likewise. (fixuns_trunc<mode>ti2): Likewise. Diff: --- gcc/config/rs6000/float16.md | 121 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) diff --git a/gcc/config/rs6000/float16.md b/gcc/config/rs6000/float16.md index 955e84d045bb..3fae46ee6828 100644 --- a/gcc/config/rs6000/float16.md +++ b/gcc/config/rs6000/float16.md @@ -420,6 +420,127 @@ "xscvdpspn %x0,%x1" [(set_attr "type" "fp")]) + +;; Convert 128-bit integers to 16-bit floating point if IEEE 128-bit +;; floating point is available by first using a conversion to IEEE +;; 128-bit, then converting that to double, and finally converting it +;; to 16-bit floating point. + +(define_expand "floatti<mode>2" + [(use (match_operand:FP16 0 "vsx_register_operand")) + (use (match_operand:TI 1 "altivec_register_operand"))] + "TARGET_POWER10 && TARGET_FLOAT128_HW && can_create_pseudo_p ()" +{ + rtx tmp_df = gen_reg_rtx (DFmode); + + if (FLOAT128_IEEE_P (TFmode)) + { + rtx tmp_tf = gen_reg_rtx (TFmode); + emit_insn (gen_floattitf2 (tmp_tf, operands[1])); + emit_insn (gen_trunctfdf2 (tmp_df, tmp_tf)); + } + + else if (FLOAT128_IEEE_P (KFmode)) + { + rtx tmp_kf = gen_reg_rtx (KFmode); + emit_insn (gen_floattikf2 (tmp_kf, operands[1])); + emit_insn (gen_trunckfdf2 (tmp_df, tmp_kf)); + } + + else + gcc_unreachable (); + + emit_insn (gen_truncdf<mode>2 (operands[0], tmp_df)); + DONE; +}) + +(define_expand "floatunsti<mode>2" + [(use (match_operand:FP16 0 "vsx_register_operand")) + (use (match_operand:TI 1 "altivec_register_operand"))] + "TARGET_POWER10 && TARGET_FLOAT128_HW && can_create_pseudo_p ()" +{ + rtx tmp_df = gen_reg_rtx (DFmode); + + if (FLOAT128_IEEE_P (TFmode)) + { + rtx tmp_tf = gen_reg_rtx (TFmode); + emit_insn (gen_floatunstitf2 (tmp_tf, operands[1])); + emit_insn (gen_trunctfdf2 (tmp_df, tmp_tf)); + } + + else if (FLOAT128_IEEE_P (KFmode)) + { + rtx tmp_kf = gen_reg_rtx (KFmode); + emit_insn (gen_floatunstikf2 (tmp_kf, operands[1])); + emit_insn (gen_trunckfdf2 (tmp_df, tmp_kf)); + } + + else + gcc_unreachable (); + + emit_insn (gen_truncdf<mode>2 (operands[0], tmp_df)); + DONE; +}) + +;; Convert 16-bit floating point to 128-bit integers if IEEE 128-bit +;; floating point is available by first using a conversion to double, +;; then to IEEE 128-bit, and finally to 128-bit integers. + +(define_expand "fix_trunc<mode>ti2" + [(use (match_operand:TI 0 "altivec_register_operand")) + (use (match_operand:FP16 1 "vsx_register_operand"))] + "TARGET_POWER10 && TARGET_FLOAT128_HW && can_create_pseudo_p ()" +{ + rtx tmp_df = gen_reg_rtx (DFmode); + + emit_insn (gen_extend<mode>df2 (tmp_df, operands[1])); + if (FLOAT128_IEEE_P (TFmode)) + { + rtx tmp_tf = gen_reg_rtx (TFmode); + emit_insn (gen_extenddftf2 (tmp_tf, tmp_df)); + emit_insn (gen_fix_trunctfti2 (operands[0], tmp_tf)); + } + + else if (FLOAT128_IEEE_P (KFmode)) + { + rtx tmp_kf = gen_reg_rtx (KFmode); + emit_insn (gen_extenddfkf2 (tmp_kf, tmp_df)); + emit_insn (gen_fix_trunckfti2 (operands[0], tmp_kf)); + } + + else + gcc_unreachable (); + + DONE; +}) + +(define_expand "fixuns_trunc<mode>ti2" + [(use (match_operand:TI 0 "altivec_register_operand")) + (use (match_operand:FP16 1 "vsx_register_operand"))] + "TARGET_POWER10 && TARGET_FLOAT128_HW && can_create_pseudo_p ()" +{ + rtx tmp_df = gen_reg_rtx (DFmode); + + emit_insn (gen_extend<mode>df2 (tmp_df, operands[1])); + if (FLOAT128_IEEE_P (TFmode)) + { + rtx tmp_tf = gen_reg_rtx (TFmode); + emit_insn (gen_extenddftf2 (tmp_tf, tmp_df)); + emit_insn (gen_fixuns_trunctfti2 (operands[0], tmp_tf)); + } + + else if (FLOAT128_IEEE_P (KFmode)) + { + rtx tmp_kf = gen_reg_rtx (KFmode); + emit_insn (gen_extenddfkf2 (tmp_kf, tmp_df)); + emit_insn (gen_fixuns_trunckfti2 (operands[0], tmp_kf)); + } + + else + gcc_unreachable (); + + DONE; +}) ;; Convert the even elements of a vector 16-bit floating point to ;; V4SFmode. Deal with little endian vs. big endian element ordering
