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);
}
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" } */
+
+#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:
+** 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