https://gcc.gnu.org/g:5db69fda20936cdcc84bb9df41a41bb88e385670

commit 5db69fda20936cdcc84bb9df41a41bb88e385670
Author: Michael Meissner <[email protected]>
Date:   Tue Oct 14 21:30:06 2025 -0400

    Upgrade float16 vector optimizations.
    
    2025-10-14  Michael Meissner  <[email protected]>
    
    gcc/
    
            * config/rs6000/float16.cc (bfloat16_operation_as_v4sf): Upgrade 
float16
            vector optimizations to use new names.
            (float16_vectorization): New function for _Float16 vectorization
            support.
            * config/rs6000/float16.md (FLOAT16_UNARY_OP): New code iterator.
            (FLOAT16_BINARY_OP): Likewise.
            (float16_names): New code attribute.
            (vecdup<mode>): New insns.
            (bfloat16_binary_op_internal1): Upgrade float16 optimizations and 
change
            bfloat16 optimization names.
            (bfloat16_binary_op_internal2): Likewise.
            (bfloat16_binary_op_internal2): Likewise.
            (bfloat16_fma_op_internal1): Likewise.
            (bfloat16_fma_op_internal2): Likewise.
            (bfloat16_fms_op_internal1): Likewise.
            (bfloat16_fms_op_internal2): Likewise.
            (bfloat16_nfma_op_internal1): Likewise.
            (bfloat16_nfma_op_internal2): Likewise.
            (bfloat16_nfma_op_internal3): Likewise.
            (bfloat16_nfms_op_internal1): Likewise.
            (bfloat16_nfms_op_internal2): Likewise.
            (bfloat16_nfms_op_internal3): Likewise.
            (<float16_names>v8hf, FLOAT16_UNARY_OP iterator): Likewise.
            (<float16_names>v8hf, FLOAT16_BINARY_OP iterator): Likewise.
            (neg_<float16_names>v8hf3): Likewise.
            (abs_<float16_names>v8hf3): Likewise.
            (fmav8hf3): Likewise.
            (fmsv8hf3): Likewise.
            (nfmav8hf3): Likewise.
            (nfmsv8hf3): Likewise.
            * config/rs6000/predicates.md (fp16_binary_operator): Rename from
            bfloat16_binary_operator.
            * config/rs6000/rs6000-protos.h (enum fp16_operation): Rename from 
enum
            bfloat16_operation.  Rename all enums.
            (float16_vectorization): New declaration.
            * config/rs6000/rs6000cc (rs6000_expand_vector_init): Add support 
for
            creating 16-bit floating point value where all values are the same.
            * config/rs6000/rs6000.h (FP16_VECTOR_MODE_P): New macro.

Diff:
---
 gcc/config/rs6000/float16.cc      | 214 ++++++++++++++++++++++++++++++++++----
 gcc/config/rs6000/float16.md      | 194 +++++++++++++++++++++++++++++++---
 gcc/config/rs6000/predicates.md   |   2 +-
 gcc/config/rs6000/rs6000-protos.h |  21 ++--
 gcc/config/rs6000/rs6000.cc       |   9 ++
 gcc/config/rs6000/rs6000.h        |   5 +
 6 files changed, 399 insertions(+), 46 deletions(-)

diff --git a/gcc/config/rs6000/float16.cc b/gcc/config/rs6000/float16.cc
index 3dc7273719c1..b887d400312a 100644
--- a/gcc/config/rs6000/float16.cc
+++ b/gcc/config/rs6000/float16.cc
@@ -42,7 +42,7 @@
 #include "common/common-target.h"
 #include "rs6000-internal.h"
 
