Home | History | Annotate | Line # | Download | only in riscv
      1 /* Definition of RISC-V target for GNU compiler.
      2    Copyright (C) 2011-2024 Free Software Foundation, Inc.
      3    Contributed by Andrew Waterman (andrew (at) sifive.com).
      4    Based on MIPS target for GNU compiler.
      5 
      6 This file is part of GCC.
      7 
      8 GCC is free software; you can redistribute it and/or modify
      9 it under the terms of the GNU General Public License as published by
     10 the Free Software Foundation; either version 3, or (at your option)
     11 any later version.
     12 
     13 GCC is distributed in the hope that it will be useful,
     14 but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 GNU General Public License for more details.
     17 
     18 You should have received a copy of the GNU General Public License
     19 along with GCC; see the file COPYING3.  If not see
     20 <http://www.gnu.org/licenses/>.  */
     21 
     22 #ifndef GCC_RISCV_PROTOS_H
     23 #define GCC_RISCV_PROTOS_H
     24 
     25 #include "memmodel.h"
     26 
     27 /* Symbol types we understand.  The order of this list must match that of
     28    the unspec enum in riscv.md, subsequent to UNSPEC_ADDRESS_FIRST.  */
     29 enum riscv_symbol_type {
     30   SYMBOL_ABSOLUTE,
     31   SYMBOL_FORCE_TO_MEM,
     32   SYMBOL_PCREL,
     33   SYMBOL_GOT_DISP,
     34   SYMBOL_TLS,
     35   SYMBOL_TLS_LE,
     36   SYMBOL_TLS_IE,
     37   SYMBOL_TLS_GD,
     38   SYMBOL_TLSDESC,
     39 };
     40 #define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
     41 
     42 /* Classifies an address.
     43 
     44    ADDRESS_REG
     45        A natural register + offset address.  The register satisfies
     46        riscv_valid_base_register_p and the offset is a const_arith_operand.
     47 
     48    ADDRESS_REG_REG
     49        A base register indexed by (optionally scaled) register.
     50 
     51    ADDRESS_REG_UREG
     52        A base register indexed by (optionally scaled) zero-extended register.
     53 
     54    ADDRESS_REG_WB
     55        A base register indexed by immediate offset with writeback.
     56 
     57    ADDRESS_LO_SUM
     58        A LO_SUM rtx.  The first operand is a valid base register and
     59        the second operand is a symbolic address.
     60 
     61    ADDRESS_CONST_INT
     62        A signed 16-bit constant address.
     63 
     64    ADDRESS_SYMBOLIC:
     65        A constant symbolic address.  */
     66 enum riscv_address_type {
     67   ADDRESS_REG,
     68   ADDRESS_REG_REG,
     69   ADDRESS_REG_UREG,
     70   ADDRESS_REG_WB,
     71   ADDRESS_LO_SUM,
     72   ADDRESS_CONST_INT,
     73   ADDRESS_SYMBOLIC
     74 };
     75 
     76 /* Information about an address described by riscv_address_type.
     77 
     78    ADDRESS_CONST_INT
     79        No fields are used.
     80 
     81    ADDRESS_REG
     82        REG is the base register and OFFSET is the constant offset.
     83 
     84    ADDRESS_REG_REG and ADDRESS_REG_UREG
     85        REG is the base register and OFFSET is the index register.
     86 
     87    ADDRESS_REG_WB
     88        REG is the base register, OFFSET is the constant offset, and
     89        shift is the shift amount for the offset.
     90 
     91    ADDRESS_LO_SUM
     92        REG and OFFSET are the operands to the LO_SUM and SYMBOL_TYPE
     93        is the type of symbol it references.
     94 
     95    ADDRESS_SYMBOLIC
     96        SYMBOL_TYPE is the type of symbol that the address references.  */
     97 struct riscv_address_info {
     98   enum riscv_address_type type;
     99   rtx reg;
    100   rtx offset;
    101   enum riscv_symbol_type symbol_type;
    102   int shift;
    103 };
    104 
    105 /* Routines implemented in riscv.cc.  */
    106 extern const char *riscv_asm_output_opcode (FILE *asm_out_file, const char *p);
    107 extern enum riscv_symbol_type riscv_classify_symbolic_expression (rtx);
    108 extern bool riscv_symbolic_constant_p (rtx, enum riscv_symbol_type *);
    109 extern int riscv_float_const_rtx_index_for_fli (rtx);
    110 extern int riscv_regno_mode_ok_for_base_p (int, machine_mode, bool);
    111 extern bool riscv_valid_base_register_p (rtx, machine_mode, bool);
    112 extern enum reg_class riscv_index_reg_class ();
    113 extern int riscv_regno_ok_for_index_p (int);
    114 extern int riscv_address_insns (rtx, machine_mode, bool);
    115 extern int riscv_const_insns (rtx);
    116 extern int riscv_split_const_insns (rtx);
    117 extern int riscv_load_store_insns (rtx, rtx_insn *);
    118 extern rtx riscv_emit_move (rtx, rtx);
    119 extern bool riscv_split_symbol (rtx, rtx, machine_mode, rtx *);
    120 extern bool riscv_split_symbol_type (enum riscv_symbol_type);
    121 extern rtx riscv_unspec_address (rtx, enum riscv_symbol_type);
    122 extern void riscv_move_integer (rtx, rtx, HOST_WIDE_INT, machine_mode);
    123 extern bool riscv_legitimize_move (machine_mode, rtx, rtx);
    124 extern rtx riscv_subword (rtx, bool);
    125 extern bool riscv_split_64bit_move_p (rtx, rtx);
    126 extern void riscv_split_doubleword_move (rtx, rtx);
    127 extern const char *riscv_output_move (rtx, rtx);
    128 extern const char *riscv_output_return ();
    129 extern void riscv_declare_function_name (FILE *, const char *, tree);
    130 extern void riscv_declare_function_size (FILE *, const char *, tree);
    131 extern void riscv_asm_output_alias (FILE *, const tree, const tree);
    132 extern void riscv_asm_output_external (FILE *, const tree, const char *);
    133 extern bool
    134 riscv_zcmp_valid_stack_adj_bytes_p (HOST_WIDE_INT, int);
    135 extern void riscv_legitimize_poly_move (machine_mode, rtx, rtx, rtx);
    136 
    137 #ifdef RTX_CODE
    138 extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx, bool *invert_ptr = 0);
    139 extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx,
    140 				    bool *invert_ptr = nullptr);
    141 extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx);
    142 extern rtx riscv_emit_unary (enum rtx_code code, rtx dest, rtx x);
    143 extern rtx riscv_emit_binary (enum rtx_code code, rtx dest, rtx x, rtx y);
    144 #endif
    145 extern bool riscv_expand_conditional_move (rtx, rtx, rtx, rtx);
    146 extern rtx riscv_legitimize_call_address (rtx);
    147 extern void riscv_set_return_address (rtx, rtx);
    148 extern rtx riscv_return_addr (int, rtx);
    149 extern poly_int64 riscv_initial_elimination_offset (int, int);
    150 extern void riscv_expand_prologue (void);
    151 extern void riscv_expand_epilogue (int);
    152 extern bool riscv_epilogue_uses (unsigned int);
    153 extern bool riscv_can_use_return_insn (void);
    154 extern rtx riscv_function_value (const_tree, const_tree, enum machine_mode);
    155 extern bool riscv_store_data_bypass_p (rtx_insn *, rtx_insn *);
    156 extern rtx riscv_gen_gpr_save_insn (struct riscv_frame_info *);
    157 extern bool riscv_gpr_save_operation_p (rtx);
    158 extern void riscv_reinit (void);
    159 extern poly_uint64 riscv_regmode_natural_size (machine_mode);
    160 extern bool riscv_v_ext_vector_mode_p (machine_mode);
    161 extern bool riscv_v_ext_tuple_mode_p (machine_mode);
    162 extern bool riscv_v_ext_vls_mode_p (machine_mode);
    163 extern int riscv_get_v_regno_alignment (machine_mode);
    164 extern bool riscv_shamt_matches_mask_p (int, HOST_WIDE_INT);
    165 extern void riscv_subword_address (rtx, rtx *, rtx *, rtx *, rtx *);
    166 extern void riscv_lshift_subword (machine_mode, rtx, rtx, rtx *);
    167 extern enum memmodel riscv_union_memmodels (enum memmodel, enum memmodel);
    168 
    169 /* Routines implemented in riscv-c.cc.  */
    170 void riscv_cpu_cpp_builtins (cpp_reader *);
    171 void riscv_register_pragmas (void);
    172 
    173 /* Routines implemented in riscv-builtins.cc.  */
    174 extern void riscv_atomic_assign_expand_fenv (tree *, tree *, tree *);
    175 extern bool riscv_gimple_fold_builtin (gimple_stmt_iterator *);
    176 extern rtx riscv_expand_builtin (tree, rtx, rtx, machine_mode, int);
    177 extern tree riscv_builtin_decl (unsigned int, bool);
    178 extern void riscv_init_builtins (void);
    179 
    180 /* Routines implemented in riscv-common.cc.  */
    181 extern std::string riscv_arch_str (bool version_p = true);
    182 extern void riscv_parse_arch_string (const char *, struct gcc_options *, location_t);
    183 
    184 extern bool riscv_hard_regno_rename_ok (unsigned, unsigned);
    185 
    186 rtl_opt_pass * make_pass_shorten_memrefs (gcc::context *ctxt);
    187 rtl_opt_pass * make_pass_avlprop (gcc::context *ctxt);
    188 rtl_opt_pass * make_pass_vsetvl (gcc::context *ctxt);
    189 
    190 /* Routines implemented in riscv-string.c.  */
    191 extern bool riscv_expand_block_move (rtx, rtx, rtx);
    192 
    193 /* Information about one CPU we know about.  */
    194 struct riscv_cpu_info {
    195   /* This CPU's canonical name.  */
    196   const char *name;
    197 
    198   /* Default arch for this CPU, could be NULL if no default arch.  */
    199   const char *arch;
    200 
    201   /* Which automaton to use for tuning.  */
    202   const char *tune;
    203 };
    204 
    205 extern const riscv_cpu_info *riscv_find_cpu (const char *);
    206 
    207 /* Common vector costs in any kind of vectorization (e.g VLA and VLS).  */
    208 struct common_vector_cost
    209 {
    210   /* Cost of any integer vector operation, excluding the ones handled
    211      specially below.  */
    212   const int int_stmt_cost;
    213 
    214   /* Cost of any fp vector operation, excluding the ones handled
    215      specially below.  */
    216   const int fp_stmt_cost;
    217 
    218   /* Gather/scatter vectorization cost.  */
    219   const int gather_load_cost;
    220   const int scatter_store_cost;
    221 
    222   /* Cost of a vector-to-scalar operation.  */
    223   const int vec_to_scalar_cost;
    224 
    225   /* Cost of a scalar-to-vector operation.  */
    226   const int scalar_to_vec_cost;
    227 
    228   /* Cost of a permute operation.  */
    229   const int permute_cost;
    230 
    231   /* Cost of an aligned vector load.  */
    232   const int align_load_cost;
    233 
    234   /* Cost of an aligned vector store.  */
    235   const int align_store_cost;
    236 
    237   /* Cost of an unaligned vector load.  */
    238   const int unalign_load_cost;
    239 
    240   /* Cost of an unaligned vector store.  */
    241   const int unalign_store_cost;
    242 };
    243 
    244 /* scalable vectorization (VLA) specific cost.  */
    245 struct scalable_vector_cost : common_vector_cost
    246 {
    247   CONSTEXPR scalable_vector_cost (const common_vector_cost &base)
    248     : common_vector_cost (base)
    249   {}
    250 
    251   /* TODO: We will need more other kinds of vector cost for VLA.
    252      E.g. fold_left reduction cost, lanes load/store cost, ..., etc.  */
    253 };
    254 
    255 /* Additional costs for register copies.  Cost is for one register.  */
    256 struct regmove_vector_cost
    257 {
    258   const int GR2VR;
    259   const int FR2VR;
    260   const int VR2GR;
    261   const int VR2FR;
    262 };
    263 
    264 /* Cost for vector insn classes.  */
    265 struct cpu_vector_cost
    266 {
    267   /* Cost of any integer scalar operation, excluding load and store.  */
    268   const int scalar_int_stmt_cost;
    269 
    270   /* Cost of any fp scalar operation, excluding load and store.  */
    271   const int scalar_fp_stmt_cost;
    272 
    273   /* Cost of a scalar load.  */
    274   const int scalar_load_cost;
    275 
    276   /* Cost of a scalar store.  */
    277   const int scalar_store_cost;
    278 
    279   /* Cost of a taken branch.  */
    280   const int cond_taken_branch_cost;
    281 
    282   /* Cost of a not-taken branch.  */
    283   const int cond_not_taken_branch_cost;
    284 
    285   /* Cost of an VLS modes operations.  */
    286   const common_vector_cost *vls;
    287 
    288   /* Cost of an VLA modes operations.  */
    289   const scalable_vector_cost *vla;
    290 
    291   /* Cost of vector register move operations.  */
    292   const regmove_vector_cost *regmove;
    293 };
    294 
    295 /* Routines implemented in riscv-selftests.cc.  */
    296 #if CHECKING_P
    297 namespace selftest {
    298 void riscv_run_selftests (void);
    299 } // namespace selftest
    300 #endif
    301 
    302 namespace riscv_vector {
    303 #define RVV_VLMAX regno_reg_rtx[X0_REGNUM]
    304 #define RVV_VUNDEF(MODE)                                                       \
    305   gen_rtx_UNSPEC (MODE, gen_rtvec (1, RVV_VLMAX), UNSPEC_VUNDEF)
    306 
    307 /* These flags describe how to pass the operands to a rvv insn pattern.
    308    e.g.:
    309      If a insn has this flags:
    310        HAS_DEST_P | HAS_MASK_P | USE_VUNDEF_MERGE_P
    311 	 | TU_POLICY_P | BINARY_OP_P | FRM_DYN_P
    312      that means:
    313        operands[0] is the dest operand
    314        operands[1] is the mask operand
    315        operands[2] is the merge operand
    316        operands[3] and operands[4] is the two operand to do the operation.
    317        operands[5] is the vl operand
    318        operands[6] is the tail policy operand
    319        operands[7] is the mask policy operands
    320        operands[8] is the rounding mode operands
    321 
    322      Then you can call `emit_vlmax_insn (flags, icode, ops)` to emit a insn.
    323      and ops[0] is the dest operand (operands[0]), ops[1] is the mask
    324      operand (operands[1]), ops[2] and ops[3] is the two
    325      operands (operands[3], operands[4]) to do the operation. Other operands
    326      will be created by emit_vlmax_insn according to the flags information.
    327 */
    328 enum insn_flags : unsigned int
    329 {
    330   /* flags for dest, mask, merge operands.  */
    331   /* Means INSN has dest operand. False for STORE insn.  */
    332   HAS_DEST_P = 1 << 0,
    333   /* Means INSN has mask operand.  */
    334   HAS_MASK_P = 1 << 1,
    335   /* Means using ALL_TRUES for mask operand.  */
    336   USE_ALL_TRUES_MASK_P = 1 << 2,
    337   /* Means using ONE_TRUE for mask operand.  */
    338   USE_ONE_TRUE_MASK_P = 1 << 3,
    339   /* Means INSN has merge operand.  */
    340   HAS_MERGE_P = 1 << 4,
    341   /* Means using VUNDEF for merge operand.  */
    342   USE_VUNDEF_MERGE_P = 1 << 5,
    343 
    344   /* flags for tail policy and mask plicy operands.  */
    345   /* Means the tail policy is TAIL_UNDISTURBED.  */
    346   TU_POLICY_P = 1 << 6,
    347   /* Means the tail policy is default (return by get_prefer_tail_policy).  */
    348   TDEFAULT_POLICY_P = 1 << 7,
    349   /* Means the mask policy is MASK_UNDISTURBED.  */
    350   MU_POLICY_P = 1 << 8,
    351   /* Means the mask policy is default (return by get_prefer_mask_policy).  */
    352   MDEFAULT_POLICY_P = 1 << 9,
    353 
    354   /* flags for the number operands to do the operation.  */
    355   /* Means INSN need zero operand to do the operation. e.g. vid.v */
    356   NULLARY_OP_P = 1 << 10,
    357   /* Means INSN need one operand to do the operation.  */
    358   UNARY_OP_P = 1 << 11,
    359   /* Means INSN need two operands to do the operation.  */
    360   BINARY_OP_P = 1 << 12,
    361   /* Means INSN need two operands to do the operation.  */
    362   TERNARY_OP_P = 1 << 13,
    363 
    364   /* flags for get vtype mode from the index number. default from dest operand.  */
    365   VTYPE_MODE_FROM_OP1_P = 1 << 14,
    366 
    367   /* flags for the floating-point rounding mode.  */
    368   /* Means INSN has FRM operand and the value is FRM_DYN.  */
    369   FRM_DYN_P = 1 << 15,
    370 
    371   /* Means INSN has FRM operand and the value is FRM_RUP.  */
    372   FRM_RUP_P = 1 << 16,
    373 
    374   /* Means INSN has FRM operand and the value is FRM_RDN.  */
    375   FRM_RDN_P = 1 << 17,
    376 
    377   /* Means INSN has FRM operand and the value is FRM_RMM.  */
    378   FRM_RMM_P = 1 << 18,
    379 
    380   /* Means INSN has FRM operand and the value is FRM_RNE.  */
    381   FRM_RNE_P = 1 << 19,
    382 
    383   /* Means INSN has VXRM operand and the value is VXRM_RNU.  */
    384   VXRM_RNU_P = 1 << 20,
    385 
    386   /* Means INSN has VXRM operand and the value is VXRM_RDN.  */
    387   VXRM_RDN_P = 1 << 21,
    388 };
    389 
    390 enum insn_type : unsigned int
    391 {
    392   /* some flags macros.  */
    393   /* For non-mask insn with tama.  */
    394   __NORMAL_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
    395 		| USE_VUNDEF_MERGE_P | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P,
    396   /* For non-mask insn with ta, without mask policy operand.  */
    397   __NORMAL_OP_TA = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
    398 		   | USE_VUNDEF_MERGE_P | TDEFAULT_POLICY_P,
    399   /* For non-mask insn with ta, without mask operand and mask policy operand. */
    400   __NORMAL_OP_TA2
    401   = HAS_DEST_P | HAS_MERGE_P | USE_VUNDEF_MERGE_P | TDEFAULT_POLICY_P,
    402   /* For non-mask insn with ma, without tail policy operand.  */
    403   __NORMAL_OP_MA = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
    404 		   | USE_VUNDEF_MERGE_P | MDEFAULT_POLICY_P,
    405   /* For mask insn with tama.  */
    406   __MASK_OP_TAMA = HAS_DEST_P | HAS_MASK_P | HAS_MERGE_P | USE_VUNDEF_MERGE_P
    407 		   | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P,
    408   /* For mask insn with tamu.  */
    409   __MASK_OP_TAMU
    410   = HAS_DEST_P | HAS_MASK_P | HAS_MERGE_P | TDEFAULT_POLICY_P | MU_POLICY_P,
    411   /* For mask insn with tuma.  */
    412   __MASK_OP_TUMA = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
    413 		   | TU_POLICY_P | MDEFAULT_POLICY_P,
    414   /* For mask insn with mu.  */
    415   __MASK_OP_MU = HAS_DEST_P | HAS_MASK_P | HAS_MERGE_P | MU_POLICY_P,
    416   /* For mask insn with ta, without mask policy operand.  */
    417   __MASK_OP_TA = HAS_DEST_P | HAS_MASK_P | HAS_MERGE_P | USE_VUNDEF_MERGE_P
    418 		 | TDEFAULT_POLICY_P,
    419 
    420   /* Nullary operator. e.g. vid.v  */
    421   NULLARY_OP = __NORMAL_OP | NULLARY_OP_P,
    422 
    423   /* Unary operator.  */
    424   UNARY_OP = __NORMAL_OP | UNARY_OP_P,
    425   UNARY_OP_TAMA = __MASK_OP_TAMA | UNARY_OP_P,
    426   UNARY_OP_TAMU = __MASK_OP_TAMU | UNARY_OP_P,
    427   UNARY_OP_FRM_DYN = UNARY_OP | FRM_DYN_P,
    428   UNARY_OP_FRM_RMM = UNARY_OP | FRM_RMM_P,
    429   UNARY_OP_FRM_RUP = UNARY_OP | FRM_RUP_P,
    430   UNARY_OP_FRM_RDN = UNARY_OP | FRM_RDN_P,
    431   UNARY_OP_TAMA_FRM_DYN = UNARY_OP_TAMA | FRM_DYN_P,
    432   UNARY_OP_TAMA_FRM_RUP = UNARY_OP_TAMA | FRM_RUP_P,
    433   UNARY_OP_TAMA_FRM_RDN = UNARY_OP_TAMA | FRM_RDN_P,
    434   UNARY_OP_TAMA_FRM_RMM = UNARY_OP_TAMA | FRM_RMM_P,
    435   UNARY_OP_TAMA_FRM_RNE = UNARY_OP_TAMA | FRM_RNE_P,
    436   UNARY_OP_TAMU_FRM_DYN = UNARY_OP_TAMU | FRM_DYN_P,
    437   UNARY_OP_TAMU_FRM_RUP = UNARY_OP_TAMU | FRM_RUP_P,
    438   UNARY_OP_TAMU_FRM_RDN = UNARY_OP_TAMU | FRM_RDN_P,
    439   UNARY_OP_TAMU_FRM_RMM = UNARY_OP_TAMU | FRM_RMM_P,
    440   UNARY_OP_TAMU_FRM_RNE = UNARY_OP_TAMU | FRM_RNE_P,
    441 
    442   /* Binary operator.  */
    443   BINARY_OP = __NORMAL_OP | BINARY_OP_P,
    444   BINARY_OP_TAMA = __MASK_OP_TAMA | BINARY_OP_P,
    445   BINARY_OP_TAMU = __MASK_OP_TAMU | BINARY_OP_P,
    446   BINARY_OP_TUMA = __MASK_OP_TUMA | BINARY_OP_P,
    447   BINARY_OP_FRM_DYN = BINARY_OP | FRM_DYN_P,
    448   BINARY_OP_VXRM_RNU = BINARY_OP | VXRM_RNU_P,
    449   BINARY_OP_VXRM_RDN = BINARY_OP | VXRM_RDN_P,
    450 
    451   /* Ternary operator. Always have real merge operand.  */
    452   TERNARY_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
    453 	       | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P | TERNARY_OP_P,
    454   TERNARY_OP_FRM_DYN = TERNARY_OP | FRM_DYN_P,
    455 
    456   /* For vwmacc, no merge operand.  */
    457   WIDEN_TERNARY_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P
    458 		     | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P | TERNARY_OP_P,
    459   WIDEN_TERNARY_OP_FRM_DYN = WIDEN_TERNARY_OP | FRM_DYN_P,
    460 
    461   /* For vmerge, no mask operand, no mask policy operand.  */
    462   MERGE_OP = __NORMAL_OP_TA2 | TERNARY_OP_P,
    463 
    464   /* For vmerge with TU policy.  */
    465   MERGE_OP_TU = HAS_DEST_P | HAS_MERGE_P | TERNARY_OP_P | TU_POLICY_P,
    466 
    467   /* For vm<compare>, no tail policy operand.  */
    468   COMPARE_OP = __NORMAL_OP_MA | TERNARY_OP_P,
    469   COMPARE_OP_MU = __MASK_OP_MU | TERNARY_OP_P,
    470 
    471   /* For scatter insn: no dest operand, no merge operand, no tail and mask
    472      policy operands.  */
    473   SCATTER_OP_M = HAS_MASK_P | TERNARY_OP_P,
    474 
    475   /* For vcpop.m, no merge operand, no tail and mask policy operands.  */
    476   CPOP_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | UNARY_OP_P
    477 	    | VTYPE_MODE_FROM_OP1_P,
    478 
    479   /* For mask instrunctions, no tail and mask policy operands.  */
    480   UNARY_MASK_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
    481 		  | USE_VUNDEF_MERGE_P | UNARY_OP_P,
    482   BINARY_MASK_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
    483 		   | USE_VUNDEF_MERGE_P | BINARY_OP_P,
    484 
    485   /* For vcompress.vm */
    486   COMPRESS_OP = __NORMAL_OP_TA2 | BINARY_OP_P,
    487   /* has merge operand but use tu.  */
    488   COMPRESS_OP_MERGE
    489   = HAS_DEST_P | HAS_MERGE_P | TU_POLICY_P | BINARY_OP_P,
    490 
    491   /* For vslideup.up has merge operand but use ta.  */
    492   SLIDEUP_OP_MERGE = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P
    493 		     | HAS_MERGE_P | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P
    494 		     | BINARY_OP_P,
    495 
    496   /* For vreduce, no mask policy operand. */
    497   REDUCE_OP = __NORMAL_OP_TA | BINARY_OP_P | VTYPE_MODE_FROM_OP1_P,
    498   REDUCE_OP_M = __MASK_OP_TA | BINARY_OP_P | VTYPE_MODE_FROM_OP1_P,
    499   REDUCE_OP_FRM_DYN = REDUCE_OP | FRM_DYN_P | VTYPE_MODE_FROM_OP1_P,
    500   REDUCE_OP_M_FRM_DYN
    501   = __MASK_OP_TA | BINARY_OP_P | FRM_DYN_P | VTYPE_MODE_FROM_OP1_P,
    502 
    503   /* For vmv.s.x/vfmv.s.f.  */
    504   SCALAR_MOVE_OP = HAS_DEST_P | HAS_MASK_P | USE_ONE_TRUE_MASK_P | HAS_MERGE_P
    505 		   | USE_VUNDEF_MERGE_P | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P
    506 		   | UNARY_OP_P,
    507 
    508   SCALAR_MOVE_MERGED_OP = HAS_DEST_P | HAS_MASK_P | USE_ONE_TRUE_MASK_P
    509 			  | HAS_MERGE_P | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P
    510 			  | UNARY_OP_P,
    511 
    512   SCALAR_MOVE_MERGED_OP_TU = HAS_DEST_P | HAS_MASK_P | USE_ONE_TRUE_MASK_P
    513 			  | HAS_MERGE_P | TU_POLICY_P | MDEFAULT_POLICY_P
    514 			  | UNARY_OP_P,
    515 };
    516 
    517 enum vlmul_type
    518 {
    519   LMUL_1 = 0,
    520   LMUL_2 = 1,
    521   LMUL_4 = 2,
    522   LMUL_8 = 3,
    523   LMUL_RESERVED = 4,
    524   LMUL_F8 = 5,
    525   LMUL_F4 = 6,
    526   LMUL_F2 = 7,
    527   NUM_LMUL = 8
    528 };
    529 
    530 /* The RISC-V vsetvli pass uses "known vlmax" operations for optimization.
    531    Whether or not an instruction actually is a vlmax operation is not
    532    recognizable from the length operand alone but the avl_type operand
    533    is used instead.  In general, there are two cases:
    534 
    535     - Emit a vlmax operation by calling emit_vlmax_insn[_lra].  Here we emit
    536       a vsetvli with vlmax configuration and set the avl_type to VLMAX for
    537       VLA modes or VLS for VLS modes.
    538     - Emit an operation that uses the existing (last-set) length and
    539       set the avl_type to NONVLMAX.
    540 
    541     Sometimes we also need to set the VLMAX or VLS avl_type to an operation that
    542     already uses a given length register.  This can happen during or after
    543     register allocation when we are not allowed to create a new register.
    544     For that case we also allow to set the avl_type to VLMAX or VLS.
    545 */
    546 enum avl_type
    547 {
    548   NONVLMAX = 0,
    549   VLMAX = 1,
    550   VLS = 2,
    551 };
    552 /* Routines implemented in riscv-vector-builtins.cc.  */
    553 void init_builtins (void);
    554 void reinit_builtins (void);
    555 const char *mangle_builtin_type (const_tree);
    556 tree lookup_vector_type_attribute (const_tree);
    557 bool builtin_type_p (const_tree);
    558 #ifdef GCC_TARGET_H
    559 bool verify_type_context (location_t, type_context_kind, const_tree, bool);
    560 bool expand_vec_perm_const (machine_mode, machine_mode, rtx, rtx, rtx,
    561 			    const vec_perm_indices &);
    562 #endif
    563 void handle_pragma_vector (void);
    564 tree builtin_decl (unsigned, bool);
    565 gimple *gimple_fold_builtin (unsigned int, gimple_stmt_iterator *, gcall *);
    566 rtx expand_builtin (unsigned int, tree, rtx);
    567 bool check_builtin_call (location_t, vec<location_t>, unsigned int,
    568 			   tree, unsigned int, tree *);
    569 tree resolve_overloaded_builtin (location_t, unsigned int, tree, vec<tree, va_gc> *);
    570 bool const_vec_all_same_in_range_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
    571 bool legitimize_move (rtx, rtx *);
    572 void emit_vlmax_vsetvl (machine_mode, rtx);
    573 void emit_hard_vlmax_vsetvl (machine_mode, rtx);
    574 void emit_vlmax_insn (unsigned, unsigned, rtx *);
    575 void emit_nonvlmax_insn (unsigned, unsigned, rtx *, rtx);
    576 void emit_vlmax_insn_lra (unsigned, unsigned, rtx *, rtx);
    577 enum vlmul_type get_vlmul (machine_mode);
    578 rtx get_vlmax_rtx (machine_mode);
    579 unsigned int get_ratio (machine_mode);
    580 unsigned int get_nf (machine_mode);
    581 machine_mode get_subpart_mode (machine_mode);
    582 int get_ta (rtx);
    583 int get_ma (rtx);
    584 int get_avl_type (rtx);
    585 unsigned int calculate_ratio (unsigned int, enum vlmul_type);
    586 enum tail_policy
    587 {
    588   TAIL_UNDISTURBED = 0,
    589   TAIL_AGNOSTIC = 1,
    590   TAIL_ANY = 2,
    591 };
    592 
    593 enum mask_policy
    594 {
    595   MASK_UNDISTURBED = 0,
    596   MASK_AGNOSTIC = 1,
    597   MASK_ANY = 2,
    598 };
    599 
    600 /* Return true if VALUE is agnostic or any policy.  */
    601 #define IS_AGNOSTIC(VALUE) (bool) (VALUE & 0x1 || (VALUE >> 1 & 0x1))
    602 
    603 enum tail_policy get_prefer_tail_policy ();
    604 enum mask_policy get_prefer_mask_policy ();
    605 rtx get_avl_type_rtx (enum avl_type);
    606 opt_machine_mode get_vector_mode (scalar_mode, poly_uint64);
    607 opt_machine_mode get_tuple_mode (machine_mode, unsigned int);
    608 bool simm5_p (rtx);
    609 bool neg_simm5_p (rtx);
    610 #ifdef RTX_CODE
    611 bool has_vi_variant_p (rtx_code, rtx);
    612 void expand_vec_cmp (rtx, rtx_code, rtx, rtx, rtx = nullptr, rtx = nullptr);
    613 bool expand_vec_cmp_float (rtx, rtx_code, rtx, rtx, bool);
    614 void expand_cond_len_unop (unsigned, rtx *);
    615 void expand_cond_len_binop (unsigned, rtx *);
    616 void expand_reduction (unsigned, unsigned, unsigned, rtx *, rtx);
    617 void expand_vec_ceil (rtx, rtx, machine_mode, machine_mode);
    618 void expand_vec_floor (rtx, rtx, machine_mode, machine_mode);
    619 void expand_vec_nearbyint (rtx, rtx, machine_mode, machine_mode);
    620 void expand_vec_rint (rtx, rtx, machine_mode, machine_mode);
    621 void expand_vec_round (rtx, rtx, machine_mode, machine_mode);
    622 void expand_vec_trunc (rtx, rtx, machine_mode, machine_mode);
    623 void expand_vec_roundeven (rtx, rtx, machine_mode, machine_mode);
    624 void expand_vec_lrint (rtx, rtx, machine_mode, machine_mode, machine_mode);
    625 void expand_vec_lround (rtx, rtx, machine_mode, machine_mode, machine_mode);
    626 void expand_vec_lceil (rtx, rtx, machine_mode, machine_mode);
    627 void expand_vec_lfloor (rtx, rtx, machine_mode, machine_mode);
    628 #endif
    629 bool sew64_scalar_helper (rtx *, rtx *, rtx, machine_mode,
    630 			  bool, void (*)(rtx *, rtx), enum avl_type);
    631 rtx gen_scalar_move_mask (machine_mode);
    632 rtx gen_no_side_effects_vsetvl_rtx (machine_mode, rtx, rtx);
    633 
    634 /* RVV vector register sizes.
    635    TODO: Currently, we only add RVV_32/RVV_64/RVV_128, we may need to
    636    support other values in the future.  */
    637 enum vlen_enum
    638 {
    639   RVV_32 = 32,
    640   RVV_64 = 64,
    641   RVV_65536 = 65536
    642 };
    643 bool slide1_sew64_helper (int, machine_mode, machine_mode,
    644 			  machine_mode, rtx *);
    645 rtx gen_avl_for_scalar_move (rtx);
    646 void expand_tuple_move (rtx *);
    647 bool expand_block_move (rtx, rtx, rtx);
    648 machine_mode preferred_simd_mode (scalar_mode);
    649 machine_mode get_mask_mode (machine_mode);
    650 void expand_vec_series (rtx, rtx, rtx, rtx = 0);
    651 void expand_vec_init (rtx, rtx);
    652 void expand_vec_perm (rtx, rtx, rtx, rtx);
    653 void expand_select_vl (rtx *);
    654 void expand_load_store (rtx *, bool);
    655 void expand_gather_scatter (rtx *, bool);
    656 void expand_cond_len_ternop (unsigned, rtx *);
    657 void prepare_ternary_operands (rtx *);
    658 void expand_lanes_load_store (rtx *, bool);
    659 void expand_fold_extract_last (rtx *);
    660 void expand_cond_unop (unsigned, rtx *);
    661 void expand_cond_binop (unsigned, rtx *);
    662 void expand_cond_ternop (unsigned, rtx *);
    663 void expand_popcount (rtx *);
    664 void expand_rawmemchr (machine_mode, rtx, rtx, rtx, bool = false);
    665 bool expand_strcmp (rtx, rtx, rtx, rtx, unsigned HOST_WIDE_INT, bool);
    666 void emit_vec_extract (rtx, rtx, rtx);
    667 
    668 /* Rounding mode bitfield for fixed point VXRM.  */
    669 enum fixed_point_rounding_mode
    670 {
    671   VXRM_RNU,
    672   VXRM_RNE,
    673   VXRM_RDN,
    674   VXRM_ROD
    675 };
    676 
    677 /* Rounding mode bitfield for floating point FRM.  The value of enum comes
    678    from the below link.
    679    https://github.com/riscv/riscv-isa-manual/blob/main/src/f-st-ext.adoc#floating-point-control-and-status-register
    680  */
    681 enum floating_point_rounding_mode
    682 {
    683   FRM_RNE = 0, /* Aka 0b000.  */
    684   FRM_RTZ = 1, /* Aka 0b001.  */
    685   FRM_RDN = 2, /* Aka 0b010.  */
    686   FRM_RUP = 3, /* Aka 0b011.  */
    687   FRM_RMM = 4, /* Aka 0b100.  */
    688   FRM_DYN = 7, /* Aka 0b111.  */
    689   FRM_STATIC_MIN = FRM_RNE,
    690   FRM_STATIC_MAX = FRM_RMM,
    691   FRM_DYN_EXIT = 8,
    692   FRM_DYN_CALL = 9,
    693   FRM_NONE = 10,
    694 };
    695 
    696 enum floating_point_rounding_mode get_frm_mode (rtx);
    697 opt_machine_mode vectorize_related_mode (machine_mode, scalar_mode,
    698 					 poly_uint64);
    699 unsigned int autovectorize_vector_modes (vec<machine_mode> *, bool);
    700 bool cmp_lmul_le_one (machine_mode);
    701 bool cmp_lmul_gt_one (machine_mode);
    702 bool vls_mode_valid_p (machine_mode);
    703 bool vlmax_avl_type_p (rtx_insn *);
    704 bool has_vl_op (rtx_insn *);
    705 bool tail_agnostic_p (rtx_insn *);
    706 void validate_change_or_fail (rtx, rtx *, rtx, bool);
    707 bool nonvlmax_avl_type_p (rtx_insn *);
    708 bool vlmax_avl_p (rtx);
    709 uint8_t get_sew (rtx_insn *);
    710 enum vlmul_type get_vlmul (rtx_insn *);
    711 int count_regno_occurrences (rtx_insn *, unsigned int);
    712 bool imm_avl_p (machine_mode);
    713 bool can_be_broadcasted_p (rtx);
    714 bool gather_scatter_valid_offset_p (machine_mode);
    715 HOST_WIDE_INT estimated_poly_value (poly_int64, unsigned int);
    716 bool whole_reg_to_reg_move_p (rtx *, machine_mode, int);
    717 bool splat_to_scalar_move_p (rtx *);
    718 }
    719 
    720 /* We classify builtin types into two classes:
    721    1. General builtin class which is defined in riscv_builtins.
    722    2. Vector builtin class which is a special builtin architecture
    723       that implement intrinsic short into "pragma".  */
    724 enum riscv_builtin_class
    725 {
    726   RISCV_BUILTIN_GENERAL,
    727   RISCV_BUILTIN_VECTOR
    728 };
    729 
    730 const unsigned int RISCV_BUILTIN_SHIFT = 1;
    731 
    732 /* Mask that selects the riscv_builtin_class part of a function code.  */
    733 const unsigned int RISCV_BUILTIN_CLASS = (1 << RISCV_BUILTIN_SHIFT) - 1;
    734 
    735 /* Routines implemented in riscv-string.cc.  */
    736 extern bool riscv_expand_strcmp (rtx, rtx, rtx, rtx, rtx);
    737 extern bool riscv_expand_strlen (rtx, rtx, rtx, rtx);
    738 
    739 /* Routines implemented in thead.cc.  */
    740 extern bool extract_base_offset_in_addr (rtx, rtx *, rtx *);
    741 extern bool th_mempair_operands_p (rtx[4], bool, machine_mode);
    742 extern void th_mempair_order_operands (rtx[4], bool, machine_mode);
    743 extern void th_mempair_prepare_save_restore_operands (rtx[4], bool,
    744 						      machine_mode,
    745 						      int, HOST_WIDE_INT,
    746 						      int, HOST_WIDE_INT);
    747 extern void th_mempair_save_restore_regs (rtx[4], bool, machine_mode);
    748 extern unsigned int th_int_get_mask (unsigned int);
    749 extern unsigned int th_int_get_save_adjustment (void);
    750 extern rtx th_int_adjust_cfi_prologue (unsigned int);
    751 extern const char *th_asm_output_opcode (FILE *asm_out_file, const char *p);
    752 #ifdef RTX_CODE
    753 extern const char*
    754 th_mempair_output_move (rtx[4], bool, machine_mode, RTX_CODE);
    755 extern bool th_memidx_legitimate_modify_p (rtx);
    756 extern bool th_memidx_legitimate_modify_p (rtx, bool);
    757 extern bool th_memidx_legitimate_index_p (rtx);
    758 extern bool th_memidx_legitimate_index_p (rtx, bool);
    759 extern bool th_classify_address (struct riscv_address_info *,
    760 					rtx, machine_mode, bool);
    761 extern const char *th_output_move (rtx, rtx);
    762 extern bool th_print_operand_address (FILE *, machine_mode, rtx);
    763 #endif
    764 
    765 extern bool riscv_use_divmod_expander (void);
    766 void riscv_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
    767 extern bool
    768 riscv_option_valid_attribute_p (tree, tree, tree, int);
    769 extern void
    770 riscv_override_options_internal (struct gcc_options *);
    771 extern void riscv_option_override (void);
    772 
    773 struct riscv_tune_param;
    774 /* Information about one micro-arch we know about.  */
    775 struct riscv_tune_info {
    776   /* This micro-arch canonical name.  */
    777   const char *name;
    778 
    779   /* Which automaton to use for tuning.  */
    780   enum riscv_microarchitecture_type microarchitecture;
    781 
    782   /* Tuning parameters for this micro-arch.  */
    783   const struct riscv_tune_param *tune_param;
    784 };
    785 
    786 const struct riscv_tune_info *
    787 riscv_parse_tune (const char *, bool);
    788 const cpu_vector_cost *get_vector_costs ();
    789 
    790 enum
    791 {
    792   RISCV_MAJOR_VERSION_BASE = 1000000,
    793   RISCV_MINOR_VERSION_BASE = 1000,
    794   RISCV_REVISION_VERSION_BASE = 1,
    795 };
    796 
    797 #endif /* ! GCC_RISCV_PROTOS_H */
    798