[gcc r17-2751] aarch64: Add Support for SVE2p3/SME2p3 dot product intrinsics
Richard Ball via Gcc-cvs <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
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 {