-/* Expand a bfloat16 floating point operation:
+/* Expand a bfloat16 scalar floating point operation:
 
    ICODE:   Operation to perform.
    RESULT:  Result of the operation.
@@ -64,7 +64,7 @@ bfloat16_operation_as_v4sf (enum rtx_code icode,
                            rtx op1,
                            rtx op2,
                            rtx op3,
-                           enum bfloat16_operation subtype)
+                           enum fp16_operation subtype)
 {
   gcc_assert (can_create_pseudo_p ());
 
@@ -75,19 +75,22 @@ bfloat16_operation_as_v4sf (enum rtx_code icode,
 
   switch (subtype)
     {
-    case BF16_BINARY:
+    case FP16_BINARY:
       n_opts = 2;
       gcc_assert (op3 == NULL_RTX);
       break;
 
-    case BF16_FMA:
-    case BF16_FMS:
-    case BF16_NFMA:
-    case BF16_NFMS:
+    case FP16_FMA:
+    case FP16_FMS:
+    case FP16_NFMA:
+    case FP16_NFMS:
       gcc_assert (icode == FMA);
       n_opts = 3;
       break;
 
+    case FP16_UNARY:
+    case FP16_ABS_BINARY:
+    case FP16_NEG_BINARY:
     default:
       gcc_unreachable ();
     }
@@ -144,27 +147,41 @@ bfloat16_operation_as_v4sf (enum rtx_code icode,
     }
 
   /* Do the operation in V4SFmode.  */
-  if (subtype == BF16_BINARY)
-    emit_insn (gen_rtx_SET (result_v4sf,
-                           gen_rtx_fmt_ee (icode, V4SFmode,
-                                           ops_v4sf[0],
-                                           ops_v4sf[1])));
-
-  else         /* FMA/FMS/NFMA/NFMS operation.  */
+  switch (subtype)
     {
-      rtx op1 = ops_v4sf[0];
-      rtx op2 = ops_v4sf[1];
-      rtx op3 = ops_v4sf[2];
+    case FP16_BINARY:
+      emit_insn (gen_rtx_SET (result_v4sf,
+                             gen_rtx_fmt_ee (icode, V4SFmode,
+                                             ops_v4sf[0],
+                                             ops_v4sf[1])));
+      break;
 
-      if (subtype == BF16_FMS || subtype == BF16_NFMS)
-       op3 = gen_rtx_NEG (V4SFmode, op3);
+    case FP16_FMA:
+    case FP16_FMS:
+    case FP16_NFMA:
+    case FP16_NFMS:
+      {
+       rtx op1 = ops_v4sf[0];
+       rtx op2 = ops_v4sf[1];
+       rtx op3 = ops_v4sf[2];
 
-      rtx op_fma = gen_rtx_FMA (V4SFmode, op1, op2, op3);
+       if (subtype == FP16_FMS || subtype == FP16_NFMS)
+         op3 = gen_rtx_NEG (V4SFmode, op3);
 
-      if (subtype == BF16_NFMA || subtype == BF16_NFMS)
-       op_fma = gen_rtx_NEG (V4SFmode, op_fma);
+       rtx op_fma = gen_rtx_FMA (V4SFmode, op1, op2, op3);
 
-      emit_insn (gen_rtx_SET (result_v4sf, op_fma));
+       if (subtype == FP16_NFMA || subtype == FP16_NFMS)
+         op_fma = gen_rtx_NEG (V4SFmode, op_fma);
+
+       emit_insn (gen_rtx_SET (result_v4sf, op_fma));
+      }
+      break;
+
+    case FP16_UNARY:
+    case FP16_ABS_BINARY:
+    case FP16_NEG_BINARY:
+    default:
+      gcc_unreachable ();
     }
 
   /* Convert V4SF result back to scalar mode.  */
@@ -180,3 +197,154 @@ bfloat16_operation_as_v4sf (enum rtx_code icode,
   else
     gcc_unreachable ();
 }
