Home | History | Annotate | Line # | Download | only in riscv
      1 /* Builtins definitions for RISC-V 'V' Extension for GNU compiler.
      2    Copyright (C) 2022-2024 Free Software Foundation, Inc.
      3    Contributed by Ju-Zhe Zhong (juzhe.zhong (at) rivai.ai), RiVAI Technologies Ltd.
      4 
      5    This file is part of GCC.
      6 
      7    GCC is free software; you can redistribute it and/or modify it
      8    under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3, or (at your option)
     10    any later version.
     11 
     12    GCC is distributed in the hope that it will be useful, but
     13    WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15    General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with GCC; see the file COPYING3.  If not see
     19    <http://www.gnu.org/licenses/>.  */
     20 
     21 #ifndef GCC_RISCV_VECTOR_BUILTINS_H
     22 #define GCC_RISCV_VECTOR_BUILTINS_H
     23 
     24 /* The full name of an RVV intrinsic function is the concatenation of:
     25 
     26    - the base name ("vadd", etc.)
     27    - the operand suffix ("_vv", "_vx", etc.)
     28    - the type suffix ("_i32m1", "_i32mf2", etc.)
     29    - the predication suffix ("_tamu", "_tumu", etc.)
     30 
     31    Each piece of information is individually useful, so we retain this
     32    classification throughout:
     33 
     34    - function_base represents the base name.
     35 
     36    - operand_type_index can be used as an index to get operand suffix.
     37 
     38    - rvv_op_info can be used as an index to get argument suffix.
     39 
     40    - predication_type_index can be used as an index to get predication suffix.
     41 
     42    In addition to its unique full name, a function may have a shorter
     43    overloaded alias.  This alias removes pieces of the suffixes that
     44    can be inferred from the arguments, such as by shortening the mode
     45    suffix or dropping some of the type suffixes.  The base name and the
     46    predication suffix stay the same.
     47 
     48    - The function_instance class describes contains all properties of each
     49      individual function. Such these information will be used by
     50      function_builder, function_base, function_shape, gimple_folder,
     51      function_expander, etc.
     52 
     53    - The function_builder class provides several helper function to add an
     54      intrinsic function.
     55 
     56    - The function_shape class describes how that instruction has been presented
     57      at the language level:
     58 
     59       1. Determine the function name for C and C++ overload function which can
     60 	 be recognized by compiler at language level for each instruction
     61 	 according to members of function_instance (base name, operand suffix,
     62 	 type suffix, predication suffix, etc.).
     63 
     64       2. Specify the arguments type and return type of each function to
     65 	 describe how that instruction has presented at language level.
     66 
     67    - The function_base describes how the underlying instruction behaves.
     68 
     69    The static list of functions uses function_group to describe a group
     70    of related functions.  The function_builder class is responsible for
     71    expanding this static description into a list of individual functions
     72    and registering the associated built-in functions.  function_instance
     73    describes one of these individual functions in terms of the properties
     74    described above.
     75 
     76    The classes involved in compiling a function call are:
     77 
     78    - function_resolver, which resolves an overloaded function call to a
     79      specific function_instance and its associated function decl.
     80 
     81    - function_checker, which checks whether the values of the arguments
     82      conform to the RVV ISA specification.
     83 
     84    - gimple_folder, which tries to fold a function call at the gimple level
     85 
     86    - function_expander, which expands a function call into rtl instructions
     87 
     88    function_resolver and function_checker operate at the language level
     89    and so are associated with the function_shape.  gimple_folder and
     90    function_expander are concerned with the behavior of the function
     91    and so are associated with the function_base.  */
     92 
     93 namespace riscv_vector {
     94 
     95 /* Flags that describe what a function might do, in addition to reading
     96    its arguments and returning a result.  */
     97 static const unsigned int CP_READ_FPCR = 1U << 0;
     98 static const unsigned int CP_RAISE_FP_EXCEPTIONS = 1U << 1;
     99 static const unsigned int CP_READ_MEMORY = 1U << 2;
    100 static const unsigned int CP_WRITE_MEMORY = 1U << 3;
    101 static const unsigned int CP_READ_CSR = 1U << 4;
    102 static const unsigned int CP_WRITE_CSR = 1U << 5;
    103 
    104 /* Bit values used to identify required extensions for RVV intrinsics.  */
    105 #define RVV_REQUIRE_RV64BIT (1 << 0)	/* Require RV64.  */
    106 #define RVV_REQUIRE_ELEN_64 (1 << 1)	/* Require TARGET_VECTOR_ELEN_64.  */
    107 #define RVV_REQUIRE_ELEN_FP_32 (1 << 2) /* Require FP ELEN >= 32.  */
    108 #define RVV_REQUIRE_ELEN_FP_64 (1 << 3) /* Require FP ELEN >= 64.  */
    109 #define RVV_REQUIRE_FULL_V (1 << 4) /* Require Full 'V' extension.  */
    110 #define RVV_REQUIRE_MIN_VLEN_64 (1 << 5)	/* Require TARGET_MIN_VLEN >= 64.  */
    111 #define RVV_REQUIRE_ELEN_FP_16 (1 << 6) /* Require FP ELEN >= 32.  */
    112 
    113 /* Enumerates the required extensions.  */
    114 enum required_ext
    115 {
    116   VECTOR_EXT,   /* Vector extension */
    117   ZVBB_EXT,    /* Cryto vector Zvbb sub-ext */
    118   ZVBB_OR_ZVKB_EXT, /* Cryto vector Zvbb or zvkb sub-ext */
    119   ZVBC_EXT,    /* Crypto vector Zvbc sub-ext */
    120   ZVKG_EXT,    /* Crypto vector Zvkg sub-ext */
    121   ZVKNED_EXT,  /* Crypto vector Zvkned sub-ext */
    122   ZVKNHA_OR_ZVKNHB_EXT, /* Crypto vector Zvknh[ab] sub-ext */
    123   ZVKNHB_EXT,  /* Crypto vector Zvknhb sub-ext */
    124   ZVKSED_EXT,  /* Crypto vector Zvksed sub-ext */
    125   ZVKSH_EXT,   /* Crypto vector Zvksh sub-ext */
    126   XTHEADVECTOR_EXT,   /* XTheadVector extension */
    127   /* Please update below to isa_name func when add or remove enum type(s).  */
    128 };
    129 
    130 static inline const char * reqired_ext_to_isa_name (enum required_ext required)
    131 {
    132   switch (required)
    133   {
    134     case VECTOR_EXT:
    135       return "v";
    136     case ZVBB_EXT:
    137       return "zvbb";
    138     case ZVBB_OR_ZVKB_EXT:
    139       return "zvbb or zvkb";
    140     case ZVBC_EXT:
    141       return "zvbc";
    142     case ZVKG_EXT:
    143       return "zvkg";
    144     case ZVKNED_EXT:
    145       return "zvkned";
    146     case ZVKNHA_OR_ZVKNHB_EXT:
    147       return "zvknha or zvknhb";
    148     case ZVKNHB_EXT:
    149       return "zvknhb";
    150     case ZVKSED_EXT:
    151       return "zvksed";
    152     case ZVKSH_EXT:
    153       return "zvksh";
    154     case XTHEADVECTOR_EXT:
    155       return "xthreadvector";
    156     default:
    157       gcc_unreachable ();
    158   }
    159 
    160   gcc_unreachable ();
    161 }
    162 
    163 static inline bool required_extensions_specified (enum required_ext required)
    164 {
    165   switch (required)
    166   {
    167     case VECTOR_EXT:
    168       return TARGET_VECTOR;;
    169     case ZVBB_EXT:
    170       return TARGET_ZVBB;
    171     case ZVBB_OR_ZVKB_EXT:
    172       return TARGET_ZVBB || TARGET_ZVKB;
    173     case ZVBC_EXT:
    174       return TARGET_ZVBC;
    175     case ZVKG_EXT:
    176       return TARGET_ZVKG;
    177     case ZVKNED_EXT:
    178       return TARGET_ZVKNED;
    179     case ZVKNHA_OR_ZVKNHB_EXT:
    180       return TARGET_ZVKNHA || TARGET_ZVKNHB;
    181     case ZVKNHB_EXT:
    182       return TARGET_ZVKNHB;
    183     case ZVKSED_EXT:
    184       return TARGET_ZVKSED;
    185     case ZVKSH_EXT:
    186       return TARGET_ZVKSH;
    187     case XTHEADVECTOR_EXT:
    188       return TARGET_XTHEADVECTOR;
    189     default:
    190       gcc_unreachable ();
    191   }
    192 
    193   gcc_unreachable ();
    194 }
    195 
    196 /* Enumerates the RVV operand types.  */
    197 enum operand_type_index
    198 {
    199   OP_TYPE_none,
    200 #define DEF_RVV_OP_TYPE(NAME) OP_TYPE_##NAME,
    201 #include "riscv-vector-builtins.def"
    202   NUM_OP_TYPES
    203 };
    204 
    205 /* Enumerates the RVV types, together called
    206    "vector types" for brevity.  */
    207 enum vector_type_index
    208 {
    209 #define DEF_RVV_TYPE(NAME, ABI_NAME, NCHARS, ARGS...) VECTOR_TYPE_##NAME,
    210 #define DEF_RVV_TUPLE_TYPE(NAME, ABI_NAME, NCHARS, ARGS...) VECTOR_TYPE_##NAME,
    211 #include "riscv-vector-builtins.def"
    212   NUM_VECTOR_TYPES,
    213   VECTOR_TYPE_INVALID = NUM_VECTOR_TYPES
    214 };
    215 
    216 /* Enumerates the RVV governing predication types.  */
    217 enum predication_type_index
    218 {
    219   PRED_TYPE_none,
    220 #define DEF_RVV_PRED_TYPE(NAME) PRED_TYPE_##NAME,
    221 #include "riscv-vector-builtins.def"
    222   NUM_PRED_TYPES
    223 };
    224 
    225 /* Enumerates the RVV base types.  */
    226 enum rvv_base_type
    227 {
    228 #define DEF_RVV_BASE_TYPE(NAME, ARGS...) RVV_BASE_##NAME,
    229 #include "riscv-vector-builtins.def"
    230   NUM_BASE_TYPES
    231 };
    232 
    233 /* Builtin types that are used to register RVV intrinsics.  */
    234 struct GTY (()) rvv_builtin_types_t
    235 {
    236   tree vector;
    237   tree scalar;
    238   tree vector_ptr;
    239   tree scalar_ptr;
    240   tree scalar_const_ptr;
    241 };
    242 
    243 /* Builtin suffix that are used to register RVV intrinsics.  */
    244 struct rvv_builtin_suffixes
    245 {
    246   const char *vector;
    247   const char *scalar;
    248   const char *vsetvl;
    249 };
    250 
    251 /* Builtin base type used to specify the type of builtin function
    252    argument or return result.  */
    253 struct function_type_info
    254 {
    255   enum vector_type_index type_indexes[NUM_BASE_TYPES];
    256 };
    257 
    258 /* RVV Builtin argument information.  */
    259 struct rvv_arg_type_info
    260 {
    261   CONSTEXPR rvv_arg_type_info (rvv_base_type base_type_in)
    262     : base_type (base_type_in)
    263   {}
    264   enum rvv_base_type base_type;
    265 
    266   tree get_scalar_ptr_type (vector_type_index) const;
    267   tree get_scalar_const_ptr_type (vector_type_index) const;
    268   vector_type_index get_function_type_index (vector_type_index) const;
    269   tree get_scalar_type (vector_type_index) const;
    270   tree get_vector_type (vector_type_index) const;
    271   tree get_tree_type (vector_type_index) const;
    272   tree get_tuple_subpart_type (vector_type_index) const;
    273 };
    274 
    275 /* Static information for each operand.  */
    276 struct rvv_type_info
    277 {
    278   enum vector_type_index index;
    279   uint64_t required_extensions;
    280 };
    281 
    282 /* RVV Builtin operands information.  */
    283 struct rvv_op_info
    284 {
    285   const rvv_type_info *types;
    286   const operand_type_index op;
    287   rvv_arg_type_info ret;
    288   const rvv_arg_type_info *args;
    289 };
    290 
    291 class registered_function;
    292 class function_base;
    293 class function_shape;
    294 
    295 /* Static information about a set of functions.  */
    296 struct function_group_info
    297 {
    298   /* Return true if required extension is enabled */
    299   bool match (required_ext ext_value) const
    300   {
    301     switch (ext_value)
    302     {
    303       case VECTOR_EXT:
    304         return TARGET_VECTOR;
    305       case ZVBB_EXT:
    306         return TARGET_ZVBB;
    307       case ZVBB_OR_ZVKB_EXT:
    308         return (TARGET_ZVBB || TARGET_ZVKB);
    309       case ZVBC_EXT:
    310         return TARGET_ZVBC;
    311       case ZVKG_EXT:
    312         return TARGET_ZVKG;
    313       case ZVKNED_EXT:
    314         return TARGET_ZVKNED;
    315       case ZVKNHA_OR_ZVKNHB_EXT:
    316         return (TARGET_ZVKNHA || TARGET_ZVKNHB);
    317       case ZVKNHB_EXT:
    318         return TARGET_ZVKNHB;
    319       case ZVKSED_EXT:
    320         return TARGET_ZVKSED;
    321       case ZVKSH_EXT:
    322         return TARGET_ZVKSH;
    323       case XTHEADVECTOR_EXT:
    324 	return TARGET_XTHEADVECTOR;
    325       default:
    326         gcc_unreachable ();
    327     }
    328   }
    329   /* The base name, as a string.  */
    330   const char *base_name;
    331 
    332   /* Describes the behavior associated with the function base name.  */
    333   const function_base *const *base;
    334 
    335   /* The shape of the functions, as described above the class definition.
    336      It's possible to have entries with the same base name but different
    337      shapes.  */
    338   const function_shape *const *shape;
    339 
    340   /* A list of the available operand types, predication types,
    341      and of the available operand datatype.
    342      The function supports every combination of the two.
    343      The list of predication is terminated by two NUM_PRED_TYPES,
    344      while the list of operand info is terminated by NUM_BASE_TYPES.
    345      The list of these type suffix is lexicographically ordered based
    346      on the index value.  */
    347   const predication_type_index *preds;
    348   const rvv_op_info ops_infos;
    349   /* The required extension value, using it to get the enabled flag.  */
    350   required_ext required_extensions;
    351 };
    352 
    353 class GTY ((user)) function_instance
    354 {
    355 public:
    356   function_instance (const char *, const function_base *,
    357 		     const function_shape *, rvv_type_info,
    358 		     predication_type_index, const rvv_op_info *);
    359 
    360   bool operator== (const function_instance &) const;
    361   bool operator!= (const function_instance &) const;
    362   hashval_t hash () const;
    363 
    364   unsigned int call_properties () const;
    365   bool reads_global_state_p () const;
    366   bool modifies_global_state_p () const;
    367   bool could_trap_p () const;
    368 
    369   /* Return true if return type or arguments are floating point type.  */
    370   bool any_type_float_p () const;
    371 
    372   tree get_return_type () const;
    373   tree get_arg_type (unsigned opno) const;
    374 
    375   /* The properties of the function.  (The explicit "enum"s are required
    376      for gengtype.)  */
    377   const char *base_name;
    378   const function_base *base;
    379   const function_shape *shape;
    380   rvv_type_info type;
    381   enum predication_type_index pred;
    382   const rvv_op_info *op_info;
    383 };
    384 
    385 /* A class for building and registering function decls.  */
    386 class function_builder
    387 {
    388 public:
    389   function_builder ();
    390   ~function_builder ();
    391 
    392   void allocate_argument_types (const function_instance &, vec<tree> &) const;
    393   void apply_predication (const function_instance &, tree, vec<tree> &) const;
    394   void add_unique_function (const function_instance &, const function_shape *,
    395 			    tree, vec<tree> &, enum required_ext);
    396   void add_overloaded_function (const function_instance &,
    397 				const function_shape *,
    398 				enum required_ext);
    399   void register_function_group (const function_group_info &);
    400   void append_name (const char *);
    401   void append_base_name (const char *);
    402   void append_sew (int);
    403   void append_nf (int);
    404   char *finish_name ();
    405 
    406 private:
    407   tree get_attributes (const function_instance &);
    408 
    409   registered_function &add_function (const function_instance &, const char *,
    410 				     tree, tree, bool, const char *,
    411 				     const vec<tree> &, enum required_ext,
    412 				     bool);
    413 
    414   /* True if we should create a separate decl for each instance of an
    415      overloaded function, instead of using function_builder.  */
    416   bool m_direct_overloads;
    417 
    418   /* Used for building up function names.  */
    419   obstack m_string_obstack;
    420 };
    421 
    422 /* A base class for handling calls to built-in functions.  */
    423 class function_call_info : public function_instance
    424 {
    425 public:
    426   function_call_info (location_t, const function_instance &, tree);
    427 
    428   bool function_returns_void_p ();
    429 
    430   /* The location of the call.  */
    431   location_t location;
    432 
    433   /* The FUNCTION_DECL that is being called.  */
    434   tree fndecl;
    435 };
    436 
    437 /* Return true if the function has no return value.  */
    438 inline bool
    439 function_call_info::function_returns_void_p ()
    440 {
    441   return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
    442 }
    443 
    444 /* A class for folding a gimple function call.  */
    445 class gimple_folder : public function_call_info
    446 {
    447 public:
    448   gimple_folder (const function_instance &, tree, gimple_stmt_iterator *,
    449 		 gcall *);
    450 
    451   gimple *fold ();
    452 
    453   /* Where to insert extra statements that feed the final replacement.  */
    454   gimple_stmt_iterator *gsi;
    455 
    456   /* The call we're folding.  */
    457   gcall *call;
    458 
    459   /* The result of the call, or null if none.  */
    460   tree lhs;
    461 };
    462 
    463 /* A class for expanding a function call into RTL.  */
    464 class function_expander : public function_call_info
    465 {
    466 public:
    467   function_expander (const function_instance &, tree, tree, rtx);
    468   rtx expand ();
    469 
    470   void add_input_operand (machine_mode, rtx);
    471   void add_input_operand (unsigned);
    472   void add_output_operand (machine_mode, rtx);
    473   void add_all_one_mask_operand (machine_mode);
    474   void add_scalar_move_mask_operand (machine_mode);
    475   void add_vundef_operand (machine_mode);
    476   void add_fixed_operand (rtx);
    477   void add_integer_operand (rtx);
    478   void add_mem_operand (machine_mode, unsigned);
    479 
    480   machine_mode vector_mode (void) const;
    481   machine_mode index_mode (void) const;
    482   machine_mode arg_mode (int) const;
    483   machine_mode mask_mode (void) const;
    484   machine_mode ret_mode (void) const;
    485 
    486   rtx use_exact_insn (insn_code);
    487   rtx use_contiguous_load_insn (insn_code);
    488   rtx use_contiguous_store_insn (insn_code);
    489   rtx use_compare_insn (rtx_code, insn_code);
    490   rtx use_ternop_insn (bool, insn_code);
    491   rtx use_widen_ternop_insn (insn_code);
    492   rtx use_scalar_move_insn (insn_code);
    493   rtx generate_insn (insn_code);
    494 
    495   /* The function call expression.  */
    496   tree exp;
    497 
    498   /* For functions that return a value, this is the preferred location
    499      of that value.  It could be null or could have a different mode
    500      from the function return type.  */
    501   rtx target;
    502 
    503   /* The number of the operands.  */
    504   int opno;
    505 
    506 private:
    507   /* Used to build up the operands to an instruction.  */
    508   struct expand_operand m_ops[MAX_RECOG_OPERANDS];
    509 };
    510 
    511 /* Provides information about a particular function base name, and handles
    512    tasks related to the base name.  */
    513 class function_base
    514 {
    515 public:
    516   /* Return a set of CP_* flags that describe what the function might do,
    517      in addition to reading its arguments and returning a result.  */
    518   virtual unsigned int call_properties (const function_instance &) const;
    519 
    520   /* Return true if intrinsics should apply vl operand.  */
    521   virtual bool apply_vl_p () const;
    522 
    523   /* Return true if intrinsics should apply tail policy operand.  */
    524   virtual bool apply_tail_policy_p () const;
    525 
    526   /* Return true if intrinsics should apply mask policy operand.  */
    527   virtual bool apply_mask_policy_p () const;
    528 
    529   /* Return true if intrinsic can be overloaded.  */
    530   virtual bool can_be_overloaded_p (enum predication_type_index) const;
    531 
    532   /* Return true if intrinsics use mask predication.  */
    533   virtual bool use_mask_predication_p () const;
    534 
    535   /* Return true if intrinsics has merge operand.  */
    536   virtual bool has_merge_operand_p () const;
    537 
    538   /* Return true if intrinsics has rounding mode operand.  */
    539   virtual bool has_rounding_mode_operand_p () const;
    540 
    541   /* Return true if intrinsics maybe require vxrm operand.  */
    542   virtual bool may_require_vxrm_p () const;
    543 
    544   /* Return true if intrinsics maybe require frm operand.  */
    545   virtual bool may_require_frm_p () const;
    546 
    547   /* Try to fold the given gimple call.  Return the new gimple statement
    548      on success, otherwise return null.  */
    549   virtual gimple *fold (gimple_folder &) const { return NULL; }
    550 
    551   /* Expand the given call into rtl.  Return the result of the function,
    552      or an arbitrary value if the function doesn't return a result.  */
    553   virtual rtx expand (function_expander &) const = 0;
    554 };
    555 
    556 /* A class for checking that the semantic constraints on a function call are
    557    satisfied, such as arguments being integer constant expressions with
    558    a particular range.  The parent class's FNDECL is the decl that was
    559    called in the original source, before overload resolution.  */
    560 class function_checker : public function_call_info
    561 {
    562 public:
    563   function_checker (location_t, const function_instance &, tree, tree,
    564 		    unsigned int, tree *);
    565 
    566   machine_mode arg_mode (unsigned int) const;
    567   machine_mode ret_mode (void) const;
    568   unsigned int arg_num (void) const;
    569   bool check (void);
    570 
    571   bool require_immediate (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT) const;
    572   bool require_immediate_range_or (unsigned int, HOST_WIDE_INT,
    573 				   HOST_WIDE_INT, HOST_WIDE_INT) const;
    574 
    575 private:
    576   bool require_immediate_range (unsigned int, HOST_WIDE_INT,
    577 				HOST_WIDE_INT) const;
    578   void report_non_ice (unsigned int) const;
    579   void report_out_of_range (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
    580 			    HOST_WIDE_INT) const;
    581   void report_out_of_range_and_not (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
    582 				    HOST_WIDE_INT, HOST_WIDE_INT) const;
    583 
    584   /* The type of the resolved function.  */
    585   tree m_fntype;
    586 
    587   /* The arguments to the function.  */
    588   unsigned int m_nargs;
    589   tree *m_args;
    590 };
    591 
    592 /* Classifies functions into "shapes" base on:
    593 
    594    - Base name of the intrinsic function.
    595 
    596    - Operand types list.
    597 
    598    - Argument type list.
    599 
    600    - Predication type list.  */
    601 class function_shape
    602 {
    603 public:
    604   /* Shape the function name according to function_instance.  */
    605   virtual char *get_name (function_builder &, const function_instance &,
    606 			  bool) const
    607     = 0;
    608 
    609   /* Define all functions associated with the given group.  */
    610   virtual void build (function_builder &, const function_group_info &) const
    611     = 0;
    612 
    613   /* Check whether the given call is semantically valid.  Return true
    614    if it is, otherwise report an error and return false.  */
    615   virtual bool check (function_checker &) const { return true; }
    616 };
    617 
    618 extern const char *const operand_suffixes[NUM_OP_TYPES];
    619 extern const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1];
    620 extern const char *const predication_suffixes[NUM_PRED_TYPES];
    621 extern rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
    622 extern function_instance get_read_vl_instance (void);
    623 extern tree get_read_vl_decl (void);
    624 
    625 inline tree
    626 rvv_arg_type_info::get_scalar_type (vector_type_index type_idx) const
    627 {
    628   return get_function_type_index (type_idx) == VECTOR_TYPE_INVALID
    629 	   ? NULL_TREE
    630 	   : builtin_types[get_function_type_index (type_idx)].scalar;
    631 }
    632 
    633 inline tree
    634 rvv_arg_type_info::get_vector_type (vector_type_index type_idx) const
    635 {
    636   return get_function_type_index (type_idx) == VECTOR_TYPE_INVALID
    637 	   ? NULL_TREE
    638 	   : builtin_types[get_function_type_index (type_idx)].vector;
    639 }
    640 
    641 inline bool
    642 function_instance::operator!= (const function_instance &other) const
    643 {
    644   return !operator== (other);
    645 }
    646 
    647 /* Expand the call and return its lhs.  */
    648 inline rtx
    649 function_expander::expand ()
    650 {
    651   return base->expand (*this);
    652 }
    653 
    654 /* Create op and add it into M_OPS and increase OPNO.  */
    655 inline void
    656 function_expander::add_input_operand (machine_mode mode, rtx op)
    657 {
    658   create_input_operand (&m_ops[opno++], op, mode);
    659 }
    660 
    661 /* Create output and add it into M_OPS and increase OPNO.  */
    662 inline void
    663 function_expander::add_output_operand (machine_mode mode, rtx target)
    664 {
    665   create_output_operand (&m_ops[opno++], target, mode);
    666 }
    667 
    668 /* Since we may normalize vop/vop_tu/vop_m/vop_tumu.. into a single patter.
    669    We add a fake all true mask for the intrinsics that don't need a real mask.
    670  */
    671 inline void
    672 function_expander::add_all_one_mask_operand (machine_mode mode)
    673 {
    674   add_input_operand (mode, CONSTM1_RTX (mode));
    675 }
    676 
    677 /* Add mask operand for scalar move instruction.  */
    678 inline void
    679 function_expander::add_scalar_move_mask_operand (machine_mode mode)
    680 {
    681   add_input_operand (mode, gen_scalar_move_mask (mode));
    682 }
    683 
    684 /* Add an operand that must be X.  The only way of legitimizing an
    685    invalid X is to reload the address of a MEM.  */
    686 inline void
    687 function_expander::add_fixed_operand (rtx x)
    688 {
    689   create_fixed_operand (&m_ops[opno++], x);
    690 }
    691 
    692 /* Add an integer operand X.  */
    693 inline void
    694 function_expander::add_integer_operand (rtx x)
    695 {
    696   create_integer_operand (&m_ops[opno++], INTVAL (x));
    697 }
    698 
    699 /* Return the machine_mode of the corresponding vector type.  */
    700 inline machine_mode
    701 function_expander::vector_mode (void) const
    702 {
    703   return TYPE_MODE (builtin_types[type.index].vector);
    704 }
    705 
    706 /* Return the machine_mode of the corresponding index type.  */
    707 inline machine_mode
    708 function_expander::index_mode (void) const
    709 {
    710   return TYPE_MODE (op_info->args[1].get_tree_type (type.index));
    711 }
    712 
    713 /* Return the machine_mode of the corresponding arg type.  */
    714 inline machine_mode
    715 function_expander::arg_mode (int idx) const
    716 {
    717   return TYPE_MODE (op_info->args[idx].get_tree_type (type.index));
    718 }
    719 
    720 /* Return the machine_mode of the corresponding return type.  */
    721 inline machine_mode
    722 function_expander::ret_mode (void) const
    723 {
    724   return TYPE_MODE (op_info->ret.get_tree_type (type.index));
    725 }
    726 
    727 inline machine_mode
    728 function_checker::arg_mode (unsigned int argno) const
    729 {
    730   return TYPE_MODE (TREE_TYPE (m_args[argno]));
    731 }
    732 
    733 inline machine_mode
    734 function_checker::ret_mode () const
    735 {
    736   return TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl)));
    737 }
    738 
    739 inline unsigned int
    740 function_checker::arg_num () const
    741 {
    742   return m_nargs;
    743 }
    744 
    745 /* Default implementation of function_base::call_properties, with conservatively
    746    correct behavior for floating-point instructions.  */
    747 inline unsigned int
    748 function_base::call_properties (const function_instance &instance) const
    749 {
    750   unsigned int flags = 0;
    751   if (instance.any_type_float_p ())
    752     return flags | CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
    753   return flags;
    754 }
    755 
    756 /* We choose to apply vl operand by default since most of the intrinsics
    757    has vl operand.  */
    758 inline bool
    759 function_base::apply_vl_p () const
    760 {
    761   return true;
    762 }
    763 
    764 /* We choose to apply tail policy operand by default since most of the
    765    intrinsics has tail policy operand.  */
    766 inline bool
    767 function_base::apply_tail_policy_p () const
    768 {
    769   return true;
    770 }
    771 
    772 /* We choose to apply mask policy operand by default since most of the
    773    intrinsics has mask policy operand.  */
    774 inline bool
    775 function_base::apply_mask_policy_p () const
    776 {
    777   return true;
    778 }
    779 
    780 /* We choose to return true by default since most of the intrinsics use
    781    mask predication.  */
    782 inline bool
    783 function_base::use_mask_predication_p () const
    784 {
    785   return true;
    786 }
    787 
    788 /* We choose to return true by default since most of the intrinsics use
    789    has merge operand.  */
    790 inline bool
    791 function_base::has_merge_operand_p () const
    792 {
    793   return true;
    794 }
    795 
    796 /* We choose to return false by default since most of the intrinsics does
    797    not have rounding mode operand.  */
    798 inline bool
    799 function_base::has_rounding_mode_operand_p () const
    800 {
    801   return false;
    802 }
    803 
    804 /* We choose to return false by default since most of the intrinsics does
    805    not need frm operand.  */
    806 inline bool
    807 function_base::may_require_frm_p () const
    808 {
    809   return false;
    810 }
    811 
    812 /* We choose to return false by default since most of the intrinsics does
    813    not need vxrm operand.  */
    814 inline bool
    815 function_base::may_require_vxrm_p () const
    816 {
    817   return false;
    818 }
    819 
    820 /* Since most of intrinsics can be overloaded, we set it true by default.  */
    821 inline bool
    822 function_base::can_be_overloaded_p (enum predication_type_index) const
    823 {
    824   return true;
    825 }
    826 
    827 /* Return the single field in tuple type TYPE.  */
    828 inline tree
    829 tuple_type_field (tree type)
    830 {
    831   for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
    832     if (TREE_CODE (field) == FIELD_DECL)
    833       return field;
    834   gcc_unreachable ();
    835 }
    836 
    837 } // end namespace riscv_vector
    838 
    839 #endif
    840