https://gcc.gnu.org/g:2a64a564f5eeb5aa332816459404641fb9cf8f14

commit r17-2751-g2a64a564f5eeb5aa332816459404641fb9cf8f14
Author: Richard Ball <[email protected]>
Date:   Tue Jul 28 14:45:01 2026 +0100

    aarch64: Add Support for SVE2p3/SME2p3 dot product intrinsics
    
    Add support for SVE2p3 and SME2p3 dot product intrinsics
    
    gcc/ChangeLog:
    
            * config/aarch64/aarch64-acle-builtins.h
            (TYPES_s_narrow_su): New type array.
            (s_narrow_su): Likewise.
            * config/aarch64/aarch64-sve-builtins-base.cc
            (class svdot_impl): Update impl.
            (FUNCTION): Likewise.
            * config/aarch64/aarch64-sve-builtins-sve2.def
            (REQUIRED_EXTENSIONS): New function.
            (svdot): Likewise.
            (svdot_lane): Likewise.
            * config/aarch64/aarch64-sve2.md
            (<sur>dot_prodvnx4sivnx8hi): Renamed.
            (@<sur>dot_prod<VNx4SI_ONLY:mode><VNx8HI_ONLY:mode>): New Name.
            (@<sur>dot_prod<VNx8HI_ONLY:mode><VNx16QI_ONLY:mode>): New pattern.
            (@aarch64_<sur>dot_prod_lane<VNx8HI_ONLY:mode><VNx16QI_ONLY:mode>): 
Likewise.
            * config/aarch64/aarch64.h
            (TARGET_SVE2p3): New Target Flag.
            (TARGET_SME2p3): Likewise.
            (TARGET_STREAMING_SME2p3): Likewise.
            (TARGET_SVE2p3_OR_SME2p3): Likewise.
            * doc/invoke.texi: Add sve2p3/sme2p3.
    
    gcc/testsuite/ChangeLog:
    
            * lib/target-supports.exp: New check_effective_targets.
            * gcc.target/aarch64/sme2/acle-asm/dot_lane_s16.c: New test.
            * gcc.target/aarch64/sme2/acle-asm/dot_lane_u16.c: New test.
            * gcc.target/aarch64/sme2/acle-asm/dot_s16.c: New test.
            * gcc.target/aarch64/sme2/acle-asm/dot_u16.c: New test.
            * gcc.target/aarch64/sve2/dotproduct_intrinsicless.c: New test.

Diff:
---
 gcc/config/aarch64/aarch64-acle-builtins.h         |  6 ++
 gcc/config/aarch64/aarch64-sve-builtins-base.cc    | 13 +--
 gcc/config/aarch64/aarch64-sve-builtins-sve2.def   |  5 ++
 gcc/config/aarch64/aarch64-sve2.md                 | 49 +++++++++--
 gcc/config/aarch64/aarch64.h                       | 10 +++
 gcc/doc/invoke.texi                                |  6 ++
 .../aarch64/sme2/acle-asm/dot_lane_s16.c           | 96 ++++++++++++++++++++++
 .../aarch64/sme2/acle-asm/dot_lane_u16.c           | 96 ++++++++++++++++++++++
 .../gcc.target/aarch64/sme2/acle-asm/dot_s16.c     | 47 +++++++++++
 .../gcc.target/aarch64/sme2/acle-asm/dot_u16.c     | 47 +++++++++++
 .../aarch64/sve2/dotproduct_intrinsicless.c        | 30 +++++++
 gcc/testsuite/lib/target-supports.exp              | 28 +++++++
 12 files changed, 421 insertions(+), 12 deletions(-)

diff --git a/gcc/config/aarch64/aarch64-acle-builtins.h 
b/gcc/config/aarch64/aarch64-acle-builtins.h
index d330ac7897a7..bf495bd74a0d 100644
--- a/gcc/config/aarch64/aarch64-acle-builtins.h
+++ b/gcc/config/aarch64/aarch64-acle-builtins.h
@@ -1646,6 +1646,11 @@ function_expander::result_mode () const
 #define TYPES_s_narrow_fsu(S, D, T) \
   D (f32, f16), D (s32, s16), D (u32, u16)
 