+
+
+/* Expand a _Float16 vector operation:
+
+   ICODE:   Operation to perform.
+   RESULT:  Result of the operation.
+   OP1:     Input operand1.
+   OP2:     Input operand2.
+   OP3:     Input operand3 or NULL_RTX.
+   SUBTYPE: Describe the operation.  */
+       
+void
+float16_vectorization (enum rtx_code icode,
+                      rtx result,
+                      rtx op1,
+                      rtx op2,
+                      rtx op3,
+                      enum fp16_operation subtype)
+{
+  gcc_assert (can_create_pseudo_p ());
+
+  enum rtx_code unary_op = UNKNOWN;
+  rtx op_orig[3] = { op1, op2, op3 };
+  rtx op_hi[3];
+  rtx op_lo[3];
+  rtx result_hi;
+  rtx result_lo;
+  size_t n_opts;
+
+  switch (subtype)
+    {
+    case FP16_UNARY:
+      n_opts = 1;
+      break;
+
+    case FP16_BINARY:
+      n_opts = 2;
+      break;
+
+    case FP16_ABS_BINARY:
+      unary_op = ABS;
+      n_opts = 2;
+      break;
+
+    case FP16_NEG_BINARY:
+      unary_op = NEG;
+      n_opts = 2;
+      break;
+
+    case FP16_FMA:
+    case FP16_FMS:
+    case FP16_NFMA:
+    case FP16_NFMS:
+      n_opts = 3;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  /* Allocate 2 temporaries for the results and the input operands.  */
+  result_hi = gen_reg_rtx (V4SFmode);
+  result_lo = gen_reg_rtx (V4SFmode);
+
+  for (size_t i = 0; i < n_opts; i++)
+    {
+      gcc_assert (op_orig[i] != NULL_RTX);
+      op_hi[i] = gen_reg_rtx (V4SFmode);       /* high register.  */
+      op_lo[i] = gen_reg_rtx (V4SFmode);       /* low register.  */
+
+      emit_insn (gen_vec_unpacks_hi_v8hf (op_hi[i], op_orig[i]));
+      emit_insn (gen_vec_unpacks_lo_v8hf (op_lo[i], op_orig[i]));
+    }
+
+  /* Do 2 sets of V4SFmode operations.  */
+  switch (subtype)
+    {
+    case FP16_UNARY:
+      emit_insn (gen_rtx_SET (result_hi,
+                             gen_rtx_fmt_e (icode, V4SFmode, op_hi[0])));
+
+      emit_insn (gen_rtx_SET (result_lo,
+                             gen_rtx_fmt_e (icode, V4SFmode, op_lo[0])));
+      break;
+
+    case FP16_BINARY:
+    case FP16_ABS_BINARY:
+    case FP16_NEG_BINARY:
+      emit_insn (gen_rtx_SET (result_hi,
+                             gen_rtx_fmt_ee (icode, V4SFmode,
+                                             op_hi[0],
+                                             op_hi[1])));
+
+      emit_insn (gen_rtx_SET (result_lo,
+                             gen_rtx_fmt_ee (icode, V4SFmode,
+                                             op_lo[0],
+                                             op_lo[1])));
+      break;
+
+    case FP16_FMA:
+    case FP16_FMS:
+    case FP16_NFMA:
+    case FP16_NFMS:
+      {
+       rtx op1_hi = op_hi[0];
+       rtx op2_hi = op_hi[1];
+       rtx op3_hi = op_hi[2];
+
+       rtx op1_lo = op_lo[0];
+       rtx op2_lo = op_lo[1];
+       rtx op3_lo = op_lo[2];
+
+       if (subtype == FP16_FMS || subtype == FP16_NFMS)
+         {
+           op3_hi = gen_rtx_NEG (V4SFmode, op3_hi);
+           op3_lo = gen_rtx_NEG (V4SFmode, op3_lo);
+         }
+
+       rtx op_fma_hi = gen_rtx_FMA (V4SFmode, op1_hi, op2_hi, op3_hi);
+       rtx op_fma_lo = gen_rtx_FMA (V4SFmode, op1_lo, op2_lo, op3_lo);
+
+       if (subtype == FP16_NFMA || subtype == FP16_NFMS)
+         {
+           op_fma_hi = gen_rtx_NEG (V4SFmode, op_fma_hi);
+           op_fma_lo = gen_rtx_NEG (V4SFmode, op_fma_lo);
+         }
+
+       emit_insn (gen_rtx_SET (result_hi, op_fma_hi));
+       emit_insn (gen_rtx_SET (result_lo, op_fma_lo));
+      }
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  /* Add any unary operator modifications.  */
+  if (unary_op != UNKNOWN)
+    {
+      emit_insn (gen_rtx_SET (result_hi,
+                             gen_rtx_fmt_e (unary_op, V4SFmode, result_hi)));
+
+      emit_insn (gen_rtx_SET (result_lo,
+                             gen_rtx_fmt_e (unary_op, V4SFmode, result_lo)));
+    }
+
+  /* Combine the 2 V4SFmode operations into one V8HFmode vector.  */
+  emit_insn (gen_vec_pack_trunc_v4sf_v8hf (result, result_hi, result_lo));
+  return;
+}
+
diff --git a/gcc/config/rs6000/float16.md b/gcc/config/rs6000/float16.md
index 28586654f96e..eaba1784362b 100644
--- a/gcc/config/rs6000/float16.md
+++ b/gcc/config/rs6000/float16.md
@@ -62,6 +62,22 @@
                                (V8BF "V4BF")
                                (V8HF "V4HF")])
 
