(root)/
gcc-13.2.0/
gcc/
config/
riscv/
riscv-vector-builtins.h
       1  /* Builtins definitions for RISC-V 'V' Extension for GNU compiler.
       2     Copyright (C) 2022-2023 Free Software Foundation, Inc.
       3     Contributed by Ju-Zhe Zhong (juzhe.zhong@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  
     112  /* Enumerates the RVV operand types.  */
     113  enum operand_type_index
     114  {
     115    OP_TYPE_none,
     116  #define DEF_RVV_OP_TYPE(NAME) OP_TYPE_##NAME,
     117  #include "riscv-vector-builtins.def"
     118    NUM_OP_TYPES
     119  };
     120  
     121  /* Enumerates the RVV types, together called
     122     "vector types" for brevity.  */
     123  enum vector_type_index
     124  {
     125  #define DEF_RVV_TYPE(NAME, ABI_NAME, NCHARS, ARGS...) VECTOR_TYPE_##NAME,
     126  #include "riscv-vector-builtins.def"
     127    NUM_VECTOR_TYPES,
     128    VECTOR_TYPE_INVALID = NUM_VECTOR_TYPES
     129  };
     130  
     131  /* Enumerates the RVV governing predication types.  */
     132  enum predication_type_index
     133  {
     134    PRED_TYPE_none,
     135  #define DEF_RVV_PRED_TYPE(NAME) PRED_TYPE_##NAME,
     136  #include "riscv-vector-builtins.def"
     137    NUM_PRED_TYPES
     138  };
     139  
     140  /* Enumerates the RVV base types.  */
     141  enum rvv_base_type
     142  {
     143  #define DEF_RVV_BASE_TYPE(NAME, ARGS...) RVV_BASE_##NAME,
     144  #include "riscv-vector-builtins.def"
     145    NUM_BASE_TYPES
     146  };
     147  
     148  /* Builtin types that are used to register RVV intrinsics.  */
     149  struct GTY (()) rvv_builtin_types_t
     150  {
     151    tree vector;
     152    tree scalar;
     153    tree vector_ptr;
     154    tree scalar_ptr;
     155    tree scalar_const_ptr;
     156  };
     157  
     158  /* Builtin suffix that are used to register RVV intrinsics.  */
     159  struct rvv_builtin_suffixes
     160  {
     161    const char *vector;
     162    const char *scalar;
     163    const char *vsetvl;
     164  };
     165  
     166  /* Builtin base type used to specify the type of builtin function
     167     argument or return result.  */
     168  struct function_type_info
     169  {
     170    enum vector_type_index type_indexes[NUM_BASE_TYPES];
     171  };
     172  
     173  /* RVV Builtin argument information.  */
     174  struct rvv_arg_type_info
     175  {
     176    CONSTEXPR rvv_arg_type_info (rvv_base_type base_type_in)
     177      : base_type (base_type_in)
     178    {}
     179    enum rvv_base_type base_type;
     180  
     181    tree get_scalar_ptr_type (vector_type_index) const;
     182    tree get_scalar_const_ptr_type (vector_type_index) const;
     183    vector_type_index get_function_type_index (vector_type_index) const;
     184    tree get_scalar_type (vector_type_index) const;
     185    tree get_vector_type (vector_type_index) const;
     186    tree get_tree_type (vector_type_index) const;
     187  };
     188  
     189  /* Static information for each operand.  */
     190  struct rvv_type_info
     191  {
     192    enum vector_type_index index;
     193    uint64_t required_extensions;
     194  };
     195  
     196  /* RVV Builtin operands information.  */
     197  struct rvv_op_info
     198  {
     199    const rvv_type_info *types;
     200    const operand_type_index op;
     201    rvv_arg_type_info ret;
     202    const rvv_arg_type_info *args;
     203  };
     204  
     205  class registered_function;
     206  class function_base;
     207  class function_shape;
     208  
     209  /* Static information about a set of functions.  */
     210  struct function_group_info
     211  {
     212    /* The base name, as a string.  */
     213    const char *base_name;
     214  
     215    /* Describes the behavior associated with the function base name.  */
     216    const function_base *const *base;
     217  
     218    /* The shape of the functions, as described above the class definition.
     219       It's possible to have entries with the same base name but different
     220       shapes.  */
     221    const function_shape *const *shape;
     222  
     223    /* A list of the available operand types, predication types,
     224       and of the available operand datatype.
     225       The function supports every combination of the two.
     226       The list of predication is terminated by two NUM_PRED_TYPES,
     227       while the list of operand info is terminated by NUM_BASE_TYPES.
     228       The list of these type suffix is lexicographically ordered based
     229       on the index value.  */
     230    const predication_type_index *preds;
     231    const rvv_op_info ops_infos;
     232  };
     233  
     234  class GTY ((user)) function_instance
     235  {
     236  public:
     237    function_instance (const char *, const function_base *,
     238  		     const function_shape *, rvv_type_info,
     239  		     predication_type_index, const rvv_op_info *);
     240  
     241    bool operator== (const function_instance &) const;
     242    bool operator!= (const function_instance &) const;
     243    hashval_t hash () const;
     244  
     245    unsigned int call_properties () const;
     246    bool reads_global_state_p () const;
     247    bool modifies_global_state_p () const;
     248    bool could_trap_p () const;
     249  
     250    /* Return true if return type or arguments are floating point type.  */
     251    bool any_type_float_p () const;
     252  
     253    tree get_return_type () const;
     254    tree get_arg_type (unsigned opno) const;
     255  
     256    /* The properties of the function.  (The explicit "enum"s are required
     257       for gengtype.)  */
     258    const char *base_name;
     259    const function_base *base;
     260    const function_shape *shape;
     261    rvv_type_info type;
     262    enum predication_type_index pred;
     263    const rvv_op_info *op_info;
     264  };
     265  
     266  /* A class for building and registering function decls.  */
     267  class function_builder
     268  {
     269  public:
     270    function_builder ();
     271    ~function_builder ();
     272  
     273    void allocate_argument_types (const function_instance &, vec<tree> &) const;
     274    void apply_predication (const function_instance &, tree, vec<tree> &) const;
     275    void add_unique_function (const function_instance &, const function_shape *,
     276  			    tree, vec<tree> &);
     277    void register_function_group (const function_group_info &);
     278    void append_name (const char *);
     279    void append_base_name (const char *);
     280    void append_sew (int);
     281    char *finish_name ();
     282  
     283  private:
     284    tree get_attributes (const function_instance &);
     285  
     286    registered_function &add_function (const function_instance &, const char *,
     287  				     tree, tree, bool);
     288  
     289    /* True if we should create a separate decl for each instance of an
     290       overloaded function, instead of using function_builder.  */
     291    bool m_direct_overloads;
     292  
     293    /* Used for building up function names.  */
     294    obstack m_string_obstack;
     295  };
     296  
     297  /* A base class for handling calls to built-in functions.  */
     298  class function_call_info : public function_instance
     299  {
     300  public:
     301    function_call_info (location_t, const function_instance &, tree);
     302  
     303    bool function_returns_void_p ();
     304  
     305    /* The location of the call.  */
     306    location_t location;
     307  
     308    /* The FUNCTION_DECL that is being called.  */
     309    tree fndecl;
     310  };
     311  
     312  /* Return true if the function has no return value.  */
     313  inline bool
     314  function_call_info::function_returns_void_p ()
     315  {
     316    return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
     317  }
     318  
     319  /* A class for folding a gimple function call.  */
     320  class gimple_folder : public function_call_info
     321  {
     322  public:
     323    gimple_folder (const function_instance &, tree, gimple_stmt_iterator *,
     324  		 gcall *);
     325  
     326    gimple *fold ();
     327  
     328    /* Where to insert extra statements that feed the final replacement.  */
     329    gimple_stmt_iterator *gsi;
     330  
     331    /* The call we're folding.  */
     332    gcall *call;
     333  
     334    /* The result of the call, or null if none.  */
     335    tree lhs;
     336  };
     337  
     338  /* A class for expanding a function call into RTL.  */
     339  class function_expander : public function_call_info
     340  {
     341  public:
     342    function_expander (const function_instance &, tree, tree, rtx);
     343    rtx expand ();
     344  
     345    void add_input_operand (machine_mode, rtx);
     346    void add_input_operand (unsigned);
     347    void add_output_operand (machine_mode, rtx);
     348    void add_all_one_mask_operand (machine_mode);
     349    void add_scalar_move_mask_operand (machine_mode);
     350    void add_vundef_operand (machine_mode);
     351    void add_fixed_operand (rtx);
     352    void add_integer_operand (rtx);
     353    void add_mem_operand (machine_mode, unsigned);
     354  
     355    machine_mode vector_mode (void) const;
     356    machine_mode index_mode (void) const;
     357    machine_mode arg_mode (int) const;
     358    machine_mode mask_mode (void) const;
     359    machine_mode ret_mode (void) const;
     360  
     361    rtx use_exact_insn (insn_code);
     362    rtx use_contiguous_load_insn (insn_code);
     363    rtx use_contiguous_store_insn (insn_code);
     364    rtx use_compare_insn (rtx_code, insn_code);
     365    rtx use_ternop_insn (bool, insn_code);
     366    rtx use_widen_ternop_insn (insn_code);
     367    rtx use_scalar_move_insn (insn_code);
     368    rtx generate_insn (insn_code);
     369  
     370    /* The function call expression.  */
     371    tree exp;
     372  
     373    /* For functions that return a value, this is the preferred location
     374       of that value.  It could be null or could have a different mode
     375       from the function return type.  */
     376    rtx target;
     377  
     378    /* The number of the operands.  */
     379    int opno;
     380  
     381  private:
     382    /* Used to build up the operands to an instruction.  */
     383    struct expand_operand m_ops[MAX_RECOG_OPERANDS];
     384  };
     385  
     386  /* Provides information about a particular function base name, and handles
     387     tasks related to the base name.  */
     388  class function_base
     389  {
     390  public:
     391    /* Return a set of CP_* flags that describe what the function might do,
     392       in addition to reading its arguments and returning a result.  */
     393    virtual unsigned int call_properties (const function_instance &) const;
     394  
     395    /* Return true if intrinsics should apply vl operand.  */
     396    virtual bool apply_vl_p () const;
     397  
     398    /* Return true if intrinsics should apply tail policy operand.  */
     399    virtual bool apply_tail_policy_p () const;
     400  
     401    /* Return true if intrinsics should apply mask policy operand.  */
     402    virtual bool apply_mask_policy_p () const;
     403  
     404    /* Return true if intrinsic can be overloaded.  */
     405    virtual bool can_be_overloaded_p (enum predication_type_index) const;
     406  
     407    /* Return true if intrinsics use mask predication.  */
     408    virtual bool use_mask_predication_p () const;
     409  
     410    /* Return true if intrinsics has merge operand.  */
     411    virtual bool has_merge_operand_p () const;
     412  
     413    /* Try to fold the given gimple call.  Return the new gimple statement
     414       on success, otherwise return null.  */
     415    virtual gimple *fold (gimple_folder &) const { return NULL; }
     416  
     417    /* Expand the given call into rtl.  Return the result of the function,
     418       or an arbitrary value if the function doesn't return a result.  */
     419    virtual rtx expand (function_expander &) const = 0;
     420  };
     421  
     422  /* A class for checking that the semantic constraints on a function call are
     423     satisfied, such as arguments being integer constant expressions with
     424     a particular range.  The parent class's FNDECL is the decl that was
     425     called in the original source, before overload resolution.  */
     426  class function_checker : public function_call_info
     427  {
     428  public:
     429    function_checker (location_t, const function_instance &, tree, tree,
     430  		    unsigned int, tree *);
     431  
     432    machine_mode arg_mode (unsigned int) const;
     433    machine_mode ret_mode (void) const;
     434    bool check (void);
     435  
     436    bool require_immediate (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT) const;
     437  
     438  private:
     439    bool require_immediate_range (unsigned int, HOST_WIDE_INT,
     440  				HOST_WIDE_INT) const;
     441    void report_non_ice (unsigned int) const;
     442    void report_out_of_range (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
     443  			    HOST_WIDE_INT) const;
     444  
     445    /* The type of the resolved function.  */
     446    tree m_fntype;
     447  
     448    /* The arguments to the function.  */
     449    unsigned int m_nargs;
     450    tree *m_args;
     451  };
     452  
     453  /* Classifies functions into "shapes" base on:
     454  
     455     - Base name of the intrinsic function.
     456  
     457     - Operand types list.
     458  
     459     - Argument type list.
     460  
     461     - Predication type list.  */
     462  class function_shape
     463  {
     464  public:
     465    /* Shape the function name according to function_instance.  */
     466    virtual char *get_name (function_builder &, const function_instance &,
     467  			  bool) const
     468      = 0;
     469  
     470    /* Define all functions associated with the given group.  */
     471    virtual void build (function_builder &, const function_group_info &) const
     472      = 0;
     473  
     474    /* Check whether the given call is semantically valid.  Return true
     475     if it is, otherwise report an error and return false.  */
     476    virtual bool check (function_checker &) const { return true; }
     477  };
     478  
     479  extern const char *const operand_suffixes[NUM_OP_TYPES];
     480  extern const rvv_builtin_suffixes type_suffixes[NUM_VECTOR_TYPES + 1];
     481  extern const char *const predication_suffixes[NUM_PRED_TYPES];
     482  extern rvv_builtin_types_t builtin_types[NUM_VECTOR_TYPES + 1];
     483  extern function_instance get_read_vl_instance (void);
     484  extern tree get_read_vl_decl (void);
     485  
     486  inline tree
     487  rvv_arg_type_info::get_scalar_type (vector_type_index type_idx) const
     488  {
     489    return get_function_type_index (type_idx) == VECTOR_TYPE_INVALID
     490  	   ? NULL_TREE
     491  	   : builtin_types[get_function_type_index (type_idx)].scalar;
     492  }
     493  
     494  inline tree
     495  rvv_arg_type_info::get_vector_type (vector_type_index type_idx) const
     496  {
     497    return get_function_type_index (type_idx) == VECTOR_TYPE_INVALID
     498  	   ? NULL_TREE
     499  	   : builtin_types[get_function_type_index (type_idx)].vector;
     500  }
     501  
     502  inline bool
     503  function_instance::operator!= (const function_instance &other) const
     504  {
     505    return !operator== (other);
     506  }
     507  
     508  /* Expand the call and return its lhs.  */
     509  inline rtx
     510  function_expander::expand ()
     511  {
     512    return base->expand (*this);
     513  }
     514  
     515  /* Create op and add it into M_OPS and increase OPNO.  */
     516  inline void
     517  function_expander::add_input_operand (machine_mode mode, rtx op)
     518  {
     519    create_input_operand (&m_ops[opno++], op, mode);
     520  }
     521  
     522  /* Create output and add it into M_OPS and increase OPNO.  */
     523  inline void
     524  function_expander::add_output_operand (machine_mode mode, rtx target)
     525  {
     526    create_output_operand (&m_ops[opno++], target, mode);
     527  }
     528  
     529  /* Since we may normalize vop/vop_tu/vop_m/vop_tumu.. into a single patter.
     530     We add a fake all true mask for the intrinsics that don't need a real mask.
     531   */
     532  inline void
     533  function_expander::add_all_one_mask_operand (machine_mode mode)
     534  {
     535    add_input_operand (mode, CONSTM1_RTX (mode));
     536  }
     537  
     538  /* Add mask operand for scalar move instruction.  */
     539  inline void
     540  function_expander::add_scalar_move_mask_operand (machine_mode mode)
     541  {
     542    add_input_operand (mode, gen_scalar_move_mask (mode));
     543  }
     544  
     545  /* Add an operand that must be X.  The only way of legitimizing an
     546     invalid X is to reload the address of a MEM.  */
     547  inline void
     548  function_expander::add_fixed_operand (rtx x)
     549  {
     550    create_fixed_operand (&m_ops[opno++], x);
     551  }
     552  
     553  /* Add an integer operand X.  */
     554  inline void
     555  function_expander::add_integer_operand (rtx x)
     556  {
     557    create_integer_operand (&m_ops[opno++], INTVAL (x));
     558  }
     559  
     560  /* Return the machine_mode of the corresponding vector type.  */
     561  inline machine_mode
     562  function_expander::vector_mode (void) const
     563  {
     564    return TYPE_MODE (builtin_types[type.index].vector);
     565  }
     566  
     567  /* Return the machine_mode of the corresponding index type.  */
     568  inline machine_mode
     569  function_expander::index_mode (void) const
     570  {
     571    return TYPE_MODE (op_info->args[1].get_tree_type (type.index));
     572  }
     573  
     574  /* Return the machine_mode of the corresponding arg type.  */
     575  inline machine_mode
     576  function_expander::arg_mode (int idx) const
     577  {
     578    return TYPE_MODE (op_info->args[idx].get_tree_type (type.index));
     579  }
     580  
     581  /* Return the machine_mode of the corresponding return type.  */
     582  inline machine_mode
     583  function_expander::ret_mode (void) const
     584  {
     585    return TYPE_MODE (op_info->ret.get_tree_type (type.index));
     586  }
     587  
     588  inline machine_mode
     589  function_checker::arg_mode (unsigned int argno) const
     590  {
     591    return TYPE_MODE (TREE_TYPE (m_args[argno]));
     592  }
     593  
     594  inline machine_mode
     595  function_checker::ret_mode () const
     596  {
     597    return TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl)));
     598  }
     599  
     600  /* Default implementation of function_base::call_properties, with conservatively
     601     correct behavior for floating-point instructions.  */
     602  inline unsigned int
     603  function_base::call_properties (const function_instance &instance) const
     604  {
     605    unsigned int flags = 0;
     606    if (instance.any_type_float_p ())
     607      return flags | CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
     608    return flags;
     609  }
     610  
     611  /* We choose to apply vl operand by default since most of the intrinsics
     612     has vl operand.  */
     613  inline bool
     614  function_base::apply_vl_p () const
     615  {
     616    return true;
     617  }
     618  
     619  /* We choose to apply tail policy operand by default since most of the
     620     intrinsics has tail policy operand.  */
     621  inline bool
     622  function_base::apply_tail_policy_p () const
     623  {
     624    return true;
     625  }
     626  
     627  /* We choose to apply mask policy operand by default since most of the
     628     intrinsics has mask policy operand.  */
     629  inline bool
     630  function_base::apply_mask_policy_p () const
     631  {
     632    return true;
     633  }
     634  
     635  /* We choose to return true by default since most of the intrinsics use
     636     mask predication.  */
     637  inline bool
     638  function_base::use_mask_predication_p () const
     639  {
     640    return true;
     641  }
     642  
     643  /* We choose to return true by default since most of the intrinsics use
     644     has merge operand.  */
     645  inline bool
     646  function_base::has_merge_operand_p () const
     647  {
     648    return true;
     649  }
     650  
     651  /* Since most of intrinsics can be overloaded, we set it true by default.  */
     652  inline bool
     653  function_base::can_be_overloaded_p (enum predication_type_index) const
     654  {
     655    return true;
     656  }
     657  
     658  } // end namespace riscv_vector
     659  
     660  #endif