+/* _s16_s8
+   _u16_u8.  */
+#define TYPES_s_narrow_su(S, D, T) \
+  D (s16, s8), D (u16, u8)
+
 /* _za8 _za16 _za32 _za64 _za128.  */
 #define TYPES_all_za(S, D, T) \
   S (za8), S (za16), S (za32), S (za64), S (za128)
@@ -2025,6 +2030,7 @@ DEF_SVE_TYPES_ARRAY (while);
 DEF_SVE_TYPES_ARRAY (while_x);
 DEF_SVE_TYPES_ARRAY (while_x_c);
 DEF_SVE_TYPES_ARRAY (s_narrow_fsu);
+DEF_SVE_TYPES_ARRAY (s_narrow_su);
 DEF_SVE_TYPES_ARRAY (all_za);
 DEF_SVE_TYPES_ARRAY (d_za);
 DEF_SVE_TYPES_ARRAY (za_bhsd_data);
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc 
b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
index e841972cb422..7f047bb64686 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
@@ -938,13 +938,17 @@ public:
 };
 
 
-class svdot_impl : public function_base
+class svdot_impl : public unspec_based_function_base
 {
 public:
+  using unspec_based_function_base::unspec_based_function_base;
+
   rtx
   expand (function_expander &e) const override
   {
     insn_code icode;
+    machine_mode mode0 = GET_MODE (e.args[0]);
+    machine_mode mode1 = GET_MODE (e.args[1]);
     if (e.fpm_mode == aarch64_acle::FPM_set)
       icode = code_for_aarch64_sve_dot (e.result_mode ());
     else
@@ -952,6 +956,7 @@ public:
        /* In the optab, the multiplication operands come before the accumulator
           operand.  The optab is keyed off the multiplication mode.  */
        e.rotate_inputs_left (0, 3);
+       int unspec = unspec_for (e);
        if (e.type_suffix_ids[1] == NUM_TYPE_SUFFIXES)
          icode = e.convert_optab_handler_for_sign (sdot_prod_optab,
                                                    udot_prod_optab,
@@ -960,9 +965,7 @@ public:
        else
          icode = (e.type_suffix (0).float_p
                   ? CODE_FOR_aarch64_sve_fdotvnx4sfvnx8hf
-                  : e.type_suffix (0).unsigned_p
-                  ? CODE_FOR_udot_prodvnx4sivnx8hi
-                  : CODE_FOR_sdot_prodvnx4sivnx8hi);
+                  : code_for_dot_prod (unspec, mode0, mode1));
       }
     return e.use_unpred_insn (icode);
   }
@@ -3617,7 +3620,7 @@ FUNCTION (svcvt, svcvt_impl,)
 FUNCTION (svcvtnt, NARROWING_TOP_CONVERT0 (aarch64_sve_cvtnt),)
 FUNCTION (svdiv, svdiv_impl,)
 FUNCTION (svdivr, rtx_code_function_rotated, (DIV, UDIV, UNSPEC_COND_FDIV))
-FUNCTION (svdot, svdot_impl,)
+FUNCTION (svdot, svdot_impl,(UNSPEC_SDOT, UNSPEC_UDOT, UNSPEC_FDOT))
 FUNCTION (svdot_lane, svdotprod_lane_impl, (UNSPEC_SDOT, UNSPEC_UDOT,
                                            UNSPEC_FDOT, UNSPEC_DOT_LANE_FP8))
 FUNCTION (svdup, svdup_impl,)
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def 
b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
index 16524cfedab0..62474935b49c 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
+++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
@@ -465,6 +465,11 @@ DEF_SVE_FUNCTION_GS_FPM (svmmla, mmla, h_float_mf8, none, 
none, set)
 DEF_SVE_FUNCTION_GS_FPM (svmmla, mmla, s_float_mf8, none, none, set)
 #undef REQUIRED_EXTENSIONS
 
