https://gcc.gnu.org/g:802f59b795da69dd22f127a7ac1d6420f38653e8

commit 802f59b795da69dd22f127a7ac1d6420f38653e8
Author: Michael Meissner <[email protected]>
Date:   Mon Oct 6 12:56:02 2025 -0400

    Add bf and hf duplicate to v4sf.
    
    2025-10-06  Michael Meissner  <[email protected]>
    
    gcc/
    
            * config/rs6000/float16.md (CVT_FP16_TO_V4SF_INSN): New mode 
attribute.
            (FP16_VECTOR8): Likewise.
            (fp16_vector8): Likewise.
            (FP16_VECTOR4): Likewise.
            (UNSPEC_CVT_FP16_TO_V4SF): Replace UNSPEC_XVCVBF16SPN_BF and
            UNSPEC_XVCVBF16SPN_V8BF.
            (extendbf<mode>2): Change xvcvbf16spn_v8bf to cvt_fp16_to_v4sf_v8bf.
            (cvt_fp16_to_v4sf_<mode>): Rename from xvcvbf16spn_v8bf, and add 
HFmode
            support.
            (cvt_fp16_to_v4sf_<mode>_le): New insns.
            (cvt_fp16_to_v4sf_<mode>_be): Likewise.
            (dup_<mode>_to_v4sf): Likewise.
            (xvcvbf16spn_bf): Change UNSPEC_XVCVBF16SPN_BF to
            UNSPEC_CVT_FP16_TO_V4SF.
            * config/rs6000/rs6000-modes.def (V4BFmode): New mode.
            (V4HFmode): Likewise.

Diff:
---
 gcc/config/rs6000/float16.md       | 103 +++++++++++++++++++++++++++++++++----
 gcc/config/rs6000/rs6000-modes.def |   2 +
 2 files changed, 95 insertions(+), 10 deletions(-)

diff --git a/gcc/config/rs6000/float16.md b/gcc/config/rs6000/float16.md
index f92ea6de0713..c00e01ca4826 100644
--- a/gcc/config/rs6000/float16.md
+++ b/gcc/config/rs6000/float16.md
@@ -53,11 +53,32 @@
                                    (smax  "smax")
                                    (smin  "smin")])
 
+;; Mode attribute giving the instruction to convert the even
+;; V8HFmode or V8BFmode elements to V4SFmode
+(define_mode_attr CVT_FP16_TO_V4SF_INSN [(BF   "xvcvbf16spn")
+                                        (HF   "xvcvhpsp")
+                                        (V8BF "xvcvbf16spn")
+                                        (V8HF "xvcvhpsp")])
+
+;; Mode attribute giving the vector mode for a 16-bit floating point
+;; scalar in both upper and lower case.
+(define_mode_attr FP16_VECTOR8 [(BF "V8BF")
+                               (HF "V8HF")])
+
+(define_mode_attr fp16_vector8 [(BF "v8bf")
+                               (HF "v8hf")])
+
+;; Mode attribute giving the vector mode with 4 16-bit floating point
+;; elements given a scalar or 8 element vector.
+(define_mode_attr FP16_VECTOR4 [(BF   "V4BF")
+                               (HF   "V4HF")
+                               (V8BF "V4BF")
+                               (V8HF "V4HF")])
+
 ;; UNSPEC constants
 (define_c_enum "unspec"
   [UNSPEC_V8BF_SHIFT_LEFT_32BIT
-   UNSPEC_XVCVBF16SPN_BF
-   UNSPEC_XVCVBF16SPN_V8BF
+   UNSPEC_CVT_FP16_TO_V4SF
    UNSPEC_XXSPLTW_FP16
    UNSPEC_XVCVSPBF16_BF])
 
@@ -169,7 +190,7 @@
   emit_insn (gen_v8bf_shift_left_32bit (op2_v8bf, op1));
 
   /* XVCVBF16SPN -- convert even V8BFmode elements to V4SFmode.  */
-  emit_insn (gen_xvcvbf16spn_v8bf (op2_v4sf, op2_v8bf));
+  emit_insn (gen_cvt_fp16_to_v4sf_v8bf (op2_v4sf, op2_v8bf));
 
   /* XSCVSPNDP -- convert single V4SFmode element to DFmode.  */
   emit_insn (GET_MODE (op0) == SFmode
@@ -307,14 +328,76 @@
   DONE;
 })
 
