Home | History | Annotate | Line # | Download | only in aarch64
aarch64-sve-builtins.h revision 1.1.1.2
      1 /* ACLE support for AArch64 SVE
      2    Copyright (C) 2018-2022 Free Software Foundation, Inc.
      3 
      4    This file is part of GCC.
      5 
      6    GCC is free software; you can redistribute it and/or modify it
      7    under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3, or (at your option)
      9    any later version.
     10 
     11    GCC is distributed in the hope that it will be useful, but
     12    WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14    General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with GCC; see the file COPYING3.  If not see
     18    <http://www.gnu.org/licenses/>.  */
     19 
     20 #ifndef GCC_AARCH64_SVE_BUILTINS_H
     21 #define GCC_AARCH64_SVE_BUILTINS_H
     22 
     23 /* The full name of an SVE ACLE function is the concatenation of:
     24 
     25    - the base name ("svadd", etc.)
     26    - the "mode" suffix ("_n", "_index", etc.)
     27    - the type suffixes ("_s32", "_b8", etc.)
     28    - the predication suffix ("_x", "_z", etc.)
     29 
     30    Each piece of information is individually useful, so we retain this
     31    classification throughout:
     32 
     33    - function_base represents the base name
     34 
     35    - mode_suffix_index represents the mode suffix
     36 
     37    - type_suffix_index represents individual type suffixes, while
     38      type_suffix_pair represents a pair of them
     39 
     40    - prediction_index extends the predication suffix with an additional
     41      alternative: PRED_implicit for implicitly-predicated operations
     42 
     43    In addition to its unique full name, a function may have a shorter
     44    overloaded alias.  This alias removes pieces of the suffixes that
     45    can be inferred from the arguments, such as by shortening the mode
     46    suffix or dropping some of the type suffixes.  The base name and the
     47    predication suffix stay the same.
     48 
     49    The function_shape class describes what arguments a given function
     50    takes and what its overloaded alias is called.  In broad terms,
     51    function_base describes how the underlying instruction behaves while
     52    function_shape describes how that instruction has been presented at
     53    the language level.
     54 
     55    The static list of functions uses function_group to describe a group
     56    of related functions.  The function_builder class is responsible for
     57    expanding this static description into a list of individual functions
     58    and registering the associated built-in functions.  function_instance
     59    describes one of these individual functions in terms of the properties
     60    described above.
     61 
     62    The classes involved in compiling a function call are:
     63 
     64    - function_resolver, which resolves an overloaded function call to a
     65      specific function_instance and its associated function decl
     66 
     67    - function_checker, which checks whether the values of the arguments
     68      conform to the ACLE specification
     69 
     70    - gimple_folder, which tries to fold a function call at the gimple level
     71 
     72    - function_expander, which expands a function call into rtl instructions
     73 
     74    function_resolver and function_checker operate at the language level
     75    and so are associated with the function_shape.  gimple_folder and
     76    function_expander are concerned with the behavior of the function
     77    and so are associated with the function_base.
     78 
     79    Note that we've specifically chosen not to fold calls in the frontend,
     80    since SVE intrinsics will hardly ever fold a useful language-level
     81    constant.  */
     82 namespace aarch64_sve
     83 {
     84 /* The maximum number of vectors in an ACLE tuple type.  */
     85 const unsigned int MAX_TUPLE_SIZE = 4;
     86 
     87 /* Used to represent the default merge argument index for _m functions.
     88    The actual index depends on how many arguments the function takes.  */
     89 const unsigned int DEFAULT_MERGE_ARGNO = ~0U;
     90 
     91 /* Flags that describe what a function might do, in addition to reading
     92    its arguments and returning a result.  */
     93 const unsigned int CP_READ_FPCR = 1U << 0;
     94 const unsigned int CP_RAISE_FP_EXCEPTIONS = 1U << 1;
     95 const unsigned int CP_READ_MEMORY = 1U << 2;
     96 const unsigned int CP_PREFETCH_MEMORY = 1U << 3;
     97 const unsigned int CP_WRITE_MEMORY = 1U << 4;
     98 const unsigned int CP_READ_FFR = 1U << 5;
     99 const unsigned int CP_WRITE_FFR = 1U << 6;
    100 
    101 /* Enumerates the SVE predicate and (data) vector types, together called
    102    "vector types" for brevity.  */
    103 enum vector_type_index
    104 {
    105 #define DEF_SVE_TYPE(ACLE_NAME, NCHARS, ABI_NAME, SCALAR_TYPE) \
    106   VECTOR_TYPE_ ## ACLE_NAME,
    107 #include "aarch64-sve-builtins.def"
    108   NUM_VECTOR_TYPES
    109 };
    110 
    111 /* Classifies the available measurement units for an address displacement.  */
    112 enum units_index
    113 {
    114   UNITS_none,
    115   UNITS_bytes,
    116   UNITS_elements,
    117   UNITS_vectors
    118 };
    119 
    120 /* Describes the various uses of a governing predicate.  */
    121 enum predication_index
    122 {
    123   /* No governing predicate is present.  */
    124   PRED_none,
    125 
    126   /* A governing predicate is present but there is no predication suffix
    127      associated with it.  This is used when the result is neither a vector
    128      nor a predicate, since the distinction between "zeroing" and "merging"
    129      doesn't apply in that case.  It is also used when a suffix would be
    130      redundant (such as for loads and comparisons, which are inherently
    131      zeroing operations).  */
    132   PRED_implicit,
    133 
    134   /* Merging predication: copy inactive lanes from the first data argument
    135      to the vector result.  */
    136   PRED_m,
    137 
    138   /* "Don't care" predication: set inactive lanes of the vector result
    139      to arbitrary values.  */
    140   PRED_x,
    141 
    142   /* Zero predication: set inactive lanes of the vector result to zero.  */
    143   PRED_z,
    144 
    145   NUM_PREDS
    146 };
    147 
    148 /* Classifies element types, based on type suffixes with the bit count
    149    removed.  */
    150 enum type_class_index
    151 {
    152   TYPE_bool,
    153   TYPE_bfloat,
    154   TYPE_float,
    155   TYPE_signed,
    156   TYPE_unsigned,
    157   NUM_TYPE_CLASSES
    158 };
    159 
    160 /* Classifies an operation into "modes"; for example, to distinguish
    161    vector-scalar operations from vector-vector operations, or to
    162    distinguish between different addressing modes.  This classification
    163    accounts for the function suffixes that occur between the base name
    164    and the first type suffix.  */
    165 enum mode_suffix_index
    166 {
    167 #define DEF_SVE_MODE(NAME, BASE, DISPLACEMENT, UNITS) MODE_##NAME,
    168 #include "aarch64-sve-builtins.def"
    169   MODE_none
    170 };
    171 
    172 /* Enumerates the possible type suffixes.  Each suffix is associated with
    173    a vector type, but for predicates provides extra information about the
    174    element size.  */
    175 enum type_suffix_index
    176 {
    177 #define DEF_SVE_TYPE_SUFFIX(NAME, ACLE_TYPE, CLASS, BITS, MODE) \
    178   TYPE_SUFFIX_ ## NAME,
    179 #include "aarch64-sve-builtins.def"
    180   NUM_TYPE_SUFFIXES
    181 };
    182 
    183 /* Combines two type suffixes.  */
    184 typedef enum type_suffix_index type_suffix_pair[2];
    185 
    186 class function_base;
    187 class function_shape;
    188 
    189 /* Static information about a mode suffix.  */
    190 struct mode_suffix_info
    191 {
    192   /* The suffix string itself.  */
    193   const char *string;
    194 
    195   /* The type of the vector base address, or NUM_VECTOR_TYPES if the
    196      mode does not include a vector base address.  */
    197   vector_type_index base_vector_type;
    198 
    199   /* The type of the vector displacement, or NUM_VECTOR_TYPES if the
    200      mode does not include a vector displacement.  (Note that scalar
    201      displacements are always int64_t.)  */
    202   vector_type_index displacement_vector_type;
    203 
    204   /* The units in which the vector or scalar displacement is measured,
    205      or UNITS_none if the mode doesn't take a displacement.  */
    206   units_index displacement_units;
    207 };
    208 
    209 /* Static information about a type suffix.  */
    210 struct type_suffix_info
    211 {
    212   /* The suffix string itself.  */
    213   const char *string;
    214 
    215   /* The associated ACLE vector or predicate type.  */
    216   vector_type_index vector_type : 8;
    217 
    218   /* What kind of type the suffix represents.  */
    219   type_class_index tclass : 8;
    220 
    221   /* The number of bits and bytes in an element.  For predicates this
    222      measures the associated data elements.  */
    223   unsigned int element_bits : 8;
    224   unsigned int element_bytes : 8;
    225 
    226   /* True if the suffix is for an integer type.  */
    227   unsigned int integer_p : 1;
    228   /* True if the suffix is for an unsigned type.  */
    229   unsigned int unsigned_p : 1;
    230   /* True if the suffix is for a floating-point type.  */
    231   unsigned int float_p : 1;
    232   /* True if the suffix is for a boolean type.  */
    233   unsigned int bool_p : 1;
    234   unsigned int spare : 12;
    235 
    236   /* The associated vector or predicate mode.  */
    237   machine_mode vector_mode : 16;
    238 };
    239 
    240 /* Static information about a set of functions.  */
    241 struct function_group_info
    242 {
    243   /* The base name, as a string.  */
    244   const char *base_name;
    245 
    246   /* Describes the behavior associated with the function base name.  */
    247   const function_base *const *base;
    248 
    249   /* The shape of the functions, as described above the class definition.
    250      It's possible to have entries with the same base name but different
    251      shapes.  */
    252   const function_shape *const *shape;
    253 
    254   /* A list of the available type suffixes, and of the available predication
    255      types.  The function supports every combination of the two.
    256 
    257      The list of type suffixes is terminated by two NUM_TYPE_SUFFIXES
    258      while the list of predication types is terminated by NUM_PREDS.
    259      The list of type suffixes is lexicographically ordered based
    260      on the index value.  */
    261   const type_suffix_pair *types;
    262   const predication_index *preds;
    263 
    264   /* The architecture extensions that the functions require, as a set of
    265      AARCH64_FL_* flags.  */
    266   uint64_t required_extensions;
    267 };
    268 
    269 /* Describes a single fully-resolved function (i.e. one that has a
    270    unique full name).  */
    271 class GTY((user)) function_instance
    272 {
    273 public:
    274   function_instance (const char *, const function_base *,
    275 		     const function_shape *, mode_suffix_index,
    276 		     const type_suffix_pair &, predication_index);
    277 
    278   bool operator== (const function_instance &) const;
    279   bool operator!= (const function_instance &) const;
    280   hashval_t hash () const;
    281 
    282   unsigned int call_properties () const;
    283   bool reads_global_state_p () const;
    284   bool modifies_global_state_p () const;
    285   bool could_trap_p () const;
    286 
    287   unsigned int vectors_per_tuple () const;
    288   tree memory_scalar_type () const;
    289   machine_mode memory_vector_mode () const;
    290 
    291   const mode_suffix_info &mode_suffix () const;
    292   tree base_vector_type () const;
    293   tree displacement_vector_type () const;
    294   units_index displacement_units () const;
    295 
    296   const type_suffix_info &type_suffix (unsigned int) const;
    297   tree scalar_type (unsigned int) const;
    298   tree vector_type (unsigned int) const;
    299   tree tuple_type (unsigned int) const;
    300   unsigned int elements_per_vq (unsigned int i) const;
    301   machine_mode vector_mode (unsigned int) const;
    302   machine_mode gp_mode (unsigned int) const;
    303 
    304   /* The properties of the function.  (The explicit "enum"s are required
    305      for gengtype.)  */
    306   const char *base_name;
    307   const function_base *base;
    308   const function_shape *shape;
    309   enum mode_suffix_index mode_suffix_id;
    310   type_suffix_pair type_suffix_ids;
    311   enum predication_index pred;
    312 };
    313 
    314 class registered_function;
    315 
    316 /* A class for building and registering function decls.  */
    317 class function_builder
    318 {
    319 public:
    320   function_builder ();
    321   ~function_builder ();
    322 
    323   void add_unique_function (const function_instance &, tree,
    324 			    vec<tree> &, uint64_t, bool);
    325   void add_overloaded_function (const function_instance &, uint64_t);
    326   void add_overloaded_functions (const function_group_info &,
    327 				 mode_suffix_index);
    328 
    329   void register_function_group (const function_group_info &);
    330 
    331 private:
    332   void append_name (const char *);
    333   char *finish_name ();
    334 
    335   char *get_name (const function_instance &, bool);
    336 
    337   tree get_attributes (const function_instance &);
    338 
    339   registered_function &add_function (const function_instance &,
    340 				     const char *, tree, tree,
    341 				     uint64_t, bool, bool);
    342 
    343   /* The function type to use for functions that are resolved by
    344      function_resolver.  */
    345   tree m_overload_type;
    346 
    347   /* True if we should create a separate decl for each instance of an
    348      overloaded function, instead of using function_resolver.  */
    349   bool m_direct_overloads;
    350 
    351   /* Used for building up function names.  */
    352   obstack m_string_obstack;
    353 
    354   /* Maps all overloaded function names that we've registered so far
    355      to their associated function_instances.  */
    356   hash_map<nofree_string_hash, registered_function *> m_overload_names;
    357 };
    358 
    359 /* A base class for handling calls to built-in functions.  */
    360 class function_call_info : public function_instance
    361 {
    362 public:
    363   function_call_info (location_t, const function_instance &, tree);
    364 
    365   bool function_returns_void_p ();
    366 
    367   /* The location of the call.  */
    368   location_t location;
    369 
    370   /* The FUNCTION_DECL that is being called.  */
    371   tree fndecl;
    372 };
    373 
    374 /* A class for resolving an overloaded function call.  */
    375 class function_resolver : public function_call_info
    376 {
    377 public:
    378   enum { SAME_SIZE = 256, HALF_SIZE, QUARTER_SIZE };
    379   static const type_class_index SAME_TYPE_CLASS = NUM_TYPE_CLASSES;
    380 
    381   function_resolver (location_t, const function_instance &, tree,
    382 		     vec<tree, va_gc> &);
    383 
    384   tree get_vector_type (type_suffix_index);
    385   const char *get_scalar_type_name (type_suffix_index);
    386   tree get_argument_type (unsigned int);
    387   bool scalar_argument_p (unsigned int);
    388 
    389   tree report_no_such_form (type_suffix_index);
    390   tree lookup_form (mode_suffix_index,
    391 		    type_suffix_index = NUM_TYPE_SUFFIXES,
    392 		    type_suffix_index = NUM_TYPE_SUFFIXES);
    393   tree resolve_to (mode_suffix_index,
    394 		   type_suffix_index = NUM_TYPE_SUFFIXES,
    395 		   type_suffix_index = NUM_TYPE_SUFFIXES);
    396 
    397   type_suffix_index infer_integer_scalar_type (unsigned int);
    398   type_suffix_index infer_pointer_type (unsigned int, bool = false);
    399   type_suffix_index infer_vector_or_tuple_type (unsigned int, unsigned int);
    400   type_suffix_index infer_vector_type (unsigned int);
    401   type_suffix_index infer_integer_vector_type (unsigned int);
    402   type_suffix_index infer_unsigned_vector_type (unsigned int);
    403   type_suffix_index infer_sd_vector_type (unsigned int);
    404   type_suffix_index infer_tuple_type (unsigned int);
    405 
    406   bool require_vector_or_scalar_type (unsigned int);
    407 
    408   bool require_vector_type (unsigned int, vector_type_index);
    409   bool require_matching_vector_type (unsigned int, type_suffix_index);
    410   bool require_derived_vector_type (unsigned int, unsigned int,
    411 				    type_suffix_index,
    412 				    type_class_index = SAME_TYPE_CLASS,
    413 				    unsigned int = SAME_SIZE);
    414 
    415   bool require_scalar_type (unsigned int, const char *);
    416   bool require_pointer_type (unsigned int);
    417   bool require_matching_integer_scalar_type (unsigned int, unsigned int,
    418 					     type_suffix_index);
    419   bool require_derived_scalar_type (unsigned int, type_class_index,
    420 				    unsigned int = SAME_SIZE);
    421   bool require_matching_pointer_type (unsigned int, unsigned int,
    422 				      type_suffix_index);
    423   bool require_integer_immediate (unsigned int);
    424 
    425   vector_type_index infer_vector_base_type (unsigned int);
    426   vector_type_index infer_vector_displacement_type (unsigned int);
    427 
    428   mode_suffix_index resolve_sv_displacement (unsigned int,
    429 					     type_suffix_index, bool);
    430   mode_suffix_index resolve_gather_address (unsigned int,
    431 					    type_suffix_index, bool);
    432   mode_suffix_index resolve_adr_address (unsigned int);
    433 
    434   bool check_num_arguments (unsigned int);
    435   bool check_gp_argument (unsigned int, unsigned int &, unsigned int &);
    436   tree resolve_unary (type_class_index = SAME_TYPE_CLASS,
    437 		      unsigned int = SAME_SIZE, bool = false);
    438   tree resolve_uniform (unsigned int, unsigned int = 0);
    439   tree resolve_uniform_opt_n (unsigned int);
    440   tree finish_opt_n_resolution (unsigned int, unsigned int, type_suffix_index,
    441 				type_class_index = SAME_TYPE_CLASS,
    442 				unsigned int = SAME_SIZE,
    443 				type_suffix_index = NUM_TYPE_SUFFIXES);
    444 
    445   tree resolve ();
    446 
    447 private:
    448   /* The arguments to the overloaded function.  */
    449   vec<tree, va_gc> &m_arglist;
    450 };
    451 
    452 /* A class for checking that the semantic constraints on a function call are
    453    satisfied, such as arguments being integer constant expressions with
    454    a particular range.  The parent class's FNDECL is the decl that was
    455    called in the original source, before overload resolution.  */
    456 class function_checker : public function_call_info
    457 {
    458 public:
    459   function_checker (location_t, const function_instance &, tree,
    460 		    tree, unsigned int, tree *);
    461 
    462   bool require_immediate_either_or (unsigned int, HOST_WIDE_INT,
    463 				    HOST_WIDE_INT);
    464   bool require_immediate_enum (unsigned int, tree);
    465   bool require_immediate_lane_index (unsigned int, unsigned int = 1);
    466   bool require_immediate_one_of (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
    467 				 HOST_WIDE_INT, HOST_WIDE_INT);
    468   bool require_immediate_range (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT);
    469 
    470   bool check ();
    471 
    472 private:
    473   bool argument_exists_p (unsigned int);
    474 
    475   bool require_immediate (unsigned int, HOST_WIDE_INT &);
    476 
    477   /* The type of the resolved function.  */
    478   tree m_fntype;
    479 
    480   /* The arguments to the function.  */
    481   unsigned int m_nargs;
    482   tree *m_args;
    483 
    484   /* The first argument not associated with the function's predication
    485      type.  */
    486   unsigned int m_base_arg;
    487 };
    488 
    489 /* A class for folding a gimple function call.  */
    490 class gimple_folder : public function_call_info
    491 {
    492 public:
    493   gimple_folder (const function_instance &, tree,
    494 		 gimple_stmt_iterator *, gcall *);
    495 
    496   tree force_vector (gimple_seq &, tree, tree);
    497   tree convert_pred (gimple_seq &, tree, unsigned int);
    498   tree fold_contiguous_base (gimple_seq &, tree);
    499   tree load_store_cookie (tree);
    500 
    501   gimple *redirect_call (const function_instance &);
    502   gimple *fold_to_pfalse ();
    503   gimple *fold_to_ptrue ();
    504   gimple *fold_to_vl_pred (unsigned int);
    505 
    506   gimple *fold ();
    507 
    508   /* Where to insert extra statements that feed the final replacement.  */
    509   gimple_stmt_iterator *gsi;
    510 
    511   /* The call we're folding.  */
    512   gcall *call;
    513 
    514   /* The result of the call, or null if none.  */
    515   tree lhs;
    516 };
    517 
    518 /* A class for expanding a function call into RTL.  */
    519 class function_expander : public function_call_info
    520 {
    521 public:
    522   function_expander (const function_instance &, tree, tree, rtx);
    523   rtx expand ();
    524 
    525   insn_code direct_optab_handler (optab, unsigned int = 0);
    526   insn_code direct_optab_handler_for_sign (optab, optab, unsigned int = 0,
    527 					   machine_mode = E_VOIDmode);
    528 
    529   bool overlaps_input_p (rtx);
    530 
    531   rtx convert_to_pmode (rtx);
    532   rtx get_contiguous_base (machine_mode);
    533   rtx get_fallback_value (machine_mode, unsigned int,
    534 			  unsigned int, unsigned int &);
    535   rtx get_reg_target ();
    536   rtx get_nonoverlapping_reg_target ();
    537 
    538   void add_output_operand (insn_code);
    539   void add_input_operand (insn_code, rtx);
    540   void add_integer_operand (HOST_WIDE_INT);
    541   void add_mem_operand (machine_mode, rtx);
    542   void add_address_operand (rtx);
    543   void add_fixed_operand (rtx);
    544   rtx generate_insn (insn_code);
    545 
    546   void prepare_gather_address_operands (unsigned int, bool = true);
    547   void prepare_prefetch_operands ();
    548   void add_ptrue_hint (unsigned int, machine_mode);
    549   void rotate_inputs_left (unsigned int, unsigned int);
    550   bool try_negating_argument (unsigned int, machine_mode);
    551 
    552   rtx use_exact_insn (insn_code);
    553   rtx use_unpred_insn (insn_code);
    554   rtx use_pred_x_insn (insn_code);
    555   rtx use_cond_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
    556   rtx use_vcond_mask_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
    557   rtx use_contiguous_load_insn (insn_code);
    558   rtx use_contiguous_prefetch_insn (insn_code);
    559   rtx use_contiguous_store_insn (insn_code);
    560 
    561   rtx map_to_rtx_codes (rtx_code, rtx_code, int,
    562 			unsigned int = DEFAULT_MERGE_ARGNO);
    563   rtx map_to_unspecs (int, int, int, unsigned int = DEFAULT_MERGE_ARGNO);
    564 
    565   /* The function call expression.  */
    566   tree call_expr;
    567 
    568   /* For functions that return a value, this is the preferred location
    569      of that value.  It could be null or could have a different mode
    570      from the function return type.  */
    571   rtx possible_target;
    572 
    573   /* The expanded arguments.  */
    574   auto_vec<rtx, 16> args;
    575 
    576 private:
    577   /* Used to build up the operands to an instruction.  */
    578   auto_vec<expand_operand, 8> m_ops;
    579 };
    580 
    581 /* Provides information about a particular function base name, and handles
    582    tasks related to the base name.  */
    583 class function_base
    584 {
    585 public:
    586   /* Return a set of CP_* flags that describe what the function might do,
    587      in addition to reading its arguments and returning a result.  */
    588   virtual unsigned int call_properties (const function_instance &) const;
    589 
    590   /* If the function operates on tuples of vectors, return the number
    591      of vectors in the tuples, otherwise return 1.  */
    592   virtual unsigned int vectors_per_tuple () const { return 1; }
    593 
    594   /* If the function addresses memory, return the type of a single
    595      scalar memory element.  */
    596   virtual tree
    597   memory_scalar_type (const function_instance &) const
    598   {
    599     gcc_unreachable ();
    600   }
    601 
    602   /* If the function addresses memory, return a vector mode whose
    603      GET_MODE_NUNITS is the number of elements addressed and whose
    604      GET_MODE_INNER is the mode of a single scalar memory element.  */
    605   virtual machine_mode
    606   memory_vector_mode (const function_instance &) const
    607   {
    608     gcc_unreachable ();
    609   }
    610 
    611   /* Try to fold the given gimple call.  Return the new gimple statement
    612      on success, otherwise return null.  */
    613   virtual gimple *fold (gimple_folder &) const { return NULL; }
    614 
    615   /* Expand the given call into rtl.  Return the result of the function,
    616      or an arbitrary value if the function doesn't return a result.  */
    617   virtual rtx expand (function_expander &) const = 0;
    618 };
    619 
    620 /* Classifies functions into "shapes".  The idea is to take all the
    621    type signatures for a set of functions, remove the governing predicate
    622    (if any), and classify what's left based on:
    623 
    624    - the number of arguments
    625 
    626    - the process of determining the types in the signature from the mode
    627      and type suffixes in the function name (including types that are not
    628      affected by the suffixes)
    629 
    630    - which arguments must be integer constant expressions, and what range
    631      those arguments have
    632 
    633    - the process for mapping overloaded names to "full" names.  */
    634 class function_shape
    635 {
    636 public:
    637   virtual bool explicit_type_suffix_p (unsigned int) const = 0;
    638 
    639   /* Define all functions associated with the given group.  */
    640   virtual void build (function_builder &,
    641 		      const function_group_info &) const = 0;
    642 
    643   /* Try to resolve the overloaded call.  Return the non-overloaded
    644      function decl on success and error_mark_node on failure.  */
    645   virtual tree resolve (function_resolver &) const = 0;
    646 
    647   /* Check whether the given call is semantically valid.  Return true
    648      if it is, otherwise report an error and return false.  */
    649   virtual bool check (function_checker &) const { return true; }
    650 };
    651 
    652 /* RAII class for enabling enough SVE features to define the built-in
    653    types and implement the arm_sve.h pragma.  */
    654 class sve_switcher : public aarch64_simd_switcher
    655 {
    656 public:
    657   sve_switcher ();
    658   ~sve_switcher ();
    659 
    660 private:
    661   unsigned int m_old_maximum_field_alignment;
    662   bool m_old_have_regs_of_mode[MAX_MACHINE_MODE];
    663 };
    664 
    665 extern const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1];
    666 extern const mode_suffix_info mode_suffixes[MODE_none + 1];
    667 
    668 extern tree scalar_types[NUM_VECTOR_TYPES];
    669 extern tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1];
    670 extern tree acle_svpattern;
    671 extern tree acle_svprfop;
    672 
    673 /* Return the ACLE type svbool_t.  */
    674 inline tree
    675 get_svbool_t (void)
    676 {
    677   return acle_vector_types[0][VECTOR_TYPE_svbool_t];
    678 }
    679 
    680 /* Try to find a mode with the given mode_suffix_info fields.  Return the
    681    mode on success or MODE_none on failure.  */
    682 inline mode_suffix_index
    683 find_mode_suffix (vector_type_index base_vector_type,
    684 		  vector_type_index displacement_vector_type,
    685 		  units_index displacement_units)
    686 {
    687   for (unsigned int mode_i = 0; mode_i < ARRAY_SIZE (mode_suffixes); ++mode_i)
    688     {
    689       const mode_suffix_info &mode = mode_suffixes[mode_i];
    690       if (mode.base_vector_type == base_vector_type
    691 	  && mode.displacement_vector_type == displacement_vector_type
    692 	  && mode.displacement_units == displacement_units)
    693 	return mode_suffix_index (mode_i);
    694     }
    695   return MODE_none;
    696 }
    697 
    698 /* Return the type suffix associated with ELEMENT_BITS-bit elements of type
    699    class TCLASS.  */
    700 inline type_suffix_index
    701 find_type_suffix (type_class_index tclass, unsigned int element_bits)
    702 {
    703   for (unsigned int i = 0; i < NUM_TYPE_SUFFIXES; ++i)
    704     if (type_suffixes[i].tclass == tclass
    705 	&& type_suffixes[i].element_bits == element_bits)
    706       return type_suffix_index (i);
    707   gcc_unreachable ();
    708 }
    709 
    710 /* Return the single field in tuple type TYPE.  */
    711 inline tree
    712 tuple_type_field (tree type)
    713 {
    714   for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
    715     if (TREE_CODE (field) == FIELD_DECL)
    716       return field;
    717   gcc_unreachable ();
    718 }
    719 
    720 inline function_instance::
    721 function_instance (const char *base_name_in,
    722 		   const function_base *base_in,
    723 		   const function_shape *shape_in,
    724 		   mode_suffix_index mode_suffix_id_in,
    725 		   const type_suffix_pair &type_suffix_ids_in,
    726 		   predication_index pred_in)
    727   : base_name (base_name_in), base (base_in), shape (shape_in),
    728     mode_suffix_id (mode_suffix_id_in), pred (pred_in)
    729 {
    730   memcpy (type_suffix_ids, type_suffix_ids_in, sizeof (type_suffix_ids));
    731 }
    732 
    733 inline bool
    734 function_instance::operator== (const function_instance &other) const
    735 {
    736   return (base == other.base
    737 	  && shape == other.shape
    738 	  && mode_suffix_id == other.mode_suffix_id
    739 	  && pred == other.pred
    740 	  && type_suffix_ids[0] == other.type_suffix_ids[0]
    741 	  && type_suffix_ids[1] == other.type_suffix_ids[1]);
    742 }
    743 
    744 inline bool
    745 function_instance::operator!= (const function_instance &other) const
    746 {
    747   return !operator== (other);
    748 }
    749 
    750 /* If the function operates on tuples of vectors, return the number
    751    of vectors in the tuples, otherwise return 1.  */
    752 inline unsigned int
    753 function_instance::vectors_per_tuple () const
    754 {
    755   return base->vectors_per_tuple ();
    756 }
    757 
    758 /* If the function addresses memory, return the type of a single
    759    scalar memory element.  */
    760 inline tree
    761 function_instance::memory_scalar_type () const
    762 {
    763   return base->memory_scalar_type (*this);
    764 }
    765 
    766 /* If the function addresses memory, return a vector mode whose
    767    GET_MODE_NUNITS is the number of elements addressed and whose
    768    GET_MODE_INNER is the mode of a single scalar memory element.  */
    769 inline machine_mode
    770 function_instance::memory_vector_mode () const
    771 {
    772   return base->memory_vector_mode (*this);
    773 }
    774 
    775 /* Return information about the function's mode suffix.  */
    776 inline const mode_suffix_info &
    777 function_instance::mode_suffix () const
    778 {
    779   return mode_suffixes[mode_suffix_id];
    780 }
    781 
    782 /* Return the type of the function's vector base address argument,
    783    or null it doesn't have a vector base address.  */
    784 inline tree
    785 function_instance::base_vector_type () const
    786 {
    787   return acle_vector_types[0][mode_suffix ().base_vector_type];
    788 }
    789 
    790 /* Return the type of the function's vector index or offset argument,
    791    or null if doesn't have a vector index or offset argument.  */
    792 inline tree
    793 function_instance::displacement_vector_type () const
    794 {
    795   return acle_vector_types[0][mode_suffix ().displacement_vector_type];
    796 }
    797 
    798 /* If the function takes a vector or scalar displacement, return the units
    799    in which the displacement is measured, otherwise return UNITS_none.  */
    800 inline units_index
    801 function_instance::displacement_units () const
    802 {
    803   return mode_suffix ().displacement_units;
    804 }
    805 
    806 /* Return information about type suffix I.  */
    807 inline const type_suffix_info &
    808 function_instance::type_suffix (unsigned int i) const
    809 {
    810   return type_suffixes[type_suffix_ids[i]];
    811 }
    812 
    813 /* Return the scalar type associated with type suffix I.  */
    814 inline tree
    815 function_instance::scalar_type (unsigned int i) const
    816 {
    817   return scalar_types[type_suffix (i).vector_type];
    818 }
    819 
    820 /* Return the vector type associated with type suffix I.  */
    821 inline tree
    822 function_instance::vector_type (unsigned int i) const
    823 {
    824   return acle_vector_types[0][type_suffix (i).vector_type];
    825 }
    826 
    827 /* If the function operates on tuples of vectors, return the tuple type
    828    associated with type suffix I, otherwise return the vector type associated
    829    with type suffix I.  */
    830 inline tree
    831 function_instance::tuple_type (unsigned int i) const
    832 {
    833   unsigned int num_vectors = vectors_per_tuple ();
    834   return acle_vector_types[num_vectors - 1][type_suffix (i).vector_type];
    835 }
    836 
    837 /* Return the number of elements of type suffix I that fit within a
    838    128-bit block.  */
    839 inline unsigned int
    840 function_instance::elements_per_vq (unsigned int i) const
    841 {
    842   return 128 / type_suffix (i).element_bits;
    843 }
    844 
    845 /* Return the vector or predicate mode associated with type suffix I.  */
    846 inline machine_mode
    847 function_instance::vector_mode (unsigned int i) const
    848 {
    849   return type_suffix (i).vector_mode;
    850 }
    851 
    852 /* Return the mode of the governing predicate to use when operating on
    853    type suffix I.  */
    854 inline machine_mode
    855 function_instance::gp_mode (unsigned int i) const
    856 {
    857   return aarch64_sve_pred_mode (type_suffix (i).element_bytes).require ();
    858 }
    859 
    860 /* Return true if the function has no return value.  */
    861 inline bool
    862 function_call_info::function_returns_void_p ()
    863 {
    864   return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
    865 }
    866 
    867 /* Default implementation of function::call_properties, with conservatively
    868    correct behavior for floating-point instructions.  */
    869 inline unsigned int
    870 function_base::call_properties (const function_instance &instance) const
    871 {
    872   unsigned int flags = 0;
    873   if (instance.type_suffix (0).float_p || instance.type_suffix (1).float_p)
    874     flags |= CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
    875   return flags;
    876 }
    877 
    878 }
    879 
    880 #endif
    881