+#define REQUIRED_EXTENSIONS sve_and_sme (AARCH64_FL_SVE2p3, AARCH64_FL_SME2p3)
+DEF_SVE_FUNCTION (svdot, ternary_qq_opt_n_or_011, s_narrow_su, none)
+DEF_SVE_FUNCTION (svdot_lane, ternary_qq_or_011_lane, s_narrow_su, none)
+#undef REQUIRED_EXTENSIONS
+
 #define REQUIRED_EXTENSIONS nonstreaming_sve (AARCH64_FL_SVE_F16F32MM)
 DEF_SVE_FUNCTION (svmmla, mmla, cvt_f32_f16, none)
 #undef REQUIRED_EXTENSIONS
diff --git a/gcc/config/aarch64/aarch64-sve2.md 
b/gcc/config/aarch64/aarch64-sve2.md
index 860c63460eb9..873d47368294 100644
--- a/gcc/config/aarch64/aarch64-sve2.md
+++ b/gcc/config/aarch64/aarch64-sve2.md
@@ -2862,14 +2862,14 @@
 )
 
 ;; Two-way dot-product.
-(define_insn "<sur>dot_prodvnx4sivnx8hi"
-  [(set (match_operand:VNx4SI 0 "register_operand")
-       (plus:VNx4SI
-         (unspec:VNx4SI
-           [(match_operand:VNx8HI 1 "register_operand")
-            (match_operand:VNx8HI 2 "register_operand")]
+(define_insn "@<sur>dot_prod<VNx4SI_ONLY:mode><VNx8HI_ONLY:mode>"
+  [(set (match_operand:VNx4SI_ONLY 0 "register_operand")
+       (plus:VNx4SI_ONLY
+         (unspec:VNx4SI_ONLY
+           [(match_operand:VNx8HI_ONLY 1 "register_operand")
+            (match_operand:VNx8HI_ONLY 2 "register_operand")]
            DOTPROD)
-         (match_operand:VNx4SI 3 "register_operand")))]
+         (match_operand:VNx4SI_ONLY 3 "register_operand")))]
   "TARGET_SVE2p1_OR_SME2"
   {@ [ cons: =0 , 1 , 2 , 3 ; attrs: movprfx ]
      [ w        , w , w , 0 ; *              ] <sur>dot\t%0.s, %1.h, %2.h
@@ -2878,6 +2878,41 @@
   [(set_attr "sve_type" "sve_int_dot")]
 )
 
+;; Two-way dot-product SME2p3 || SVE2p3.
+(define_insn "@<sur>dot_prod<VNx8HI_ONLY:mode><VNx16QI_ONLY:mode>"
+  [(set (match_operand:VNx8HI_ONLY 0 "register_operand")
+       (plus:VNx8HI_ONLY
+         (unspec:VNx8HI_ONLY
+           [(match_operand:VNx16QI_ONLY 1 "register_operand")
+            (match_operand:VNx16QI_ONLY 2 "register_operand")]
+           DOTPROD)
+         (match_operand:VNx8HI_ONLY 3 "register_operand")))]
+  "TARGET_SVE2p3_OR_SME2p3"
+  {@ [ cons: =0 , 1 , 2 , 3 ; attrs: movprfx ]
+     [ w        , w , w , 0 ; *              ] <sur>dot\t%0.h, %1.b, %2.b
+     [ ?&w      , w , w , w ; yes            ] movprfx\t%0, 
%3\;<sur>dot\t%0.h, %1.b, %2.b
+  }
+  [(set_attr "sve_type" "sve_int_dot")]
+)
+
+(define_insn "@aarch64_<sur>dot_prod_lane<VNx8HI_ONLY:mode><VNx16QI_ONLY:mode>"
+  [(set (match_operand:VNx8HI_ONLY 0 "register_operand")
+       (plus:VNx8HI_ONLY
+         (unspec:VNx8HI_ONLY
+           [(match_operand:VNx16QI_ONLY 1 "register_operand")
+            (unspec:VNx16QI_ONLY
+              [(match_operand:VNx16QI_ONLY 2 "register_operand")
+               (match_operand:SI 3 "const_int_operand")]
+              UNSPEC_SVE_LANE_SELECT)]
+           DOTPROD)
+         (match_operand:VNx8HI_ONLY 4 "register_operand")))]
+  "TARGET_SVE2p3_OR_SME2p3"
+  {@ [ cons: =0 , 1 , 2 , 4 ; attrs: movprfx ]
+     [ w        , w , y , 0 ; *              ] <sur>dot\t%0.h, %1.b, %2.b[%3]
+     [ ?&w      , w , y , w ; yes            ] movprfx\t%0, 
%4\;<sur>dot\t%0.h, %1.b, %2.b[%3]
+  }
+  [(set_attr "sve_type" "sve_fp_mul")]
+)
 ;; -------------------------------------------------------------------------
 ;; ---- [FP] Multi-register operations
 ;; -------------------------------------------------------------------------
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 26db4958a80f..752f74386c6e 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -318,6 +318,9 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE ATTRIBUTE_UNUSED
 /* SVE2p2 instructions, enabled through +sve2p2.  */
 #define TARGET_SVE2p2 AARCH64_HAVE_ISA (SVE2p2)
 
+/* SVE2p3 instructions, enabled through +sve2p3.  */
+#define TARGET_SVE2p3 AARCH64_HAVE_ISA (SVE2p3)
+
 /* SME instructions, enabled through +sme.  Note that this does not
    imply anything about the state of PSTATE.SM; instructions that require
    SME and streaming mode should use TARGET_STREAMING instead.  */
@@ -351,6 +354,9 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE ATTRIBUTE_UNUSED
 /* SME2p2 instructions, enabled through +sme2p2.  */
 #define TARGET_SME2p2 AARCH64_HAVE_ISA (SME2p2)
 
+/* SME2p3 instructions, enabled through +sme2p3.  */
+#define TARGET_SME2p3 AARCH64_HAVE_ISA (SME2p3)
+
 /* Same with streaming mode enabled.  */
 #define TARGET_STREAMING_SME2 (TARGET_STREAMING && TARGET_SME2)
 
@@ -358,6 +364,8 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE ATTRIBUTE_UNUSED
 
 #define TARGET_STREAMING_SME2p2 (TARGET_STREAMING && AARCH64_HAVE_ISA (SME2p2))
 
+#define TARGET_STREAMING_SME2p3 (TARGET_STREAMING && AARCH64_HAVE_ISA (SME2p3))
+
 #define TARGET_SME_B16B16 AARCH64_HAVE_ISA (SME_B16B16)
 
 /* ARMv8.3-A features.  */
@@ -532,6 +540,8 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE ATTRIBUTE_UNUSED
    functions, since streaming mode itself implies SME.  */
 #define TARGET_SVE2p1_OR_SME (TARGET_SVE2p1 || TARGET_STREAMING)
 
+#define TARGET_SVE2p3_OR_SME2p3 (TARGET_SVE2p3 || TARGET_SME2p3)
+
 #define TARGET_SVE2p1_OR_SME2 \
   ((TARGET_SVE2p1 || TARGET_STREAMING) \
    && (TARGET_SME2 || TARGET_NON_STREAMING))
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5be3851a9296..322d0a726b9c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -21997,6 +21997,9 @@ Enable SVE2 sha3 instructions.  This also enables SVE2 
instructions.
 Enable SVE2.1 instructions.  This also enables SVE2 instructions.
 @item sve2p2
 Enable SVE2.2 instructions.  This also enables SVE2 and SVE2.1 instructions.
+@item sve2p3
+Enable SVE2.3 instructions.  This also enables SVE2 and SVE2.1 and
+SVE2.2 instructions.
 @item i8mm
 Enable 8-bit Integer Matrix Multiply instructions.  This also enables
 Advanced SIMD and floating-point instructions.  This option is enabled by
@@ -22060,6 +22063,9 @@ instructions.
 @item sme2p2
 Enable the Scalable Matrix Extension version 2.2.  This also enables SME2
 and SME2.1 instructions.
+@item sme2p3
+Enable the Scalable Matrix Extension version 2.3.  This also enables SME2,
+SME2.1 and SME2.2 instructions.
 @item fcma
 Enable the complex number SIMD extensions.
 @item jscvt
diff --git a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_lane_s16.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_lane_s16.c
new file mode 100644
index 000000000000..8e5d10339294
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_lane_s16.c
@@ -0,0 +1,96 @@
+/* { dg-do assemble { target aarch64_asm_sme2p3_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme2p3_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+#pragma GCC target "+sme2p3"
+
+/*
+** dot_lane_0_s16_tied1:
+**     sdot    z0\.h, z4\.b, z5\.b\[0\]
+**     ret
+*/
+TEST_DUAL_Z (dot_lane_0_s16_tied1, svint16_t, svint8_t,
+            z0 = svdot_lane_s16_s8 (z0, z4, z5, 0),
+            z0 = svdot_lane (z0, z4, z5, 0))
+
+/*
+** dot_lane_0_s16_tied2:
+**     mov     (z[0-9]+)\.d, z0\.d
+**     movprfx z0, z4
+**     sdot    z0\.h, \1\.b, z1\.b\[0\]
+**     ret
+*/
+TEST_DUAL_Z_REV (dot_lane_0_s16_tied2, svint16_t, svint8_t,
+                z0_res = svdot_lane_s16_s8 (z4, z0, z1, 0),
+                z0_res = svdot_lane (z4, z0, z1, 0))
+
+/*
+** dot_lane_0_s16_tied3:
+**     mov     (z[0-9]+)\.d, z0\.d
+**     movprfx z0, z4
+**     sdot    z0\.h, z1\.b, \1\.b\[0\]
+**     ret
+*/
+TEST_DUAL_Z_REV (dot_lane_0_s16_tied3, svint16_t, svint8_t,
+                z0_res = svdot_lane_s16_s8 (z4, z1, z0, 0),
+                z0_res = svdot_lane (z4, z1, z0, 0))
+
+/*
+** dot_lane_0_s16_untied:
+**     movprfx z0, z1
+**     sdot    z0\.h, z4\.b, z5\.b\[0\]
+**     ret
+*/
+TEST_DUAL_Z (dot_lane_0_s16_untied, svint16_t, svint8_t,
+            z0 = svdot_lane_s16_s8 (z1, z4, z5, 0),
+            z0 = svdot_lane (z1, z4, z5, 0))
+
+/*
+** dot_lane_1_s16:
+**     sdot    z0\.h, z4\.b, z5\.b\[1\]
+**     ret
+*/
+TEST_DUAL_Z (dot_lane_1_s16, svint16_t, svint8_t,
+            z0 = svdot_lane_s16_s8 (z0, z4, z5, 1),
+            z0 = svdot_lane (z0, z4, z5, 1))
+
+/*
+** dot_lane_2_s16:
+**     sdot    z0\.h, z4\.b, z5\.b\[2\]
+**     ret
+*/
+TEST_DUAL_Z (dot_lane_2_s16, svint16_t, svint8_t,
+            z0 = svdot_lane_s16_s8 (z0, z4, z5, 2),
+            z0 = svdot_lane (z0, z4, z5, 2))
+
+/*
+** dot_lane_3_s16:
+**     sdot    z0\.h, z4\.b, z5\.b\[3\]
+**     ret
+*/
+TEST_DUAL_Z (dot_lane_3_s16, svint16_t, svint8_t,
+            z0 = svdot_lane_s16_s8 (z0, z4, z5, 3),
+            z0 = svdot_lane (z0, z4, z5, 3))
+
+/*
+** dot_lane_z8_s16:
+**     str     d8, \[sp, -16\]!
+**     mov     (z[0-7])\.d, z8\.d
+**     sdot    z0\.h, z1\.b, \1\.b\[1\]
+**     ldr     d8, \[sp\], 16
+**     ret
+*/
+TEST_DUAL_LANE_REG (dot_lane_z8_s16, svint16_t, svint8_t, z8,
+                   z0 = svdot_lane_s16_s8 (z0, z1, z8, 1),
+                   z0 = svdot_lane (z0, z1, z8, 1))
+
+/*
+** dot_lane_z16_s16:
+**     mov     (z[0-7])\.d, z16\.d
+**     sdot    z0\.h, z1\.b, \1\.b\[1\]
+**     ret
+*/
+TEST_DUAL_LANE_REG (dot_lane_z16_s16, svint16_t, svint8_t, z16,
+                   z0 = svdot_lane_s16_s8 (z0, z1, z16, 1),
+                   z0 = svdot_lane (z0, z1, z16, 1))
diff --git a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_lane_u16.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_lane_u16.c
new file mode 100644
index 000000000000..8ad5dbb81156
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_lane_u16.c
@@ -0,0 +1,96 @@
+/* { dg-do assemble { target aarch64_asm_sme2p3_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme2p3_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+#pragma GCC target "+sme2p3"
+
+/*
+** dot_lane_0_u16_tied1:
+**     udot    z0\.h, z4\.b, z5\.b\[0\]
+**     ret
+*/
+TEST_DUAL_Z (dot_lane_0_u16_tied1, svuint16_t, svuint8_t,
+            z0 = svdot_lane_u16_u8 (z0, z4, z5, 0),
+            z0 = svdot_lane (z0, z4, z5, 0))
+
+/*
+** dot_lane_0_u16_tied2:
+**     mov     (z[0-9]+)\.d, z0\.d
+**     movprfx z0, z4
+**     udot    z0\.h, \1\.b, z1\.b\[0\]
+**     ret
+*/
+TEST_DUAL_Z_REV (dot_lane_0_u16_tied2, svuint16_t, svuint8_t,
+                z0_res = svdot_lane_u16_u8 (z4, z0, z1, 0),
+                z0_res = svdot_lane (z4, z0, z1, 0))
+
+/*
+** dot_lane_0_u16_tied3:
+**     mov     (z[0-9]+)\.d, z0\.d
+**     movprfx z0, z4
+**     udot    z0\.h, z1\.b, \1\.b\[0\]
+**     ret
+*/
+TEST_DUAL_Z_REV (dot_lane_0_u16_tied3, svuint16_t, svuint8_t,
+                z0_res = svdot_lane_u16_u8 (z4, z1, z0, 0),
+                z0_res = svdot_lane (z4, z1, z0, 0))
+
+/*
+** dot_lane_0_u16_untied:
+**     movprfx z0, z1
+**     udot    z0\.h, z4\.b, z5\.b\[0\]
+**     ret
+*/
+TEST_DUAL_Z (dot_lane_0_u16_untied, svuint16_t, svuint8_t,
+            z0 = svdot_lane_u16_u8 (z1, z4, z5, 0),
+            z0 = svdot_lane (z1, z4, z5, 0))
+
+/*
+** dot_lane_1_u16:
+**     udot    z0\.h, z4\.b, z5\.b\[1\]
+**     ret
+*/
+TEST_DUAL_Z (dot_lane_1_u16, svuint16_t, svuint8_t,
+            z0 = svdot_lane_u16_u8 (z0, z4, z5, 1),
+            z0 = svdot_lane (z0, z4, z5, 1))
+
+/*
+** dot_lane_2_u16:
+**     udot    z0\.h, z4\.b, z5\.b\[2\]
+**     ret
+*/
+TEST_DUAL_Z (dot_lane_2_u16, svuint16_t, svuint8_t,
+            z0 = svdot_lane_u16_u8 (z0, z4, z5, 2),
+            z0 = svdot_lane (z0, z4, z5, 2))
+
+/*
+** dot_lane_3_u16:
+**     udot    z0\.h, z4\.b, z5\.b\[3\]
+**     ret
+*/
+TEST_DUAL_Z (dot_lane_3_u16, svuint16_t, svuint8_t,
+            z0 = svdot_lane_u16_u8 (z0, z4, z5, 3),
+            z0 = svdot_lane (z0, z4, z5, 3))
+
+/*
+** dot_lane_z8_u16:
+**     str     d8, \[sp, -16\]!
+**     mov     (z[0-7])\.d, z8\.d
+**     udot    z0\.h, z1\.b, \1\.b\[1\]
+**     ldr     d8, \[sp\], 16
+**     ret
+*/
+TEST_DUAL_LANE_REG (dot_lane_z8_u16, svuint16_t, svuint8_t, z8,
+                   z0 = svdot_lane_u16_u8 (z0, z1, z8, 1),
+                   z0 = svdot_lane (z0, z1, z8, 1))
+
+/*
+** dot_lane_z16_u16:
+**     mov     (z[0-7])\.d, z16\.d
+**     udot    z0\.h, z1\.b, \1\.b\[1\]
+**     ret
+*/
+TEST_DUAL_LANE_REG (dot_lane_z16_u16, svuint16_t, svuint8_t, z16,
+                   z0 = svdot_lane_u16_u8 (z0, z1, z16, 1),
+                   z0 = svdot_lane (z0, z1, z16, 1))
diff --git a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_s16.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_s16.c
new file mode 100644
index 000000000000..be9883660939
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_s16.c
@@ -0,0 +1,47 @@
+/* { dg-do assemble { target aarch64_asm_sme2p3_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme2p3_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+#pragma GCC target "+sme2p3"
+
+/*
+** dot_s16_tied1:
+**     sdot    z0\.h, z4\.b, z5\.b
+**     ret
+*/
+TEST_DUAL_Z (dot_s16_tied1, svint16_t, svint8_t,
+            z0 = svdot_s16_s8 (z0, z4, z5),
+            z0 = svdot (z0, z4, z5))
+
+/*
+** dot_s16_tied2:
+**     mov     (z[0-9]+)\.d, z0\.d
+**     movprfx z0, z4
+**     sdot    z0\.h, \1\.b, z1\.b
+**     ret
+*/
+TEST_DUAL_Z_REV (dot_s16_tied2, svint16_t, svint8_t,
+                z0_res = svdot_s16_s8 (z4, z0, z1),
+                z0_res = svdot (z4, z0, z1))
+
+/*
+** dot_s16_tied3:
+**     mov     (z[0-9]+)\.d, z0\.d
+**     movprfx z0, z4
+**     sdot    z0\.h, z1\.b, \1\.b
+**     ret
+*/
+TEST_DUAL_Z_REV (dot_s16_tied3, svint16_t, svint8_t,
+                z0_res = svdot_s16_s8 (z4, z1, z0),
+                z0_res = svdot (z4, z1, z0))
+
+/*
+** dot_s16_untied:
+**     movprfx z0, z1
+**     sdot    z0\.h, z4\.b, z5\.b
+**     ret
+*/
+TEST_DUAL_Z (dot_s16_untied, svint16_t, svint8_t,
+            z0 = svdot_s16_s8 (z1, z4, z5),
+            z0 = svdot (z1, z4, z5))
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_u16.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_u16.c
new file mode 100644
index 000000000000..c4168495a698
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_u16.c
@@ -0,0 +1,47 @@
+/* { dg-do assemble { target aarch64_asm_sme2p3_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme2p3_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+#pragma GCC target "+sme2p3"
+
+/*
+** dot_u16_tied1:
+**     udot    z0\.h, z4\.b, z5\.b
+**     ret
+*/
+TEST_DUAL_Z (dot_u16_tied1, svuint16_t, svuint8_t,
+            z0 = svdot_u16_u8 (z0, z4, z5),
+            z0 = svdot (z0, z4, z5))
+
+/*
+** dot_u16_tied2:
+**     mov     (z[0-9]+)\.d, z0\.d
+**     movprfx z0, z4
+**     udot    z0\.h, \1\.b, z1\.b
+**     ret
+*/
+TEST_DUAL_Z_REV (dot_u16_tied2, svuint16_t, svuint8_t,
+                z0_res = svdot_u16_u8 (z4, z0, z1),
+                z0_res = svdot (z4, z0, z1))
+
+/*
+** dot_u16_tied3:
+**     mov     (z[0-9]+)\.d, z0\.d
+**     movprfx z0, z4
+**     udot    z0\.h, z1\.b, \1\.b
+**     ret
+*/
+TEST_DUAL_Z_REV (dot_u16_tied3, svuint16_t, svuint8_t,
+                z0_res = svdot_u16_u8 (z4, z1, z0),
+                z0_res = svdot (z4, z1, z0))
+
+/*
+** dot_u16_untied:
+**     movprfx z0, z1
+**     udot    z0\.h, z4\.b, z5\.b
+**     ret
+*/
+TEST_DUAL_Z (dot_u16_untied, svuint16_t, svuint8_t,
+            z0 = svdot_u16_u8 (z1, z4, z5),
+            z0 = svdot (z1, z4, z5))
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/dotproduct_intrinsicless.c 
b/gcc/testsuite/gcc.target/aarch64/sve2/dotproduct_intrinsicless.c
new file mode 100644
index 000000000000..82e2c2596b63
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve2/dotproduct_intrinsicless.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv9-a+sve2p3 -mautovec-preference=sve-only 
--param=aarch64-vect-unroll-limit=1" } */
+
+#include <stdint.h>
+#include <stddef.h>
+int16_t dot_s8_s8_to_s16(const int8_t *restrict a,
+                          const int8_t *restrict b,
+                          unsigned n) {
+  int16_t acc = 0;
+
+
+  for (unsigned i = 0; i < n; ++i)
+    acc += (int16_t)a[i] * (int16_t)b[i];
+
+  return acc;
+}
+
+uint16_t dot_u8_u8_to_u16(const uint8_t *restrict a,
+                          const uint8_t *restrict b,
+                          unsigned n) {
+  uint16_t acc = 0;
+
+  for (unsigned i = 0; i < n; ++i)
+    acc += (uint16_t)a[i] * (uint16_t)b[i];
+
+  return acc;
+}
+
+/* { dg-final { scan-assembler-times {\tsdot\tz[0-9]+.h, z[0-9]+\.b, 
z[0-9]+\.b} 1 } } */
+/* { dg-final { scan-assembler-times {\tudot\tz[0-9]+.h, z[0-9]+\.b, 
z[0-9]+\.b} 1 } } */
\ No newline at end of file
diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index ab6aab6f935d..c22033c47b8d 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -6815,6 +6815,23 @@ proc check_effective_target_aarch64_sve2p2_hw { } {
     }]
 }
 
+# Return true if this is an AArch64 target that can run SVE2.3 code.
+
+proc check_effective_target_aarch64_sve2p3_hw { } {
+    if { ![istarget aarch64*-*-*] } {
+       return 0
+    }
+    return [check_runtime aarch64_sve2p3_hw_available {
+       #pragma GCC target "+sve2p3"
+       int
+       main (void)
+       {
+         asm volatile ("sdot z0.h,z0.b,z1.b");
+         return 0;
+       }
+    }]
+}
+
 # Return true if this is an AArch64 target that can run SVE code and
 # if its SVE vectors have exactly BITS bits.
 
@@ -12991,6 +13008,7 @@ set exts {
     "sve-sha3" "f8f16mm" "f8f32mm" "sve-f16f32mm"
     "sme-f8f16" "sme-f8f32"
     "sme-b16b16" "sme-f16f16" "sme-i16i64" "sme" "sme2" "sme2p1" "sme2p2"
+    "sme2p3"
     "ssve-fp8dot2" "ssve-fp8dot4" "ssve-fp8fma" "sve-bfscale" "sme-lutv2"
     "ssve-fexpa" "ssve-bitperm" "ssve-aes"
 }
@@ -13039,6 +13057,16 @@ proc check_effective_target_aarch64_asm_sve2p2_ok { } {
     }
 }
 
+proc check_effective_target_aarch64_asm_sve2p3_ok { } {
+    if { [istarget aarch64*-*-*] } {
+       return [check_no_compiler_messages aarch64_sve2p3_assembler object {
+           __asm__ (".arch_extension sve2p3; sdot z0.h,z0.b,z1.b");
+       } "-march=armv8-a+sve2p3"]
+    } else {
+       return 0
+    }
+}
+
 proc check_effective_target_aarch64_small { } {
     if { [istarget aarch64*-*-*] } {
        return [check_no_compiler_messages aarch64_small object {

Reply via email to