Hi,

I think this is going to be the last one, I'm running out of steam :)

This patch adds autovec patterns for Zvdota as well as tests.
The implementation is pretty mechanical, in particular the usual
VLS-mode massacre that will sure contain one or two mishaps.
The actual expansion borrows from our reduction expansion and
re-uses its M1 VLA mode accumulation idea.
The patch depends on Jiawei's series and I still wanted to send it
before stage 1 closes.

Regtested on top of Jiawei's series on rva23u64.

Assisted-By: Claude Code for the tests.

Regards
 Robin

gcc/ChangeLog:

        * config/riscv/autovec.md (sdot_prod<mode><v_quad_trunc>): New
        pattern.
        (udot_prod<mode><v_quad_trunc>): Ditto.
        (usdot_prod<mode><v_quad_trunc>): Ditto.
        (sdot_prod<mode><v_double_trunc_bf>): Ditto.
        * config/riscv/riscv-protos.h (enum insn_flags): New flag for
        dot prod.
        (enum insn_type): New.
        (expand_dot_prod): New function to expand dot products.
        * config/riscv/riscv-v.cc (expand_dot_prod): Declare.
        * config/riscv/vector-dot.md: Declare.
        * config/riscv/vector-iterators.md: Move VI_Q iterator
        to here...
        * config/riscv/xuantie-vector.md: ...From here.

gcc/testsuite/ChangeLog:

        * lib/target-supports.exp: Add Zvdota plumbing.
        * gcc.target/riscv/rvv/autovec/reduc/dot-bf-neg-1.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot-bf-neg-2.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot-bf.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot-hi-ss.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot-hi-us.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot-hi-uu.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot-noext.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot-qi-ss.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot-qi-su.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot-qi-us.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot-qi-uu.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot.h: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot_run-bf.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-ss.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-us.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-uu.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-ss.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-su.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-us.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-uu.c: New test.
        * gcc.target/riscv/rvv/autovec/reduc/dot_run.h: New test.
---
 gcc/config/riscv/autovec.md                   |  54 +++++++++
 gcc/config/riscv/riscv-protos.h               |   6 +
 gcc/config/riscv/riscv-v.cc                   |  42 +++++++
 gcc/config/riscv/vector-dot.md                |   4 +-
 gcc/config/riscv/vector-iterators.md          | 105 +++++++++++++++++
 gcc/config/riscv/xuantie-vector.md            |   5 -
 .../riscv/rvv/autovec/reduc/dot-bf-neg-1.c    |   9 ++
 .../riscv/rvv/autovec/reduc/dot-bf-neg-2.c    |  12 ++
 .../riscv/rvv/autovec/reduc/dot-bf.c          |  13 +++
 .../riscv/rvv/autovec/reduc/dot-hi-ss.c       |  14 +++
 .../riscv/rvv/autovec/reduc/dot-hi-us.c       |  14 +++
 .../riscv/rvv/autovec/reduc/dot-hi-uu.c       |  14 +++
 .../riscv/rvv/autovec/reduc/dot-noext.c       |  11 ++
 .../riscv/rvv/autovec/reduc/dot-qi-ss.c       |  14 +++
 .../riscv/rvv/autovec/reduc/dot-qi-su.c       |  14 +++
 .../riscv/rvv/autovec/reduc/dot-qi-us.c       |  14 +++
 .../riscv/rvv/autovec/reduc/dot-qi-uu.c       |  14 +++
 .../gcc.target/riscv/rvv/autovec/reduc/dot.h  |  20 ++++
 .../riscv/rvv/autovec/reduc/dot_run-bf.c      |  30 +++++
 .../riscv/rvv/autovec/reduc/dot_run-hi-ss.c   |  16 +++
 .../riscv/rvv/autovec/reduc/dot_run-hi-us.c   |  16 +++
 .../riscv/rvv/autovec/reduc/dot_run-hi-uu.c   |  16 +++
 .../riscv/rvv/autovec/reduc/dot_run-qi-ss.c   |  16 +++
 .../riscv/rvv/autovec/reduc/dot_run-qi-su.c   |  16 +++
 .../riscv/rvv/autovec/reduc/dot_run-qi-us.c   |  16 +++
 .../riscv/rvv/autovec/reduc/dot_run-qi-uu.c   |  16 +++
 .../riscv/rvv/autovec/reduc/dot_run.h         |  49 ++++++++
 gcc/testsuite/lib/target-supports.exp         | 110 +++++++++++++++++-
 28 files changed, 672 insertions(+), 8 deletions(-)
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf-neg-1.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf-neg-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-ss.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-us.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-uu.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-noext.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-ss.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-su.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-us.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-uu.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot.h
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-bf.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-ss.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-us.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-uu.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-ss.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-su.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-us.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-uu.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run.h

diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 607b9891405..db1f599753c 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -1227,6 +1227,60 @@ (define_expand "<su>sad<mode><v_quad_trunc>"
   DONE;
 })
 