+;; Unary operators for float16 vectorization.
+(define_code_iterator FLOAT16_UNARY_OP [abs neg])
+
+;; Binary operators for float16 vectorization.
+(define_code_iterator FLOAT16_BINARY_OP [plus minus mult smax smin])
+
+;; Standard names for the unary/binary/ternary operators
+(define_code_attr float16_names [(abs   "abs")
+                                (fma   "fma")
+                                (plus  "add")
+                                (minus "sub")
+                                (mult  "mul")
+                                (neg   "neg")
+                                (smax  "smax")
+                                (smin  "smin")])
+
 ;; UNSPEC constants
 (define_c_enum "unspec"
   [UNSPEC_FP16_SHIFT_LEFT_32BIT
@@ -133,6 +149,15 @@
    (set_attr "isa"  "*,         p9v,       p9v,       *,         *,
                      *,         p8v,       p8v,       p9v,       *")])
 
+;; Vector duplicate
+(define_insn "*vecdup<mode>"
+  [(set (match_operand:<FP16_VECTOR8> 0 "altivec_register_operand" "=v")
+       (vec_duplicate:<FP16_VECTOR8>
+        (match_operand:FP16 1 "altivec_register_operand" "v")))]
+  ""
+  "vsplth %0,%1,3"
+  [(set_attr "type" "vecperm")])
+
 
 ;; Convert IEEE 16-bit floating point to/from other floating point modes.
 
@@ -446,7 +471,7 @@
 
 (define_insn_and_split "*bfloat16_binary_op_internal1"
   [(set (match_operand:SF 0 "vsx_register_operand")
-       (match_operator:SF 1 "bfloat16_binary_operator"
+       (match_operator:SF 1 "fp16_binary_operator"
                           [(match_operand:SF 2 "bfloat16_v4sf_operand")
                            (match_operand:SF 3 "bfloat16_v4sf_operand")]))]
   "TARGET_BFLOAT16_HW && can_create_pseudo_p ()
@@ -457,14 +482,14 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (GET_CODE (operands[1]), operands[0], operands[2],
-                             operands[3], NULL_RTX, BF16_BINARY);
+                             operands[3], NULL_RTX, FP16_BINARY);
   DONE;
 })
 
 (define_insn_and_split "*bfloat16_binary_op_internal2"
   [(set (match_operand:BF 0 "vsx_register_operand")
        (float_truncate:BF
-        (match_operator:SF 1 "bfloat16_binary_operator"
+        (match_operator:SF 1 "fp16_binary_operator"
                            [(match_operand:SF 2 "bfloat16_v4sf_operand")
                             (match_operand:SF 3 "bfloat16_v4sf_operand")])))]
   "TARGET_BFLOAT16_HW && can_create_pseudo_p ()
@@ -475,7 +500,7 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (GET_CODE (operands[1]), operands[0], operands[2],
-                             operands[3], NULL_RTX, BF16_BINARY);
+                             operands[3], NULL_RTX, FP16_BINARY);
   DONE;
 })
 
@@ -494,7 +519,7 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (FMA, operands[0], operands[1], operands[2],
-                             operands[3], BF16_FMA);
+                             operands[3], FP16_FMA);
   DONE;
 })
 