-(define_insn "xvcvbf16spn_v8bf"
-  [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
-       (unspec:V4SF [(match_operand:V8BF 1 "vsx_register_operand" "wa")]
-                    UNSPEC_XVCVBF16SPN_V8BF))]
-  "TARGET_BFLOAT16"
-  "xvcvbf16spn %x0,%x1"
+;; Convert the even elements of a vector 16-bit floating point to
+;; V4SFmode.
+
+(define_expand "cvt_fp16_to_v4sf_<mode>"
+  [(set (match_operand:V4SF 0 "vsx_register_operand")
+       (float_extend:V4SF
+        (vec_select:<FP16_VECTOR4>
+         (match_operand:VFP16_HW 1 "vsx_register_operand")
+         (parallel [(match_dup 2)
+                    (match_dup 3)
+                    (match_dup 4)
+                    (match_dup 5)]))))]
+  ""
+{
+  int endian_adjust = WORDS_BIG_ENDIAN ? 0 : 1;
+  operands[2] = GEN_INT (0 + endian_adjust);
+  operands[3] = GEN_INT (2 + endian_adjust);
+  operands[4] = GEN_INT (4 + endian_adjust);
+  operands[5] = GEN_INT (6 + endian_adjust);
+})
+
+(define_insn "*cvt_fp16_to_v4sf_<mode>_le"
+  [(set (match_operand:V4SF 0 "vsx_register_operand")
+       (float_extend:V4SF
+        (vec_select:<FP16_VECTOR4>
+         (match_operand:VFP16_HW 1 "vsx_register_operand")
+         (parallel [(const_int 1)
+                    (const_int 3)
+                    (const_int 5)
+                    (const_int 7)]))))]
+  "!WORDS_BIG_ENDIAN"
+  "<CVT_FP16_TO_V4SF_INSN> %x0,%x1"
   [(set_attr "type" "vecfloat")])
 
+(define_insn "*cvt_fp16_to_v4sf_<mode>_be"
+  [(set (match_operand:V4SF 0 "vsx_register_operand")
+       (float_extend:V4SF
+        (vec_select:<FP16_VECTOR4>
+         (match_operand:VFP16_HW 1 "vsx_register_operand")
+         (parallel [(const_int 0)
+                    (const_int 2)
+                    (const_int 4)
+                    (const_int 6)]))))]
+  "WORDS_BIG_ENDIAN"
+  "<CVT_FP16_TO_V4SF_INSN> %x0,%x1"
+  [(set_attr "type" "vecfloat")])
+
+;; Duplicate and convert a 16-bit floating point scalar to V4SFmode.
+
+(define_insn_and_split "*dup_<mode>_to_v4sf"
+  [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
+       (vec_duplicate:V4SF
+        (float_extend:SF
+         (match_operand:FP16_HW 1 "vsx_register_operand" "wa"))))]
+  ""
+  "#"
+  "&& 1"
+  [(pc)]
+{
+  rtx op0 = operands[0];
+  rtx op1 = operands[1];
+  rtx op0_vfp16 = gen_lowpart (<FP16_VECTOR8>mode, op0);
+
+  emit_insn (gen_xxspltw_<mode> (op0, op1));
+  emit_insn (gen_cvt_fp16_to_v4sf_<fp16_vector8> (op0, op0_vfp16));
+  DONE;
+}
+  [(set_attr "length" "8")
+   (set_attr "type" "vecperm")])
+
 
 ;; Bfloat16 floating point operations.  We convert the 16-bit scalar to a
 ;; V4SF vector, do the operation, and then convert the value back to
@@ -414,7 +497,7 @@
 (define_insn "xvcvbf16spn_bf"
   [(set (match_operand:V4SF 0 "vsx_register_operand" "=wa")
        (unspec:V4SF [(match_operand:V4SF 1 "vsx_register_operand" "wa")]
-                    UNSPEC_XVCVBF16SPN_BF))]
+                    UNSPEC_CVT_FP16_TO_V4SF))]
   "TARGET_BFLOAT16_HW"
   "xvcvbf16spn %x0,%x1"
   [(set_attr "type" "vecperm")])
diff --git a/gcc/config/rs6000/rs6000-modes.def 
b/gcc/config/rs6000/rs6000-modes.def
index 81de144a987f..f8b11b2c8576 100644
--- a/gcc/config/rs6000/rs6000-modes.def
+++ b/gcc/config/rs6000/rs6000-modes.def
@@ -76,6 +76,8 @@ VECTOR_MODES (FLOAT, 32);     /*       V16HF V8SF V4DF */
 /* Half VMX/VSX vector (for internal use)  */
 VECTOR_MODE (FLOAT, SF, 2);   /*                 V2SF  */
 VECTOR_MODE (INT, SI, 2);     /*                 V2SI  */
+VECTOR_MODE (FLOAT, BF, 4);   /*                 V4BF  */
+VECTOR_MODE (FLOAT, HF, 4);   /*                 V4HF  */
 
 /* Replacement for TImode that only is allowed in GPRs.  We also use PTImode
    for quad memory atomic operations to force getting an even/odd register

Reply via email to