+;; -------------------------------------------------------------------------
+;; ---- [INT,FP] Dot product
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - vqwdotas.vv
+;; - vqwdotau.vv
+;; - vfwdota.vv
+;; -------------------------------------------------------------------------
+
+(define_expand "sdot_prod<mode><v_quad_trunc>"
+  [(match_operand:VQEXTI_DOT 0 "register_operand")
+   (match_operand:<V_QUAD_TRUNC> 1 "register_operand")
+   (match_operand:<V_QUAD_TRUNC> 2 "register_operand")
+   (match_operand:VQEXTI_DOT 3 "register_operand")]
+  "TARGET_VECTOR"
+{
+  riscv_vector::expand_dot_prod (UNSPEC_VQWDOTA_SS, operands);
+  DONE;
+})
+
+(define_expand "udot_prod<mode><v_quad_trunc>"
+  [(match_operand:VQEXTI_DOT 0 "register_operand")
+   (match_operand:<V_QUAD_TRUNC> 1 "register_operand")
+   (match_operand:<V_QUAD_TRUNC> 2 "register_operand")
+   (match_operand:VQEXTI_DOT 3 "register_operand")]
+  "TARGET_VECTOR"
+{
+  riscv_vector::expand_dot_prod (UNSPEC_VQWDOTA_UU, operands);
+  DONE;
+})
+
+(define_expand "usdot_prod<mode><v_quad_trunc>"
+  [(match_operand:VQEXTI_DOT 0 "register_operand")
+   (match_operand:<V_QUAD_TRUNC> 1 "register_operand")
+   (match_operand:<V_QUAD_TRUNC> 2 "register_operand")
+   (match_operand:VQEXTI_DOT 3 "register_operand")]
+  "TARGET_VECTOR"
+{
+  riscv_vector::expand_dot_prod (UNSPEC_VQWDOTA_US, operands);
+  DONE;
+})
+
+;; ??? Can we enable these unconditionally?
+(define_expand "sdot_prod<mode><v_double_trunc_bf>"
+  [(match_operand:VWEXTF_DOT_BF 0 "register_operand")
+   (match_operand:<V_DOUBLE_TRUNC_BF> 1 "register_operand")
+   (match_operand:<V_DOUBLE_TRUNC_BF> 2 "register_operand")
+   (match_operand:VWEXTF_DOT_BF 3 "register_operand")]
+  "TARGET_VECTOR && flag_unsafe_math_optimizations && !flag_rounding_math"
+{
+  riscv_vector::expand_dot_prod (UNSPEC_VFWDOTA, operands);
+  DONE;
+})
+
 ;; 
-------------------------------------------------------------------------------
 ;; ---- [FP] Unary operations
 ;; 
-------------------------------------------------------------------------------
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 75d812bba64..b1acbd131f8 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -449,6 +449,8 @@ enum insn_flags : unsigned int
 
   /* Means INSN has VXRM operand and the value is VXRM_ROD.  */
   VXRM_ROD_P = 1 << 23,
+
+  VTYPE_MODE_FROM_OP2_P = 1 << 24,
 };
 
 enum insn_type : unsigned int
@@ -524,6 +526,9 @@ enum insn_type : unsigned int
                     | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P | TERNARY_OP_P,
   WIDEN_TERNARY_OP_FRM_DYN = WIDEN_TERNARY_OP | FRM_DYN_P,
 
+  DOT_PROD_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | TU_POLICY_P
+               | MDEFAULT_POLICY_P | TERNARY_OP_P | VTYPE_MODE_FROM_OP2_P,
+
   /* For vmerge, no mask operand, no mask policy operand.  */
   MERGE_OP = __NORMAL_OP_TA2 | TERNARY_OP_P,
 