@@ -514,7 +539,7 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (FMA, operands[0], operands[1], operands[2],
-                             operands[3], BF16_FMA);
+                             operands[3], FP16_FMA);
   DONE;
 })
 
@@ -534,7 +559,7 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (FMA, operands[0], operands[1], operands[2],
-                             operands[3], BF16_FMS);
+                             operands[3], FP16_FMS);
   DONE;
 })
 
@@ -555,7 +580,7 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (FMA, operands[0], operands[1], operands[2],
-                             operands[3], BF16_FMS);
+                             operands[3], FP16_FMS);
   DONE;
 })
 
@@ -575,7 +600,7 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (FMA, operands[0], operands[1], operands[2],
-                             operands[3], BF16_NFMA);
+                             operands[3], FP16_NFMA);
   DONE;
 })
 
@@ -596,7 +621,7 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (FMA, operands[0], operands[1], operands[2],
-                             operands[3], BF16_NFMA);
+                             operands[3], FP16_NFMA);
   DONE;
 })
 
@@ -617,7 +642,7 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (FMA, operands[0], operands[1], operands[2],
-                             operands[3], BF16_NFMA);
+                             operands[3], FP16_NFMA);
   DONE;
 })
 
@@ -638,7 +663,7 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (FMA, operands[0], operands[1], operands[2],
-                             operands[3], BF16_NFMS);
+                             operands[3], FP16_NFMS);
   DONE;
 })
 
@@ -660,7 +685,7 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (FMA, operands[0], operands[1], operands[2],
-                             operands[3], BF16_NFMS);
+                             operands[3], FP16_NFMS);
   DONE;
 })
 
