https://gcc.gnu.org/g:cbb97d0c4212643ff49dbfd260aaac8633c8549a

commit cbb97d0c4212643ff49dbfd260aaac8633c8549a
Author: Michael Meissner <[email protected]>
Date:   Thu Oct 1 20:43:45 2026 -0400

    Add conversions between 128-bit integers and 16-bit floating point
    
    This patch adds support for converting between 128-bit integers and 16-bit
    floating point using the IEEE 128-bit floating on power10 systems.
    
    2026-10-01  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

Reply via email to