@@ -696,6 +701,7 @@ bool expand_vec_cmp_float (rtx, rtx_code, rtx, rtx, bool, 
rtx = nullptr,
 void expand_cond_len_unop (unsigned, rtx *);
 void expand_cond_len_binop (unsigned, rtx *);
 void expand_reduction (unsigned, unsigned, unsigned, rtx *, rtx);
+void expand_dot_prod (unsigned, rtx *);
 void expand_mask_reduction (rtx *, rtx_code);
 void expand_vec_ceil (rtx, rtx, machine_mode, machine_mode);
 void expand_vec_floor (rtx, rtx, machine_mode, machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 6ae806e01aa..b188592dc43 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -240,6 +240,8 @@ public:
     machine_mode vtype_mode;
     if (m_insn_flags & VTYPE_MODE_FROM_OP1_P)
       vtype_mode = GET_MODE (ops[1]);
+    else if (m_insn_flags & VTYPE_MODE_FROM_OP2_P)
+      vtype_mode = GET_MODE (ops[2]);
     else
       vtype_mode = GET_MODE (ops[0]);
     return vtype_mode;
@@ -4992,6 +4994,46 @@ expand_cond_ternop (unsigned icode, rtx *ops)
   expand_cond_len_op (icode, TERNARY_OP_P, cond_ops, len);
 }
 
+/* Expand vfqdota and vfwdota.  */
+
+void
+expand_dot_prod (unsigned unspec, rtx *ops)
+{
+  machine_mode acc_mode = GET_MODE (ops[0]);
+  machine_mode src_mode = GET_MODE (ops[1]);
+  machine_mode m1_mode = get_m1_mode (GET_MODE_INNER (acc_mode)).require ();
+
+  insn_code icode;
+  if (unspec == UNSPEC_VFWDOTA)
+    icode = code_for_pred_vfwdota_vv_zvdota (src_mode);
+  else
+    icode = code_for_pred_vv_zvdota (unspec, src_mode);
+
+  /* Perform our reduction "M1" trick, i.e. accumulate into an "VLA" M1 mode
+     for VLS by mode-punning input and output.  */
+  if (riscv_vls_mode_p (acc_mode)
+      && !known_le (GET_MODE_BITSIZE (acc_mode), GET_MODE_BITSIZE (m1_mode)))
+    {
+      scalar_mode inner = GET_MODE_INNER (acc_mode);
+      machine_mode pun_mode
+       = get_vector_mode (inner, TARGET_MIN_VLEN
+                          / GET_MODE_BITSIZE (inner)).require ();
+      rtx tmp = gen_reg_rtx (pun_mode);
+      emit_move_insn (tmp, lowpart_subreg (pun_mode, ops[3], acc_mode));
+      rtx acc_m1 = lowpart_subreg (m1_mode, tmp, pun_mode);
+      rtx dot_ops[] = {acc_m1, acc_m1, ops[1], ops[2]};
+      emit_vlmax_insn (icode, DOT_PROD_OP, dot_ops);
+      emit_move_insn (ops[0], ops[3]);
+      emit_move_insn (lowpart_subreg (pun_mode, ops[0], acc_mode), tmp);
+      return;
+    }
+
+  emit_move_insn (ops[0], ops[3]);
+  rtx acc = lowpart_subreg (m1_mode, ops[0], acc_mode);
+  rtx dot_ops[] = {acc, acc, ops[1], ops[2]};
+  emit_vlmax_insn (icode, DOT_PROD_OP, dot_ops);
+}
+
 /* Expand reduction operations.
      Case 1: ops = {scalar_dest, vector_src}
      Case 2: ops = {scalar_dest, vector_src, mask, vl}
diff --git a/gcc/config/riscv/vector-dot.md b/gcc/config/riscv/vector-dot.md
index b5babf4df82..1c1225b9e32 100644
--- a/gcc/config/riscv/vector-dot.md
+++ b/gcc/config/riscv/vector-dot.md
@@ -64,8 +64,8 @@ (define_insn "@pred_vfwdota_vv_zvdota<mode>"
             (reg:SI VL_REGNUM)
             (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
           (unspec:<V_EXT_LMUL1>
-            [(match_operand:VF_ZVFBF16 3 "register_operand"           "vr")
-             (match_operand:VF_ZVFBF16 4 "register_operand"           "vr")
+            [(match_operand:VF_ZVFWDOTA_BF 3 "register_operand"     "vr")
+             (match_operand:VF_ZVFWDOTA_BF 4 "register_operand"     "vr")
              (match_operand:<V_EXT_LMUL1> 2 "register_operand"        "0")]
             UNSPEC_VFWDOTA)
           (match_dup 2)] UNSPEC_REDUC))]
diff --git a/gcc/config/riscv/vector-iterators.md 
b/gcc/config/riscv/vector-iterators.md
index 274f1b17d0e..f186cb6bfe3 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -1508,6 +1508,28 @@ (define_mode_iterator VI_ZVQWDOTA [
   (RVVM1HI "TARGET_ZVQWDOTA16I && TARGET_VECTOR_ELEN_64")
   (RVVMF2HI "TARGET_ZVQWDOTA16I && TARGET_VECTOR_ELEN_64")
   (RVVMF4HI "TARGET_ZVQWDOTA16I && TARGET_VECTOR_ELEN_64")
+
+  (V1QI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V1QImode)")
+  (V2QI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V2QImode)")
+  (V4QI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V4QImode)")
+  (V8QI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V8QImode)")
+  (V16QI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V16QImode)")
+  (V32QI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V32QImode)")
+  (V64QI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V64QImode) && 
TARGET_MIN_VLEN >= 64")
+  (V128QI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V128QImode) && 
TARGET_MIN_VLEN >= 128")
+  (V256QI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V256QImode) && 
TARGET_MIN_VLEN >= 256")
+  (V512QI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V512QImode) && 
TARGET_MIN_VLEN >= 512")
+  (V1024QI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V1024QImode) 
&& TARGET_MIN_VLEN >= 1024")
+  (V1HI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V1HImode) && 
TARGET_VECTOR_ELEN_64")
+  (V2HI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V2HImode) && 
TARGET_VECTOR_ELEN_64")
+  (V4HI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V4HImode) && 
TARGET_VECTOR_ELEN_64")
+  (V8HI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V8HImode) && 
TARGET_VECTOR_ELEN_64")
+  (V16HI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V16HImode) && 
TARGET_VECTOR_ELEN_64")
+  (V32HI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V32HImode) && 
TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 64")
+  (V64HI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V64HImode) && 
TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 128")
+  (V128HI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V128HImode) 
&& TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 256")
+  (V256HI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V256HImode) 
&& TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 512")
+  (V512HI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V512HImode) 
&& TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 1024")
 ])
 
 ;; Scalable integer accumulator modes for batched dot products.
@@ -1530,6 +1552,79 @@ (define_mode_iterator VF_S_NOFRAC [
   (RVVM1SF "TARGET_VECTOR_ELEN_FP_32")
 ])
 
+(define_mode_iterator VQEXTI_DOT [
+  (RVVM8SI "TARGET_ZVQWDOTA8I")
+  (RVVM4SI "TARGET_ZVQWDOTA8I")
+  (RVVM2SI "TARGET_ZVQWDOTA8I")
+  (RVVM1SI "TARGET_ZVQWDOTA8I")
+  (RVVM8DI "TARGET_ZVQWDOTA16I && TARGET_VECTOR_ELEN_64")
+  (RVVM4DI "TARGET_ZVQWDOTA16I && TARGET_VECTOR_ELEN_64")
+  (RVVM2DI "TARGET_ZVQWDOTA16I && TARGET_VECTOR_ELEN_64")
+  (RVVM1DI "TARGET_ZVQWDOTA16I && TARGET_VECTOR_ELEN_64")
+
+  (V1SI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V1SImode)")
+  (V2SI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V2SImode)")
+  (V4SI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V4SImode)")
+  (V8SI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V8SImode)")
+  (V16SI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V16SImode) && 
TARGET_MIN_VLEN >= 64")
+  (V32SI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V32SImode) && 
TARGET_MIN_VLEN >= 128")
+  (V64SI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V64SImode) && 
TARGET_MIN_VLEN >= 256")
+  (V128SI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V128SImode) && 
TARGET_MIN_VLEN >= 512")
+  (V256SI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V256SImode) && 
TARGET_MIN_VLEN >= 1024")
+  (V512SI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V512SImode) && 
TARGET_MIN_VLEN >= 2048")
+  (V1024SI "TARGET_ZVQWDOTA8I && riscv_vector::vls_mode_valid_p (V1024SImode) 
&& TARGET_MIN_VLEN >= 4096")
+  (V1DI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V1DImode) && 
TARGET_VECTOR_ELEN_64")
+  (V2DI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V2DImode) && 
TARGET_VECTOR_ELEN_64")
+  (V4DI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V4DImode) && 
TARGET_VECTOR_ELEN_64")
+  (V8DI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V8DImode) && 
TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 64")
+  (V16DI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V16DImode) && 
TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 128")
+  (V32DI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V32DImode) && 
TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 256")
+  (V64DI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V64DImode) && 
TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 512")
+  (V128DI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V128DImode) 
&& TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 1024")
+  (V256DI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V256DImode) 
&& TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 2048")
+  (V512DI "TARGET_ZVQWDOTA16I && riscv_vector::vls_mode_valid_p (V512DImode) 
&& TARGET_VECTOR_ELEN_64 && TARGET_MIN_VLEN >= 4096")
+])
+
+(define_mode_iterator VWEXTF_DOT_BF [
+  (RVVM8SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32
+           && TARGET_VECTOR_ELEN_BF_16")
+  (RVVM4SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32
+           && TARGET_VECTOR_ELEN_BF_16")
+  (RVVM2SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32
+           && TARGET_VECTOR_ELEN_BF_16")
+  (RVVM1SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32
+           && TARGET_VECTOR_ELEN_BF_16")
+  (V1SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32 && 
TARGET_VECTOR_ELEN_BF_16 && riscv_vector::vls_mode_valid_p (V1SFmode)")
+  (V2SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32 && 
TARGET_VECTOR_ELEN_BF_16 && riscv_vector::vls_mode_valid_p (V2SFmode)")
+  (V4SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32 && 
TARGET_VECTOR_ELEN_BF_16 && riscv_vector::vls_mode_valid_p (V4SFmode)")
+  (V8SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32 && 
TARGET_VECTOR_ELEN_BF_16 && riscv_vector::vls_mode_valid_p (V8SFmode)")
+  (V16SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32 && 
TARGET_VECTOR_ELEN_BF_16 && riscv_vector::vls_mode_valid_p (V16SFmode) && 
TARGET_MIN_VLEN >= 64")
+  (V32SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32 && 
TARGET_VECTOR_ELEN_BF_16 && riscv_vector::vls_mode_valid_p (V32SFmode) && 
TARGET_MIN_VLEN >= 128")
+  (V64SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32 && 
TARGET_VECTOR_ELEN_BF_16 && riscv_vector::vls_mode_valid_p (V64SFmode) && 
TARGET_MIN_VLEN >= 256")
+  (V128SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32 && 
TARGET_VECTOR_ELEN_BF_16 && riscv_vector::vls_mode_valid_p (V128SFmode) && 
TARGET_MIN_VLEN >= 512")
+  (V256SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32 && 
TARGET_VECTOR_ELEN_BF_16 && riscv_vector::vls_mode_valid_p (V256SFmode) && 
TARGET_MIN_VLEN >= 1024")
+  (V512SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32 && 
TARGET_VECTOR_ELEN_BF_16 && riscv_vector::vls_mode_valid_p (V512SFmode) && 
TARGET_MIN_VLEN >= 2048")
+  (V1024SF "TARGET_ZVFWDOTA16BF && TARGET_VECTOR_ELEN_FP_32 && 
TARGET_VECTOR_ELEN_BF_16 && riscv_vector::vls_mode_valid_p (V1024SFmode) && 
TARGET_MIN_VLEN >= 4096")
+])
+
+(define_mode_iterator VF_ZVFWDOTA_BF [VF_ZVFBF16 VLSF_ZVFBF16])
+
+(define_mode_attr V_DOUBLE_TRUNC_BF [
+  (RVVM8SF "RVVM4BF") (RVVM4SF "RVVM2BF") (RVVM2SF "RVVM1BF")
+  (RVVM1SF "RVVMF2BF")
+  (V1SF "V1BF") (V2SF "V2BF") (V4SF "V4BF") (V8SF "V8BF")
+  (V16SF "V16BF") (V32SF "V32BF") (V64SF "V64BF") (V128SF "V128BF")
+  (V256SF "V256BF") (V512SF "V512BF") (V1024SF "V1024BF")
+])
+
+(define_mode_attr v_double_trunc_bf [
+  (RVVM8SF "rvvm4bf") (RVVM4SF "rvvm2bf") (RVVM2SF "rvvm1bf")
+  (RVVM1SF "rvvmf2bf")
+  (V1SF "v1bf") (V2SF "v2bf") (V4SF "v4bf") (V8SF "v8bf")
+  (V16SF "v16bf") (V32SF "v32bf") (V64SF "v64bf") (V128SF "v128bf")
+  (V256SF "v256bf") (V512SF "v512bf") (V1024SF "v1024bf")
+])
+
 ;; Quadruple the element width and use LMUL=1.
 (define_mode_attr V_QUAD_EXT_LMUL1 [
   (RVVMF8QI "RVVM1SI")
@@ -1545,6 +1640,12 @@ (define_mode_attr V_QUAD_EXT_LMUL1 [
   (RVVM2HI "RVVM1DI")
   (RVVM4HI "RVVM1DI")
   (RVVM8HI "RVVM1DI")
+  (V1QI "RVVM1SI") (V2QI "RVVM1SI") (V4QI "RVVM1SI") (V8QI "RVVM1SI")
+  (V16QI "RVVM1SI") (V32QI "RVVM1SI") (V64QI "RVVM1SI") (V128QI "RVVM1SI")
+  (V256QI "RVVM1SI") (V512QI "RVVM1SI") (V1024QI "RVVM1SI")
+  (V1HI "RVVM1DI") (V2HI "RVVM1DI") (V4HI "RVVM1DI") (V8HI "RVVM1DI")
+  (V16HI "RVVM1DI") (V32HI "RVVM1DI") (V64HI "RVVM1DI") (V128HI "RVVM1DI")
+  (V256HI "RVVM1DI") (V512HI "RVVM1DI")
 ])
 
 ;; Quarter the element width and select a fixed register-group size.
@@ -1872,6 +1973,10 @@ (define_mode_attr V_EXT_LMUL1 [
   (RVVM2BF "RVVM1SF")
   (RVVM4BF "RVVM1SF")
   (RVVM8BF "RVVM1SF")
+  (V1BF "RVVM1SF") (V2BF "RVVM1SF") (V4BF "RVVM1SF") (V8BF "RVVM1SF")
+  (V16BF "RVVM1SF") (V32BF "RVVM1SF") (V64BF "RVVM1SF") (V128BF "RVVM1SF")
+  (V256BF "RVVM1SF") (V512BF "RVVM1SF") (V1024BF "RVVM1SF")
+  (V2048BF "RVVM1SF")
 
   (RVVM8QI "RVVM1HI") (RVVM4QI "RVVM1HI") (RVVM2QI "RVVM1HI") (RVVM1QI 
"RVVM1HI") (RVVMF2QI "RVVM1HI") (RVVMF4QI "RVVM1HI") (RVVMF8QI "RVVM1HI")
 
diff --git a/gcc/config/riscv/xuantie-vector.md 
b/gcc/config/riscv/xuantie-vector.md
index 00e9659b08a..d4a62b9faba 100644
--- a/gcc/config/riscv/xuantie-vector.md
+++ b/gcc/config/riscv/xuantie-vector.md
@@ -48,11 +48,6 @@ (define_int_attr xxtvarith_ins_name [
   (UNSPEC_XT_VCRCFOLDR "vcrcfoldr") (UNSPEC_XT_VCRCFOLDN "vcrcfoldn")
 ])
 
-(define_mode_iterator VI_Q [
-  RVVM8QI RVVM4QI RVVM2QI RVVM1QI RVVMF2QI RVVMF4QI
-  (RVVMF8QI "TARGET_MIN_VLEN > 32")
-])
-
 (define_insn "@xt_pred_<xxtvarith_ins_name><mode>"
   [(set (match_operand:VI_Q 0 "register_operand"    "=vr")
      (if_then_else:VI_Q
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf-neg-1.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf-neg-1.c
new file mode 100644
index 00000000000..390892d8bd9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf-neg-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rva23u64_zvfwdota16bf -mabi=lp64d 
-mrvv-vector-bits=scalable -fno-associative-math -fno-vect-cost-model 
-fdump-tree-vect-details" } */
+
+#include "dot.h"
+
+DEF_DOT (float, __bf16, __bf16, dot)
+
+/* { dg-final { scan-tree-dump-not "vect_recog_dot_prod_pattern: detected" 
"vect" } } */
+/* { dg-final { scan-assembler-not {\tvfwdota\.vv\t} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf-neg-2.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf-neg-2.c
new file mode 100644
index 00000000000..2b0b36eb54e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf-neg-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rva23u64_zvfwdota16bf -mabi=lp64d 
-mrvv-vector-bits=scalable -ffast-math -fno-vect-cost-model" } */
+
+float
+dot (float sum, __bf16 *__restrict a, __bf16 *__restrict b, int n)
+{
+  for (int i = 0; i < n; i++)
+    sum += (float) (__bf16) (a[i] * b[i]);
+  return sum;
+}
+
+/* { dg-final { scan-assembler-not {\tvfwdota\.vv\t} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf.c
new file mode 100644
index 00000000000..eb5c1c17562
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-bf.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rva23u64_zvfwdota16bf -mabi=lp64d 
-mrvv-vector-bits=scalable -ffast-math -fno-vect-cost-model --param 
vect-epilogues-nomask=0 -fdump-tree-vect-details" } */
+
+#include "dot.h"
+
+DEF_DOT (float, __bf16, __bf16, dot)
+
+/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "vect" 
} } */
+/* { dg-final { scan-assembler {\tvfwdota\.vv\t} } } */
+/* { dg-final { scan-assembler 
{vsetvli\t[a-z0-9]+,\s*[a-z0-9]+,\s*e16alt,\s*mf?[1248],\s*tu,\s*m[au]} } } */
+/* { dg-final { scan-assembler-not {\tvfwmul} } } */
+/* { dg-final { scan-assembler-not {\tvfwmacc} } } */
+/* { dg-final { scan-assembler-not {\tvfwcvt} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-ss.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-ss.c
new file mode 100644
index 00000000000..ef662b0e641
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-ss.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rva23u64_zvqwdota16i -mabi=lp64d 
-mrvv-vector-bits=scalable -fno-vect-cost-model --param vect-epilogues-nomask=0 
-fdump-tree-vect-details" } */
+
+#include "dot.h"
+
+DEF_DOT (int64_t, int16_t, int16_t, dot)
+
+/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "vect" 
} } */
+/* { dg-final { scan-assembler {\tvqwdotas\.vv\t} } } */
+/* { dg-final { scan-assembler 
{vsetvli\t[a-z0-9]+,\s*[a-z0-9]+,\s*e16alt,\s*mf?[1248],\s*tu,\s*m[au]} } } */
+/* { dg-final { scan-assembler-not {\tvwmul} } } */
+/* { dg-final { scan-assembler-not {\tvwmacc} } } */
+/* { dg-final { scan-assembler-not {\tvsext} } } */
+/* { dg-final { scan-assembler-not {\tvzext} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-us.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-us.c
new file mode 100644
index 00000000000..861d471684a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-us.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rva23u64_zvqwdota16i -mabi=lp64d 
-mrvv-vector-bits=scalable -fno-vect-cost-model --param vect-epilogues-nomask=0 
-fdump-tree-vect-details" } */
+
+#include "dot.h"
+
+DEF_DOT (int64_t, uint16_t, int16_t, dot)
+
+/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "vect" 
} } */
+/* { dg-final { scan-assembler {\tvqwdotau\.vv\t} } } */
+/* { dg-final { scan-assembler 
{vsetvli\t[a-z0-9]+,\s*[a-z0-9]+,\s*e16alt,\s*mf?[1248],\s*tu,\s*m[au]} } } */
+/* { dg-final { scan-assembler-not {\tvwmul} } } */
+/* { dg-final { scan-assembler-not {\tvwmacc} } } */
+/* { dg-final { scan-assembler-not {\tvsext} } } */
+/* { dg-final { scan-assembler-not {\tvzext} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-uu.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-uu.c
new file mode 100644
index 00000000000..8d09104e5ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-hi-uu.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rva23u64_zvqwdota16i -mabi=lp64d 
-mrvv-vector-bits=scalable -fno-vect-cost-model --param vect-epilogues-nomask=0 
-fdump-tree-vect-details" } */
+
+#include "dot.h"
+
+DEF_DOT (uint64_t, uint16_t, uint16_t, dot)
+
+/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "vect" 
} } */
+/* { dg-final { scan-assembler {\tvqwdotau\.vv\t} } } */
+/* { dg-final { scan-assembler 
{vsetvli\t[a-z0-9]+,\s*[a-z0-9]+,\s*e16,\s*mf?[1248],\s*tu,\s*m[au]} } } */
+/* { dg-final { scan-assembler-not {\tvwmul} } } */
+/* { dg-final { scan-assembler-not {\tvwmacc} } } */
+/* { dg-final { scan-assembler-not {\tvsext} } } */
+/* { dg-final { scan-assembler-not {\tvzext} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-noext.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-noext.c
new file mode 100644
index 00000000000..aed97ef9ee3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-noext.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rva23u64 -mabi=lp64d 
-mrvv-vector-bits=scalable -ffast-math -fno-vect-cost-model" } */
+
+#include "dot.h"
+
+DEF_DOT (int32_t, int8_t, int8_t, dot_ss)
+DEF_DOT (uint64_t, uint16_t, uint16_t, dot_uu)
+DEF_DOT (float, __bf16, __bf16, dot_bf)
+
+/* { dg-final { scan-assembler-not {\tvqwdota[su]\.vv\t} } } */
+/* { dg-final { scan-assembler-not {\tvfwdota\.vv\t} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-ss.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-ss.c
new file mode 100644
index 00000000000..6e82bc43f38
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-ss.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rva23u64_zvqwdota8i -mabi=lp64d 
-mrvv-vector-bits=scalable -fno-vect-cost-model --param vect-epilogues-nomask=0 
-fdump-tree-vect-details" } */
+
+#include "dot.h"
+
+DEF_DOT (int32_t, int8_t, int8_t, dot)
+
+/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "vect" 
} } */
+/* { dg-final { scan-assembler {\tvqwdotas\.vv\t} } } */
+/* { dg-final { scan-assembler 
{vsetvli\t[a-z0-9]+,\s*[a-z0-9]+,\s*e8alt,\s*mf?[1248],\s*tu,\s*m[au]} } } */
+/* { dg-final { scan-assembler-not {\tvwmul} } } */
+/* { dg-final { scan-assembler-not {\tvwmacc} } } */
+/* { dg-final { scan-assembler-not {\tvsext} } } */
+/* { dg-final { scan-assembler-not {\tvzext} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-su.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-su.c
new file mode 100644
index 00000000000..cb739e47f58
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-su.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rva23u64_zvqwdota8i -mabi=lp64d 
-mrvv-vector-bits=scalable -fno-vect-cost-model --param vect-epilogues-nomask=0 
-fdump-tree-vect-details" } */
+
+#include "dot.h"
+
+DEF_DOT (int32_t, int8_t, uint8_t, dot)
+
+/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "vect" 
} } */
+/* { dg-final { scan-assembler {\tvqwdotau\.vv\t} } } */
+/* { dg-final { scan-assembler 
{vsetvli\t[a-z0-9]+,\s*[a-z0-9]+,\s*e8alt,\s*mf?[1248],\s*tu,\s*m[au]} } } */
+/* { dg-final { scan-assembler-not {\tvwmul} } } */
+/* { dg-final { scan-assembler-not {\tvwmacc} } } */
+/* { dg-final { scan-assembler-not {\tvsext} } } */
+/* { dg-final { scan-assembler-not {\tvzext} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-us.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-us.c
new file mode 100644
index 00000000000..16d85ebed4f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-us.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rva23u64_zvqwdota8i -mabi=lp64d 
-mrvv-vector-bits=scalable -fno-vect-cost-model --param vect-epilogues-nomask=0 
-fdump-tree-vect-details" } */
+
+#include "dot.h"
+
+DEF_DOT (int32_t, uint8_t, int8_t, dot)
+
+/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "vect" 
} } */
+/* { dg-final { scan-assembler {\tvqwdotau\.vv\t} } } */
+/* { dg-final { scan-assembler 
{vsetvli\t[a-z0-9]+,\s*[a-z0-9]+,\s*e8alt,\s*mf?[1248],\s*tu,\s*m[au]} } } */
+/* { dg-final { scan-assembler-not {\tvwmul} } } */
+/* { dg-final { scan-assembler-not {\tvwmacc} } } */
+/* { dg-final { scan-assembler-not {\tvsext} } } */
+/* { dg-final { scan-assembler-not {\tvzext} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-uu.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-uu.c
new file mode 100644
index 00000000000..288cbdfd0a8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot-qi-uu.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=rva23u64_zvqwdota8i -mabi=lp64d 
-mrvv-vector-bits=scalable -fno-vect-cost-model --param vect-epilogues-nomask=0 
-fdump-tree-vect-details" } */
+
+#include "dot.h"
+
+DEF_DOT (uint32_t, uint8_t, uint8_t, dot)
+
+/* { dg-final { scan-tree-dump "vect_recog_dot_prod_pattern: detected" "vect" 
} } */
+/* { dg-final { scan-assembler {\tvqwdotau\.vv\t} } } */
+/* { dg-final { scan-assembler 
{vsetvli\t[a-z0-9]+,\s*[a-z0-9]+,\s*e8,\s*mf?[1248],\s*tu,\s*m[au]} } } */
+/* { dg-final { scan-assembler-not {\tvwmul} } } */
+/* { dg-final { scan-assembler-not {\tvwmacc} } } */
+/* { dg-final { scan-assembler-not {\tvsext} } } */
+/* { dg-final { scan-assembler-not {\tvzext} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot.h 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot.h
new file mode 100644
index 00000000000..5a1f25ea201
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot.h
@@ -0,0 +1,20 @@
+#include <stdint-gcc.h>
+
+#define DEF_DOT(ACC, TA, TB, NAME)                                     \
+  __attribute__ ((noipa)) ACC                                          \
+  NAME (ACC sum, TA *__restrict a, TB *__restrict b, int n)            \
+  {                                                                    \
+    for (int i = 0; i < n; i++)                                                
\
+      sum += (ACC) a[i] * (ACC) b[i];                                  \
+    return sum;                                                                
\
+  }
+
+#define DEF_DOT_REF(ACC, TA, TB, NAME)                                 \
+  __attribute__ ((noipa)) ACC                                          \
+  NAME##_ref (ACC sum, TA *__restrict a, TB *__restrict b, int n)      \
+  {                                                                    \
+    _Pragma ("GCC novector")                                           \
+    for (int i = 0; i < n; i++)                                                
\
+      sum += (ACC) a[i] * (ACC) b[i];                                  \
+    return sum;                                                                
\
+  }
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-bf.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-bf.c
new file mode 100644
index 00000000000..7771376a630
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-bf.c
@@ -0,0 +1,30 @@
+/* { dg-do run { target { riscv_v && riscv_zvfwdota16bf_ok } } } */
+/* { dg-add-options riscv_zvfwdota16bf } */
+/* { dg-additional-options "-mrvv-vector-bits=scalable -ffast-math 
-fno-vect-cost-model" } */
+
+#include "dot.h"
+
+#define N 301
+
+DEF_DOT (float, __bf16, __bf16, dot)
+DEF_DOT_REF (float, __bf16, __bf16, dot)
+
+__bf16 a[N];
+__bf16 b[N];
+
+int
+main ()
+{
+  for (int i = 0; i < N; i++)
+    {
+      a[i] = (__bf16) (i % 7 - 3);
+      b[i] = (__bf16) (i % 5 - 2);
+    }
+  for (int n = 0; n < N; n++)
+    {
+      float init_sum = n * 0.5f - 17.0f;
+      if (dot (init_sum, a, b, n) != dot_ref (init_sum, a, b, n))
+       __builtin_abort ();
+    }
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-ss.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-ss.c
new file mode 100644
index 00000000000..13c460fe0d7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-ss.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v && riscv_zvqwdota16i_ok } } } */
+/* { dg-add-options riscv_zvqwdota16i } */
+/* { dg-additional-options "-mrvv-vector-bits=scalable -fno-vect-cost-model" } 
*/
+
+#include "dot.h"
+
+#define ACC int64_t
+#define TA int16_t
+#define TB int16_t
+#define DOT dot
+#define DOT_REF dot_ref
+
+DEF_DOT (ACC, TA, TB, dot)
+DEF_DOT_REF (ACC, TA, TB, dot)
+
+#include "dot_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-us.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-us.c
new file mode 100644
index 00000000000..da19d27e958
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-us.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v && riscv_zvqwdota16i_ok } } } */
+/* { dg-add-options riscv_zvqwdota16i } */
+/* { dg-additional-options "-mrvv-vector-bits=scalable -fno-vect-cost-model" } 
*/
+
+#include "dot.h"
+
+#define ACC int64_t
+#define TA uint16_t
+#define TB int16_t
+#define DOT dot
+#define DOT_REF dot_ref
+
+DEF_DOT (ACC, TA, TB, dot)
+DEF_DOT_REF (ACC, TA, TB, dot)
+
+#include "dot_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-uu.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-uu.c
new file mode 100644
index 00000000000..cfc45aad13f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-hi-uu.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v && riscv_zvqwdota16i_ok } } } */
+/* { dg-add-options riscv_zvqwdota16i } */
+/* { dg-additional-options "-mrvv-vector-bits=scalable -fno-vect-cost-model" } 
*/
+
+#include "dot.h"
+
+#define ACC uint64_t
+#define TA uint16_t
+#define TB uint16_t
+#define DOT dot
+#define DOT_REF dot_ref
+
+DEF_DOT (ACC, TA, TB, dot)
+DEF_DOT_REF (ACC, TA, TB, dot)
+
+#include "dot_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-ss.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-ss.c
new file mode 100644
index 00000000000..1c4bc0a518d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-ss.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v && riscv_zvqwdota8i_ok } } } */
+/* { dg-add-options riscv_zvqwdota8i } */
+/* { dg-additional-options "-mrvv-vector-bits=scalable -fno-vect-cost-model" } 
*/
+
+#include "dot.h"
+
+#define ACC int32_t
+#define TA int8_t
+#define TB int8_t
+#define DOT dot
+#define DOT_REF dot_ref
+
+DEF_DOT (ACC, TA, TB, dot)
+DEF_DOT_REF (ACC, TA, TB, dot)
+
+#include "dot_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-su.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-su.c
new file mode 100644
index 00000000000..f95145f18c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-su.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v && riscv_zvqwdota8i_ok } } } */
+/* { dg-add-options riscv_zvqwdota8i } */
+/* { dg-additional-options "-mrvv-vector-bits=scalable -fno-vect-cost-model" } 
*/
+
+#include "dot.h"
+
+#define ACC int32_t
+#define TA int8_t
+#define TB uint8_t
+#define DOT dot
+#define DOT_REF dot_ref
+
+DEF_DOT (ACC, TA, TB, dot)
+DEF_DOT_REF (ACC, TA, TB, dot)
+
+#include "dot_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-us.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-us.c
new file mode 100644
index 00000000000..6335559507b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-us.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v && riscv_zvqwdota8i_ok } } } */
+/* { dg-add-options riscv_zvqwdota8i } */
+/* { dg-additional-options "-mrvv-vector-bits=scalable -fno-vect-cost-model" } 
*/
+
+#include "dot.h"
+
+#define ACC int32_t
+#define TA uint8_t
+#define TB int8_t
+#define DOT dot
+#define DOT_REF dot_ref
+
+DEF_DOT (ACC, TA, TB, dot)
+DEF_DOT_REF (ACC, TA, TB, dot)
+
+#include "dot_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-uu.c 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-uu.c
new file mode 100644
index 00000000000..1bbabd4570d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run-qi-uu.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v && riscv_zvqwdota8i_ok } } } */
+/* { dg-add-options riscv_zvqwdota8i } */
+/* { dg-additional-options "-mrvv-vector-bits=scalable -fno-vect-cost-model" } 
*/
+
+#include "dot.h"
+
+#define ACC uint32_t
+#define TA uint8_t
+#define TB uint8_t
+#define DOT dot
+#define DOT_REF dot_ref
+
+DEF_DOT (ACC, TA, TB, dot)
+DEF_DOT_REF (ACC, TA, TB, dot)
+
+#include "dot_run.h"
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run.h 
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run.h
new file mode 100644
index 00000000000..5795d2fd22d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/reduc/dot_run.h
@@ -0,0 +1,49 @@
+#define N 301
+
+#define MAXV(T) ((T) -1 > 0 ? (T) -1                                   \
+                : (T) ((1ULL << (sizeof (T) * 8 - 1)) - 1))
+#define MINV(T) ((T) -1 > 0 ? (T) 0 : (T) (-MAXV (T) - 1))
+
+TA a[N];
+TB b[N];
+
+static void
+init (int kind)
+{
+  for (int i = 0; i < N; i++)
+    switch (kind)
+      {
+      case 0:
+       a[i] = (TA) (i * 37 + 11);
+       b[i] = (TB) (i * 101 - 7);
+       break;
+      case 1:
+       a[i] = i & 1 ? MAXV (TA) : MINV (TA);
+       b[i] = i % 3 ? MINV (TB) : MAXV (TB);
+       break;
+      case 2:
+       a[i] = MINV (TA);
+       b[i] = MINV (TB);
+       break;
+      default:
+       a[i] = MAXV (TA);
+       b[i] = MAXV (TB);
+       break;
+      }
+}
+
+int
+main ()
+{
+  for (int kind = 0; kind < 4; kind++)
+    {
+      init (kind);
+      for (int n = 0; n < N; n++)
+       {
+         ACC init_sum = (ACC) (n * 3 - 17);
+         if (DOT (init_sum, a, b, n) != DOT_REF (init_sum, a, b, n))
+           __builtin_abort ();
+       }
+    }
+  return 0;
+}
diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index 3ce06189d2e..71b4a83c02c 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2388,6 +2388,30 @@ proc check_effective_target_riscv_zvbb { } {
     }]
 }
 