@@ -682,10 +707,151 @@
   [(pc)]
 {
   bfloat16_operation_as_v4sf (FMA, operands[0], operands[1], operands[2],
-                             operands[3], BF16_NFMS);
+                             operands[3], FP16_NFMS);
+  DONE;
+})
+
+
+;; Add vectorization support for _Float16.  Unfortunately, since there
+;; can only be one vec_pack_trunc_v4sf, we choose to support automatic
+;; vectorization for BFmode.  The following insns define vectorization
+;; for HFmode.
+
+;; Unary operators being vectorized.
+(define_insn_and_split "<float16_names>v8hf3"
+  [(set (match_operand:V8HF 0 "vsx_register_operand")
+       (FLOAT16_UNARY_OP:V8HF
+        (match_operand:V8HF 1 "vsx_register_operand")))]
+  "TARGET_FLOAT16_HW && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(pc)]
+{
+  float16_vectorization (<CODE>, operands[0], operands[1], NULL_RTX, NULL_RTX,
+                        FP16_UNARY);
+  DONE;
+})
+
+;; Binary operators being vectorized.
+(define_insn_and_split "<float16_names>v8hf3"
+  [(set (match_operand:V8HF 0 "vsx_register_operand")
+       (FLOAT16_BINARY_OP:V8HF
+        (match_operand:V8HF 1 "vsx_register_operand")
+        (match_operand:V8HF 2 "vsx_register_operand")))]
+  "TARGET_FLOAT16_HW && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(pc)]
+{
+  float16_vectorization (<CODE>, operands[0], operands[1], operands[2],
+                        NULL_RTX, FP16_BINARY);
+  DONE;
+})
+
+;; Negative of binary operators being vectorized.
+(define_insn_and_split "*neg_<float16_names>v8hf3"
+  [(set (match_operand:V8HF 0 "vsx_register_operand")
+       (neg:V8HF
+        (FLOAT16_BINARY_OP:V8HF
+         (match_operand:V8HF 1 "vsx_register_operand")
+         (match_operand:V8HF 2 "vsx_register_operand"))))]
+  "TARGET_FLOAT16_HW && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(pc)]
+{
+  float16_vectorization (<CODE>, operands[0], operands[1], operands[2],
+                        NULL_RTX, FP16_NEG_BINARY);
+  DONE;
+})
+
+;; Absolute value of binary operators being vectorized.
+(define_insn_and_split "*abs_<float16_names>v8hf3"
+  [(set (match_operand:V8HF 0 "vsx_register_operand")
+       (abs:V8HF
+        (FLOAT16_BINARY_OP:V8HF
+         (match_operand:V8HF 1 "vsx_register_operand")
+         (match_operand:V8HF 2 "vsx_register_operand"))))]
+  "TARGET_FLOAT16_HW && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(pc)]
+{
+  float16_vectorization (<CODE>, operands[0], operands[1], operands[2],
+                        NULL_RTX, FP16_ABS_BINARY);
+  DONE;
+})
+
+;; FMA operations being vectorized.
+(define_insn_and_split "fmav8hf3"
+  [(set (match_operand:V8HF 0 "vsx_register_operand")
+       (fma:V8HF
+        (match_operand:V8HF 1 "vsx_register_operand")
+        (match_operand:V8HF 2 "vsx_register_operand")
+        (match_operand:V8HF 3 "vsx_register_operand")))]
+  "TARGET_FLOAT16_HW && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(pc)]
+{
+  float16_vectorization (FMA, operands[0], operands[1], operands[2],
+                        operands[3], FP16_FMA);
+  DONE;
+})
+
+(define_insn_and_split "*fmsv8hf3"
+  [(set (match_operand:V8HF 0 "vsx_register_operand")
+       (fma:V8HF
+        (match_operand:V8HF 1 "vsx_register_operand")
+        (match_operand:V8HF 2 "vsx_register_operand")
+        (neg:V8HF
+         (match_operand:V8HF 3 "vsx_register_operand"))))]
+  "TARGET_FLOAT16_HW && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(pc)]
+{
+  float16_vectorization (FMA, operands[0], operands[1], operands[2],
+                        operands[3], FP16_FMS);
   DONE;
 })
 
+(define_insn_and_split "*nfmav8hf3"
+  [(set (match_operand:V8HF 0 "vsx_register_operand")
+       (neg:V8HF
+        (fma:V8HF
+         (match_operand:V8HF 1 "vsx_register_operand")
+         (match_operand:V8HF 2 "vsx_register_operand")
+         (match_operand:V8HF 3 "vsx_register_operand"))))]
+  "TARGET_FLOAT16_HW && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(pc)]
+{
+  float16_vectorization (FMA, operands[0], operands[1], operands[2],
+                        operands[3], FP16_NFMA);
+  DONE;
+})
+
+(define_insn_and_split "*nfmsv8hf3"
+  [(set (match_operand:V8HF 0 "vsx_register_operand")
+       (neg:V8HF
+        (fma:V8HF
+         (match_operand:V8HF 1 "vsx_register_operand")
+         (match_operand:V8HF 2 "vsx_register_operand")
+         (neg:V8HF
+          (match_operand:V8HF 3 "vsx_register_operand")))))]
+  "TARGET_FLOAT16_HW && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(pc)]
+{
+  float16_vectorization (FMA, operands[0], operands[1], operands[2],
+                        operands[3], FP16_NFMS);
+  DONE;
+})
+
+
 ;; If we do multiple __bfloat16 operations, between the first and
 ;; second operation, GCC will want to convert the first operation from
 ;; V4SFmode to SFmode and then reconvert it back to V4SFmode.  On the
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index d47d09cf73db..4394b4a6daa1 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -2208,7 +2208,7 @@
 ;; the operation in vector mode rather than convverting the BFmode to a
 ;; V8BFmode vector, converting that V8BFmode vector to V4SFmode, and
 ;; then converting the V4SFmode element to SFmode scalar.
