Hi Richard,
> -----Original Message-----
> From: ricbal02 via Sourceware Forge <forge-bot+ricbal02@forge-
> stage.sourceware.org>
> Sent: 31 May 2026 12:16
> To: gcc-patches mailing list <[email protected]>
> Cc: Tamar Christina <[email protected]>; Richard Earnshaw
> <[email protected]>; [email protected]; Wilco Dijkstra
> <[email protected]>; Alex Coplan <[email protected]>; Alice
> Carlotti <[email protected]>
> Subject: [PATCH v1 1/2] aarch64: Add Support for SVE2p3/SME2p3 dot
> product intrinsics
>
> From: Richard Ball <[email protected]>
>
> This patch adds support for intrinsics which utilise the
> dot product instructions added in SVE2p3/SME2p3.
>
> gcc/ChangeLog:
>
> * config/aarch64/aarch64-sve-builtins-base.cc: Update impl.
> * config/aarch64/aarch64-sve-builtins-sve2.def
> (REQUIRED_EXTENSIONS): New function.
> (svdot): Likewise.
> (svdot_lane): Likewise.
> * config/aarch64/aarch64-sve-builtins.cc
> (TYPES_s_narrow_fsu_sve2p3): New type array.
> (s_narrow_fsu_sve2p3): Likewise.
> * config/aarch64/aarch64-sve2.md
> (<sur>dot_prodvnx8hivnx16qi): New pattern.
> (<sur>dot_prod_lanevnx8hivnx16qi): 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:
>
> * gcc.target/aarch64/dotproduct_intrinsicless.c: New test.
> * 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.
> ---
> .../aarch64/aarch64-sve-builtins-base.cc | 29 +++++-
> .../aarch64/aarch64-sve-builtins-sve2.def | 5 +
> gcc/config/aarch64/aarch64-sve-builtins.cc | 6 ++
> gcc/config/aarch64/aarch64-sve2.md | 35 +++++++
> gcc/config/aarch64/aarch64.h | 8 ++
> gcc/doc/invoke.texi | 4 +
> .../aarch64/dotproduct_intrinsicless.c | 30 ++++++
> .../aarch64/sme2/acle-asm/dot_lane_s16.c | 94 +++++++++++++++++++
> .../aarch64/sme2/acle-asm/dot_lane_u16.c | 94 +++++++++++++++++++
> .../aarch64/sme2/acle-asm/dot_s16.c | 45 +++++++++
> .../aarch64/sme2/acle-asm/dot_u16.c | 45 +++++++++
> 11 files changed, 391 insertions(+), 4 deletions(-)
> create mode 100644
> gcc/testsuite/gcc.target/aarch64/dotproduct_intrinsicless.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/sme2/acle-
> asm/dot_lane_s16.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/sme2/acle-
> asm/dot_lane_u16.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/sme2/acle-
> asm/dot_s16.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/sme2/acle-
> asm/dot_u16.c
>
> diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
> b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
> index 1fa7473283dc..212002574e8d 100644
> --- a/gcc/config/aarch64/aarch64-sve-builtins-base.cc
> +++ b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
> @@ -958,11 +958,23 @@ public:
> 0, e.result_mode (),
> GET_MODE (e.args[0]));
> else
> - icode = (e.type_suffix (0).float_p
> + {
> + if (e.type_suffix (0).element_bits > 16)
> + {
> + 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);
> + }
> + else
> + {
> + icode = (e.type_suffix (0).unsigned_p
> + ? CODE_FOR_udot_prodvnx8hivnx16qi
> + : CODE_FOR_sdot_prodvnx8hivnx16qi);
> + }
> + }
> +
> }
> return e.use_unpred_insn (icode);
> }
> @@ -989,10 +1001,19 @@ public:
> accumulator last. */
> e.rotate_inputs_left (0, 4);
> int unspec = unspec_for (e);
> - if (unspec == UNSPEC_FDOT)
> - icode = CODE_FOR_aarch64_fdot_prod_lanevnx4sfvnx8hf;
> + if (e.type_suffix (0).element_bits > 16)
> + {
> + if (unspec == UNSPEC_FDOT)
> + icode = CODE_FOR_aarch64_fdot_prod_lanevnx4sfvnx8hf;
> + else
> + icode = code_for_aarch64_dot_prod_lane (unspec, mode0,
> mode1);
> + }
> else
> - icode = code_for_aarch64_dot_prod_lane (unspec, mode0, mode1);
> + {
> + icode = (e.type_suffix (0).unsigned_p
> + ? CODE_FOR_udot_prod_lanevnx8hivnx16qi
> + : CODE_FOR_sdot_prod_lanevnx8hivnx16qi);
> + }
> }
> return e.use_exact_insn (icode);
> }
I think we can clean these up, especially since there are other dotprod variants
coming.
So instead of making the list of exceptions longer lets go through the
code_for_aarch64_dot_prod_lane and code_for_aarch64_dot_prod
helpers to find the optabs.
These are generates by the @ attribute syntax. So for instance to support
FDOT this would have done it
diff --git a/gcc/config/aarch64/aarch64-sve2.md
b/gcc/config/aarch64/aarch64-sve2.md
index 4dd01d63b68..20acf985c80 100644
--- a/gcc/config/aarch64/aarch64-sve2.md
+++ b/gcc/config/aarch64/aarch64-sve2.md
@@ -2896,6 +2896,26 @@ (define_insn "<sur>dot_prod_lanevnx8hivnx16qi"
}
[(set_attr "sve_type" "sve_fp_mul")]
)
+
+(define_insn "@aarch64_<sur>dot_prod_lane<VNx4SF_ONLY:mode><VNx8HF_ONLY:mode>"
+ [(set (match_operand:VNx4SF_ONLY 0 "register_operand")
+ (plus:VNx4SF_ONLY
+ (unspec:VNx4SF_ONLY
+ [(match_operand:VNx8HF_ONLY 1 "register_operand")
+ (unspec:VNx8HF_ONLY
+ [(match_operand:VNx8HF_ONLY 2 "register_operand")
+ (match_operand:SI 3 "const_int_operand")]
+ UNSPEC_SVE_LANE_SELECT)]
+ DORPROD_F_ONLY)
+ (match_operand:VNx4SF_ONLY 4 "register_operand")))]
+ "TARGET_SVE2p1_OR_SME2"
+ {@ [ cons: =0 , 1 , 2 , 4 ; attrs: movprfx ]
+ [ w , w , y , 0 ; * ] fdot\t%0.s, %1.h, %2.h[%3]
+ [ ?&w , w , y , w ; yes ] movprfx\t%0, %4\;fdot\t%0.s,
%1.h, %2.h[%3]
+ }
+ [(set_attr "sve_type" "sve_fp_mul")]
+)
;; -------------------------------------------------------------------------
;; ---- [FP] Multi-register operations
;; -------------------------------------------------------------------------
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index 0f689e85234..504d80b7fb9 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -3601,6 +3601,7 @@ (define_int_iterator DOTPROD [UNSPEC_SDOT UNSPEC_UDOT])
(define_int_iterator DOTPROD_I8MM [UNSPEC_USDOT UNSPEC_SUDOT])
(define_int_iterator DOTPROD_US_ONLY [UNSPEC_USDOT])
+(define_int_iterator DORPROD_F_ONLY [UNSPEC_FDOT])
(define_int_iterator FMAXMIN_UNS [UNSPEC_FMAX UNSPEC_FMIN
UNSPEC_FMAXNM UNSPEC_FMINNM])
@@ -4642,7 +4643,7 @@ (define_int_attr sur [(UNSPEC_SHADD "s") (UNSPEC_UHADD
"u")
(UNSPEC_SDOT "s") (UNSPEC_UDOT "u")
(UNSPEC_USDOT "us") (UNSPEC_SUDOT "su")
(UNSPEC_SMATMUL "s") (UNSPEC_UMATMUL "u")
- (UNSPEC_USMATMUL "us")
+ (UNSPEC_USMATMUL "us") (UNSPEC_FDOT "s")
])
(define_int_attr r [(UNSPEC_SQDMULH "") (UNSPEC_SQRDMULH "r")
--
This then allows us to simplify those expanders, so refactoring stuff to use @
we can clean these up.
> diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
> b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
> index a2ad77106748..63c1c27074ce 100644
> --- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
> +++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
> @@ -463,6 +463,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_fsu_sve2p3, none)
> +DEF_SVE_FUNCTION (svdot_lane, ternary_qq_or_011_lane,
> s_narrow_fsu_sve2p3, 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-sve-builtins.cc
> b/gcc/config/aarch64/aarch64-sve-builtins.cc
> index 99acd13edf84..04d7500845e3 100644
> --- a/gcc/config/aarch64/aarch64-sve-builtins.cc
> +++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
> @@ -636,6 +636,11 @@ CONSTEXPR const group_suffix_info
> group_suffixes[] = {
> #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_fsu_sve2p3(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)
> @@ -868,6 +873,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_fsu_sve2p3);
> 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-sve2.md
> b/gcc/config/aarch64/aarch64-sve2.md
> index 4f842a61d8b3..521029136fa9 100644
> --- a/gcc/config/aarch64/aarch64-sve2.md
> +++ b/gcc/config/aarch64/aarch64-sve2.md
> @@ -2861,6 +2861,41 @@
> [(set_attr "sve_type" "sve_int_dot")]
> )
>
> +;; Two-way dot-product SME2p3 || SVE2p3.
> +(define_insn "<sur>dot_prodvnx8hivnx16qi"
> + [(set (match_operand:VNx8HI 0 "register_operand")
> + (plus:VNx8HI
> + (unspec:VNx8HI
> + [(match_operand:VNx16QI 1 "register_operand")
> + (match_operand:VNx16QI 2 "register_operand")]
> + DOTPROD)
> + (match_operand:VNx8HI 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 "<sur>dot_prod_lanevnx8hivnx16qi"
> + [(set (match_operand:VNx8HI 0 "register_operand")
> + (plus:VNx8HI
> + (unspec:VNx8HI
> + [(match_operand:VNx16QI 1 "register_operand")
> + (unspec:VNx16QI
> + [(match_operand:VNx16QI 2 "register_operand")
> + (match_operand:SI 3 "const_int_operand")]
> + UNSPEC_SVE_LANE_SELECT)]
> + DOTPROD)
> + (match_operand:VNx8HI 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 5bd3379cb0db..1c8f9db81f30 100644
> --- a/gcc/config/aarch64/aarch64.h
> +++ b/gcc/config/aarch64/aarch64.h
> @@ -316,6 +316,8 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE
> ATTRIBUTE_UNUSED
> /* SVE2p2 instructions, enabled through +sve2p2. */
> #define TARGET_SVE2p2 AARCH64_HAVE_ISA (SVE2p2)
>
> +#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. */
> @@ -349,6 +351,8 @@ constexpr auto AARCH64_FL_DEFAULT_ISA_MODE
> ATTRIBUTE_UNUSED
> /* SME2p2 instructions, enabled through +sme2p2. */
> #define TARGET_SME2p2 AARCH64_HAVE_ISA (SME2p2)
>
> +#define TARGET_SME2p3 AARCH64_HAVE_ISA (SME2p3)
> +
> /* Same with streaming mode enabled. */
> #define TARGET_STREAMING_SME2 (TARGET_STREAMING &&
> TARGET_SME2)
>
> @@ -356,6 +360,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. */
> @@ -530,6 +536,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 09321ca5da95..e239503626c7 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -21968,6 +21968,8 @@ 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 instructions.
> @item tme
> Enable the Transactional Memory Extension.
> @item i8mm
> @@ -22033,6 +22035,8 @@ 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
> @item fcma
> Enable the complex number SIMD extensions.
> @item jscvt
> diff --git a/gcc/testsuite/gcc.target/aarch64/dotproduct_intrinsicless.c
> b/gcc/testsuite/gcc.target/aarch64/dotproduct_intrinsicless.c
> new file mode 100644
> index 000000000000..5fc3ae675afc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/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" } */
This needs to be in aarch64/sve2/ subfolder.
> +
> +#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 "sdot" } } */
> +/* { dg-final { scan-assembler "udot" } } */
> \ No newline at end of file
> 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..f51cba33e697
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_lane_s16.c
> @@ -0,0 +1,94 @@
> +/* { 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..f6f5b81dec39
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_lane_u16.c
> @@ -0,0 +1,94 @@
> +/* { 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..dd1b827cbba3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_s16.c
> @@ -0,0 +1,45 @@
> +/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
> +
> +#include "test_sme2_acle.h"
> +#pragma GCC target "+sme2p3"
> +
> +/*
> +** dot_f32_tied1:
I'm confused about the testnames, why f32? Given these are integers.
Should they be s32?
Speaking of f32, in your Adv. SIMD version of the patch you introduce the
two way FDOTs which already existed for SVE. But as I mentioned both
should be supported by the vectorizer.
Since you're adding the Adv. SIMD variants, lets fix that:
In optabs.def change
OPTAB_CD (sdot_prod_optab, "sdot_prod$I$a$b")
OPTAB_CD (udot_prod_optab, "udot_prod$I$a$b")
OPTAB_CD (usdot_prod_optab, "usdot_prod$I$a$b")
The sdot_prod_optab to drop the $I which restricts it to
integers. Note that the documentation in md.texi for
sdot_prod has already been updated to remove the integer
restriction.
Since dot product is a contraction, you then have to change
vect_recog_dot_prod_pattern in gcc/tree-vect-pattern.cc
to check
/* It's only valid to form FDOT with -ffp-contract=fast. */
if (flag_fp_contract_mode != FP_CONTRACT_FAST
&& FLOAT_TYPE_P (type))
return IFN_LAST;
as soon as type is available.
You can then use the sdot_optab for the floating point
variants and we can get auto-vectorizer support here.
This would then allow us to also auto-vectorize BF
and FP8 dotprod. I won't ask you to add support for
those, though I'd appreciate it if you did. They already
exist but the optabs in the backend need to have the
right name.
Thanks,
Tamar
> +** sdot z0\.h, z4\.b, z5\.b
> +** ret
> +*/
> +TEST_DUAL_Z (dot_f32_tied1, svint16_t, svint8_t,
> + z0 = svdot_s16_s8 (z0, z4, z5),
> + z0 = svdot (z0, z4, z5))
> +
> +/*
> +** dot_f32_tied2:
> +** mov (z[0-9]+)\.d, z0\.d
> +** movprfx z0, z4
> +** sdot z0\.h, \1\.b, z1\.b
> +** ret
> +*/
> +TEST_DUAL_Z_REV (dot_f32_tied2, svint16_t, svint8_t,
> + z0_res = svdot_s16_s8 (z4, z0, z1),
> + z0_res = svdot (z4, z0, z1))
> +
> +/*
> +** dot_f32_tied3:
> +** mov (z[0-9]+)\.d, z0\.d
> +** movprfx z0, z4
> +** sdot z0\.h, z1\.b, \1\.b
> +** ret
> +*/
> +TEST_DUAL_Z_REV (dot_f32_tied3, svint16_t, svint8_t,
> + z0_res = svdot_s16_s8 (z4, z1, z0),
> + z0_res = svdot (z4, z1, z0))
> +
> +/*
> +** dot_f32_untied:
> +** movprfx z0, z1
> +** sdot z0\.h, z4\.b, z5\.b
> +** ret
> +*/
> +TEST_DUAL_Z (dot_f32_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..3ea9fbfbcc31
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/dot_u16.c
> @@ -0,0 +1,45 @@
> +/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
> +
> +#include "test_sme2_acle.h"
> +#pragma GCC target "+sme2p3"
> +
> +/*
> +** dot_f32_tied1:
> +** udot z0\.h, z4\.b, z5\.b
> +** ret
> +*/
> +TEST_DUAL_Z (dot_f32_tied1, svuint16_t, svuint8_t,
> + z0 = svdot_u16_u8 (z0, z4, z5),
> + z0 = svdot (z0, z4, z5))
> +
> +/*
> +** dot_f32_tied2:
> +** mov (z[0-9]+)\.d, z0\.d
> +** movprfx z0, z4
> +** udot z0\.h, \1\.b, z1\.b
> +** ret
> +*/
> +TEST_DUAL_Z_REV (dot_f32_tied2, svuint16_t, svuint8_t,
> + z0_res = svdot_u16_u8 (z4, z0, z1),
> + z0_res = svdot (z4, z0, z1))
> +
> +/*
> +** dot_f32_tied3:
> +** mov (z[0-9]+)\.d, z0\.d
> +** movprfx z0, z4
> +** udot z0\.h, z1\.b, \1\.b
> +** ret
> +*/
> +TEST_DUAL_Z_REV (dot_f32_tied3, svuint16_t, svuint8_t,
> + z0_res = svdot_u16_u8 (z4, z1, z0),
> + z0_res = svdot (z4, z1, z0))
> +
> +/*
> +** dot_f32_untied:
> +** movprfx z0, z1
> +** udot z0\.h, z4\.b, z5\.b
> +** ret
> +*/
> +TEST_DUAL_Z (dot_f32_untied, svuint16_t, svuint8_t,
> + z0 = svdot_u16_u8 (z1, z4, z5),
> + z0 = svdot (z1, z4, z5))
> \ No newline at end of file
> --
> 2.54.0