+proc check_effective_target_riscv_zvqwdota8i { } {
+    return [check_no_compiler_messages riscv_ext_zvqwdota8i assembly {
+       #ifndef __riscv_zvqwdota8i
+       #error "Not __riscv_zvqwdota8i"
+       #endif
+    }]
+}
+
+proc check_effective_target_riscv_zvqwdota16i { } {
+    return [check_no_compiler_messages riscv_ext_zvqwdota16i assembly {
+       #ifndef __riscv_zvqwdota16i
+       #error "Not __riscv_zvqwdota16i"
+       #endif
+    }]
+}
+
+proc check_effective_target_riscv_zvfwdota16bf { } {
+    return [check_no_compiler_messages riscv_ext_zvfwdota16bf assembly {
+       #ifndef __riscv_zvfwdota16bf
+       #error "Not __riscv_zvfwdota16bf"
+       #endif
+    }]
+}
+
 proc check_effective_target_riscv_zvabd { } {
     return [check_no_compiler_messages riscv_ext_zvabd assembly {
        #ifndef __riscv_zvabd
@@ -2671,6 +2695,69 @@ proc check_effective_target_riscv_zvbb_ok { } {
     return 0
 }
 
+proc check_effective_target_riscv_zvqwdota8i_ok { } {
+    if { ![istarget riscv*-*-*] } {
+       return 0
+    }
+
+    set gcc_march [riscv_get_arch]
+    if { [check_effective_target_riscv_zvqwdota8i] } {
+       set opts ""
+    } else {
+       set opts "-march=${gcc_march}_zvqwdota8i"
+    }
+
+    return [check_runtime ${gcc_march}_zvqwdota8i_exec {
+       int main()
+       {
+           asm ("vsetivli zero,8,e8,m1,tu,ma");
+           asm ("vqwdotau.vv v8,v16,v17" : : : "v8");
+           return 0;
+       } } $opts]
+}
+
+proc check_effective_target_riscv_zvqwdota16i_ok { } {
+    if { ![istarget riscv*-*-*] } {
+       return 0
+    }
+
+    set gcc_march [riscv_get_arch]
+    if { [check_effective_target_riscv_zvqwdota16i] } {
+       set opts ""
+    } else {
+       set opts "-march=${gcc_march}_zvqwdota16i"
+    }
+
+    return [check_runtime ${gcc_march}_zvqwdota16i_exec {
+       int main()
+       {
+           asm ("vsetivli zero,4,e16,m1,tu,ma");
+           asm ("vqwdotau.vv v8,v16,v17" : : : "v8");
+           return 0;
+       } } $opts]
+}
+
+proc check_effective_target_riscv_zvfwdota16bf_ok { } {
+    if { ![istarget riscv*-*-*] } {
+       return 0
+    }
+
+    set gcc_march [riscv_get_arch]
+    if { [check_effective_target_riscv_zvfwdota16bf] } {
+       set opts ""
+    } else {
+       set opts "-march=${gcc_march}_zvfwdota16bf"
+    }
+
+    return [check_runtime ${gcc_march}_zvfwdota16bf_exec {
+       int main()
+       {
+           asm ("vsetivli zero,4,e16alt,m1,tu,ma");
+           asm ("vfwdota.vv v8,v16,v17" : : : "v8");
+           return 0;
+       } } $opts]
+}
+
 proc check_effective_target_riscv_zvabd_ok { } {
     if { ![istarget riscv*-*-*] } {
        return 0
@@ -2968,11 +3055,32 @@ proc remove_options_for_riscv_zvbb { flags } {
     return [add_options_for_riscv_multi_letter_ext zvbb $flags]
 }
 
+proc add_options_for_riscv_zvqwdota8i { flags } {
+    if { ![check_effective_target_riscv_zvqwdota8i_ok] } {
+       return $flags
+    }
+    return [add_options_for_riscv_multi_letter_ext zvqwdota8i $flags]
+}
+
+proc add_options_for_riscv_zvqwdota16i { flags } {
+    if { ![check_effective_target_riscv_zvqwdota16i_ok] } {
+       return $flags
+    }
+    return [add_options_for_riscv_multi_letter_ext zvqwdota16i $flags]
+}
+
+proc add_options_for_riscv_zvfwdota16bf { flags } {
+    if { ![check_effective_target_riscv_zvfwdota16bf_ok] } {
+       return $flags
+    }
+    return [add_options_for_riscv_multi_letter_ext zvfwdota16bf $flags]
+}
+
 proc add_options_for_riscv_zvabd { flags } {
     if { ![check_effective_target_riscv_zvabd_ok] } {
        return $flags
     }
-    return [add_options_for_riscv_z_ext zvabd $flags]
+    return [add_options_for_riscv_multi_letter_ext zvabd $flags]
 }
 
 proc add_options_for_riscv_zvfh { flags } {
-- 
2.56.0

Reply via email to