diff mbox series

[pushed,v2,05/25] aarch64: Add sve_type to SVE builtins code

Message ID 20231205101323.1914247-6-richard.sandiford@arm.com
State New
Headers show
Series aarch64: Add support for SME | expand

Commit Message

Richard Sandiford Dec. 5, 2023, 10:13 a.m. UTC
Until now, the SVE ACLE code had mostly been able to represent
individual SVE arguments with just an element type suffix (s32, u32,
etc.).  However, the SME2 ACLE provides many overloaded intrinsics
that operate on tuples rather than single vectors.  This patch
therefore adds a new type (sve_type) that combines an element
type suffix with a vector count.  This is enough to uniquely
represent all SVE ACLE types.

gcc/
	* config/aarch64/aarch64-sve-builtins.h (sve_type): New struct.
	(sve_type::operator==): New function.
	(function_resolver::get_vector_type): Delete.
	(function_resolver::report_no_such_form): Take an sve_type rather
	than a type_suffix_index.
	* config/aarch64/aarch64-sve-builtins.cc (get_vector_type): New
	function.
	(function_resolver::get_vector_type): Delete.
	(function_resolver::report_no_such_form): Take an sve_type rather
	than a type_suffix_index.
	(find_sve_type): New function, split out from...
	(function_resolver::infer_vector_or_tuple_type): ...here.
---
 gcc/config/aarch64/aarch64-sve-builtins.cc | 93 ++++++++++++----------
 gcc/config/aarch64/aarch64-sve-builtins.h  | 37 ++++++++-
 2 files changed, 88 insertions(+), 42 deletions(-)
diff mbox series

Patch

diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
index 55938413ef0..058b1defa9e 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
@@ -659,6 +659,14 @@  find_type_suffix_for_scalar_type (const_tree type)
   return NUM_TYPE_SUFFIXES;
 }
 
+/* Return the vector type associated with TYPE.  */
+static tree
+get_vector_type (sve_type type)
+{
+  auto vector_type = type_suffixes[type.type].vector_type;
+  return acle_vector_types[type.num_vectors - 1][vector_type];
+}
+
 /* Report an error against LOCATION that the user has tried to use
    function FNDECL when extension EXTENSION is disabled.  */
 static void
@@ -1190,13 +1198,6 @@  function_resolver::function_resolver (location_t location,
 {
 }
 
-/* Return the vector type associated with type suffix TYPE.  */
-tree
-function_resolver::get_vector_type (type_suffix_index type)
-{
-  return acle_vector_types[0][type_suffixes[type].vector_type];
-}
-
 /* Return the <stdint.h> name associated with TYPE.  Using the <stdint.h>
    name should be more user-friendly than the underlying canonical type,
    since it makes the signedness and bitwidth explicit.  */
@@ -1227,10 +1228,10 @@  function_resolver::scalar_argument_p (unsigned int i)
 	  || SCALAR_FLOAT_TYPE_P (type));
 }
 
-/* Report that the function has no form that takes type suffix TYPE.
+/* Report that the function has no form that takes type TYPE.
    Return error_mark_node.  */
 tree
