1  /* ACLE support for AArch64 SVE
       2     Copyright (C) 2018-2023 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    aarch64_feature_flags 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> &, aarch64_feature_flags, bool);
     325    void add_overloaded_function (const function_instance &,
     326  				aarch64_feature_flags);
     327    void add_overloaded_functions (const function_group_info &,
     328  				 mode_suffix_index);
     329  
     330    void register_function_group (const function_group_info &);
     331  
     332  private:
     333    void append_name (const char *);
     334    char *finish_name ();
     335  
     336    char *get_name (const function_instance &, bool);
     337  
     338    tree get_attributes (const function_instance &);
     339  
     340    registered_function &add_function (const function_instance &,
     341  				     const char *, tree, tree,
     342  				     aarch64_feature_flags, bool, bool);
     343  
     344    /* The function type to use for functions that are resolved by
     345       function_resolver.  */
     346    tree m_overload_type;
     347  
     348    /* True if we should create a separate decl for each instance of an
     349       overloaded function, instead of using function_resolver.  */
     350    bool m_direct_overloads;
     351  
     352    /* Used for building up function names.  */
     353    obstack m_string_obstack;
     354  
     355    /* Maps all overloaded function names that we've registered so far
     356       to their associated function_instances.  */
     357    hash_map<nofree_string_hash, registered_function *> m_overload_names;
     358  };
     359  
     360  /* A base class for handling calls to built-in functions.  */
     361  class function_call_info : public function_instance
     362  {
     363  public:
     364    function_call_info (location_t, const function_instance &, tree);
     365  
     366    bool function_returns_void_p ();
     367  
     368    /* The location of the call.  */
     369    location_t location;
     370  
     371    /* The FUNCTION_DECL that is being called.  */
     372    tree fndecl;
     373  };
     374  
     375  /* A class for resolving an overloaded function call.  */
     376  class function_resolver : public function_call_info
     377  {
     378  public:
     379    enum { SAME_SIZE = 256, HALF_SIZE, QUARTER_SIZE };
     380    static const type_class_index SAME_TYPE_CLASS = NUM_TYPE_CLASSES;
     381  
     382    function_resolver (location_t, const function_instance &, tree,
     383  		     vec<tree, va_gc> &);
     384  
     385    tree get_vector_type (type_suffix_index);
     386    const char *get_scalar_type_name (type_suffix_index);
     387    tree get_argument_type (unsigned int);
     388    bool scalar_argument_p (unsigned int);
     389  
     390    tree report_no_such_form (type_suffix_index);
     391    tree lookup_form (mode_suffix_index,
     392  		    type_suffix_index = NUM_TYPE_SUFFIXES,
     393  		    type_suffix_index = NUM_TYPE_SUFFIXES);
     394    tree resolve_to (mode_suffix_index,
     395  		   type_suffix_index = NUM_TYPE_SUFFIXES,
     396  		   type_suffix_index = NUM_TYPE_SUFFIXES);
     397  
     398    type_suffix_index infer_integer_scalar_type (unsigned int);
     399    type_suffix_index infer_pointer_type (unsigned int, bool = false);
     400    type_suffix_index infer_vector_or_tuple_type (unsigned int, unsigned int);
     401    type_suffix_index infer_vector_type (unsigned int);
     402    type_suffix_index infer_integer_vector_type (unsigned int);
     403    type_suffix_index infer_unsigned_vector_type (unsigned int);
     404    type_suffix_index infer_sd_vector_type (unsigned int);
     405    type_suffix_index infer_tuple_type (unsigned int);
     406  
     407    bool require_vector_or_scalar_type (unsigned int);
     408  
     409    bool require_vector_type (unsigned int, vector_type_index);
     410    bool require_matching_vector_type (unsigned int, type_suffix_index);
     411    bool require_derived_vector_type (unsigned int, unsigned int,
     412  				    type_suffix_index,
     413  				    type_class_index = SAME_TYPE_CLASS,
     414  				    unsigned int = SAME_SIZE);
     415  
     416    bool require_scalar_type (unsigned int, const char *);
     417    bool require_pointer_type (unsigned int);
     418    bool require_matching_integer_scalar_type (unsigned int, unsigned int,
     419  					     type_suffix_index);
     420    bool require_derived_scalar_type (unsigned int, type_class_index,
     421  				    unsigned int = SAME_SIZE);
     422    bool require_matching_pointer_type (unsigned int, unsigned int,
     423  				      type_suffix_index);
     424    bool require_integer_immediate (unsigned int);
     425  
     426    vector_type_index infer_vector_base_type (unsigned int);
     427    vector_type_index infer_vector_displacement_type (unsigned int);
     428  
     429    mode_suffix_index resolve_sv_displacement (unsigned int,
     430  					     type_suffix_index, bool);
     431    mode_suffix_index resolve_gather_address (unsigned int,
     432  					    type_suffix_index, bool);
     433    mode_suffix_index resolve_adr_address (unsigned int);
     434  
     435    bool check_num_arguments (unsigned int);
     436    bool check_gp_argument (unsigned int, unsigned int &, unsigned int &);
     437    tree resolve_unary (type_class_index = SAME_TYPE_CLASS,
     438  		      unsigned int = SAME_SIZE, bool = false);
     439    tree resolve_uniform (unsigned int, unsigned int = 0);
     440    tree resolve_uniform_opt_n (unsigned int);
     441    tree finish_opt_n_resolution (unsigned int, unsigned int, type_suffix_index,
     442  				type_class_index = SAME_TYPE_CLASS,
     443  				unsigned int = SAME_SIZE,
     444  				type_suffix_index = NUM_TYPE_SUFFIXES);
     445  
     446    tree resolve ();
     447  
     448  private:
     449    /* The arguments to the overloaded function.  */
     450    vec<tree, va_gc> &m_arglist;
     451  };
     452  
     453  /* A class for checking that the semantic constraints on a function call are
     454     satisfied, such as arguments being integer constant expressions with
     455     a particular range.  The parent class's FNDECL is the decl that was
     456     called in the original source, before overload resolution.  */
     457  class function_checker : public function_call_info
     458  {
     459  public:
     460    function_checker (location_t, const function_instance &, tree,
     461  		    tree, unsigned int, tree *);
     462  
     463    bool require_immediate_either_or (unsigned int, HOST_WIDE_INT,
     464  				    HOST_WIDE_INT);
     465    bool require_immediate_enum (unsigned int, tree);
     466    bool require_immediate_lane_index (unsigned int, unsigned int = 1);
     467    bool require_immediate_one_of (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
     468  				 HOST_WIDE_INT, HOST_WIDE_INT);
     469    bool require_immediate_range (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT);
     470  
     471    bool check ();
     472  
     473  private:
     474    bool argument_exists_p (unsigned int);
     475  
     476    bool require_immediate (unsigned int, HOST_WIDE_INT &);
     477  
     478    /* The type of the resolved function.  */
     479    tree m_fntype;
     480  
     481    /* The arguments to the function.  */
     482    unsigned int m_nargs;
     483    tree *m_args;
     484  
     485    /* The first argument not associated with the function's predication
     486       type.  */
     487    unsigned int m_base_arg;
     488  };
     489  
     490  /* A class for folding a gimple function call.  */
     491  class gimple_folder : public function_call_info
     492  {
     493  public:
     494    gimple_folder (const function_instance &, tree,
     495  		 gimple_stmt_iterator *, gcall *);
     496  
     497    tree force_vector (gimple_seq &, tree, tree);
     498    tree convert_pred (gimple_seq &, tree, unsigned int);
     499    tree fold_contiguous_base (gimple_seq &, tree);
     500    tree load_store_cookie (tree);
     501  
     502    gimple *redirect_call (const function_instance &);
     503    gimple *fold_to_cstu (poly_uint64);
     504    gimple *fold_to_pfalse ();
     505    gimple *fold_to_ptrue ();
     506    gimple *fold_to_vl_pred (unsigned int);
     507  
     508    gimple *fold ();
     509  
     510    /* Where to insert extra statements that feed the final replacement.  */
     511    gimple_stmt_iterator *gsi;
     512  
     513    /* The call we're folding.  */
     514    gcall *call;
     515  
     516    /* The result of the call, or null if none.  */
     517    tree lhs;
     518  };
     519  
     520  /* A class for expanding a function call into RTL.  */
     521  class function_expander : public function_call_info
     522  {
     523  public:
     524    function_expander (const function_instance &, tree, tree, rtx);
     525    rtx expand ();
     526  
     527    insn_code direct_optab_handler (optab, unsigned int = 0);
     528    insn_code direct_optab_handler_for_sign (optab, optab, unsigned int = 0,
     529  					   machine_mode = E_VOIDmode);
     530  
     531    bool overlaps_input_p (rtx);
     532  
     533    rtx convert_to_pmode (rtx);
     534    rtx get_contiguous_base (machine_mode);
     535    rtx get_fallback_value (machine_mode, unsigned int,
     536  			  unsigned int, unsigned int &);
     537    rtx get_reg_target ();
     538    rtx get_nonoverlapping_reg_target ();
     539  
     540    void add_output_operand (insn_code);
     541    void add_input_operand (insn_code, rtx);
     542    void add_integer_operand (HOST_WIDE_INT);
     543    void add_mem_operand (machine_mode, rtx);
     544    void add_address_operand (rtx);
     545    void add_fixed_operand (rtx);
     546    rtx generate_insn (insn_code);
     547  
     548    void prepare_gather_address_operands (unsigned int, bool = true);
     549    void prepare_prefetch_operands ();
     550    void add_ptrue_hint (unsigned int, machine_mode);
     551    void rotate_inputs_left (unsigned int, unsigned int);
     552    bool try_negating_argument (unsigned int, machine_mode);
     553  
     554    rtx use_exact_insn (insn_code);
     555    rtx use_unpred_insn (insn_code);
     556    rtx use_pred_x_insn (insn_code);
     557    rtx use_cond_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
     558    rtx use_vcond_mask_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
     559    rtx use_contiguous_load_insn (insn_code);
     560    rtx use_contiguous_prefetch_insn (insn_code);
     561    rtx use_contiguous_store_insn (insn_code);
     562  
     563    rtx map_to_rtx_codes (rtx_code, rtx_code, int,
     564  			unsigned int = DEFAULT_MERGE_ARGNO);
     565    rtx map_to_unspecs (int, int, int, unsigned int = DEFAULT_MERGE_ARGNO);
     566  
     567    /* The function call expression.  */
     568    tree call_expr;
     569  
     570    /* For functions that return a value, this is the preferred location
     571       of that value.  It could be null or could have a different mode
     572       from the function return type.  */
     573    rtx possible_target;
     574  
     575    /* The expanded arguments.  */
     576    auto_vec<rtx, 16> args;
     577  
     578  private:
     579    /* Used to build up the operands to an instruction.  */
     580    auto_vec<expand_operand, 8> m_ops;
     581  };
     582  
     583  /* Provides information about a particular function base name, and handles
     584     tasks related to the base name.  */
     585  class function_base
     586  {
     587  public:
     588    /* Return a set of CP_* flags that describe what the function might do,
     589       in addition to reading its arguments and returning a result.  */
     590    virtual unsigned int call_properties (const function_instance &) const;
     591  
     592    /* If the function operates on tuples of vectors, return the number
     593       of vectors in the tuples, otherwise return 1.  */
     594    virtual unsigned int vectors_per_tuple () const { return 1; }
     595  
     596    /* If the function addresses memory, return the type of a single
     597       scalar memory element.  */
     598    virtual tree
     599    memory_scalar_type (const function_instance &) const
     600    {
     601      gcc_unreachable ();
     602    }
     603  
     604    /* If the function addresses memory, return a vector mode whose
     605       GET_MODE_NUNITS is the number of elements addressed and whose
     606       GET_MODE_INNER is the mode of a single scalar memory element.  */
     607    virtual machine_mode
     608    memory_vector_mode (const function_instance &) const
     609    {
     610      gcc_unreachable ();
     611    }
     612  
     613    /* Try to fold the given gimple call.  Return the new gimple statement
     614       on success, otherwise return null.  */
     615    virtual gimple *fold (gimple_folder &) const { return NULL; }
     616  
     617    /* Expand the given call into rtl.  Return the result of the function,
     618       or an arbitrary value if the function doesn't return a result.  */
     619    virtual rtx expand (function_expander &) const = 0;
     620  };
     621  
     622  /* Classifies functions into "shapes".  The idea is to take all the
     623     type signatures for a set of functions, remove the governing predicate
     624     (if any), and classify what's left based on:
     625  
     626     - the number of arguments
     627  
     628     - the process of determining the types in the signature from the mode
     629       and type suffixes in the function name (including types that are not
     630       affected by the suffixes)
     631  
     632     - which arguments must be integer constant expressions, and what range
     633       those arguments have
     634  
     635     - the process for mapping overloaded names to "full" names.  */
     636  class function_shape
     637  {
     638  public:
     639    virtual bool explicit_type_suffix_p (unsigned int) const = 0;
     640  
     641    /* Define all functions associated with the given group.  */
     642    virtual void build (function_builder &,
     643  		      const function_group_info &) const = 0;
     644  
     645    /* Try to resolve the overloaded call.  Return the non-overloaded
     646       function decl on success and error_mark_node on failure.  */
     647    virtual tree resolve (function_resolver &) const = 0;
     648  
     649    /* Check whether the given call is semantically valid.  Return true
     650       if it is, otherwise report an error and return false.  */
     651    virtual bool check (function_checker &) const { return true; }
     652  };
     653  
     654  /* RAII class for enabling enough SVE features to define the built-in
     655     types and implement the arm_sve.h pragma.  */
     656  class sve_switcher : public aarch64_simd_switcher
     657  {
     658  public:
     659    sve_switcher ();
     660    ~sve_switcher ();
     661  
     662  private:
     663    unsigned int m_old_maximum_field_alignment;
     664    bool m_old_have_regs_of_mode[MAX_MACHINE_MODE];
     665  };
     666  
     667  extern const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1];
     668  extern const mode_suffix_info mode_suffixes[MODE_none + 1];
     669  
     670  extern tree scalar_types[NUM_VECTOR_TYPES];
     671  extern tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1];
     672  extern tree acle_svpattern;
     673  extern tree acle_svprfop;
     674  
     675  /* Return the ACLE type svbool_t.  */
     676  inline tree
     677  get_svbool_t (void)
     678  {
     679    return acle_vector_types[0][VECTOR_TYPE_svbool_t];
     680  }
     681  
     682  /* Try to find a mode with the given mode_suffix_info fields.  Return the
     683     mode on success or MODE_none on failure.  */
     684  inline mode_suffix_index
     685  find_mode_suffix (vector_type_index base_vector_type,
     686  		  vector_type_index displacement_vector_type,
     687  		  units_index displacement_units)
     688  {
     689    for (unsigned int mode_i = 0; mode_i < ARRAY_SIZE (mode_suffixes); ++mode_i)
     690      {
     691        const mode_suffix_info &mode = mode_suffixes[mode_i];
     692        if (mode.base_vector_type == base_vector_type
     693  	  && mode.displacement_vector_type == displacement_vector_type
     694  	  && mode.displacement_units == displacement_units)
     695  	return mode_suffix_index (mode_i);
     696      }
     697    return MODE_none;
     698  }
     699  
     700  /* Return the type suffix associated with ELEMENT_BITS-bit elements of type
     701     class TCLASS.  */
     702  inline type_suffix_index
     703  find_type_suffix (type_class_index tclass, unsigned int element_bits)
     704  {
     705    for (unsigned int i = 0; i < NUM_TYPE_SUFFIXES; ++i)
     706      if (type_suffixes[i].tclass == tclass
     707  	&& type_suffixes[i].element_bits == element_bits)
     708        return type_suffix_index (i);
     709    gcc_unreachable ();
     710  }
     711  
     712  /* Return the single field in tuple type TYPE.  */
     713  inline tree
     714  tuple_type_field (tree type)
     715  {
     716    for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     717      if (TREE_CODE (field) == FIELD_DECL)
     718        return field;
     719    gcc_unreachable ();
     720  }
     721  
     722  inline function_instance::
     723  function_instance (const char *base_name_in,
     724  		   const function_base *base_in,
     725  		   const function_shape *shape_in,
     726  		   mode_suffix_index mode_suffix_id_in,
     727  		   const type_suffix_pair &type_suffix_ids_in,
     728  		   predication_index pred_in)
     729    : base_name (base_name_in), base (base_in), shape (shape_in),
     730      mode_suffix_id (mode_suffix_id_in), pred (pred_in)
     731  {
     732    memcpy (type_suffix_ids, type_suffix_ids_in, sizeof (type_suffix_ids));
     733  }
     734  
     735  inline bool
     736  function_instance::operator== (const function_instance &other) const
     737  {
     738    return (base == other.base
     739  	  && shape == other.shape
     740  	  && mode_suffix_id == other.mode_suffix_id
     741  	  && pred == other.pred
     742  	  && type_suffix_ids[0] == other.type_suffix_ids[0]
     743  	  && type_suffix_ids[1] == other.type_suffix_ids[1]);
     744  }
     745  
     746  inline bool
     747  function_instance::operator!= (const function_instance &other) const
     748  {
     749    return !operator== (other);
     750  }
     751  
     752  /* If the function operates on tuples of vectors, return the number
     753     of vectors in the tuples, otherwise return 1.  */
     754  inline unsigned int
     755  function_instance::vectors_per_tuple () const
     756  {
     757    return base->vectors_per_tuple ();
     758  }
     759  
     760  /* If the function addresses memory, return the type of a single
     761     scalar memory element.  */
     762  inline tree
     763  function_instance::memory_scalar_type () const
     764  {
     765    return base->memory_scalar_type (*this);
     766  }
     767  
     768  /* If the function addresses memory, return a vector mode whose
     769     GET_MODE_NUNITS is the number of elements addressed and whose
     770     GET_MODE_INNER is the mode of a single scalar memory element.  */
     771  inline machine_mode
     772  function_instance::memory_vector_mode () const
     773  {
     774    return base->memory_vector_mode (*this);
     775  }
     776  
     777  /* Return information about the function's mode suffix.  */
     778  inline const mode_suffix_info &
     779  function_instance::mode_suffix () const
     780  {
     781    return mode_suffixes[mode_suffix_id];
     782  }
     783  
     784  /* Return the type of the function's vector base address argument,
     785     or null it doesn't have a vector base address.  */
     786  inline tree
     787  function_instance::base_vector_type () const
     788  {
     789    return acle_vector_types[0][mode_suffix ().base_vector_type];
     790  }
     791  
     792  /* Return the type of the function's vector index or offset argument,
     793     or null if doesn't have a vector index or offset argument.  */
     794  inline tree
     795  function_instance::displacement_vector_type () const
     796  {
     797    return acle_vector_types[0][mode_suffix ().displacement_vector_type];
     798  }
     799  
     800  /* If the function takes a vector or scalar displacement, return the units
     801     in which the displacement is measured, otherwise return UNITS_none.  */
     802  inline units_index
     803  function_instance::displacement_units () const
     804  {
     805    return mode_suffix ().displacement_units;
     806  }
     807  
     808  /* Return information about type suffix I.  */
     809  inline const type_suffix_info &
     810  function_instance::type_suffix (unsigned int i) const
     811  {
     812    return type_suffixes[type_suffix_ids[i]];
     813  }
     814  
     815  /* Return the scalar type associated with type suffix I.  */
     816  inline tree
     817  function_instance::scalar_type (unsigned int i) const
     818  {
     819    return scalar_types[type_suffix (i).vector_type];
     820  }
     821  
     822  /* Return the vector type associated with type suffix I.  */
     823  inline tree
     824  function_instance::vector_type (unsigned int i) const
     825  {
     826    return acle_vector_types[0][type_suffix (i).vector_type];
     827  }
     828  
     829  /* If the function operates on tuples of vectors, return the tuple type
     830     associated with type suffix I, otherwise return the vector type associated
     831     with type suffix I.  */
     832  inline tree
     833  function_instance::tuple_type (unsigned int i) const
     834  {
     835    unsigned int num_vectors = vectors_per_tuple ();
     836    return acle_vector_types[num_vectors - 1][type_suffix (i).vector_type];
     837  }
     838  
     839  /* Return the number of elements of type suffix I that fit within a
     840     128-bit block.  */
     841  inline unsigned int
     842  function_instance::elements_per_vq (unsigned int i) const
     843  {
     844    return 128 / type_suffix (i).element_bits;
     845  }
     846  
     847  /* Return the vector or predicate mode associated with type suffix I.  */
     848  inline machine_mode
     849  function_instance::vector_mode (unsigned int i) const
     850  {
     851    return type_suffix (i).vector_mode;
     852  }
     853  
     854  /* Return the mode of the governing predicate to use when operating on
     855     type suffix I.  */
     856  inline machine_mode
     857  function_instance::gp_mode (unsigned int i) const
     858  {
     859    return aarch64_sve_pred_mode (type_suffix (i).element_bytes).require ();
     860  }
     861  
     862  /* Return true if the function has no return value.  */
     863  inline bool
     864  function_call_info::function_returns_void_p ()
     865  {
     866    return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
     867  }
     868  
     869  /* Default implementation of function::call_properties, with conservatively
     870     correct behavior for floating-point instructions.  */
     871  inline unsigned int
     872  function_base::call_properties (const function_instance &instance) const
     873  {
     874    unsigned int flags = 0;
     875    if (instance.type_suffix (0).float_p || instance.type_suffix (1).float_p)
     876      flags |= CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
     877    return flags;
     878  }
     879  
     880  }
     881  
     882  #endif