summaryrefslogtreecommitdiff
path: root/0164-Backport-SME-aarch64-Add-group-suffixes-to-SVE-intri.patch
diff options
context:
space:
mode:
Diffstat (limited to '0164-Backport-SME-aarch64-Add-group-suffixes-to-SVE-intri.patch')
-rw-r--r--0164-Backport-SME-aarch64-Add-group-suffixes-to-SVE-intri.patch562
1 files changed, 562 insertions, 0 deletions
diff --git a/0164-Backport-SME-aarch64-Add-group-suffixes-to-SVE-intri.patch b/0164-Backport-SME-aarch64-Add-group-suffixes-to-SVE-intri.patch
new file mode 100644
index 0000000..4497814
--- /dev/null
+++ b/0164-Backport-SME-aarch64-Add-group-suffixes-to-SVE-intri.patch
@@ -0,0 +1,562 @@
+From e99332e15895156632949f3b6c3080fc9d994b13 Mon Sep 17 00:00:00 2001
+From: Richard Sandiford <richard.sandiford@arm.com>
+Date: Tue, 5 Dec 2023 10:11:19 +0000
+Subject: [PATCH 065/157] [Backport][SME] aarch64: Add group suffixes to SVE
+ intrinsics
+
+Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=7b607f197967e052d7d7e29f6b41eded18f8c65d
+
+The SME2 ACLE adds a new "group" suffix component to the naming
+convention for SVE intrinsics. This is also used in the new tuple
+forms of the svreinterpret intrinsics.
+
+This patch adds support for group suffixes and defines the
+x2, x3 and x4 suffixes that are needed for the svreinterprets.
+
+gcc/
+ * config/aarch64/aarch64-sve-builtins-shapes.cc (build_one): Take
+ a group suffix index parameter.
+ (build_32_64, build_all): Update accordingly. Iterate over all
+ group suffixes.
+ * config/aarch64/aarch64-sve-builtins-sve2.cc (svqrshl_impl::fold)
+ (svqshl_impl::fold, svrshl_impl::fold): Update function_instance
+ constructors.
+ * config/aarch64/aarch64-sve-builtins.cc (group_suffixes): New array.
+ (groups_none): New constant.
+ (function_groups): Initialize the groups field.
+ (function_instance::hash): Hash the group index.
+ (function_builder::get_name): Add the group suffix.
+ (function_builder::add_overloaded_functions): Iterate over all
+ group suffixes.
+ (function_resolver::lookup_form): Take a group suffix parameter.
+ (function_resolver::resolve_to): Likewise.
+ * config/aarch64/aarch64-sve-builtins.def (DEF_SVE_GROUP_SUFFIX): New
+ macro.
+ (x2, x3, x4): New group suffixes.
+ * config/aarch64/aarch64-sve-builtins.h (group_suffix_index): New enum.
+ (group_suffix_info): New structure.
+ (function_group_info::groups): New member variable.
+ (function_instance::group_suffix_id): Likewise.
+ (group_suffixes): New array.
+ (function_instance::operator==): Compare the group suffixes.
+ (function_instance::group_suffix): New function.
+---
+ .../aarch64/aarch64-sve-builtins-shapes.cc | 53 ++++++------
+ .../aarch64/aarch64-sve-builtins-sve2.cc | 10 +--
+ gcc/config/aarch64/aarch64-sve-builtins.cc | 84 +++++++++++++------
+ gcc/config/aarch64/aarch64-sve-builtins.def | 9 ++
+ gcc/config/aarch64/aarch64-sve-builtins.h | 81 ++++++++++++++----
+ 5 files changed, 165 insertions(+), 72 deletions(-)
+
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+index 4fa4181b9..3ecef026c 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
+@@ -275,18 +275,20 @@ parse_signature (const function_instance &instance, const char *format,
+ }
+
+ /* Add one function instance for GROUP, using mode suffix MODE_SUFFIX_ID,
+- the type suffixes at index TI and the predication suffix at index PI.
+- The other arguments are as for build_all. */
++ the type suffixes at index TI, the group suffixes at index GI, and the
++ predication suffix at index PI. The other arguments are as for
++ build_all. */
+ static void
+ build_one (function_builder &b, const char *signature,
+ const function_group_info &group, mode_suffix_index mode_suffix_id,
+- unsigned int ti, unsigned int pi, bool force_direct_overloads)
++ unsigned int ti, unsigned int gi, unsigned int pi,
++ bool force_direct_overloads)
+ {
+ /* Byte forms of svdupq take 16 arguments. */
+ auto_vec<tree, 16> argument_types;
+ function_instance instance (group.base_name, *group.base, *group.shape,
+ mode_suffix_id, group.types[ti],
+- group.preds[pi]);
++ group.groups[gi], group.preds[pi]);
+ tree return_type = parse_signature (instance, signature, argument_types);
+ apply_predication (instance, return_type, argument_types);
+ b.add_unique_function (instance, return_type, argument_types,
+@@ -312,24 +314,26 @@ build_32_64 (function_builder &b, const char *signature,
+ mode_suffix_index mode64, bool force_direct_overloads = false)
+ {
+ for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
+- if (group.types[0][0] == NUM_TYPE_SUFFIXES)
+- {
+- gcc_assert (mode32 != MODE_none && mode64 != MODE_none);
+- build_one (b, signature, group, mode32, 0, pi,
+- force_direct_overloads);
+- build_one (b, signature, group, mode64, 0, pi,
+- force_direct_overloads);
+- }
+- else
+- for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
++ for (unsigned int gi = 0; group.groups[gi] != NUM_GROUP_SUFFIXES; ++gi)
++ if (group.types[0][0] == NUM_TYPE_SUFFIXES)
+ {
+- unsigned int bits = type_suffixes[group.types[ti][0]].element_bits;
+- gcc_assert (bits == 32 || bits == 64);
+- mode_suffix_index mode = bits == 32 ? mode32 : mode64;
+- if (mode != MODE_none)
+- build_one (b, signature, group, mode, ti, pi,
+- force_direct_overloads);
++ gcc_assert (mode32 != MODE_none && mode64 != MODE_none);
++ build_one (b, signature, group, mode32, 0, gi, pi,
++ force_direct_overloads);
++ build_one (b, signature, group, mode64, 0, gi, pi,
++ force_direct_overloads);
+ }
++ else
++ for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES;
++ ++ti)
++ {
++ unsigned int bits = type_suffixes[group.types[ti][0]].element_bits;
++ gcc_assert (bits == 32 || bits == 64);
++ mode_suffix_index mode = bits == 32 ? mode32 : mode64;
++ if (mode != MODE_none)
++ build_one (b, signature, group, mode, ti, gi, pi,
++ force_direct_overloads);
++ }
+ }
+
+ /* For every type and predicate combination in GROUP, add one function
+@@ -423,10 +427,11 @@ build_all (function_builder &b, const char *signature,
+ bool force_direct_overloads = false)
+ {
+ for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
+- for (unsigned int ti = 0;
+- ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
+- build_one (b, signature, group, mode_suffix_id, ti, pi,
+- force_direct_overloads);
++ for (unsigned int gi = 0; group.groups[gi] != NUM_GROUP_SUFFIXES; ++gi)
++ for (unsigned int ti = 0;
++ ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
++ build_one (b, signature, group, mode_suffix_id, ti, gi, pi,
++ force_direct_overloads);
+ }
+
+ /* TYPE is the largest type suffix associated with the arguments of R,
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
+index e066f096d..a94e5e269 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins-sve2.cc
+@@ -252,7 +252,7 @@ public:
+ that we can use for sensible shift amounts. */
+ function_instance instance ("svqshl", functions::svqshl,
+ shapes::binary_int_opt_n, MODE_n,
+- f.type_suffix_ids, f.pred);
++ f.type_suffix_ids, GROUP_none, f.pred);
+ return f.redirect_call (instance);
+ }
+ else
+@@ -261,7 +261,7 @@ public:
+ that we can use for sensible shift amounts. */
+ function_instance instance ("svrshl", functions::svrshl,
+ shapes::binary_int_opt_n, MODE_n,
+- f.type_suffix_ids, f.pred);
++ f.type_suffix_ids, GROUP_none, f.pred);
+ return f.redirect_call (instance);
+ }
+ }
+@@ -290,7 +290,7 @@ public:
+ -wi::to_wide (amount));
+ function_instance instance ("svasr", functions::svasr,
+ shapes::binary_uint_opt_n, MODE_n,
+- f.type_suffix_ids, f.pred);
++ f.type_suffix_ids, GROUP_none, f.pred);
+ if (f.type_suffix (0).unsigned_p)
+ {
+ instance.base_name = "svlsr";
+@@ -322,7 +322,7 @@ public:
+ that we can use for sensible shift amounts. */
+ function_instance instance ("svlsl", functions::svlsl,
+ shapes::binary_uint_opt_n, MODE_n,
+- f.type_suffix_ids, f.pred);
++ f.type_suffix_ids, GROUP_none, f.pred);
+ gcall *call = as_a <gcall *> (f.redirect_call (instance));
+ gimple_call_set_arg (call, 2, amount);
+ return call;
+@@ -335,7 +335,7 @@ public:
+ -wi::to_wide (amount));
+ function_instance instance ("svrshr", functions::svrshr,
+ shapes::shift_right_imm, MODE_n,
+- f.type_suffix_ids, f.pred);
++ f.type_suffix_ids, GROUP_none, f.pred);
+ gcall *call = as_a <gcall *> (f.redirect_call (instance));
+ gimple_call_set_arg (call, 2, amount);
+ return call;
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
+index dde01f676..dc3fd80da 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
++++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
+@@ -144,6 +144,13 @@ CONSTEXPR const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1] = {
+ 0, VOIDmode }
+ };
+
++CONSTEXPR const group_suffix_info group_suffixes[] = {
++#define DEF_SVE_GROUP_SUFFIX(NAME, VG, VECTORS_PER_TUPLE) \
++ { "_" #NAME, VG, VECTORS_PER_TUPLE },
++#include "aarch64-sve-builtins.def"
++ { "", 0, 1 }
++};
++
+ /* Define a TYPES_<combination> macro for each combination of type
+ suffixes that an ACLE function can have, where <combination> is the
+ name used in DEF_SVE_FUNCTION entries.
+@@ -483,6 +490,10 @@ DEF_SVE_TYPES_ARRAY (inc_dec_n);
+ DEF_SVE_TYPES_ARRAY (reinterpret);
+ DEF_SVE_TYPES_ARRAY (while);
+
++static const group_suffix_index groups_none[] = {
++ GROUP_none, NUM_GROUP_SUFFIXES
++};
++
+ /* Used by functions that have no governing predicate. */
+ static const predication_index preds_none[] = { PRED_none, NUM_PREDS };
+
+@@ -524,8 +535,8 @@ static const predication_index preds_z[] = { PRED_z, NUM_PREDS };
+ /* A list of all SVE ACLE functions. */
+ static CONSTEXPR const function_group_info function_groups[] = {
+ #define DEF_SVE_FUNCTION(NAME, SHAPE, TYPES, PREDS) \
+- { #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, preds_##PREDS, \
+- REQUIRED_EXTENSIONS },
++ { #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, groups_none, \
++ preds_##PREDS, REQUIRED_EXTENSIONS },
+ #include "aarch64-sve-builtins.def"
+ };
+
+@@ -788,6 +799,7 @@ function_instance::hash () const
+ h.add_int (mode_suffix_id);
+ h.add_int (type_suffix_ids[0]);
+ h.add_int (type_suffix_ids[1]);
++ h.add_int (group_suffix_id);
+ h.add_int (pred);
+ return h.end ();
+ }
+@@ -957,6 +969,8 @@ function_builder::get_name (const function_instance &instance,
+ for (unsigned int i = 0; i < 2; ++i)
+ if (!overloaded_p || instance.shape->explicit_type_suffix_p (i))
+ append_name (instance.type_suffix (i).string);
++ if (!overloaded_p || instance.shape->explicit_group_suffix_p ())
++ append_name (instance.group_suffix ().string);
+ append_name (pred_suffixes[instance.pred]);
+ return finish_name ();
+ }
+@@ -1113,19 +1127,26 @@ void
+ function_builder::add_overloaded_functions (const function_group_info &group,
+ mode_suffix_index mode)
+ {
+- unsigned int explicit_type0 = (*group.shape)->explicit_type_suffix_p (0);
+- unsigned int explicit_type1 = (*group.shape)->explicit_type_suffix_p (1);
+- for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
++ bool explicit_type0 = (*group.shape)->explicit_type_suffix_p (0);
++ bool explicit_type1 = (*group.shape)->explicit_type_suffix_p (1);
++ bool explicit_group = (*group.shape)->explicit_group_suffix_p ();
++ auto add_function = [&](const type_suffix_pair &types,
++ group_suffix_index group_suffix_id,
++ unsigned int pi)
++ {
++ function_instance instance (group.base_name, *group.base,
++ *group.shape, mode, types,
++ group_suffix_id, group.preds[pi]);
++ add_overloaded_function (instance, group.required_extensions);
++ };
++
++ auto add_group_suffix = [&](group_suffix_index group_suffix_id,
++ unsigned int pi)
+ {
+ if (!explicit_type0 && !explicit_type1)
+- {
+- /* Deal with the common case in which there is one overloaded
+- function for all type combinations. */
+- function_instance instance (group.base_name, *group.base,
+- *group.shape, mode, types_none[0],
+- group.preds[pi]);
+- add_overloaded_function (instance, group.required_extensions);
+- }
++ /* Deal with the common case in which there is one overloaded
++ function for all type combinations. */
++ add_function (types_none[0], group_suffix_id, pi);
+ else
+ for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES;
+ ++ti)
+@@ -1136,12 +1157,16 @@ function_builder::add_overloaded_functions (const function_group_info &group,
+ explicit_type0 ? group.types[ti][0] : NUM_TYPE_SUFFIXES,
+ explicit_type1 ? group.types[ti][1] : NUM_TYPE_SUFFIXES
+ };
+- function_instance instance (group.base_name, *group.base,
+- *group.shape, mode, types,
+- group.preds[pi]);
+- add_overloaded_function (instance, group.required_extensions);
++ add_function (types, group_suffix_id, pi);
+ }
+- }
++ };
++
++ for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
++ if (explicit_group)
++ for (unsigned int gi = 0; group.groups[gi] != NUM_GROUP_SUFFIXES; ++gi)
++ add_group_suffix (group.groups[gi], pi);
++ else
++ add_group_suffix (GROUP_none, pi);
+ }
+
+ /* Register all the functions in GROUP. */
+@@ -1213,29 +1238,34 @@ function_resolver::report_no_such_form (type_suffix_index type)
+ }
+
+ /* Silently check whether there is an instance of the function with the
+- mode suffix given by MODE and the type suffixes given by TYPE0 and TYPE1.
+- Return its function decl if so, otherwise return null. */
++ mode suffix given by MODE, the type suffixes given by TYPE0 and TYPE1,
++ and the group suffix given by GROUP. Return its function decl if so,
++ otherwise return null. */
+ tree
+ function_resolver::lookup_form (mode_suffix_index mode,
+ type_suffix_index type0,
+- type_suffix_index type1)
++ type_suffix_index type1,
++ group_suffix_index group)
+ {
+ type_suffix_pair types = { type0, type1 };
+- function_instance instance (base_name, base, shape, mode, types, pred);
++ function_instance instance (base_name, base, shape, mode, types,
++ group, pred);
+ registered_function *rfn
+ = function_table->find_with_hash (instance, instance.hash ());
+ return rfn ? rfn->decl : NULL_TREE;
+ }
+
+-/* Resolve the function to one with the mode suffix given by MODE and the
+- type suffixes given by TYPE0 and TYPE1. Return its function decl on
+- success, otherwise report an error and return error_mark_node. */
++/* Resolve the function to one with the mode suffix given by MODE, the
++ type suffixes given by TYPE0 and TYPE1, and group suffix given by
++ GROUP. Return its function decl on success, otherwise report an
++ error and return error_mark_node. */
+ tree
+ function_resolver::resolve_to (mode_suffix_index mode,
+ type_suffix_index type0,
+- type_suffix_index type1)
++ type_suffix_index type1,
++ group_suffix_index group)
+ {
+- tree res = lookup_form (mode, type0, type1);
++ tree res = lookup_form (mode, type0, type1, group);
+ if (!res)
+ {
+ if (type1 == NUM_TYPE_SUFFIXES)
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.def b/gcc/config/aarch64/aarch64-sve-builtins.def
+index 6e4dcdbc9..d9bf9c350 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.def
++++ b/gcc/config/aarch64/aarch64-sve-builtins.def
+@@ -29,6 +29,10 @@
+ #define DEF_SVE_TYPE_SUFFIX(A, B, C, D, E)
+ #endif
+
++#ifndef DEF_SVE_GROUP_SUFFIX
++#define DEF_SVE_GROUP_SUFFIX(A, B, C)
++#endif
++
+ #ifndef DEF_SVE_FUNCTION
+ #define DEF_SVE_FUNCTION(A, B, C, D)
+ #endif
+@@ -95,10 +99,15 @@ DEF_SVE_TYPE_SUFFIX (u16, svuint16_t, unsigned, 16, VNx8HImode)
+ DEF_SVE_TYPE_SUFFIX (u32, svuint32_t, unsigned, 32, VNx4SImode)
+ DEF_SVE_TYPE_SUFFIX (u64, svuint64_t, unsigned, 64, VNx2DImode)
+
++DEF_SVE_GROUP_SUFFIX (x2, 0, 2)
++DEF_SVE_GROUP_SUFFIX (x3, 0, 3)
++DEF_SVE_GROUP_SUFFIX (x4, 0, 4)
++
+ #include "aarch64-sve-builtins-base.def"
+ #include "aarch64-sve-builtins-sve2.def"
+
+ #undef DEF_SVE_FUNCTION
++#undef DEF_SVE_GROUP_SUFFIX
+ #undef DEF_SVE_TYPE_SUFFIX
+ #undef DEF_SVE_TYPE
+ #undef DEF_SVE_MODE
+diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
+index 824c31cd7..374c57e93 100644
+--- a/gcc/config/aarch64/aarch64-sve-builtins.h
++++ b/gcc/config/aarch64/aarch64-sve-builtins.h
+@@ -180,6 +180,17 @@ enum type_suffix_index
+ NUM_TYPE_SUFFIXES
+ };
+
++/* Enumerates the possible group suffixes. Each suffix combines two
++ optional pieces of information: the vector group size in a ZA index,
++ and the number of vectors in the largest tuple argument. */
++enum group_suffix_index
++{
++#define DEF_SVE_GROUP_SUFFIX(NAME, VG, VECTORS_PER_TUPLE) GROUP_##NAME,
++#include "aarch64-sve-builtins.def"
++ GROUP_none,
++ NUM_GROUP_SUFFIXES
++};
++
+ /* Combines two type suffixes. */
+ typedef enum type_suffix_index type_suffix_pair[2];
+
+@@ -237,6 +248,21 @@ struct type_suffix_info
+ machine_mode vector_mode : 16;
+ };
+
++/* Static information about a group suffix. */
++struct group_suffix_info
++{
++ /* The suffix string itself. */
++ const char *string;
++
++ /* If the suffix describes a vector group in a ZA index, this is the
++ size of that group, otherwise it is zero. */
++ unsigned int vg;
++
++ /* The number of vectors in the largest (or only) tuple argument,
++ or 1 if the suffix does not convey this information. */
++ unsigned int vectors_per_tuple;
++};
++
+ /* Static information about a set of functions. */
+ struct function_group_info
+ {
+@@ -251,14 +277,16 @@ struct function_group_info
+ shapes. */
+ const function_shape *const *shape;
+
+- /* A list of the available type suffixes, and of the available predication
+- types. The function supports every combination of the two.
++ /* A list of the available type suffixes, group suffixes, and predication
++ types. The function supports every combination of the three.
++
++ The list of type suffixes is terminated by two NUM_TYPE_SUFFIXES.
++ It is lexicographically ordered based on the index value.
+
+- The list of type suffixes is terminated by two NUM_TYPE_SUFFIXES
+- while the list of predication types is terminated by NUM_PREDS.
+- The list of type suffixes is lexicographically ordered based
+- on the index value. */
++ The list of group suffixes is terminated by NUM_GROUP_SUFFIXES
++ and the list of predication types is terminated by NUM_PREDS. */
+ const type_suffix_pair *types;
++ const group_suffix_index *groups;
+ const predication_index *preds;
+
+ /* The architecture extensions that the functions require, as a set of
+@@ -273,7 +301,8 @@ class GTY((user)) function_instance
+ public:
+ function_instance (const char *, const function_base *,
+ const function_shape *, mode_suffix_index,
+- const type_suffix_pair &, predication_index);
++ const type_suffix_pair &, group_suffix_index,
++ predication_index);
+
+ bool operator== (const function_instance &) const;
+ bool operator!= (const function_instance &) const;
+@@ -294,6 +323,8 @@ public:
+ units_index displacement_units () const;
+
+ const type_suffix_info &type_suffix (unsigned int) const;
++ const group_suffix_info &group_suffix () const;
++
+ tree scalar_type (unsigned int) const;
+ tree vector_type (unsigned int) const;
+ tree tuple_type (unsigned int) const;
+@@ -301,14 +332,14 @@ public:
+ machine_mode vector_mode (unsigned int) const;
+ machine_mode gp_mode (unsigned int) const;
+
+- /* The properties of the function. (The explicit "enum"s are required
+- for gengtype.) */
++ /* The properties of the function. */
+ const char *base_name;
+ const function_base *base;
+ const function_shape *shape;
+- enum mode_suffix_index mode_suffix_id;
++ mode_suffix_index mode_suffix_id;
+ type_suffix_pair type_suffix_ids;
+- enum predication_index pred;
++ group_suffix_index group_suffix_id;
++ predication_index pred;
+ };
+
+ class registered_function;
+@@ -390,10 +421,12 @@ public:
+ tree report_no_such_form (type_suffix_index);
+ tree lookup_form (mode_suffix_index,
+ type_suffix_index = NUM_TYPE_SUFFIXES,
+- type_suffix_index = NUM_TYPE_SUFFIXES);
++ type_suffix_index = NUM_TYPE_SUFFIXES,
++ group_suffix_index = GROUP_none);
+ tree resolve_to (mode_suffix_index,
+ type_suffix_index = NUM_TYPE_SUFFIXES,
+- type_suffix_index = NUM_TYPE_SUFFIXES);
++ type_suffix_index = NUM_TYPE_SUFFIXES,
++ group_suffix_index = GROUP_none);
+
+ type_suffix_index infer_integer_scalar_type (unsigned int);
+ type_suffix_index infer_pointer_type (unsigned int, bool = false);
+@@ -641,6 +674,11 @@ class function_shape
+ public:
+ virtual bool explicit_type_suffix_p (unsigned int) const = 0;
+
++ /* True if the group suffix is present in overloaded names.
++ This isn't meaningful for pre-SME intrinsics, and true is
++ more common than false, so provide a default definition. */
++ virtual bool explicit_group_suffix_p () const { return true; }
++
+ /* Define all functions associated with the given group. */
+ virtual void build (function_builder &,
+ const function_group_info &) const = 0;
+@@ -669,6 +707,7 @@ private:
+
+ extern const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1];
+ extern const mode_suffix_info mode_suffixes[MODE_none + 1];
++extern const group_suffix_info group_suffixes[NUM_GROUP_SUFFIXES];
+
+ extern tree scalar_types[NUM_VECTOR_TYPES];
+ extern tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1];
+@@ -728,9 +767,11 @@ function_instance (const char *base_name_in,
+ const function_shape *shape_in,
+ mode_suffix_index mode_suffix_id_in,
+ const type_suffix_pair &type_suffix_ids_in,
++ group_suffix_index group_suffix_id_in,
+ predication_index pred_in)
+ : base_name (base_name_in), base (base_in), shape (shape_in),
+- mode_suffix_id (mode_suffix_id_in), pred (pred_in)
++ mode_suffix_id (mode_suffix_id_in), group_suffix_id (group_suffix_id_in),
++ pred (pred_in)
+ {
+ memcpy (type_suffix_ids, type_suffix_ids_in, sizeof (type_suffix_ids));
+ }
+@@ -741,9 +782,10 @@ function_instance::operator== (const function_instance &other) const
+ return (base == other.base
+ && shape == other.shape
+ && mode_suffix_id == other.mode_suffix_id
+- && pred == other.pred
+ && type_suffix_ids[0] == other.type_suffix_ids[0]
+- && type_suffix_ids[1] == other.type_suffix_ids[1]);
++ && type_suffix_ids[1] == other.type_suffix_ids[1]
++ && group_suffix_id == other.group_suffix_id
++ && pred == other.pred);
+ }
+
+ inline bool
+@@ -815,6 +857,13 @@ function_instance::type_suffix (unsigned int i) const
+ return type_suffixes[type_suffix_ids[i]];
+ }
+
++/* Return information about the function's group suffix. */
++inline const group_suffix_info &
++function_instance::group_suffix () const
++{
++ return group_suffixes[group_suffix_id];
++}
++
+ /* Return the scalar type associated with type suffix I. */
+ inline tree
+ function_instance::scalar_type (unsigned int i) const
+--
+2.33.0
+