-function_resolver::report_no_such_form (type_suffix_index type)
+function_resolver::report_no_such_form (sve_type type)
 {
   error_at (location, "%qE has no form that takes %qT arguments",
 	    fndecl, get_vector_type (type));
@@ -1352,6 +1353,25 @@  function_resolver::infer_pointer_type (unsigned int argno,
   return type;
 }
 
+/* If TYPE is an SVE predicate or vector type, or a tuple of such a type,
+   return the associated sve_type, otherwise return an invalid sve_type.  */
+static sve_type
+find_sve_type (const_tree type)
+{
+  /* A linear search should be OK here, since the code isn't hot and
+     the number of types is only small.  */
+  for (unsigned int size_i = 0; size_i < MAX_TUPLE_SIZE; ++size_i)
+    for (unsigned int suffix_i = 0; suffix_i < NUM_TYPE_SUFFIXES; ++suffix_i)
+      {
+	vector_type_index type_i = type_suffixes[suffix_i].vector_type;
+	tree this_type = acle_vector_types[size_i][type_i];
+	if (this_type && matches_type_p (this_type, type))
+	  return { type_suffix_index (suffix_i), size_i + 1 };
+      }
+
+  return {};
+}
+
 /* Require argument ARGNO to be a single vector or a tuple of NUM_VECTORS
    vectors; NUM_VECTORS is 1 for the former.  Return the associated type
    suffix on success, using TYPE_SUFFIX_b for predicates.  Report an error
@@ -1364,37 +1384,30 @@  function_resolver::infer_vector_or_tuple_type (unsigned int argno,
   if (actual == error_mark_node)
     return NUM_TYPE_SUFFIXES;
 
-  /* A linear search should be OK here, since the code isn't hot and
-     the number of types is only small.  */
-  for (unsigned int size_i = 0; size_i < MAX_TUPLE_SIZE; ++size_i)
-    for (unsigned int suffix_i = 0; suffix_i < NUM_TYPE_SUFFIXES; ++suffix_i)
-      {
-	vector_type_index type_i = type_suffixes[suffix_i].vector_type;
-	tree type = acle_vector_types[size_i][type_i];
-	if (type && matches_type_p (type, actual))
-	  {
-	    if (size_i + 1 == num_vectors)
-	      return type_suffix_index (suffix_i);
-
-	    if (num_vectors == 1)
-	      error_at (location, "passing %qT to argument %d of %qE, which"
-			" expects a single SVE vector rather than a tuple",
-			actual, argno + 1, fndecl);
-	    else if (size_i == 0 && type_i != VECTOR_TYPE_svbool_t)
-	      /* num_vectors is always != 1, so the singular isn't needed.  */
-	      error_n (location, num_vectors, "%qT%d%qE%d",
-		       "passing single vector %qT to argument %d"
-		       " of %qE, which expects a tuple of %d vectors",
-		       actual, argno + 1, fndecl, num_vectors);
-	    else
-	      /* num_vectors is always != 1, so the singular isn't needed.  */
-	      error_n (location, num_vectors, "%qT%d%qE%d",
-		       "passing %qT to argument %d of %qE, which"
-		       " expects a tuple of %d vectors", actual, argno + 1,
-		       fndecl, num_vectors);
-	    return NUM_TYPE_SUFFIXES;
-	  }
-      }
+  if (auto sve_type = find_sve_type (actual))
+    {
+      if (sve_type.num_vectors == num_vectors)
+	return sve_type.type;
+
+      if (num_vectors == 1)
+	error_at (location, "passing %qT to argument %d of %qE, which"
+		  " expects a single SVE vector rather than a tuple",
+		  actual, argno + 1, fndecl);
+      else if (sve_type.num_vectors == 1
+	       && sve_type.type != TYPE_SUFFIX_b)
+	/* num_vectors is always != 1, so the singular isn't needed.  */
+	error_n (location, num_vectors, "%qT%d%qE%d",
+		 "passing single vector %qT to argument %d"
+		 " of %qE, which expects a tuple of %d vectors",
+		 actual, argno + 1, fndecl, num_vectors);
+      else
+	/* num_vectors is always != 1, so the singular isn't needed.  */
+	error_n (location, num_vectors, "%qT%d%qE%d",
+		 "passing %qT to argument %d of %qE, which"
+		 " expects a tuple of %d vectors", actual, argno + 1,
+		 fndecl, num_vectors);
+      return NUM_TYPE_SUFFIXES;
+    }
 
   if (num_vectors == 1)
     error_at (location, "passing %qT to argument %d of %qE, which"
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
index dde35e15259..0dbd06791b8 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.h
+++ b/gcc/config/aarch64/aarch64-sve-builtins.h
@@ -263,6 +263,40 @@  struct group_suffix_info
   unsigned int vectors_per_tuple;
 };
 
+/* Represents an SVE vector, predicate, tuple of vectors, or tuple of
+   predicates.  There is also a representation of "no type"/"invalid type".  */
+struct sve_type
+{
+  sve_type () = default;
+  sve_type (type_suffix_index type) : type (type), num_vectors (1) {}
+  sve_type (type_suffix_index type, unsigned int num_vectors)
+    : type (type), num_vectors (num_vectors) {}
+
+  /* Return true if the type is valid.  */
+  explicit operator bool () const { return type != NUM_TYPE_SUFFIXES; }
+
+  bool operator== (const sve_type &) const;
+  bool operator!= (const sve_type &x) const { return !operator== (x); }
+
+  /* This is one of:
+
+     - TYPE_SUFFIX_b for svbool_t-based types
+     - TYPE_SUFFIX_c for svcount_t-based types
+     - the type suffix of a data element for SVE data vectors and tuples
+     - NUM_TYPE_SUFFIXES for invalid types.  */
+  type_suffix_index type = NUM_TYPE_SUFFIXES;
+
+  /* If the type is a tuple, this is the number of vectors in the tuple,
+     otherwise it is 1.  */
+  unsigned int num_vectors = 1;
+};
+
+inline bool
+sve_type::operator== (const sve_type &other) const
+{
+  return type == other.type && num_vectors == other.num_vectors;
+}
+
 /* Static information about a set of functions.  */
 struct function_group_info
 {
@@ -413,12 +447,11 @@  public:
   function_resolver (location_t, const function_instance &, tree,
 		     vec<tree, va_gc> &);
 
-  tree get_vector_type (type_suffix_index);
   const char *get_scalar_type_name (type_suffix_index);
   tree get_argument_type (unsigned int);
   bool scalar_argument_p (unsigned int);
 
-  tree report_no_such_form (type_suffix_index);
+  tree report_no_such_form (sve_type);
   tree lookup_form (mode_suffix_index,
 		    type_suffix_index = NUM_TYPE_SUFFIXES,
 		    type_suffix_index = NUM_TYPE_SUFFIXES,