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