-(define_predicate "bfloat16_binary_operator"
+(define_predicate "fp16_binary_operator"
   (match_code "plus,minus,mult,smax,smin"))
 
 ;; Match bfloat16/float operands that can be optimized to do the
diff --git a/gcc/config/rs6000/rs6000-protos.h 
b/gcc/config/rs6000/rs6000-protos.h
index db38468df816..f677506b4aa0 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -260,17 +260,22 @@ extern unsigned constant_generates_xxspltiw 
(vec_const_128bit_type *);
 extern unsigned constant_generates_xxspltidp (vec_const_128bit_type *);
 
 /* From float16.cc.  */
-/* Optimize bfloat16 operations.  */
-enum bfloat16_operation {
-  BF16_BINARY,                         /* Bfloat16 binary op.  */
-  BF16_FMA,                            /* (a * b) + c.  */
-  BF16_FMS,                            /* (a * b) - c.  */
-  BF16_NFMA,                           /* - ((a * b) + c).  */
-  BF16_NFMS                            /* - ((a * b) - c).  */
+/* Optimize bfloat16 and float16 operations.  */
+enum fp16_operation {
+  FP16_UNARY,                          /* Bfloat16/float16 unary op.  */
+  FP16_BINARY,                         /* Bfloat16/float16 binary op.  */
+  FP16_ABS_BINARY,                     /* abs (binary op).  */
+  FP16_NEG_BINARY,                     /* - binary op.  */
+  FP16_FMA,                            /* (a * b) + c.  */
+  FP16_FMS,                            /* (a * b) - c.  */
+  FP16_NFMA,                           /* - ((a * b) + c).  */
+  FP16_NFMS                            /* - ((a * b) - c).  */
 };
 
 extern void bfloat16_operation_as_v4sf (enum rtx_code, rtx, rtx, rtx, rtx,
-                                       enum bfloat16_operation);
+                                       enum fp16_operation);
+extern void float16_vectorization (enum rtx_code, rtx, rtx, rtx, rtx,
+                                  enum fp16_operation);
 #endif /* RTX_CODE */
 
 #ifdef TREE_CODE
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index bf9e1e86203f..dbbce3c5338d 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -7111,6 +7111,15 @@ rs6000_expand_vector_init (rtx target, rtx vals)
       return;
     }
 
+  /* Special case splats of 16-bit floating point.  */
+  if (all_same && FP16_VECTOR_MODE_P (mode))
+    {
+      rtx op0 = force_reg (GET_MODE_INNER (mode), XVECEXP (vals, 0, 0));
+      rtx dup = gen_rtx_VEC_DUPLICATE (mode, op0);
+      emit_insn (gen_rtx_SET (target, dup));
+      return;
+    }
+                                                    
   /* Special case initializing vector short/char that are splats if we are on
      64-bit systems with direct move.  */
   if (all_same && TARGET_DIRECT_MOVE_64BIT
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 16aa2a6443b1..7850affe6afc 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -358,6 +358,11 @@ extern const char *host_detect_local_cpu (int argc, const 
char **argv);
   (((MODE) == HFmode && TARGET_FLOAT16_HW)                             \
    || ((MODE) == BFmode && TARGET_BFLOAT16_HW))
 
+/* Is this a valid 16-bit vector floating point mode?  */
+#define FP16_VECTOR_MODE_P(MODE)                                       \
+  (((MODE) == V8HFmode && TARGET_FLOAT16)                              \
+   || ((MODE) == V8BFmode && TARGET_BFLOAT16))
+
 /* Return true for floating point that does not use a vector register.  */
 #define SCALAR_FLOAT_MODE_NOT_VECTOR_P(MODE)                           \
   (SCALAR_FLOAT_MODE_P (MODE) && !FLOAT128_VECTOR_P (MODE))

Reply via email to