On Fri, Jun 26, 2026 at 12:49:08PM +0000, Sivan Shani wrote:
> Add ACLE support for the SVE AES2 multi-vector AES indexed
> instructions and the 128-bit PMULL/PMLAL pair forms.
>
> This adds builtin shapes and expanders for svaese_lane, svaesd_lane,
> svaesemc_lane, svaesdimc_lane, svpmull_pair and svpmlal_pair, together
> with the corresponding RTL patterns and tests. Also add preprocessor
> feature macros for SVE AES2 and SSVE AES.
This is looking fairly good, although I still have various small comments
below.
>
> gcc/
> * config/aarch64/aarch64-c.cc (aarch64_update_cpp_builtins): Define
> __ARM_FEATURE_SVE_AES2 and __ARM_FEATURE_SSVE_AES.
> * config/aarch64/aarch64-sve-builtins-functions.h
> (unspec_based_aes_lane_function): New typedef.
> (unspec_based_aes_lane_mc_function): Likewise.
> * config/aarch64/aarch64-sve-builtins-shapes.cc
> (binary_tuple_uint64_n_def): New shape.
> (ternary_tuple_uint64_n_def): Likewise.
> (binary_aes_lane_def): Likewise.
> * config/aarch64/aarch64-sve-builtins-shapes.h: Declare new shapes.
> * config/aarch64/aarch64-sve-builtins-sve2.cc: Add new function
> entries.
> * config/aarch64/aarch64-sve-builtins-sve2.def: Add new ACLE
> builtin definitions.
> * config/aarch64/aarch64-sve-builtins-sve2.h: Declare new functions.
> * config/aarch64/aarch64-sve2.md: Add PMULL/PMLAL pair and AES
> indexed multi-vector patterns.
> * config/aarch64/aarch64.h (TARGET_SVE_AES2): Define.
> * config/aarch64/aarch64.md (UNSPEC_SSVE_LANE_SELECT): New unspec.
> * config/aarch64/iterators.md: Add iterators and attrs for new
> patterns.
> * config/aarch64/predicates.md (const_0_to_3_operand): New predicate.
>
> gcc/testsuite/
> * gcc.target/aarch64/pragma_cpp_predefs_5.c: Test new feature macros.
> * gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
> (TEST_XN_INDEXED): New macro.
> * gcc.target/aarch64/sve2/acle/asm/aesd_lane_u8.c: New test.
> * gcc.target/aarch64/sve2/acle/asm/aesdimc_lane_u8.c: New test.
> * gcc.target/aarch64/sve2/acle/asm/aese_lane_u8.c: New test.
> * gcc.target/aarch64/sve2/acle/asm/aesemc_lane_u8.c: New test.
> * gcc.target/aarch64/sve2/acle/asm/pmlal_pair_u64.c: New test.
> * gcc.target/aarch64/sve2/acle/asm/pmull_pair_u64.c: New test.
> * lib/target-supports.exp: Add sve-aes2 assembler probe.
> ---
> gcc/config/aarch64/aarch64-c.cc | 4 +
> .../aarch64/aarch64-sve-builtins-functions.h | 5 +
> .../aarch64/aarch64-sve-builtins-shapes.cc | 143 ++++++++++++++++++
> .../aarch64/aarch64-sve-builtins-shapes.h | 3 +
> .../aarch64/aarch64-sve-builtins-sve2.cc | 6 +
> .../aarch64/aarch64-sve-builtins-sve2.def | 10 ++
> .../aarch64/aarch64-sve-builtins-sve2.h | 6 +
> gcc/config/aarch64/aarch64-sve2.md | 86 +++++++++++
> gcc/config/aarch64/aarch64.h | 2 +
> gcc/config/aarch64/aarch64.md | 3 +
> gcc/config/aarch64/iterators.md | 14 ++
> gcc/config/aarch64/predicates.md | 4 +
> .../gcc.target/aarch64/pragma_cpp_predefs_5.c | 22 +++
> .../aarch64/sve/acle/asm/test_sve_acle.h | 16 ++
> .../aarch64/sve2/acle/asm/aesd_lane_u8.c | 67 ++++++++
> .../aarch64/sve2/acle/asm/aesdimc_lane_u8.c | 67 ++++++++
> .../aarch64/sve2/acle/asm/aese_lane_u8.c | 67 ++++++++
> .../aarch64/sve2/acle/asm/aesemc_lane_u8.c | 67 ++++++++
> .../aarch64/sve2/acle/asm/pmlal_pair_u64.c | 69 +++++++++
> .../aarch64/sve2/acle/asm/pmull_pair_u64.c | 45 ++++++
> gcc/testsuite/lib/target-supports.exp | 4 +-
> 21 files changed, 708 insertions(+), 2 deletions(-)
> create mode 100644
> gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesd_lane_u8.c
> create mode 100644
> gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesdimc_lane_u8.c
> create mode 100644
> gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aese_lane_u8.c
> create mode 100644
> gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesemc_lane_u8.c
> create mode 100644
> gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmlal_pair_u64.c
> create mode 100644
> gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmull_pair_u64.c
>
> diff --git a/gcc/config/aarch64/aarch64-c.cc b/gcc/config/aarch64/aarch64-c.cc
> index 4d83d5f0184..86ba2214e88 100644
> --- a/gcc/config/aarch64/aarch64-c.cc
> +++ b/gcc/config/aarch64/aarch64-c.cc
> @@ -228,6 +228,10 @@ aarch64_update_cpp_builtins (cpp_reader *pfile)
> aarch64_def_or_undef (AARCH64_HAVE_ISA (SVE2), "__ARM_FEATURE_SVE2",
> pfile);
> aarch64_def_or_undef (AARCH64_HAVE_ISA (SVE2) && AARCH64_HAVE_ISA
> (SVE_AES),
> "__ARM_FEATURE_SVE2_AES", pfile);
> + aarch64_def_or_undef (AARCH64_HAVE_ISA (SVE_AES2),
> "__ARM_FEATURE_SVE_AES2",
> + pfile);
> + aarch64_def_or_undef (AARCH64_HAVE_ISA (SSVE_AES),
> "__ARM_FEATURE_SSVE_AES",
> + pfile);
> aarch64_def_or_undef (AARCH64_HAVE_ISA (SVE_BITPERM)
> && AARCH64_HAVE_ISA (SVE2),
> "__ARM_FEATURE_SVE2_BITPERM", pfile);
> diff --git a/gcc/config/aarch64/aarch64-sve-builtins-functions.h
> b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
> index 8fd7a8fef52..7a62c05e08b 100644
> --- a/gcc/config/aarch64/aarch64-sve-builtins-functions.h
> +++ b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
> @@ -397,6 +397,11 @@ typedef
> unspec_based_function_exact_insn<code_for_aarch64_sve_sub>
> typedef unspec_based_function_exact_insn<code_for_aarch64_sve_sub_lane>
> unspec_based_sub_lane_function;
>
> +typedef unspec_based_function_exact_insn<code_for_aarch64_sve2_aes_lane>
> + unspec_based_aes_lane_function;
> +typedef unspec_based_function_exact_insn<code_for_aarch64_sve2_aes_lane_mc>
> + unspec_based_aes_lane_mc_function;
> +
> /* A function that has conditional and unconditional forms, with both
> forms being associated with a single unspec each. */
> class cond_or_uncond_unspec_function : public function_base
> diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
> b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
> index 8611f20f6e8..08f8d6b4ad5 100644
> --- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
> +++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
> @@ -1502,6 +1502,149 @@ struct binary_int_opt_single_n_def : public
> overloaded_base<0>
> };
> SHAPE (binary_int_opt_single_n)
>
> +/* sv<t0>x<g>_t svfoo[_t0_g](sv<t0>_t, sv<t0>_t)
> + sv<t0>x<g>_t svfoo[_n_t0_g](sv<t0>_t, <t0>_t). */
> +struct binary_tuple_uint64_n_def : public overloaded_base<0>
This doesn't follow the naming convention described in
aarch64-sve-builtins-shapes.h. I think a better name would be
"binary_to_pair_opt_n_def".
> +{
> + bool explicit_group_suffix_p () const override { return false; }
> +
> + void
> + build (function_builder &b, const function_group_info &group) const
> override
> + {
> + b.add_overloaded_functions (group, MODE_none);
> + build_all (b, "t0,v0,v0", group, MODE_none);
> + build_all (b, "t0,v0,s0", group, MODE_n);
> + }
> +
> + tree
> + resolve (function_resolver &r) const override
> + {
> + if (!r.check_num_arguments (2))
> + return error_mark_node;
> +
> + if (!r.require_vector_type (0, VECTOR_TYPE_svuint64_t))
> + return error_mark_node;
> +
> + mode_suffix_index mode;
> + if (r.scalar_argument_p (1))
> + {
> + if (!r.require_scalar_type (1, "uint64_t"))
> + return error_mark_node;
> + mode = MODE_n;
> + }
> + else
> + {
> + if (!r.require_vector_type (1, VECTOR_TYPE_svuint64_t))
> + return error_mark_node;
> + mode = MODE_none;
> + }
> +
> + return r.resolve_to (mode, { TYPE_SUFFIX_u64, 2 });
Can this function (and the next one) be simplified by using
finish_opt_n_resolution? We also probably don't need to hardcode "uint64_t"
here, since we can deduce the type from the "d_unsigned".
> + }
> +};
> +SHAPE (binary_tuple_uint64_n)
> +
> +/* sv<t0>x<g>_t svfoo[_t0_g](sv<t0>x<g>_t, sv<t0>_t, sv<t0>_t)
> + sv<t0>x<g>_t svfoo[_n_t0_g](sv<t0>x<g>_t, sv<t0>_t, <t0>_t). */
> +struct ternary_tuple_uint64_n_def : public overloaded_base<0>
Similarly, how about "ternary_to_pair_opt_n"?
> +{
> + bool explicit_group_suffix_p () const override { return false; }
> +
> + void
> + build (function_builder &b, const function_group_info &group) const
> override
> + {
> + b.add_overloaded_functions (group, MODE_none);
> + build_all (b, "t0,t0,v0,v0", group, MODE_none);
> + build_all (b, "t0,t0,v0,s0", group, MODE_n);
> + }
> +
> + tree
> + resolve (function_resolver &r) const override
> + {
> + if (!r.check_num_arguments (3))
> + return error_mark_node;
> +
> + sve_type type = r.infer_sve_type (0);
> + if (!type)
> + return error_mark_node;
> +
> + if (type.num_vectors != 2)
> + {
> + r.report_incorrect_num_vectors (0, type, 2);
> + return error_mark_node;
> + }
> +
> + if (!r.require_vector_type (1, VECTOR_TYPE_svuint64_t))
> + return error_mark_node;
> +
> + mode_suffix_index mode;
> + if (r.scalar_argument_p (2))
> + {
> + if (!r.require_scalar_type (2, "uint64_t"))
> + return error_mark_node;
> + mode = MODE_n;
> + }
> + else
> + {
> + if (!r.require_vector_type (2, VECTOR_TYPE_svuint64_t))
> + return error_mark_node;
> + mode = MODE_none;
> + }
> +
> + return r.resolve_to (mode, type);
> + }
> +};
> +SHAPE (ternary_tuple_uint64_n)
> +
> +/* svuint8x2_t svaes<...>_lane[_u8_x2] (svuint8x2_t zdn, svuint8_t zm,
> uint64_t
> + index);
> + and
> + svuint8x4_t svaes<...>_lane[_u8_x4] (svuint8x4_t zdn, svuint8_t zm,
> uint64_t
> + index);
> + When index is in range[0-3]
> +*/
> +struct binary_aes_lane_def : public overloaded_base<0>
> +{
> + bool explicit_group_suffix_p () const override { return false; }
> +
> + void
> + build (function_builder &b, const function_group_info &group) const
> override
> + {
> + b.add_overloaded_functions (group, MODE_none);
> + build_all (b, "t0,t0,v0,su64", group, MODE_none);
> + }
> +
> + tree
> + resolve (function_resolver &r) const override
> + {
> + if (!r.check_num_arguments (3))
> + return error_mark_node;
> +
> + sve_type type = r.infer_sve_type (0);
> + if (!type)
> + return error_mark_node;
> +
> + if (type.num_vectors != 2 && type.num_vectors != 4)
> + return error_mark_node;
Is this check necessary?
> +
> + if (!r.require_vector_type (1, VECTOR_TYPE_svuint8_t))
> + return error_mark_node;
> +
> + if (!r.require_integer_immediate (2))
> + return error_mark_node;
All of these checks could be done as a single if condition - for example, see
the implementation of shift_right_imm_narrowxn_def.resolve.
> +
> + return r.resolve_to (MODE_none, type);
> + }
> +
> + bool
> + check (function_checker &c) const override
> + {
> + return c.require_immediate_lane_index (2, 0, 4);
> + }
> +};
> +SHAPE (binary_aes_lane)
> +
> +
> /* sv<t0>_t svfoo_<t0>(sv<t0>_t, sv<t0>_t, uint64_t)
>
> where the final argument is an integer constant expression in the
> diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.h
> b/gcc/config/aarch64/aarch64-sve-builtins-shapes.h
> index b2c927542a8..df85f0688c5 100644
> --- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.h
> +++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.h
> @@ -85,6 +85,7 @@ namespace aarch64_sve
> extern const function_shape *const binary_int_opt_single_n;
> extern const function_shape *const binary_lane;
> extern const function_shape *const binary_long_lane;
> + extern const function_shape *const binary_aes_lane;
> extern const function_shape *const binary_long_opt_n;
> extern const function_shape *const binary_n;
> extern const function_shape *const binary_narrowb_opt_n;
> @@ -95,6 +96,7 @@ namespace aarch64_sve
> extern const function_shape *const binary_rotate;
> extern const function_shape *const binary_scalar;
> extern const function_shape *const binary_single;
> + extern const function_shape *const binary_tuple_uint64_n;
> extern const function_shape *const binary_to_uint;
> extern const function_shape *const binary_uint;
> extern const function_shape *const binary_uint_n;
> @@ -237,6 +239,7 @@ namespace aarch64_sve
> extern const function_shape *const ternary_uintq_intq;
> extern const function_shape *const ternary_uintq_intq_lane;
> extern const function_shape *const ternary_uintq_intq_opt_n;
> + extern const function_shape *const ternary_tuple_uint64_n;
> extern const function_shape *const tmad;
> extern const function_shape *const unary;
> extern const function_shape *const unary_convert;
> diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
> b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
> index 5ea08056ae3..ee67d15e51a 100644
> --- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
> +++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
> @@ -1045,6 +1045,10 @@ FUNCTION (svaesd, fixed_insn_function,
> (CODE_FOR_aarch64_sve2_aesd))
> FUNCTION (svaese, fixed_insn_function, (CODE_FOR_aarch64_sve2_aese))
> FUNCTION (svaesimc, fixed_insn_function, (CODE_FOR_aarch64_sve2_aesimc))
> FUNCTION (svaesmc, fixed_insn_function, (CODE_FOR_aarch64_sve2_aesmc))
> +FUNCTION (svaese_lane, unspec_based_aes_lane_function, (-1, UNSPEC_AESE, -1))
> +FUNCTION (svaesd_lane, unspec_based_aes_lane_function, (-1, UNSPEC_AESD, -1))
> +FUNCTION (svaesemc_lane, unspec_based_aes_lane_mc_function, (-1,
> UNSPEC_AESE, -1))
> +FUNCTION (svaesdimc_lane, unspec_based_aes_lane_mc_function, (-1,
> UNSPEC_AESD, -1))
> FUNCTION (svamax, faminmaximpl, (UNSPEC_COND_FAMAX, UNSPEC_FAMAX))
> FUNCTION (svamin, faminmaximpl, (UNSPEC_COND_FAMIN, UNSPEC_FAMIN))
> FUNCTION (svandqv, reduction, (UNSPEC_ANDQV, UNSPEC_ANDQV, -1))
> @@ -1172,6 +1176,8 @@ FUNCTION (svpmullb, unspec_based_function, (-1,
> UNSPEC_PMULLB, -1))
> FUNCTION (svpmullb_pair, unspec_based_function, (-1, UNSPEC_PMULLB_PAIR, -1))
> FUNCTION (svpmullt, unspec_based_function, (-1, UNSPEC_PMULLT, -1))
> FUNCTION (svpmullt_pair, unspec_based_function, (-1, UNSPEC_PMULLT_PAIR, -1))
> +FUNCTION (svpmull_pair, fixed_insn_function,
> (CODE_FOR_aarch64_sve_pmull_pair))
> +FUNCTION (svpmlal_pair, fixed_insn_function,
> (CODE_FOR_aarch64_sve_pmlal_pair))
> FUNCTION (svpsel_lane, svpsel_lane_impl,)
> FUNCTION (svqabs, rtx_code_function, (SS_ABS, UNKNOWN, UNKNOWN))
> FUNCTION (svqcadd, svqcadd_impl,)
> diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
> b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
> index 16524cfedab..cf7fd6e5e17 100644
> --- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
> +++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.def
> @@ -206,6 +206,16 @@ DEF_SVE_FUNCTION (svpmullb_pair, binary_opt_n,
> d_unsigned, none)
> DEF_SVE_FUNCTION (svpmullt_pair, binary_opt_n, d_unsigned, none)
> #undef REQUIRED_EXTENSIONS
>
> +#define REQUIRED_EXTENSIONS streaming_compatible (AARCH64_FL_SVE_AES2, \
> + AARCH64_FL_SSVE_AES)
> +DEF_SVE_FUNCTION_GS (svaese_lane, binary_aes_lane, b_unsigned, x24, none)
> +DEF_SVE_FUNCTION_GS (svaesd_lane, binary_aes_lane, b_unsigned, x24, none)
> +DEF_SVE_FUNCTION_GS (svaesemc_lane, binary_aes_lane, b_unsigned, x24, none)
> +DEF_SVE_FUNCTION_GS (svaesdimc_lane, binary_aes_lane, b_unsigned, x24, none)
> +DEF_SVE_FUNCTION_GS (svpmull_pair, binary_tuple_uint64_n, d_unsigned, x2,
> none)
> +DEF_SVE_FUNCTION_GS (svpmlal_pair, ternary_tuple_uint64_n, d_unsigned, x2,
> none)
> +#undef REQUIRED_EXTENSIONS
> +
> #define REQUIRED_EXTENSIONS streaming_compatible (AARCH64_FL_SVE2 \
> | AARCH64_FL_SVE_BITPERM, \
> AARCH64_FL_SSVE_BITPERM)
> diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.h
> b/gcc/config/aarch64/aarch64-sve-builtins-sve2.h
> index b2f2698b880..48f2e80baae 100644
> --- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.h
> +++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.h
> @@ -45,6 +45,10 @@ namespace aarch64_sve
> extern const function_base *const svaese;
> extern const function_base *const svaesimc;
> extern const function_base *const svaesmc;
> + extern const function_base *const svaese_lane;
> + extern const function_base *const svaesd_lane;
> + extern const function_base *const svaesemc_lane;
> + extern const function_base *const svaesdimc_lane;
> extern const function_base *const svandqv;
> extern const function_base *const svbcax;
> extern const function_base *const svbdep;
> @@ -143,6 +147,8 @@ namespace aarch64_sve
> extern const function_base *const svpmullb_pair;
> extern const function_base *const svpmullt;
> extern const function_base *const svpmullt_pair;
> + extern const function_base *const svpmull_pair;
> + extern const function_base *const svpmlal_pair;
> extern const function_base *const svpsel_lane;
> extern const function_base *const svqabs;
> extern const function_base *const svqcadd;
> diff --git a/gcc/config/aarch64/aarch64-sve2.md
> b/gcc/config/aarch64/aarch64-sve2.md
> index 4bf9710519f..ca3400ecefc 100644
> --- a/gcc/config/aarch64/aarch64-sve2.md
> +++ b/gcc/config/aarch64/aarch64-sve2.md
> @@ -4100,6 +4100,43 @@ (define_insn "@aarch64_sve_<optab><mode>"
> [(set_attr "sve_type" "sve_int_pmul")]
> )
>
> +;; Polynomial multiply corresponding D elements and return the widened Q
> +;; results as a pair of consecutive destination vectors.
> +;; PMULL { <Zd1>.Q-<Zd2>.Q }, <Zn>.D, <Zm>.D
> +;; <Zd1> must be a multiple of 2 (0, 2, ..., 30)
> +;; <Zd2> must be must be Zdn1 + 1
> +;; <Zn> (0-31) scalable vector
> +;; <Zm> (0-31) scalable vector -or- an uint64 (broadcast to a vector)
The last line of this comment is wrong, because broadcasting to a vector is
handled elsewhere. It also feels unnecessarily verbose, so perhaps we can just
remove the detailed description of the operands?
> +(define_insn "aarch64_sve_pmull_pair"
> + [(set (match_operand:VNx4DI 0 "aligned_register_operand" "=Uw2")
> + (unspec:VNx4DI
> + [(match_operand:VNx2DI 1 "register_operand" "w")
> + (match_operand:VNx2DI 2 "register_operand" "w")]
> + UNSPEC_PMULL_PAIR))]
> + "TARGET_SVE_AES2"
> + "pmull\t{%S0.q - %T0.q}, %1.d, %2.d"
> + [(set_attr "sve_type" "sve_int_pmul")]
> +)
> +
> +;; Polynomial multiply corresponding D elements and XOR-accumulate the
> widened
> +;; Q results into a pair of consecutive destination vectors.
> +;; PMLAL { <Zda1>.Q-<Zda2>.Q }, <Zn>.D, <Zm>.D
> +;; <Zda1> must be a multiple of 2 (0, 2, ..., 30)
> +;; <Zda2> must be must be Zdn1 + 1
> +;; <Zn> (0-31) scalable vector
> +;; <Zm> (0-31) scalable vector -or- an uint64 (broadcast to a vector)
> +(define_insn "aarch64_sve_pmlal_pair"
> + [(set (match_operand:VNx4DI 0 "aligned_register_operand" "=Uw2")
> + (unspec:VNx4DI
> + [(match_operand:VNx4DI 1 "aligned_register_operand" "0")
> + (match_operand:VNx2DI 2 "register_operand" "w")
> + (match_operand:VNx2DI 3 "register_operand" "w")]
> + UNSPEC_PMLAL_PAIR))]
> + "TARGET_SVE_AES2"
> + "pmlal\t{%S0.q - %T0.q}, %2.d, %3.d"
> + [(set_attr "sve_type" "sve_int_pmul")]
> +)
> +
> ;; =========================================================================
> ;; == Comparisons and selects
> ;; =========================================================================
> @@ -4705,6 +4742,10 @@ (define_insn "@aarch64_sve_luti<LUTI_BITS><mode>"
> ;; - AESE
> ;; - AESIMC
> ;; - AESMC
> +;; - AESD (indexed, two registers and four registers)
> +;; - AESE (indexed, two registers and four registers)
> +;; - AESEMC (indexed, two registers and four registers)
> +;; - AESDIMC (indexed, two registers and four registers)
> ;; -------------------------------------------------------------------------
>
> ;; AESD and AESE.
> @@ -4766,6 +4807,51 @@ (define_insn "*aarch64_sve2_aesd_fused"
> (set_attr "length" "8")]
> )
>
> +;; AESE and AESD, indexed, two registers and four registers.
> +;; AES<E/D> { <Zdn1>.B-<Zdn(2/4)>.B }, { <Zdn1>.B-<Zdn(2/4)>.B },
> <Zm>.Q[<index>]
> +;; <Zdn1> must be a multiple of 2 (0, 2, ..., 30) or 4 (0, 4, ..., 28)
> +;; <Zdn4> must be must be Zdn1 + 1 or Zdn1 + 3
This line doesn't quite make sense. However, I think you could just drop this
detail from the comment.
> +;; <Zm> (0-31)
> +;; <Index> (0-3)
> +
> +(define_insn "@aarch64_sve2_aes<aes_op>_lane<mode>"
> + [(set (match_operand:SVE_QIx24 0 "aligned_register_operand"
> "=Uw<vector_count>")
> + (unspec:SVE_QIx24
> + [(xor:SVE_QIx24
> + (match_operand:SVE_QIx24 1 "aligned_register_operand" "0")
> + (unspec:SVE_QIx24
> + [(match_operand:VNx16QI 2 "register_operand" "w")
> + (match_operand:SI 3 "const_0_to_3_operand")]
> + UNSPEC_SSVE_LANE_SELECT))]
> + CRYPTO_AES))]
> + "TARGET_SVE_AES2"
> + "aes<aes_op>\t%0, %0, %2.q[%3]"
> + [(set_attr "type" "crypto_aese")]
> +)
> +
> +;; AESEMC and AESDIMC, indexed, two registers and four registers.
> +;; AESEMC/AESDIMC { <Zdn1>.B-<Zdn (2/4)>.B }, { <Zdn1>.B-<Zdn (2/4)>.B },
> <Zm>.Q[<index>]
> +;; <Zdn1> must be a multiple of 2 (0, 2, ..., 30)
> +;; <Zdn2> must be Zdn1 + 1 or Zdn1 + 3
> +;; <Zm> (0-31)
> +
> +(define_insn "@aarch64_sve2_aes<CRYPTO_AES>_lane_mc<mode>"
> + [(set (match_operand:SVE_QIx24 0 "aligned_register_operand"
> "=Uw<vector_count>")
> + (unspec:SVE_QIx24
> + [(unspec:SVE_QIx24
> + [(xor:SVE_QIx24
> + (match_operand:SVE_QIx24 1 "aligned_register_operand" "0")
> + (unspec:SVE_QIx24
> + [(match_operand:VNx16QI 2 "register_operand" "w")
> + (match_operand:SI 3 "const_0_to_3_operand")]
> + UNSPEC_SSVE_LANE_SELECT))]
> + CRYPTO_AES)]
> + <aesemc_outer_unspec>))]
> + "TARGET_SVE_AES2"
> + "aes<aesemc_op>\t%0, %0, %2.q[%3]"
> + [(set_attr "type" "crypto_aesmc")]
> +)
> +
> ;; -------------------------------------------------------------------------
> ;; ---- Optional SHA-3 extensions
> ;; -------------------------------------------------------------------------
> diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
> index 83cbe46fed8..c0a8ab0bd00 100644
> --- a/gcc/config/aarch64/aarch64.h
> +++ b/gcc/config/aarch64/aarch64.h
> @@ -300,6 +300,8 @@ For:
> && (AARCH64_HAVE_ISA (SSVE_AES) \
> || TARGET_NON_STREAMING))
>
> +#define TARGET_SVE_AES2 (TARGET_SVE_AES && AARCH64_HAVE_ISA (SVE_AES2))
> +
> /* SVE BITPERM instructions, enabled through +sve-bitperm+sve2 for
> non-streaming
> and +ssve-bitperm for streaming. */
> #define TARGET_SVE_BITPERM (AARCH64_HAVE_ISA (SVE_BITPERM) \
> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
> index d8c8c73a632..841c563da21 100644
> --- a/gcc/config/aarch64/aarch64.md
> +++ b/gcc/config/aarch64/aarch64.md
> @@ -397,6 +397,9 @@ (define_c_enum "unspec" [
> ;; Represents an SVE-style lane index, in which the indexing applies
> ;; within the containing 128-bit block.
> UNSPEC_SVE_LANE_SELECT
> + ;; Represents an SVE-style lane index, in which the indexing applies
> + ;; within the containing 512-bit block.
> + UNSPEC_SSVE_LANE_SELECT
> UNSPEC_SVE_CNT_PAT
> UNSPEC_SVE_PREFETCH
> UNSPEC_SVE_PREFETCH_GATHER
> diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
> index f65d85be1f5..92ca35b1ba7 100644
> --- a/gcc/config/aarch64/iterators.md
> +++ b/gcc/config/aarch64/iterators.md
> @@ -708,6 +708,9 @@ (define_mode_iterator SVE_SI [VNx2SI VNx4SI])
>
> (define_mode_iterator SVE_DIx24 [VNx4DI VNx8DI])
>
> +;; SVE integer vector modes with 2 and 4 vectors of 8-bit elements.
> +(define_mode_iterator SVE_QIx24 [VNx32QI VNx64QI])
> +
> ;; SVE modes with 2 or 4 elements.
> (define_mode_iterator SVE_24 [VNx2QI VNx2HI VNx2HF VNx2BF VNx2SI VNx2SF
> VNx2DI VNx2DF
> @@ -889,6 +892,8 @@ (define_c_enum "unspec"
> UNSPEC_SQDMULH ; Used in aarch64-simd.md.
> UNSPEC_SQRDMULH ; Used in aarch64-simd.md.
> UNSPEC_PMUL ; Used in aarch64-simd.md.
> + UNSPEC_PMULL_PAIR ; Used in aarch64-sve2.md.
> + UNSPEC_PMLAL_PAIR ; Used in aarch64-sve2.md.
> UNSPEC_FMULX ; Used in aarch64-simd.md.
> UNSPEC_USQADD ; Used in aarch64-simd.md.
> UNSPEC_SUQADD ; Used in aarch64-simd.md.
> @@ -940,6 +945,8 @@ (define_c_enum "unspec"
> UNSPEC_AESD ; Used in aarch64-simd.md.
> UNSPEC_AESMC ; Used in aarch64-simd.md.
> UNSPEC_AESIMC ; Used in aarch64-simd.md.
> + UNSPEC_AESEMC ; Used in aarch64-sve2.md.
> + UNSPEC_AESDIMC ; Used in aarch64-sve2.md.
These are unused, so should be dropped.
> UNSPEC_SHA1C ; Used in aarch64-simd.md.
> UNSPEC_SHA1M ; Used in aarch64-simd.md.
> UNSPEC_SHA1P ; Used in aarch64-simd.md.
> @@ -3678,6 +3685,13 @@ (define_int_iterator CRC [UNSPEC_CRC32B UNSPEC_CRC32H
> UNSPEC_CRC32W
>
> (define_int_iterator CRYPTO_AES [UNSPEC_AESE UNSPEC_AESD])
> (define_int_iterator CRYPTO_AESMC [UNSPEC_AESMC UNSPEC_AESIMC])
> +(define_int_attr aesemc_op [(UNSPEC_AESE "emc") (UNSPEC_AESD "dimc")])
How about "aes_fused_op"?
(In any case, the "e" in "aesemc" doesn't belong in the iterator name, because
it refers specifically to the encrypt direction.)
> +(define_int_attr aesemc_outer_unspec [(UNSPEC_AESE "UNSPEC_AESMC")
> + (UNSPEC_AESD "UNSPEC_AESIMC")])
How about "aes_mc_unspec" or "aes_paired_mc_unspec"? (Same comment about the
"e" applies here).
> +
> +(define_int_attr crypto_aesemc_op [(UNSPEC_AESE "emc") (UNSPEC_AESD "dimc")])
> +(define_int_attr crypto_aesemc_outer_unspec [(UNSPEC_AESE "UNSPEC_AESMC")
> + (UNSPEC_AESD "UNSPEC_AESIMC")])
These two iterators are unused, so should be dropped.
>
> (define_int_iterator CRYPTO_SHA1 [UNSPEC_SHA1C UNSPEC_SHA1M UNSPEC_SHA1P])
>
> diff --git a/gcc/config/aarch64/predicates.md
> b/gcc/config/aarch64/predicates.md
> index f02486c2d9a..e2911a0bccd 100644
> --- a/gcc/config/aarch64/predicates.md
> +++ b/gcc/config/aarch64/predicates.md
> @@ -50,6 +50,10 @@ (define_predicate "const0_to_1_operand"
> (and (match_code "const_int")
> (match_test "IN_RANGE (INTVAL (op), 0, 1)")))
>
> +(define_predicate "const_0_to_3_operand"
> + (and (match_code "const_int")
> + (match_test "IN_RANGE (INTVAL (op), 0, 3)")))
> +
> (define_predicate "const_0_to_7_operand"
> (and (match_code "const_int")
> (match_test "IN_RANGE (INTVAL (op), 0, 7)")))
> diff --git a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_5.c
> b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_5.c
> index bb83ab434b5..0bec72d70a2 100644
> --- a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_5.c
> +++ b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_5.c
> @@ -41,6 +41,14 @@
> #error "__ARM_FEATURE_SVE2_SHA3 is defined but should not be!"
> #endif
>
> +#ifdef __ARM_FEATURE_SSVE_AES
> +#error "__ARM_FEATURE_SSVE_AES is defined but should not be!"
> +#endif
> +
> +#ifdef __ARM_FEATURE_SVE_AES2
> +#error "__ARM_FEATURE_SVE_AES2 is defined but should not be!"
> +#endif
> +
> #pragma GCC pop_options
>
> #pragma GCC push_options
> @@ -225,6 +233,20 @@
> #endif
> #pragma GCC pop_options
>
> +#pragma GCC push_options
> +#pragma GCC target "arch=armv8-a+ssve-aes"
> +#ifndef __ARM_FEATURE_SSVE_AES
> +#error "__ARM_FEATURE_SSVE_AES is not defined but should be!"
> +#endif
> +#pragma GCC pop_options
> +
> +#pragma GCC push_options
> +#pragma GCC target "arch=armv8-a+sve-aes2"
> +#ifndef __ARM_FEATURE_SVE_AES2
> +#error "__ARM_FEATURE_SVE_AES2 is not defined but should be!"
> +#endif
> +#pragma GCC pop_options
> +
> int
> foo (int a)
> {
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
> b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
> index aeb58ead0dd..cecd1c154b9 100644
> --- a/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
> +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/asm/test_sve_acle.h
> @@ -687,6 +687,22 @@
> __asm volatile ("" :: "w" (RES)); \
> }
>
> +#define TEST_XN_INDEXED(NAME, TTYPE, VTYPE, CODE1, CODE2) \
> + PROTO (NAME, TTYPE, (TTYPE t, VTYPE v)) \
> + { \
> + register TTYPE z0 __asm ("z0"); \
> + register TTYPE z1 __asm ("z1"); \
> + register TTYPE z2 __asm ("z2"); \
> + register TTYPE z3 __asm ("z3"); \
> + register VTYPE z4 __asm ("z4"); \
> + register VTYPE z5 __asm ("z5"); \
> + register VTYPE z6 __asm ("z6"); \
> + register VTYPE z7 __asm ("z7"); \
> + INVOKE (CODE1, CODE2); \
> + __asm volatile ("" :: "w" (t)); \
> + return t; \
> + }
> +
There's no need for a new macro here - you can use the existing TEST_XN_SINGLE
instead.
> #define TEST_DUAL_XN(NAME, TTYPE1, TTYPE2, RES, CODE1, CODE2) \
> PROTO (NAME, void, ()) \
> { \
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesd_lane_u8.c
> b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesd_lane_u8.c
> new file mode 100644
> index 00000000000..6d6bd63effa
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesd_lane_u8.c
> @@ -0,0 +1,67 @@
> +/* { dg-do assemble { target { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } */
> +/* { dg-do compile { target { ! { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } } */
> +/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
> +
> +#include "test_sve_acle.h"
> +
> +#pragma GCC target "+sve-aes2+ssve-aes"
> +
> +/*
> +** test_aesd_lane_u8_x2:
> +** aesd[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z2.q\[0\]
We don't use '[[:space:]]+' anywhere else in the aarch64 testsuite. Please use
a literal tab character (or whatever is needed) instead.
'.' is a wildcard, so we should probably use '\.' instead (as in 'z0\.b') to be
more precise.
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesd_lane_u8_x2, svuint8x2_t, svuint8_t,
> + t = svaesd_lane_u8_x2 (t, v, 0),
> + t = svaesd_lane (t, v, 0))
> +
> +/*
> +** test_aesd_lane_u8_x4:
> +** aesd[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesd_lane_u8_x4, svuint8x4_t, svuint8_t,
> + t = svaesd_lane_u8_x4 (t, v, 0),
> + t = svaesd_lane (t, v, 0))
> +
> +/*
> +** test_aesd_lane_u8_x2_regs:
> +** aesd[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesd_lane_u8_x2_regs, svuint8x2_t, svuint8_t,
> + t = svaesd_lane_u8_x2 (z0, z4, 0),
> + t = svaesd_lane (z0, z4, 0))
This seems a little repetitive - is there any value to having both this test
function and the first one?
> +
> +/*
> +** test_aesd_lane_u8_x4_regs:
> +** aesd[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesd_lane_u8_x4_regs, svuint8x4_t, svuint8_t,
> + t = svaesd_lane_u8_x4 (z0, z4, 0),
> + t = svaesd_lane (z0, z4, 0))
> +
> +/*
> +** test_aesd_lane_u8_x2_regs_mov:
> +** mov[[:space:]]+z0.d, z3.d
> +** mov[[:space:]]+z1.d, z4.d
> +** aesd[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesd_lane_u8_x2_regs_mov, svuint8x2_t, svuint8_t,
> + t = svaesd_lane_u8_x2 (z3, z4, 0),
> + t = svaesd_lane (z3, z4, 0))
> +
> +/*
> +** test_aesd_lane_u8_x4_regs_mov:
> +** mov[[:space:]]+z0.d, z3.d
> +** mov[[:space:]]+z1.d, z4.d
> +** mov[[:space:]]+z2.d, z5.d
> +** mov[[:space:]]+z3.d, z6.d
> +** aesd[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesd_lane_u8_x4_regs_mov, svuint8x4_t, svuint8_t,
> + t = svaesd_lane_u8_x4 (z3, z4, 0),
> + t = svaesd_lane (z3, z4, 0))
You need to test non-zero lane indices - testing both 0 and 3 should be enough.
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesdimc_lane_u8.c
> b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesdimc_lane_u8.c
> new file mode 100644
> index 00000000000..d7863c5f45e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesdimc_lane_u8.c
> @@ -0,0 +1,67 @@
> +/* { dg-do assemble { target { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } */
> +/* { dg-do compile { target { ! { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } } */
> +/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
> +
> +#include "test_sve_acle.h"
> +
> +#pragma GCC target "+sve-aes2+ssve-aes"
> +
> +/*
> +** test_aesdimc_lane_u8_x2:
> +** aesdimc[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z2.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesdimc_lane_u8_x2, svuint8x2_t, svuint8_t,
> + t = svaesdimc_lane_u8_x2 (t, v, 0),
> + t = svaesdimc_lane (t, v, 0))
> +
> +/*
> +** test_aesdimc_lane_u8_x4:
> +** aesdimc[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesdimc_lane_u8_x4, svuint8x4_t, svuint8_t,
> + t = svaesdimc_lane_u8_x4 (t, v, 0),
> + t = svaesdimc_lane (t, v, 0))
> +
> +/*
> +** test_aesdimc_lane_u8_x2_regs:
> +** aesdimc[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesdimc_lane_u8_x2_regs, svuint8x2_t, svuint8_t,
> + t = svaesdimc_lane_u8_x2 (z0, z4, 0),
> + t = svaesdimc_lane (z0, z4, 0))
> +
> +/*
> +** test_aesdimc_lane_u8_x4_regs:
> +** aesdimc[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesdimc_lane_u8_x4_regs, svuint8x4_t, svuint8_t,
> + t = svaesdimc_lane_u8_x4 (z0, z4, 0),
> + t = svaesdimc_lane (z0, z4, 0))
> +
> +/*
> +** test_aesdimc_lane_u8_x2_regs_mov:
> +** mov[[:space:]]+z0.d, z3.d
> +** mov[[:space:]]+z1.d, z4.d
> +** aesdimc[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesdimc_lane_u8_x2_regs_mov, svuint8x2_t, svuint8_t,
> + t = svaesdimc_lane_u8_x2 (z3, z4, 0),
> + t = svaesdimc_lane (z3, z4, 0))
> +
> +/*
> +** test_aesdimc_lane_u8_x4_regs_mov:
> +** mov[[:space:]]+z0.d, z3.d
> +** mov[[:space:]]+z1.d, z4.d
> +** mov[[:space:]]+z2.d, z5.d
> +** mov[[:space:]]+z3.d, z6.d
> +** aesdimc[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesdimc_lane_u8_x4_regs_mov, svuint8x4_t, svuint8_t,
> + t = svaesdimc_lane_u8_x4 (z3, z4, 0),
> + t = svaesdimc_lane (z3, z4, 0))
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aese_lane_u8.c
> b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aese_lane_u8.c
> new file mode 100644
> index 00000000000..aa826f360a4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aese_lane_u8.c
> @@ -0,0 +1,67 @@
> +/* { dg-do assemble { target { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } */
> +/* { dg-do compile { target { ! { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } } */
> +/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
> +
> +#include "test_sve_acle.h"
> +
> +#pragma GCC target "+sve-aes2+ssve-aes"
> +
> +/*
> +** test_aese_lane_u8_x2:
> +** aese[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z2.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aese_lane_u8_x2, svuint8x2_t, svuint8_t,
> + t = svaese_lane_u8_x2 (t, v, 0),
> + t = svaese_lane (t, v, 0))
> +
> +/*
> +** test_aese_lane_u8_x4:
> +** aese[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aese_lane_u8_x4, svuint8x4_t, svuint8_t,
> + t = svaese_lane_u8_x4 (t, v, 0),
> + t = svaese_lane (t, v, 0))
> +
> +/*
> +** test_aese_lane_u8_x2_regs:
> +** aese[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aese_lane_u8_x2_regs, svuint8x2_t, svuint8_t,
> + t = svaese_lane_u8_x2 (z0, z4, 0),
> + t = svaese_lane (z0, z4, 0))
> +
> +/*
> +** test_aese_lane_u8_x4_regs:
> +** aese[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aese_lane_u8_x4_regs, svuint8x4_t, svuint8_t,
> + t = svaese_lane_u8_x4 (z0, z4, 0),
> + t = svaese_lane (z0, z4, 0))
> +
> +/*
> +** test_aese_lane_u8_x2_regs_mov:
> +** mov[[:space:]]+z0.d, z3.d
> +** mov[[:space:]]+z1.d, z4.d
> +** aese[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aese_lane_u8_x2_regs_mov, svuint8x2_t, svuint8_t,
> + t = svaese_lane_u8_x2 (z3, z4, 0),
> + t = svaese_lane (z3, z4, 0))
> +
> +/*
> +** test_aese_lane_u8_x4_regs_mov:
> +** mov[[:space:]]+z0.d, z3.d
> +** mov[[:space:]]+z1.d, z4.d
> +** mov[[:space:]]+z2.d, z5.d
> +** mov[[:space:]]+z3.d, z6.d
> +** aese[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aese_lane_u8_x4_regs_mov, svuint8x4_t, svuint8_t,
> + t = svaese_lane_u8_x4 (z3, z4, 0),
> + t = svaese_lane (z3, z4, 0))
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesemc_lane_u8.c
> b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesemc_lane_u8.c
> new file mode 100644
> index 00000000000..04530a285b5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/aesemc_lane_u8.c
> @@ -0,0 +1,67 @@
> +/* { dg-do assemble { target { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } */
> +/* { dg-do compile { target { ! { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } } */
> +/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
> +
> +#include "test_sve_acle.h"
> +
> +#pragma GCC target "+sve-aes2+ssve-aes"
> +
> +/*
> +** test_aesemc_lane_u8_x2:
> +** aesemc[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z2.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesemc_lane_u8_x2, svuint8x2_t, svuint8_t,
> + t = svaesemc_lane_u8_x2 (t, v, 0),
> + t = svaesemc_lane (t, v, 0))
> +
> +/*
> +** test_aesemc_lane_u8_x4:
> +** aesemc[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesemc_lane_u8_x4, svuint8x4_t, svuint8_t,
> + t = svaesemc_lane_u8_x4 (t, v, 0),
> + t = svaesemc_lane (t, v, 0))
> +
> +/*
> +** test_aesemc_lane_u8_x2_regs:
> +** aesemc[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesemc_lane_u8_x2_regs, svuint8x2_t, svuint8_t,
> + t = svaesemc_lane_u8_x2 (z0, z4, 0),
> + t = svaesemc_lane (z0, z4, 0))
> +
> +/*
> +** test_aesemc_lane_u8_x4_regs:
> +** aesemc[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesemc_lane_u8_x4_regs, svuint8x4_t, svuint8_t,
> + t = svaesemc_lane_u8_x4 (z0, z4, 0),
> + t = svaesemc_lane (z0, z4, 0))
> +
> +/*
> +** test_aesemc_lane_u8_x2_regs_mov:
> +** mov[[:space:]]+z0.d, z3.d
> +** mov[[:space:]]+z1.d, z4.d
> +** aesemc[[:space:]]+{z0.b - z1.b}, {z0.b - z1.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesemc_lane_u8_x2_regs_mov, svuint8x2_t, svuint8_t,
> + t = svaesemc_lane_u8_x2 (z3, z4, 0),
> + t = svaesemc_lane (z3, z4, 0))
> +
> +/*
> +** test_aesemc_lane_u8_x4_regs_mov:
> +** mov[[:space:]]+z0.d, z3.d
> +** mov[[:space:]]+z1.d, z4.d
> +** mov[[:space:]]+z2.d, z5.d
> +** mov[[:space:]]+z3.d, z6.d
> +** aesemc[[:space:]]+{z0.b - z3.b}, {z0.b - z3.b}, z4.q\[0\]
> +** ret
> +*/
> +TEST_XN_INDEXED (test_aesemc_lane_u8_x4_regs_mov, svuint8x4_t, svuint8_t,
> + t = svaesemc_lane_u8_x4 (z3, z4, 0),
> + t = svaesemc_lane (z3, z4, 0))
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmlal_pair_u64.c
> b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmlal_pair_u64.c
> new file mode 100644
> index 00000000000..1e0acb259db
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmlal_pair_u64.c
> @@ -0,0 +1,69 @@
> +/* { dg-do assemble { target { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } */
> +/* { dg-do compile { target { ! { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } } */
> +/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
> +
> +#include "test_sve_acle.h"
> +
> +#pragma GCC target "+sve-aes2+ssve-aes"
> +
> +/*
> +**test_pmlal_pair_u64:
> +** pmlal[[:space:]]+{z0.q - z1.q}, z2.d, z2.d
> +** ret
> +*/
> +TEST_XN_INDEXED(test_pmlal_pair_u64, svuint64x2_t, svuint64_t,
> + t = svpmlal_pair_u64_x2(t, v, v),
> + t = svpmlal_pair(t, v, v))
> +
> +/*
> +**test_pmlal_pair_n_u64_regs:
> +** pmlal[[:space:]]+{z0.q - z1.q}, z4.d, z5.d
> +** ret
> +*/
> +TEST_XN_INDEXED(test_pmlal_pair_n_u64_regs, svuint64x2_t, svuint64_t,
> + t = svpmlal_pair_u64_x2(z0, z4, z5),
> + t = svpmlal_pair(z0, z4, z5))
> +
> +/*
> +**test_pmlal_pair_n_u64_regs_imm:
> +** movi[[:space:]]+d[0-9]{1,2}, #0
> +** pmlal[[:space:]]+{z0.q - z1.q}, z4.d, z[0-9]{1,2}\.d
> +** ret
> +*/
> +TEST_XN_INDEXED(test_pmlal_pair_n_u64_regs_imm, svuint64x2_t, svuint64_t,
> + t = svpmlal_pair_n_u64_x2(z0, z4, 0x0),
> + t = svpmlal_pair(z0, z4, 0x0))
> +
> +/*
> +**test_pmlal_pair_n_u64_regs_imm_1:
> +** mov[[:space:]]+z[0-9]{1,2}\.d, #65535
> +** pmlal[[:space:]]+{z0.q - z1.q}, z4.d, z[0-9]{1,2}\.d
> +** ret
> +*/
> +TEST_XN_INDEXED(test_pmlal_pair_n_u64_regs_imm_1, svuint64x2_t, svuint64_t,
> + t = svpmlal_pair_n_u64_x2(z0, z4, 0xFFFF),
> + t = svpmlal_pair(z0, z4, 0xFFFF))
> +
> +/*
> +**test_pmlal_pair_n_u64_regs_mov:
> +** mov[[:space:]]+z0.d, z3.d
> +** mov[[:space:]]+z1.d, z4.d
> +** movi[[:space:]]+d[0-9]{1,2}, #0
> +** pmlal[[:space:]]+{z0.q - z1.q}, z4.d, z[0-9]{1,2}\.d
> +** ret
> +*/
> +TEST_XN_INDEXED(test_pmlal_pair_n_u64_regs_mov, svuint64x2_t, svuint64_t,
> + t = svpmlal_pair_n_u64_x2(z3, z4, 0x0),
> + t = svpmlal_pair(z3, z4, 0x0))
> +
> +/*
> +**test_pmlal_pair_n_u64_regs_mov_1:
> +** mov[[:space:]]+z0.d, z3.d
> +** mov[[:space:]]+z1.d, z4.d
> +** mov[[:space:]]+z[0-9]{1,2}\.d, #65535
> +** pmlal[[:space:]]+{z0.q - z1.q}, z4.d, z[0-9]{1,2}\.d
> +** ret
> +*/
> +TEST_XN_INDEXED(test_pmlal_pair_n_u64_regs_mov_1, svuint64x2_t, svuint64_t,
> + t = svpmlal_pair_n_u64_x2(z3, z4, 0xFFFF),
> + t = svpmlal_pair(z3, z4, 0xFFFF))
I'd like to see a non-constant scalar value used in these intrinsics. The
TEST_XN_SINGLE macro doesn't currently include any GP regs, but I think it's
fine to add an x register to the macro, since it won't affect any existing
tests.
> diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmull_pair_u64.c
> b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmull_pair_u64.c
> new file mode 100644
> index 00000000000..79e45cc9319
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/sve2/acle/asm/pmull_pair_u64.c
> @@ -0,0 +1,45 @@
> +/* { dg-do assemble { target { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } */
> +/* { dg-do compile { target { ! { aarch64_asm_ssve-aes_ok &&
> aarch64_asm_sve-aes2_ok } } } } */
> +/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
> +
> +#include "test_sve_acle.h"
> +
> +#pragma GCC target "+sve-aes2+ssve-aes"
> +
> +/*
> +**test_pmull_pair_u64:
> +** pmull[[:space:]]+{z0.q - z1.q}, z2.d, z2.d
> +** ret
> +*/
> +TEST_XN_INDEXED(test_pmull_pair_u64, svuint64x2_t, svuint64_t,
> + t = svpmull_pair_u64_x2(v, v),
> + t = svpmull_pair(v, v))
> +
> +/*
> +**test_pmull_pair_n_u64:
> +** movi[[:space:]]+d([0-9]{1,2}), #0
> +** pmull[[:space:]]+{z0.q - z1.q}, z2.d, z\1.d
> +** ret
> +*/
> +TEST_XN_INDEXED(test_pmull_pair_n_u64, svuint64x2_t, svuint64_t,
> + t = svpmull_pair_n_u64_x2(v, 0x0),
> + t = svpmull_pair(v, 0x0))
> +
> +/*
> +**test_pmull_pair_u64_regs:
> +** pmull[[:space:]]+{z0.q - z1.q}, z4.d, z5.d
> +** ret
> +*/
> +TEST_XN_INDEXED(test_pmull_pair_u64_regs, svuint64x2_t, svuint64_t,
> + t = svpmull_pair_u64_x2(z4, z5),
> + t = svpmull_pair(z4, z5))
> +
> +/*
> +**test_pmull_pair_n_u64_regs:
> +** movi[[:space:]]+d([0-9]{1,2}), #0
> +** pmull[[:space:]]+{z0.q - z1.q}, z4.d, z\1.d
> +** ret
> +*/
> +TEST_XN_INDEXED(test_pmull_pair_n_u64_regs, svuint64x2_t, svuint64_t,
> + t = svpmull_pair_n_u64_x2(z4, 0x0),
> + t = svpmull_pair(z4, 0x0))
> diff --git a/gcc/testsuite/lib/target-supports.exp
> b/gcc/testsuite/lib/target-supports.exp
> index fdde04a73e4..fcccf49f1ba 100644
> --- a/gcc/testsuite/lib/target-supports.exp
> +++ b/gcc/testsuite/lib/target-supports.exp
> @@ -12901,8 +12901,8 @@ proc
> check_effective_target_aarch64_gas_has_build_attributes { } {
> set exts {
> "bf16" "cmpbr" "crc" "crypto" "dotprod" "f32mm" "f64mm" "faminmax"
> "fp" "fp8" "fp8dot2" "fp8dot4" "fp8fma" "i8mm" "ls64" "lse" "lut"
> - "sb" "simd" "sve-b16b16" "sve" "sve2" "sve-sm4" "sve-aes" "sve-bitperm"
> - "sve-sha3" "f8f16mm" "f8f32mm" "sve-f16f32mm"
> + "sb" "simd" "sve-b16b16" "sve" "sve2" "sve-sm4" "sve-aes" "sve-aes2"
> + "sve-bitperm" "sve-sha3" "f8f16mm" "f8f32mm" "sve-f16f32mm"
> "sme-f8f16" "sme-f8f32"
> "sme-b16b16" "sme-f16f16" "sme-i16i64" "sme" "sme2" "sme2p1" "sme2p2"
> "ssve-fp8dot2" "ssve-fp8dot4" "ssve-fp8fma" "sve-bfscale" "sme-lutv2"
> --
> 2.43.0
>