1 /* Subroutines used for LoongArch code generation. 2 Copyright (C) 2021-2024 Free Software Foundation, Inc. 3 Contributed by Loongson Ltd. 4 Based on MIPS and RISC-V 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 #define IN_TARGET_CODE 1 23 24 #include "config.h" 25 #include "system.h" 26 #include "coretypes.h" 27 #include "backend.h" 28 #include "target.h" 29 #include "rtl.h" 30 #include "tree.h" 31 #include "memmodel.h" 32 #include "gimple.h" 33 #include "cfghooks.h" 34 #include "df.h" 35 #include "tm_p.h" 36 #include "stringpool.h" 37 #include "attribs.h" 38 #include "optabs.h" 39 #include "regs.h" 40 #include "emit-rtl.h" 41 #include "recog.h" 42 #include "cgraph.h" 43 #include "diagnostic.h" 44 #include "insn-attr.h" 45 #include "output.h" 46 #include "alias.h" 47 #include "fold-const.h" 48 #include "varasm.h" 49 #include "stor-layout.h" 50 #include "calls.h" 51 #include "explow.h" 52 #include "expr.h" 53 #include "libfuncs.h" 54 #include "reload.h" 55 #include "common/common-target.h" 56 #include "langhooks.h" 57 #include "cfgrtl.h" 58 #include "cfganal.h" 59 #include "sched-int.h" 60 #include "gimplify.h" 61 #include "target-globals.h" 62 #include "tree-pass.h" 63 #include "context.h" 64 #include "builtins.h" 65 #include "rtl-iter.h" 66 #include "opts.h" 67 #include "function-abi.h" 68 #include "cfgloop.h" 69 #include "tree-vectorizer.h" 70 71 /* This file should be included last. */ 72 #include "target-def.h" 73 74 /* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */ 75 #define UNSPEC_ADDRESS_P(X) \ 76 (GET_CODE (X) == UNSPEC \ 77 && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST \ 78 && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES) 79 80 /* Extract the symbol or label from UNSPEC wrapper X. */ 81 #define UNSPEC_ADDRESS(X) XVECEXP (X, 0, 0) 82 83 /* Extract the symbol type from UNSPEC wrapper X. */ 84 #define UNSPEC_ADDRESS_TYPE(X) \ 85 ((enum loongarch_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST)) 86 87 /* True if INSN is a loongarch.md pattern or asm statement. */ 88 /* ??? This test exists through the compiler, perhaps it should be 89 moved to rtl.h. */ 90 #define USEFUL_INSN_P(INSN) \ 91 (NONDEBUG_INSN_P (INSN) \ 92 && GET_CODE (PATTERN (INSN)) != USE \ 93 && GET_CODE (PATTERN (INSN)) != CLOBBER) 94 95 /* True if bit BIT is set in VALUE. */ 96 #define BITSET_P(VALUE, BIT) (((VALUE) & (1 << (BIT))) != 0) 97 98 /* Classifies an address. 99 100 ADDRESS_REG 101 A natural register + offset address. The register satisfies 102 loongarch_valid_base_register_p and the offset is a const_arith_operand. 103 104 ADDRESS_REG_REG 105 A base register indexed by (optionally scaled) register. 106 107 ADDRESS_LO_SUM 108 A LO_SUM rtx. The first operand is a valid base register and the second 109 operand is a symbolic address. 110 111 ADDRESS_CONST_INT 112 A signed 16-bit constant address. 113 114 ADDRESS_SYMBOLIC: 115 A constant symbolic address. */ 116 enum loongarch_address_type 117 { 118 ADDRESS_REG, 119 ADDRESS_REG_REG, 120 ADDRESS_LO_SUM, 121 ADDRESS_CONST_INT, 122 ADDRESS_SYMBOLIC 123 }; 124 125 126 /* Information about an address described by loongarch_address_type. */ 127 struct loongarch_address_info 128 { 129 enum loongarch_address_type type; 130 rtx reg; 131 rtx offset; 132 enum loongarch_symbol_type symbol_type; 133 }; 134 135 /* Method of loading instant numbers: 136 137 METHOD_NORMAL: 138 Load 0-31 bit of the immediate number. 139 140 METHOD_LU32I: 141 Load 32-51 bit of the immediate number. 142 143 METHOD_LU52I: 144 Load 52-63 bit of the immediate number. 145 146 METHOD_MIRROR: 147 Copy 0-31 bit of the immediate number to 32-63bit. 148 */ 149 enum loongarch_load_imm_method 150 { 151 METHOD_NORMAL, 152 METHOD_LU32I, 153 METHOD_LU52I, 154 METHOD_MIRROR 155 }; 156 157 struct loongarch_integer_op 158 { 159 enum rtx_code code; 160 HOST_WIDE_INT value; 161 /* Represent the result of the immediate count of the load instruction at 162 each step. */ 163 HOST_WIDE_INT curr_value; 164 enum loongarch_load_imm_method method; 165 }; 166 167 /* The largest number of operations needed to load an integer constant. 168 The worst accepted case for 64-bit constants is LU12I.W,LU32I.D,LU52I.D,ORI 169 or LU12I.W,LU32I.D,LU52I.D,ADDI.D DECL_ASSEMBLER_NAME. */ 170 #define LARCH_MAX_INTEGER_OPS 4 171 172 /* Arrays that map GCC register numbers to debugger register numbers. */ 173 int loongarch_dwarf_regno[FIRST_PSEUDO_REGISTER]; 174 175 /* Index [M][R] is true if register R is allowed to hold a value of mode M. */ 176 static bool loongarch_hard_regno_mode_ok_p[MAX_MACHINE_MODE] 177 [FIRST_PSEUDO_REGISTER]; 178 179 /* Index C is true if character C is a valid PRINT_OPERAND punctation 180 character. */ 181 static bool loongarch_print_operand_punct[256]; 182 183 /* Cached value of can_issue_more. This is cached in loongarch_variable_issue 184 hook and returned from loongarch_sched_reorder2. */ 185 static int cached_can_issue_more; 186 187 /* Index R is the smallest register class that contains register R. */ 188 const enum reg_class loongarch_regno_to_class[FIRST_PSEUDO_REGISTER] = { 189 GR_REGS, GR_REGS, GR_REGS, GR_REGS, 190 JIRL_REGS, JIRL_REGS, JIRL_REGS, JIRL_REGS, 191 JIRL_REGS, JIRL_REGS, JIRL_REGS, JIRL_REGS, 192 SIBCALL_REGS, JIRL_REGS, SIBCALL_REGS, SIBCALL_REGS, 193 SIBCALL_REGS, SIBCALL_REGS, SIBCALL_REGS, SIBCALL_REGS, 194 SIBCALL_REGS, GR_REGS, GR_REGS, JIRL_REGS, 195 JIRL_REGS, JIRL_REGS, JIRL_REGS, JIRL_REGS, 196 JIRL_REGS, JIRL_REGS, JIRL_REGS, JIRL_REGS, 197 198 FP_REGS, FP_REGS, FP_REGS, FP_REGS, 199 FP_REGS, FP_REGS, FP_REGS, FP_REGS, 200 FP_REGS, FP_REGS, FP_REGS, FP_REGS, 201 FP_REGS, FP_REGS, FP_REGS, FP_REGS, 202 FP_REGS, FP_REGS, FP_REGS, FP_REGS, 203 FP_REGS, FP_REGS, FP_REGS, FP_REGS, 204 FP_REGS, FP_REGS, FP_REGS, FP_REGS, 205 FP_REGS, FP_REGS, FP_REGS, FP_REGS, 206 FCC_REGS, FCC_REGS, FCC_REGS, FCC_REGS, 207 FCC_REGS, FCC_REGS, FCC_REGS, FCC_REGS, 208 FRAME_REGS, FRAME_REGS 209 }; 210 211 /* Information about a single argument. */ 212 struct loongarch_arg_info 213 { 214 /* True if the argument is at least partially passed on the stack. */ 215 bool stack_p; 216 217 /* The number of integer registers allocated to this argument. */ 218 unsigned int num_gprs; 219 220 /* The offset of the first register used, provided num_gprs is nonzero. 221 If passed entirely on the stack, the value is MAX_ARGS_IN_REGISTERS. */ 222 unsigned int gpr_offset; 223 224 /* The number of floating-point registers allocated to this argument. */ 225 unsigned int num_fprs; 226 227 /* The offset of the first register used, provided num_fprs is nonzero. */ 228 unsigned int fpr_offset; 229 }; 230 231 /* Invoke MACRO (COND) for each fcmp.cond.{s/d} condition. */ 232 #define LARCH_FP_CONDITIONS(MACRO) \ 233 MACRO (f), \ 234 MACRO (un), \ 235 MACRO (eq), \ 236 MACRO (ueq), \ 237 MACRO (olt), \ 238 MACRO (ult), \ 239 MACRO (ole), \ 240 MACRO (ule), \ 241 MACRO (sf), \ 242 MACRO (ngle), \ 243 MACRO (seq), \ 244 MACRO (ngl), \ 245 MACRO (lt), \ 246 MACRO (nge), \ 247 MACRO (le), \ 248 MACRO (ngt) 249 250 /* Enumerates the codes above as LARCH_FP_COND_<X>. */ 251 #define DECLARE_LARCH_COND(X) LARCH_FP_COND_##X 252 enum loongarch_fp_condition 253 { 254 LARCH_FP_CONDITIONS (DECLARE_LARCH_COND) 255 }; 256 #undef DECLARE_LARCH_COND 257 258 /* Index X provides the string representation of LARCH_FP_COND_<X>. */ 259 #define STRINGIFY(X) #X 260 const char *const 261 loongarch_fp_conditions[16]= {LARCH_FP_CONDITIONS (STRINGIFY)}; 262 #undef STRINGIFY 263 264 /* Size of guard page. */ 265 #define STACK_CLASH_PROTECTION_GUARD_SIZE \ 266 (1 << param_stack_clash_protection_guard_size) 267 268 /* Implement TARGET_FUNCTION_ARG_BOUNDARY. Every parameter gets at 269 least PARM_BOUNDARY bits of alignment, but will be given anything up 270 to PREFERRED_STACK_BOUNDARY bits if the type requires it. */ 271 272 static unsigned int 273 loongarch_function_arg_boundary (machine_mode mode, const_tree type) 274 { 275 unsigned int alignment; 276 277 /* Use natural alignment if the type is not aggregate data. */ 278 if (type && !AGGREGATE_TYPE_P (type)) 279 alignment = TYPE_ALIGN (TYPE_MAIN_VARIANT (type)); 280 else 281 alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode); 282 283 return MIN (PREFERRED_STACK_BOUNDARY, MAX (PARM_BOUNDARY, alignment)); 284 } 285 286 /* If MODE represents an argument that can be passed or returned in 287 floating-point registers, return the number of registers, else 0. */ 288 289 static unsigned 290 loongarch_pass_mode_in_fpr_p (machine_mode mode) 291 { 292 if (GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FP_ARG) 293 { 294 if (GET_MODE_CLASS (mode) == MODE_FLOAT) 295 return 1; 296 297 if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) 298 return 2; 299 } 300 301 return 0; 302 } 303 304 typedef struct 305 { 306 const_tree type; 307 HOST_WIDE_INT offset; 308 } loongarch_aggregate_field; 309 310 /* Identify subfields of aggregates that are candidates for passing in 311 floating-point registers. */ 312 313 static int 314 loongarch_flatten_aggregate_field (const_tree type, 315 loongarch_aggregate_field fields[2], int n, 316 HOST_WIDE_INT offset) 317 { 318 switch (TREE_CODE (type)) 319 { 320 case RECORD_TYPE: 321 /* Can't handle incomplete types nor sizes that are not fixed. */ 322 if (!COMPLETE_TYPE_P (type) 323 || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST 324 || !tree_fits_uhwi_p (TYPE_SIZE (type))) 325 return -1; 326 327 for (tree f = TYPE_FIELDS (type); f; f = DECL_CHAIN (f)) 328 if (TREE_CODE (f) == FIELD_DECL) 329 { 330 if (!TYPE_P (TREE_TYPE (f))) 331 return -1; 332 333 if (DECL_SIZE (f) && integer_zerop (DECL_SIZE (f))) 334 continue; 335 336 HOST_WIDE_INT pos = offset + int_byte_position (f); 337 n = loongarch_flatten_aggregate_field (TREE_TYPE (f), fields, n, 338 pos); 339 if (n < 0) 340 return -1; 341 } 342 return n; 343 344 case ARRAY_TYPE: 345 { 346 HOST_WIDE_INT n_elts; 347 loongarch_aggregate_field subfields[2]; 348 tree index = TYPE_DOMAIN (type); 349 tree elt_size = TYPE_SIZE_UNIT (TREE_TYPE (type)); 350 int n_subfields = loongarch_flatten_aggregate_field (TREE_TYPE (type), 351 subfields, 0, 352 offset); 353 354 /* Can't handle incomplete types nor sizes that are not fixed. */ 355 if (n_subfields <= 0 356 || !COMPLETE_TYPE_P (type) 357 || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST 358 || !index 359 || !TYPE_MAX_VALUE (index) 360 || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index)) 361 || !TYPE_MIN_VALUE (index) 362 || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index)) 363 || !tree_fits_uhwi_p (elt_size)) 364 return -1; 365 366 n_elts = 1 + tree_to_uhwi (TYPE_MAX_VALUE (index)) 367 - tree_to_uhwi (TYPE_MIN_VALUE (index)); 368 gcc_assert (n_elts >= 0); 369 370 for (HOST_WIDE_INT i = 0; i < n_elts; i++) 371 for (int j = 0; j < n_subfields; j++) 372 { 373 if (n >= 2) 374 return -1; 375 376 fields[n] = subfields[j]; 377 fields[n++].offset += i * tree_to_uhwi (elt_size); 378 } 379 380 return n; 381 } 382 383 case COMPLEX_TYPE: 384 { 385 /* Complex type need consume 2 field, so n must be 0. */ 386 if (n != 0) 387 return -1; 388 389 HOST_WIDE_INT elt_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type))); 390 391 if (elt_size <= UNITS_PER_FP_ARG) 392 { 393 fields[0].type = TREE_TYPE (type); 394 fields[0].offset = offset; 395 fields[1].type = TREE_TYPE (type); 396 fields[1].offset = offset + elt_size; 397 398 return 2; 399 } 400 401 return -1; 402 } 403 404 default: 405 if (n < 2 406 && ((SCALAR_FLOAT_TYPE_P (type) 407 && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FP_ARG) 408 || (INTEGRAL_TYPE_P (type) 409 && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD))) 410 { 411 fields[n].type = type; 412 fields[n].offset = offset; 413 return n + 1; 414 } 415 else 416 return -1; 417 } 418 } 419 420 /* Identify candidate aggregates for passing in floating-point registers. 421 Candidates have at most two fields after flattening. */ 422 423 static int 424 loongarch_flatten_aggregate_argument (const_tree type, 425 loongarch_aggregate_field fields[2]) 426 { 427 if (!type || TREE_CODE (type) != RECORD_TYPE) 428 return -1; 429 430 return loongarch_flatten_aggregate_field (type, fields, 0, 0); 431 } 432 433 /* See whether TYPE is a record whose fields should be returned in one or 434 two floating-point registers. If so, populate FIELDS accordingly. */ 435 436 static unsigned 437 loongarch_pass_aggregate_num_fpr (const_tree type, 438 loongarch_aggregate_field fields[2]) 439 { 440 int n = loongarch_flatten_aggregate_argument (type, fields); 441 442 for (int i = 0; i < n; i++) 443 if (!SCALAR_FLOAT_TYPE_P (fields[i].type)) 444 return 0; 445 446 return n > 0 ? n : 0; 447 } 448 449 /* See whether TYPE is a record whose fields should be returned in one 450 floating-point register and one integer register. If so, populate 451 FIELDS accordingly. */ 452 453 static bool 454 loongarch_pass_aggregate_in_fpr_and_gpr_p (const_tree type, 455 loongarch_aggregate_field fields[2]) 456 { 457 unsigned num_int = 0, num_float = 0; 458 int n = loongarch_flatten_aggregate_argument (type, fields); 459 460 for (int i = 0; i < n; i++) 461 { 462 num_float += SCALAR_FLOAT_TYPE_P (fields[i].type); 463 num_int += INTEGRAL_TYPE_P (fields[i].type); 464 } 465 466 return num_int == 1 && num_float == 1; 467 } 468 469 /* Return the representation of an argument passed or returned in an FPR 470 when the value has mode VALUE_MODE and the type has TYPE_MODE. The 471 two modes may be different for structures like: 472 473 struct __attribute__((packed)) foo { float f; } 474 475 where the SFmode value "f" is passed in REGNO but the struct itself 476 has mode BLKmode. */ 477 478 static rtx 479 loongarch_pass_fpr_single (machine_mode type_mode, unsigned regno, 480 machine_mode value_mode, 481 HOST_WIDE_INT offset) 482 { 483 rtx x = gen_rtx_REG (value_mode, regno); 484 485 if (type_mode != value_mode) 486 { 487 x = gen_rtx_EXPR_LIST (VOIDmode, x, GEN_INT (offset)); 488 x = gen_rtx_PARALLEL (type_mode, gen_rtvec (1, x)); 489 } 490 return x; 491 } 492 493 /* Pass or return a composite value in the FPR pair REGNO and REGNO + 1. 494 MODE is the mode of the composite. MODE1 and OFFSET1 are the mode and 495 byte offset for the first value, likewise MODE2 and OFFSET2 for the 496 second value. */ 497 498 static rtx 499 loongarch_pass_fpr_pair (machine_mode mode, unsigned regno1, 500 machine_mode mode1, HOST_WIDE_INT offset1, 501 unsigned regno2, machine_mode mode2, 502 HOST_WIDE_INT offset2) 503 { 504 return gen_rtx_PARALLEL ( 505 mode, gen_rtvec (2, 506 gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode1, regno1), 507 GEN_INT (offset1)), 508 gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (mode2, regno2), 509 GEN_INT (offset2)))); 510 } 511 512 /* Fill INFO with information about a single argument, and return an 513 RTL pattern to pass or return the argument. CUM is the cumulative 514 state for earlier arguments. MODE is the mode of this argument and 515 TYPE is its type (if known). NAMED is true if this is a named 516 (fixed) argument rather than a variable one. RETURN_P is true if 517 returning the argument, or false if passing the argument. */ 518 519 static rtx 520 loongarch_get_arg_info (struct loongarch_arg_info *info, 521 const CUMULATIVE_ARGS *cum, machine_mode mode, 522 const_tree type, bool named, bool return_p) 523 { 524 unsigned num_bytes, num_words; 525 unsigned fpr_base = return_p ? FP_RETURN : FP_ARG_FIRST; 526 unsigned gpr_base = return_p ? GP_RETURN : GP_ARG_FIRST; 527 unsigned alignment = loongarch_function_arg_boundary (mode, type); 528 529 memset (info, 0, sizeof (*info)); 530 info->gpr_offset = cum->num_gprs; 531 info->fpr_offset = cum->num_fprs; 532 533 if (named) 534 { 535 loongarch_aggregate_field fields[2]; 536 unsigned fregno = fpr_base + info->fpr_offset; 537 unsigned gregno = gpr_base + info->gpr_offset; 538 539 /* Pass one- or two-element floating-point aggregates in FPRs. */ 540 if ((info->num_fprs 541 = loongarch_pass_aggregate_num_fpr (type, fields)) 542 && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS) 543 switch (info->num_fprs) 544 { 545 case 1: 546 return loongarch_pass_fpr_single (mode, fregno, 547 TYPE_MODE (fields[0].type), 548 fields[0].offset); 549 550 case 2: 551 return loongarch_pass_fpr_pair (mode, fregno, 552 TYPE_MODE (fields[0].type), 553 fields[0].offset, 554 fregno + 1, 555 TYPE_MODE (fields[1].type), 556 fields[1].offset); 557 558 default: 559 gcc_unreachable (); 560 } 561 562 /* Pass real and complex floating-point numbers in FPRs. */ 563 if ((info->num_fprs = loongarch_pass_mode_in_fpr_p (mode)) 564 && info->fpr_offset + info->num_fprs <= MAX_ARGS_IN_REGISTERS) 565 switch (GET_MODE_CLASS (mode)) 566 { 567 case MODE_FLOAT: 568 return gen_rtx_REG (mode, fregno); 569 570 case MODE_COMPLEX_FLOAT: 571 return loongarch_pass_fpr_pair (mode, fregno, 572 GET_MODE_INNER (mode), 0, 573 fregno + 1, GET_MODE_INNER (mode), 574 GET_MODE_UNIT_SIZE (mode)); 575 576 default: 577 gcc_unreachable (); 578 } 579 580 /* Pass structs with one float and one integer in an FPR and a GPR. */ 581 if (loongarch_pass_aggregate_in_fpr_and_gpr_p (type, fields) 582 && info->gpr_offset < MAX_ARGS_IN_REGISTERS 583 && info->fpr_offset < MAX_ARGS_IN_REGISTERS) 584 { 585 info->num_gprs = 1; 586 info->num_fprs = 1; 587 588 if (!SCALAR_FLOAT_TYPE_P (fields[0].type)) 589 std::swap (fregno, gregno); 590 591 return loongarch_pass_fpr_pair (mode, fregno, 592 TYPE_MODE (fields[0].type), 593 fields[0].offset, gregno, 594 TYPE_MODE (fields[1].type), 595 fields[1].offset); 596 } 597 } 598 599 /* Work out the size of the argument. */ 600 num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); 601 num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 602 603 /* Doubleword-aligned varargs start on an even register boundary. */ 604 if (!named && num_bytes != 0 && alignment > BITS_PER_WORD) 605 info->gpr_offset += info->gpr_offset & 1; 606 607 /* Partition the argument between registers and stack. */ 608 info->num_fprs = 0; 609 info->num_gprs = MIN (num_words, MAX_ARGS_IN_REGISTERS - info->gpr_offset); 610 info->stack_p = (num_words - info->num_gprs) != 0; 611 612 if (info->num_gprs || return_p) 613 return gen_rtx_REG (mode, gpr_base + info->gpr_offset); 614 615 return NULL_RTX; 616 } 617 618 /* Implement TARGET_FUNCTION_ARG. */ 619 620 static rtx 621 loongarch_function_arg (cumulative_args_t cum_v, const function_arg_info &arg) 622 { 623 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 624 struct loongarch_arg_info info; 625 626 if (arg.end_marker_p ()) 627 return NULL; 628 629 return loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, 630 false); 631 } 632 633 /* Implement TARGET_FUNCTION_ARG_ADVANCE. */ 634 635 static void 636 loongarch_function_arg_advance (cumulative_args_t cum_v, 637 const function_arg_info &arg) 638 { 639 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 640 struct loongarch_arg_info info; 641 642 loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, false); 643 644 /* Advance the register count. This has the effect of setting 645 num_gprs to MAX_ARGS_IN_REGISTERS if a doubleword-aligned 646 argument required us to skip the final GPR and pass the whole 647 argument on the stack. */ 648 cum->num_fprs = info.fpr_offset + info.num_fprs; 649 cum->num_gprs = info.gpr_offset + info.num_gprs; 650 } 651 652 /* Implement TARGET_ARG_PARTIAL_BYTES. */ 653 654 static int 655 loongarch_arg_partial_bytes (cumulative_args_t cum, 656 const function_arg_info &generic_arg) 657 { 658 struct loongarch_arg_info arg; 659 660 loongarch_get_arg_info (&arg, get_cumulative_args (cum), generic_arg.mode, 661 generic_arg.type, generic_arg.named, false); 662 return arg.stack_p ? arg.num_gprs * UNITS_PER_WORD : 0; 663 } 664 665 /* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls, 666 VALTYPE is the return type and MODE is VOIDmode. For libcalls, 667 VALTYPE is null and MODE is the mode of the return value. */ 668 669 static rtx 670 loongarch_function_value_1 (const_tree type, const_tree func, 671 machine_mode mode) 672 { 673 struct loongarch_arg_info info; 674 CUMULATIVE_ARGS args; 675 676 if (type) 677 { 678 int unsigned_p = TYPE_UNSIGNED (type); 679 680 mode = TYPE_MODE (type); 681 682 /* Since TARGET_PROMOTE_FUNCTION_MODE unconditionally promotes, 683 return values, promote the mode here too. */ 684 mode = promote_function_mode (type, mode, &unsigned_p, func, 1); 685 } 686 687 memset (&args, 0, sizeof (args)); 688 return loongarch_get_arg_info (&info, &args, mode, type, true, true); 689 } 690 691 692 /* Implement TARGET_FUNCTION_VALUE. */ 693 694 static rtx 695 loongarch_function_value (const_tree valtype, const_tree fn_decl_or_type, 696 bool outgoing ATTRIBUTE_UNUSED) 697 { 698 return loongarch_function_value_1 (valtype, fn_decl_or_type, VOIDmode); 699 } 700 701 /* Implement TARGET_LIBCALL_VALUE. */ 702 703 static rtx 704 loongarch_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED) 705 { 706 return loongarch_function_value_1 (NULL_TREE, NULL_TREE, mode); 707 } 708 709 710 /* Implement TARGET_PASS_BY_REFERENCE. */ 711 712 static bool 713 loongarch_pass_by_reference (cumulative_args_t cum_v, 714 const function_arg_info &arg) 715 { 716 HOST_WIDE_INT size = arg.type_size_in_bytes (); 717 struct loongarch_arg_info info; 718 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 719 720 /* ??? std_gimplify_va_arg_expr passes NULL for cum. Fortunately, we 721 never pass variadic arguments in floating-point registers, so we can 722 avoid the call to loongarch_get_arg_info in this case. */ 723 if (cum != NULL) 724 { 725 /* Don't pass by reference if we can use a floating-point register. */ 726 loongarch_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, 727 false); 728 if (info.num_fprs) 729 return false; 730 } 731 732 /* Pass by reference if the data do not fit in two integer registers. */ 733 return !IN_RANGE (size, 0, 2 * UNITS_PER_WORD); 734 } 735 736 /* Implement TARGET_RETURN_IN_MEMORY. */ 737 738 static bool 739 loongarch_return_in_memory (const_tree type, 740 const_tree fndecl ATTRIBUTE_UNUSED) 741 { 742 CUMULATIVE_ARGS args; 743 cumulative_args_t cum = pack_cumulative_args (&args); 744 745 /* The rules for returning in memory are the same as for passing the 746 first named argument by reference. */ 747 memset (&args, 0, sizeof (args)); 748 function_arg_info arg (const_cast<tree> (type), /*named=*/true); 749 return loongarch_pass_by_reference (cum, arg); 750 } 751 752 /* Implement TARGET_SETUP_INCOMING_VARARGS. */ 753 754 static void 755 loongarch_setup_incoming_varargs (cumulative_args_t cum, 756 const function_arg_info &arg, 757 int *pretend_size ATTRIBUTE_UNUSED, 758 int no_rtl) 759 { 760 CUMULATIVE_ARGS local_cum; 761 int gp_saved; 762 763 /* The caller has advanced CUM up to, but not beyond, the last named 764 argument. Advance a local copy of CUM past the last "real" named 765 argument, to find out how many registers are left over. */ 766 local_cum = *get_cumulative_args (cum); 767 768 /* For a C23 variadic function w/o any named argument, and w/o an 769 artifical argument for large return value, skip advancing args. 770 There is such an artifical argument iff. arg.type is non-NULL 771 (PR 114175). */ 772 if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl)) 773 || arg.type != NULL_TREE) 774 loongarch_function_arg_advance (pack_cumulative_args (&local_cum), arg); 775 776 /* Found out how many registers we need to save. */ 777 gp_saved = cfun->va_list_gpr_size / UNITS_PER_WORD; 778 if (gp_saved > (int) (MAX_ARGS_IN_REGISTERS - local_cum.num_gprs)) 779 gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs; 780 781 if (!no_rtl && gp_saved > 0) 782 { 783 rtx ptr = plus_constant (Pmode, virtual_incoming_args_rtx, 784 REG_PARM_STACK_SPACE (cfun->decl) 785 - gp_saved * UNITS_PER_WORD); 786 rtx mem = gen_frame_mem (BLKmode, ptr); 787 set_mem_alias_set (mem, get_varargs_alias_set ()); 788 789 move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST, mem, gp_saved); 790 } 791 if (REG_PARM_STACK_SPACE (cfun->decl) == 0) 792 cfun->machine->varargs_size = gp_saved * UNITS_PER_WORD; 793 } 794 795 /* Make the last instruction frame-related and note that it performs 796 the operation described by FRAME_PATTERN. */ 797 798 static void 799 loongarch_set_frame_expr (rtx frame_pattern) 800 { 801 rtx insn; 802 803 insn = get_last_insn (); 804 RTX_FRAME_RELATED_P (insn) = 1; 805 REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR, frame_pattern, 806 REG_NOTES (insn)); 807 } 808 809 /* Return a frame-related rtx that stores REG at MEM. 810 REG must be a single register. */ 811 812 static rtx 813 loongarch_frame_set (rtx mem, rtx reg) 814 { 815 rtx set = gen_rtx_SET (mem, reg); 816 RTX_FRAME_RELATED_P (set) = 1; 817 return set; 818 } 819 820 /* Return true if the current function must save register REGNO. */ 821 822 static bool 823 loongarch_save_reg_p (unsigned int regno) 824 { 825 bool call_saved = !global_regs[regno] && !call_used_regs[regno]; 826 bool might_clobber 827 = crtl->saves_all_registers || df_regs_ever_live_p (regno); 828 829 if (call_saved && might_clobber) 830 return true; 831 832 if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) 833 return true; 834 835 if (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return) 836 return true; 837 838 return false; 839 } 840 841 /* Determine which GPR save/restore routine to call. */ 842 843 static unsigned 844 loongarch_save_libcall_count (unsigned mask) 845 { 846 for (unsigned n = GP_REG_LAST; n > GP_REG_FIRST; n--) 847 if (BITSET_P (mask, n)) 848 return CALLEE_SAVED_REG_NUMBER (n) + 1; 849 abort (); 850 } 851 852 /* Populate the current function's loongarch_frame_info structure. 853 854 LoongArch stack frames grown downward. High addresses are at the top. 855 856 +-------------------------------+ 857 | | 858 | incoming stack arguments | 859 | | 860 +-------------------------------+ <-- incoming stack pointer 861 | | 862 | callee-allocated save area | 863 | for arguments that are | 864 | split between registers and | 865 | the stack | 866 | | 867 +-------------------------------+ <-- arg_pointer_rtx (virtual) 868 | | 869 | callee-allocated save area | 870 | for register varargs | 871 | | 872 +-------------------------------+ <-- hard_frame_pointer_rtx; 873 | | stack_pointer_rtx + gp_sp_offset 874 | GPR save area | + UNITS_PER_WORD 875 | | 876 +-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset 877 | | + UNITS_PER_HWVALUE 878 | FPR save area | 879 | | 880 +-------------------------------+ <-- frame_pointer_rtx (virtual) 881 | | 882 | local variables | 883 | | 884 P +-------------------------------+ 885 | | 886 | outgoing stack arguments | 887 | | 888 +-------------------------------+ <-- stack_pointer_rtx 889 890 Dynamic stack allocations such as alloca insert data at point P. 891 They decrease stack_pointer_rtx but leave frame_pointer_rtx and 892 hard_frame_pointer_rtx unchanged. */ 893 894 static void 895 loongarch_compute_frame_info (void) 896 { 897 struct loongarch_frame_info *frame; 898 HOST_WIDE_INT offset; 899 unsigned int regno, i, num_x_saved = 0, num_f_saved = 0; 900 901 frame = &cfun->machine->frame; 902 memset (frame, 0, sizeof (*frame)); 903 904 /* Find out which GPRs we need to save. */ 905 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) 906 if (loongarch_save_reg_p (regno)) 907 frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; 908 909 /* If this function calls eh_return, we must also save and restore the 910 EH data registers. */ 911 if (crtl->calls_eh_return) 912 for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++) 913 frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++; 914 915 /* Find out which FPRs we need to save. This loop must iterate over 916 the same space as its companion in loongarch_for_each_saved_reg. */ 917 if (TARGET_HARD_FLOAT) 918 for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) 919 if (loongarch_save_reg_p (regno)) 920 frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++; 921 922 /* At the bottom of the frame are any outgoing stack arguments. */ 923 offset = LARCH_STACK_ALIGN (crtl->outgoing_args_size); 924 /* Next are local stack variables. */ 925 offset += LARCH_STACK_ALIGN (get_frame_size ()); 926 /* The virtual frame pointer points above the local variables. */ 927 frame->frame_pointer_offset = offset; 928 /* Next are the callee-saved FPRs. */ 929 if (frame->fmask) 930 { 931 offset += LARCH_STACK_ALIGN (num_f_saved * UNITS_PER_FP_REG); 932 frame->fp_sp_offset = offset - UNITS_PER_FP_REG; 933 } 934 else 935 frame->fp_sp_offset = offset; 936 /* Next are the callee-saved GPRs. */ 937 if (frame->mask) 938 { 939 unsigned x_save_size = LARCH_STACK_ALIGN (num_x_saved * UNITS_PER_WORD); 940 unsigned num_save_restore 941 = 1 + loongarch_save_libcall_count (frame->mask); 942 943 /* Only use save/restore routines if they don't alter the stack size. */ 944 if (LARCH_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) == x_save_size) 945 frame->save_libcall_adjustment = x_save_size; 946 947 offset += x_save_size; 948 frame->gp_sp_offset = offset - UNITS_PER_WORD; 949 } 950 else 951 frame->gp_sp_offset = offset; 952 /* The hard frame pointer points above the callee-saved GPRs. */ 953 frame->hard_frame_pointer_offset = offset; 954 /* Above the hard frame pointer is the callee-allocated varags save area. */ 955 offset += LARCH_STACK_ALIGN (cfun->machine->varargs_size); 956 /* Next is the callee-allocated area for pretend stack arguments. */ 957 offset += LARCH_STACK_ALIGN (crtl->args.pretend_args_size); 958 /* Arg pointer must be below pretend args, but must be above alignment 959 padding. */ 960 frame->arg_pointer_offset = offset - crtl->args.pretend_args_size; 961 frame->total_size = offset; 962 /* Next points the incoming stack pointer and any incoming arguments. */ 963 964 /* Only use save/restore routines when the GPRs are atop the frame. */ 965 if (frame->hard_frame_pointer_offset != frame->total_size) 966 frame->save_libcall_adjustment = 0; 967 } 968 969 /* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame pointer 970 or argument pointer. TO is either the stack pointer or hard frame 971 pointer. */ 972 973 HOST_WIDE_INT 974 loongarch_initial_elimination_offset (int from, int to) 975 { 976 HOST_WIDE_INT src, dest; 977 978 loongarch_compute_frame_info (); 979 980 if (to == HARD_FRAME_POINTER_REGNUM) 981 dest = cfun->machine->frame.hard_frame_pointer_offset; 982 else if (to == STACK_POINTER_REGNUM) 983 dest = 0; /* The stack pointer is the base of all offsets, hence 0. */ 984 else 985 gcc_unreachable (); 986 987 if (from == FRAME_POINTER_REGNUM) 988 src = cfun->machine->frame.frame_pointer_offset; 989 else if (from == ARG_POINTER_REGNUM) 990 src = cfun->machine->frame.arg_pointer_offset; 991 else 992 gcc_unreachable (); 993 994 return src - dest; 995 } 996 997 /* A function to save or store a register. The first argument is the 998 register and the second is the stack slot. */ 999 typedef void (*loongarch_save_restore_fn) (rtx, rtx); 1000 1001 /* Use FN to save or restore register REGNO. MODE is the register's 1002 mode and OFFSET is the offset of its save slot from the current 1003 stack pointer. */ 1004 1005 static void 1006 loongarch_save_restore_reg (machine_mode mode, int regno, HOST_WIDE_INT offset, 1007 loongarch_save_restore_fn fn) 1008 { 1009 rtx mem; 1010 1011 mem = gen_frame_mem (mode, plus_constant (Pmode, stack_pointer_rtx, offset)); 1012 fn (gen_rtx_REG (mode, regno), mem); 1013 } 1014 1015 /* Call FN for each register that is saved by the current function. 1016 SP_OFFSET is the offset of the current stack pointer from the start 1017 of the frame. */ 1018 1019 static void 1020 loongarch_for_each_saved_reg (HOST_WIDE_INT sp_offset, 1021 loongarch_save_restore_fn fn, 1022 bool skip_eh_data_regs_p) 1023 { 1024 HOST_WIDE_INT offset; 1025 1026 /* Save the link register and s-registers. */ 1027 offset = cfun->machine->frame.gp_sp_offset - sp_offset; 1028 for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) 1029 if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST)) 1030 { 1031 /* Special care needs to be taken for $r4-$r7 (EH_RETURN_DATA_REGNO) 1032 when returning normally from a function that calls 1033 __builtin_eh_return. In this case, these registers are saved but 1034 should not be restored, or the return value may be clobbered. */ 1035 1036 if (!(cfun->machine->reg_is_wrapped_separately[regno] 1037 || (skip_eh_data_regs_p 1038 && GP_ARG_FIRST <= regno && regno < GP_ARG_FIRST + 4))) 1039 loongarch_save_restore_reg (word_mode, regno, offset, fn); 1040 1041 offset -= UNITS_PER_WORD; 1042 } 1043 1044 /* This loop must iterate over the same space as its companion in 1045 loongarch_compute_frame_info. */ 1046 offset = cfun->machine->frame.fp_sp_offset - sp_offset; 1047 machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode; 1048 1049 for (int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) 1050 if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST)) 1051 { 1052 if (!cfun->machine->reg_is_wrapped_separately[regno]) 1053 loongarch_save_restore_reg (word_mode, regno, offset, fn); 1054 1055 offset -= GET_MODE_SIZE (mode); 1056 } 1057 } 1058 1059 /* Emit a move from SRC to DEST. Assume that the move expanders can 1060 handle all moves if !can_create_pseudo_p (). The distinction is 1061 important because, unlike emit_move_insn, the move expanders know 1062 how to force Pmode objects into the constant pool even when the 1063 constant pool address is not itself legitimate. */ 1064 1065 rtx 1066 loongarch_emit_move (rtx dest, rtx src) 1067 { 1068 return (can_create_pseudo_p () ? emit_move_insn (dest, src) 1069 : emit_move_insn_1 (dest, src)); 1070 } 1071 1072 /* Save register REG to MEM. Make the instruction frame-related. */ 1073 1074 static void 1075 loongarch_save_reg (rtx reg, rtx mem) 1076 { 1077 loongarch_emit_move (mem, reg); 1078 loongarch_set_frame_expr (loongarch_frame_set (mem, reg)); 1079 } 1080 1081 /* Restore register REG from MEM. */ 1082 1083 static void 1084 loongarch_restore_reg (rtx reg, rtx mem) 1085 { 1086 rtx insn = loongarch_emit_move (reg, mem); 1087 rtx dwarf = NULL_RTX; 1088 dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf); 1089 REG_NOTES (insn) = dwarf; 1090 1091 RTX_FRAME_RELATED_P (insn) = 1; 1092 } 1093 1094 /* For stack frames that can't be allocated with a single ADDI instruction, 1095 compute the best value to initially allocate. It must at a minimum 1096 allocate enough space to spill the callee-saved registers. */ 1097 1098 static HOST_WIDE_INT 1099 loongarch_first_stack_step (struct loongarch_frame_info *frame) 1100 { 1101 HOST_WIDE_INT min_first_step 1102 = LARCH_STACK_ALIGN (frame->total_size - frame->fp_sp_offset); 1103 1104 /* When stack checking is required, if the sum of frame->total_size 1105 and stack_check_protect is greater than stack clash protection guard 1106 size, then return min_first_step. */ 1107 if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK 1108 || (flag_stack_clash_protection 1109 && frame->total_size > STACK_CLASH_PROTECTION_GUARD_SIZE)) 1110 return min_first_step; 1111 1112 if (IMM12_OPERAND (frame->total_size)) 1113 return frame->total_size; 1114 1115 HOST_WIDE_INT max_first_step = IMM_REACH / 2 - PREFERRED_STACK_BOUNDARY / 8; 1116 HOST_WIDE_INT min_second_step = frame->total_size - max_first_step; 1117 gcc_assert (min_first_step <= max_first_step); 1118 1119 /* As an optimization, use the least-significant bits of the total frame 1120 size, so that the second adjustment step is just LU12I + ADD. */ 1121 if (!IMM12_OPERAND (min_second_step) 1122 && frame->total_size % IMM_REACH < IMM_REACH / 2 1123 && frame->total_size % IMM_REACH >= min_first_step) 1124 return frame->total_size % IMM_REACH; 1125 1126 return max_first_step; 1127 } 1128 1129 static void 1130 loongarch_emit_stack_tie (void) 1131 { 1132 emit_insn (gen_stack_tie (Pmode, stack_pointer_rtx, 1133 frame_pointer_needed ? hard_frame_pointer_rtx 1134 : stack_pointer_rtx)); 1135 } 1136 1137 #define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP) 1138 1139 #if PROBE_INTERVAL > 16384 1140 #error Cannot use indexed addressing mode for stack probing 1141 #endif 1142 1143 /* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE, 1144 inclusive. These are offsets from the current stack pointer. */ 1145 1146 static void 1147 loongarch_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size) 1148 { 1149 HOST_WIDE_INT rounded_size; 1150 HOST_WIDE_INT interval; 1151 1152 if (flag_stack_clash_protection) 1153 interval = STACK_CLASH_PROTECTION_GUARD_SIZE; 1154 else 1155 interval = PROBE_INTERVAL; 1156 1157 rtx r12 = LARCH_PROLOGUE_TEMP2 (Pmode); 1158 rtx r14 = LARCH_PROLOGUE_TEMP3 (Pmode); 1159 1160 size = size + first; 1161 1162 /* Sanity check for the addressing mode we're going to use. */ 1163 gcc_assert (first <= 16384); 1164 1165 /* Step 1: round SIZE to the previous multiple of the interval. */ 1166 1167 rounded_size = ROUND_DOWN (size, interval); 1168 1169 /* Step 2: compute initial and final value of the loop counter. */ 1170 1171 emit_move_insn (r14, GEN_INT (interval)); 1172 1173 /* If rounded_size is zero, it means that the space requested by 1174 the local variable is less than the interval, and there is no 1175 need to display and detect the allocated space. */ 1176 if (rounded_size != 0) 1177 { 1178 /* Step 3: the loop 1179 1180 do 1181 { 1182 TEST_ADDR = TEST_ADDR + PROBE_INTERVAL 1183 probe at TEST_ADDR 1184 } 1185 while (TEST_ADDR != LAST_ADDR) 1186 1187 probes at FIRST + N * PROBE_INTERVAL for values of N from 1 1188 until it is equal to ROUNDED_SIZE. */ 1189 1190 if (rounded_size <= STACK_CLASH_MAX_UNROLL_PAGES * interval) 1191 { 1192 for (HOST_WIDE_INT i = 0; i < rounded_size; i += interval) 1193 { 1194 emit_insn (gen_rtx_SET (stack_pointer_rtx, 1195 gen_rtx_MINUS (Pmode, 1196 stack_pointer_rtx, 1197 r14))); 1198 emit_move_insn (gen_rtx_MEM (Pmode, 1199 gen_rtx_PLUS (Pmode, 1200 stack_pointer_rtx, 1201 const0_rtx)), 1202 const0_rtx); 1203 emit_insn (gen_blockage ()); 1204 } 1205 dump_stack_clash_frame_info (PROBE_INLINE, size != rounded_size); 1206 } 1207 else 1208 { 1209 emit_move_insn (r12, GEN_INT (rounded_size)); 1210 emit_insn (gen_rtx_SET (r12, 1211 gen_rtx_MINUS (Pmode, 1212 stack_pointer_rtx, 1213 r12))); 1214 1215 emit_insn (gen_probe_stack_range (Pmode, stack_pointer_rtx, 1216 stack_pointer_rtx, r12, r14)); 1217 emit_insn (gen_blockage ()); 1218 dump_stack_clash_frame_info (PROBE_LOOP, size != rounded_size); 1219 } 1220 } 1221 else 1222 dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true); 1223 1224 1225 /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time 1226 that SIZE is equal to ROUNDED_SIZE. */ 1227 1228 if (size != rounded_size) 1229 { 1230 if (size - rounded_size >= 2048) 1231 { 1232 emit_move_insn (r14, GEN_INT (size - rounded_size)); 1233 emit_insn (gen_rtx_SET (stack_pointer_rtx, 1234 gen_rtx_MINUS (Pmode, 1235 stack_pointer_rtx, 1236 r14))); 1237 } 1238 else 1239 emit_insn (gen_rtx_SET (stack_pointer_rtx, 1240 gen_rtx_PLUS (Pmode, 1241 stack_pointer_rtx, 1242 GEN_INT (rounded_size - size)))); 1243 } 1244 1245 if (first) 1246 { 1247 emit_move_insn (r12, GEN_INT (first)); 1248 emit_insn (gen_rtx_SET (stack_pointer_rtx, 1249 gen_rtx_PLUS (Pmode, 1250 stack_pointer_rtx, r12))); 1251 } 1252 /* Make sure nothing is scheduled before we are done. */ 1253 emit_insn (gen_blockage ()); 1254 } 1255 1256 /* Probe a range of stack addresses from REG1 to REG2 inclusive. These are 1257 absolute addresses. */ 1258 const char * 1259 loongarch_output_probe_stack_range (rtx reg1, rtx reg2, rtx reg3) 1260 { 1261 static int labelno = 0; 1262 char loop_lab[32], tmp[64]; 1263 rtx xops[3]; 1264 1265 ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++); 1266 1267 /* Loop. */ 1268 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab); 1269 1270 /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */ 1271 xops[0] = reg1; 1272 xops[2] = reg3; 1273 if (TARGET_64BIT) 1274 output_asm_insn ("sub.d\t%0,%0,%2", xops); 1275 else 1276 output_asm_insn ("sub.w\t%0,%0,%2", xops); 1277 1278 /* Probe at TEST_ADDR, test if TEST_ADDR == LAST_ADDR and branch. */ 1279 xops[1] = reg2; 1280 strcpy (tmp, "bne\t%0,%1,"); 1281 if (TARGET_64BIT) 1282 output_asm_insn ("st.d\t$r0,%0,0", xops); 1283 else 1284 output_asm_insn ("st.w\t$r0,%0,0", xops); 1285 output_asm_insn (strcat (tmp, &loop_lab[1]), xops); 1286 1287 return ""; 1288 } 1289 1290 /* Expand the "prologue" pattern. */ 1291 1292 void 1293 loongarch_expand_prologue (void) 1294 { 1295 struct loongarch_frame_info *frame = &cfun->machine->frame; 1296 HOST_WIDE_INT size = frame->total_size; 1297 rtx insn; 1298 1299 if (flag_stack_usage_info) 1300 current_function_static_stack_size = size; 1301 1302 /* Save the registers. */ 1303 if ((frame->mask | frame->fmask) != 0) 1304 { 1305 HOST_WIDE_INT step1 = MIN (size, loongarch_first_stack_step (frame)); 1306 1307 insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, 1308 GEN_INT (-step1)); 1309 RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; 1310 size -= step1; 1311 loongarch_for_each_saved_reg (size, loongarch_save_reg, false); 1312 } 1313 1314 /* Set up the frame pointer, if we're using one. */ 1315 if (frame_pointer_needed) 1316 { 1317 insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx, 1318 GEN_INT (frame->hard_frame_pointer_offset - size)); 1319 RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; 1320 1321 loongarch_emit_stack_tie (); 1322 } 1323 1324 if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK 1325 || flag_stack_clash_protection) 1326 { 1327 HOST_WIDE_INT first = get_stack_check_protect (); 1328 1329 if (frame->total_size == 0) 1330 { 1331 /* do nothing. */ 1332 dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false); 1333 return; 1334 } 1335 1336 if (crtl->is_leaf && !cfun->calls_alloca) 1337 { 1338 HOST_WIDE_INT interval; 1339 1340 if (flag_stack_clash_protection) 1341 interval = STACK_CLASH_PROTECTION_GUARD_SIZE; 1342 else 1343 interval = PROBE_INTERVAL; 1344 1345 if (size > interval && size > first) 1346 loongarch_emit_probe_stack_range (first, size - first); 1347 else 1348 loongarch_emit_probe_stack_range (first, size); 1349 } 1350 else 1351 loongarch_emit_probe_stack_range (first, size); 1352 1353 if (size > 0) 1354 { 1355 /* Describe the effect of the previous instructions. */ 1356 insn = plus_constant (Pmode, stack_pointer_rtx, -size); 1357 insn = gen_rtx_SET (stack_pointer_rtx, insn); 1358 loongarch_set_frame_expr (insn); 1359 } 1360 return; 1361 } 1362 1363 if (size > 0) 1364 { 1365 if (IMM12_OPERAND (-size)) 1366 { 1367 insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, 1368 GEN_INT (-size)); 1369 RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; 1370 } 1371 else 1372 { 1373 loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), 1374 GEN_INT (-size)); 1375 emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, 1376 LARCH_PROLOGUE_TEMP (Pmode))); 1377 1378 /* Describe the effect of the previous instructions. */ 1379 insn = plus_constant (Pmode, stack_pointer_rtx, -size); 1380 insn = gen_rtx_SET (stack_pointer_rtx, insn); 1381 loongarch_set_frame_expr (insn); 1382 } 1383 } 1384 } 1385 1386 /* Return nonzero if this function is known to have a null epilogue. 1387 This allows the optimizer to omit jumps to jumps if no stack 1388 was created. */ 1389 1390 bool 1391 loongarch_can_use_return_insn (void) 1392 { 1393 return reload_completed && cfun->machine->frame.total_size == 0; 1394 } 1395 1396 /* Expand function epilogue using the following insn patterns: 1397 "epilogue" (style == NORMAL_RETURN) 1398 "sibcall_epilogue" (style == SIBCALL_RETURN) 1399 "eh_return" (style == EXCEPTION_RETURN) */ 1400 1401 void 1402 loongarch_expand_epilogue (int style) 1403 { 1404 /* Split the frame into two. STEP1 is the amount of stack we should 1405 deallocate before restoring the registers. STEP2 is the amount we 1406 should deallocate afterwards. 1407 1408 Start off by assuming that no registers need to be restored. */ 1409 struct loongarch_frame_info *frame = &cfun->machine->frame; 1410 HOST_WIDE_INT step1 = frame->total_size; 1411 HOST_WIDE_INT step2 = 0; 1412 rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); 1413 rtx insn; 1414 1415 /* We need to add memory barrier to prevent read from deallocated stack. */ 1416 bool need_barrier_p 1417 = (get_frame_size () + cfun->machine->frame.arg_pointer_offset) != 0; 1418 1419 /* Handle simple returns. */ 1420 if (style == NORMAL_RETURN && loongarch_can_use_return_insn ()) 1421 { 1422 emit_jump_insn (gen_return ()); 1423 return; 1424 } 1425 1426 /* Move past any dynamic stack allocations. */ 1427 if (cfun->calls_alloca) 1428 { 1429 /* Emit a barrier to prevent loads from a deallocated stack. */ 1430 loongarch_emit_stack_tie (); 1431 need_barrier_p = false; 1432 1433 rtx adjust = GEN_INT (-frame->hard_frame_pointer_offset); 1434 if (!IMM12_OPERAND (INTVAL (adjust))) 1435 { 1436 loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), adjust); 1437 adjust = LARCH_PROLOGUE_TEMP (Pmode); 1438 } 1439 1440 insn = emit_insn (gen_add3_insn (stack_pointer_rtx, 1441 hard_frame_pointer_rtx, 1442 adjust)); 1443 1444 rtx dwarf = NULL_RTX; 1445 rtx minus_offset = GEN_INT (-frame->hard_frame_pointer_offset); 1446 rtx cfa_adjust_value = gen_rtx_PLUS (Pmode, 1447 hard_frame_pointer_rtx, 1448 minus_offset); 1449 1450 rtx cfa_adjust_rtx = gen_rtx_SET (stack_pointer_rtx, cfa_adjust_value); 1451 dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, cfa_adjust_rtx, dwarf); 1452 RTX_FRAME_RELATED_P (insn) = 1; 1453 1454 REG_NOTES (insn) = dwarf; 1455 } 1456 1457 /* If we need to restore registers, deallocate as much stack as 1458 possible in the second step without going out of range. */ 1459 if ((frame->mask | frame->fmask) != 0) 1460 { 1461 step2 = loongarch_first_stack_step (frame); 1462 step1 -= step2; 1463 } 1464 1465 /* Set TARGET to BASE + STEP1. */ 1466 if (step1 > 0) 1467 { 1468 /* Emit a barrier to prevent loads from a deallocated stack. */ 1469 loongarch_emit_stack_tie (); 1470 need_barrier_p = false; 1471 1472 /* Get an rtx for STEP1 that we can add to BASE. */ 1473 rtx adjust = GEN_INT (step1); 1474 if (!IMM12_OPERAND (step1)) 1475 { 1476 loongarch_emit_move (LARCH_PROLOGUE_TEMP (Pmode), adjust); 1477 adjust = LARCH_PROLOGUE_TEMP (Pmode); 1478 } 1479 1480 insn = emit_insn (gen_add3_insn (stack_pointer_rtx, 1481 stack_pointer_rtx, 1482 adjust)); 1483 1484 rtx dwarf = NULL_RTX; 1485 rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, 1486 GEN_INT (step2)); 1487 1488 dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf); 1489 RTX_FRAME_RELATED_P (insn) = 1; 1490 1491 REG_NOTES (insn) = dwarf; 1492 } 1493 1494 /* Restore the registers. */ 1495 loongarch_for_each_saved_reg (frame->total_size - step2, 1496 loongarch_restore_reg, 1497 crtl->calls_eh_return 1498 && style != EXCEPTION_RETURN); 1499 1500 if (need_barrier_p) 1501 loongarch_emit_stack_tie (); 1502 1503 /* Deallocate the final bit of the frame. */ 1504 if (step2 > 0) 1505 { 1506 insn = emit_insn (gen_add3_insn (stack_pointer_rtx, 1507 stack_pointer_rtx, 1508 GEN_INT (step2))); 1509 1510 rtx dwarf = NULL_RTX; 1511 rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, const0_rtx); 1512 dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf); 1513 RTX_FRAME_RELATED_P (insn) = 1; 1514 1515 REG_NOTES (insn) = dwarf; 1516 } 1517 1518 /* Add in the __builtin_eh_return stack adjustment. */ 1519 if (crtl->calls_eh_return && style == EXCEPTION_RETURN) 1520 emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, 1521 EH_RETURN_STACKADJ_RTX)); 1522 1523 /* Emit return unless doing sibcall. */ 1524 if (style != SIBCALL_RETURN) 1525 emit_jump_insn (gen_simple_return_internal (ra)); 1526 } 1527 1528 #define LU32I_B (0xfffffULL << 32) 1529 #define LU52I_B (0xfffULL << 52) 1530 1531 /* Fill CODES with a sequence of rtl operations to load VALUE. 1532 Return the number of operations needed. */ 1533 1534 static unsigned int 1535 loongarch_build_integer (struct loongarch_integer_op *codes, 1536 HOST_WIDE_INT value) 1537 1538 { 1539 unsigned int cost = 0; 1540 1541 /* Get the lower 32 bits of the value. */ 1542 HOST_WIDE_INT low_part = (int32_t)value; 1543 1544 if (IMM12_OPERAND (low_part) || IMM12_OPERAND_UNSIGNED (low_part)) 1545 { 1546 /* The value of the lower 32 bit be loaded with one instruction. 1547 lu12i.w. */ 1548 codes[cost].code = UNKNOWN; 1549 codes[cost].method = METHOD_NORMAL; 1550 codes[cost].value = low_part; 1551 codes[cost].curr_value = low_part; 1552 cost++; 1553 } 1554 else 1555 { 1556 /* lu12i.w + ior. */ 1557 codes[cost].code = UNKNOWN; 1558 codes[cost].method = METHOD_NORMAL; 1559 codes[cost].value = low_part & ~(IMM_REACH - 1); 1560 codes[cost].curr_value = codes[cost].value; 1561 cost++; 1562 HOST_WIDE_INT iorv = low_part & (IMM_REACH - 1); 1563 if (iorv != 0) 1564 { 1565 codes[cost].code = IOR; 1566 codes[cost].method = METHOD_NORMAL; 1567 codes[cost].value = iorv; 1568 codes[cost].curr_value = low_part; 1569 cost++; 1570 } 1571 } 1572 1573 if (TARGET_64BIT) 1574 { 1575 bool lu32i[2] = {(value & LU32I_B) == 0, (value & LU32I_B) == LU32I_B}; 1576 bool lu52i[2] = {(value & LU52I_B) == 0, (value & LU52I_B) == LU52I_B}; 1577 1578 int sign31 = (value & (HOST_WIDE_INT_1U << 31)) >> 31; 1579 int sign51 = (value & (HOST_WIDE_INT_1U << 51)) >> 51; 1580 1581 uint32_t hival = (uint32_t) (value >> 32); 1582 uint32_t loval = (uint32_t) value; 1583 1584 /* Determine whether the upper 32 bits are sign-extended from the lower 1585 32 bits. If it is, the instructions to load the high order can be 1586 ommitted. */ 1587 if (lu32i[sign31] && lu52i[sign31]) 1588 return cost; 1589 /* If the lower 32 bits are the same as the upper 32 bits, just copy 1590 the lower 32 bits to the upper 32 bits. */ 1591 else if (loval == hival) 1592 { 1593 codes[cost].method = METHOD_MIRROR; 1594 codes[cost].curr_value = value; 1595 return cost + 1; 1596 } 1597 /* Determine whether bits 32-51 are sign-extended from the lower 32 1598 bits. If so, directly load 52-63 bits. */ 1599 else if (lu32i[sign31]) 1600 { 1601 codes[cost].method = METHOD_LU52I; 1602 codes[cost].value = value & LU52I_B; 1603 codes[cost].curr_value = value; 1604 return cost + 1; 1605 } 1606 1607 codes[cost].method = METHOD_LU32I; 1608 codes[cost].value = (value & LU32I_B) | (sign51 ? LU52I_B : 0); 1609 codes[cost].curr_value = (value & 0xfffffffffffff) 1610 | (sign51 ? LU52I_B : 0); 1611 cost++; 1612 1613 /* Determine whether the 52-61 bits are sign-extended from the low order, 1614 and if not, load the 52-61 bits. */ 1615 if (!lu52i[(value & (HOST_WIDE_INT_1U << 51)) >> 51]) 1616 { 1617 codes[cost].method = METHOD_LU52I; 1618 codes[cost].value = value & LU52I_B; 1619 codes[cost].curr_value = value; 1620 cost++; 1621 } 1622 } 1623 1624 gcc_assert (cost <= LARCH_MAX_INTEGER_OPS); 1625 1626 return cost; 1627 } 1628 1629 /* Fill CODES with a sequence of rtl operations to load VALUE. 1630 Return the number of operations needed. 1631 Split interger in loongarch_output_move. */ 1632 1633 static unsigned int 1634 loongarch_integer_cost (HOST_WIDE_INT value) 1635 { 1636 struct loongarch_integer_op codes[LARCH_MAX_INTEGER_OPS]; 1637 return loongarch_build_integer (codes, value); 1638 } 1639 1640 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */ 1641 1642 static bool 1643 loongarch_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x) 1644 { 1645 return loongarch_const_insns (x) > 0; 1646 } 1647 1648 /* Return true if X is a thread-local symbol. */ 1649 1650 static bool 1651 loongarch_tls_symbol_p (rtx x) 1652 { 1653 return SYMBOL_REF_P (x) && SYMBOL_REF_TLS_MODEL (x) != 0; 1654 } 1655 1656 /* Return true if SYMBOL_REF X is associated with a global symbol 1657 (in the STB_GLOBAL sense). */ 1658 1659 bool 1660 loongarch_global_symbol_p (const_rtx x) 1661 { 1662 if (LABEL_REF_P (x)) 1663 return false; 1664 1665 const_tree decl = SYMBOL_REF_DECL (x); 1666 1667 if (!decl) 1668 return !SYMBOL_REF_LOCAL_P (x) || SYMBOL_REF_EXTERNAL_P (x); 1669 1670 /* Weakref symbols are not TREE_PUBLIC, but their targets are global 1671 or weak symbols. Relocations in the object file will be against 1672 the target symbol, so it's that symbol's binding that matters here. */ 1673 return DECL_P (decl) && (TREE_PUBLIC (decl) || DECL_WEAK (decl)); 1674 } 1675 1676 bool 1677 loongarch_global_symbol_noweak_p (const_rtx x) 1678 { 1679 if (LABEL_REF_P (x)) 1680 return false; 1681 1682 const_tree decl = SYMBOL_REF_DECL (x); 1683 1684 if (!decl) 1685 return !SYMBOL_REF_LOCAL_P (x) || SYMBOL_REF_EXTERNAL_P (x); 1686 1687 return DECL_P (decl) && TREE_PUBLIC (decl); 1688 } 1689 1690 bool 1691 loongarch_weak_symbol_p (const_rtx x) 1692 { 1693 const_tree decl; 1694 if (LABEL_REF_P (x) || !(decl = SYMBOL_REF_DECL (x))) 1695 return false; 1696 return DECL_P (decl) && DECL_WEAK (decl); 1697 } 1698 1699 /* Return true if SYMBOL_REF X binds locally. */ 1700 1701 bool 1702 loongarch_symbol_binds_local_p (const_rtx x) 1703 { 1704 if (TARGET_DIRECT_EXTERN_ACCESS) 1705 return true; 1706 1707 if (SYMBOL_REF_P (x)) 1708 return (SYMBOL_REF_DECL (x) 1709 ? targetm.binds_local_p (SYMBOL_REF_DECL (x)) 1710 : SYMBOL_REF_LOCAL_P (x)); 1711 else 1712 return false; 1713 } 1714 1715 /* Return true if OP is a constant vector with the number of units in MODE, 1716 and each unit has the same bit set. */ 1717 1718 bool 1719 loongarch_const_vector_bitimm_set_p (rtx op, machine_mode mode) 1720 { 1721 if (GET_CODE (op) == CONST_VECTOR && op != CONST0_RTX (mode)) 1722 { 1723 unsigned HOST_WIDE_INT val = UINTVAL (CONST_VECTOR_ELT (op, 0)); 1724 int vlog2 = exact_log2 (val & GET_MODE_MASK (GET_MODE_INNER (mode))); 1725 1726 if (vlog2 != -1) 1727 { 1728 gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_INT); 1729 gcc_assert (vlog2 >= 0 && vlog2 <= GET_MODE_UNIT_BITSIZE (mode) - 1); 1730 return loongarch_const_vector_same_val_p (op, mode); 1731 } 1732 } 1733 1734 return false; 1735 } 1736 1737 /* Return true if OP is a constant vector with the number of units in MODE, 1738 and each unit has the same bit clear. */ 1739 1740 bool 1741 loongarch_const_vector_bitimm_clr_p (rtx op, machine_mode mode) 1742 { 1743 if (GET_CODE (op) == CONST_VECTOR && op != CONSTM1_RTX (mode)) 1744 { 1745 unsigned HOST_WIDE_INT val = ~UINTVAL (CONST_VECTOR_ELT (op, 0)); 1746 int vlog2 = exact_log2 (val & GET_MODE_MASK (GET_MODE_INNER (mode))); 1747 1748 if (vlog2 != -1) 1749 { 1750 gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_INT); 1751 gcc_assert (vlog2 >= 0 && vlog2 <= GET_MODE_UNIT_BITSIZE (mode) - 1); 1752 return loongarch_const_vector_same_val_p (op, mode); 1753 } 1754 } 1755 1756 return false; 1757 } 1758 1759 /* Return true if OP is a constant vector with the number of units in MODE, 1760 and each unit has the same value. */ 1761 1762 bool 1763 loongarch_const_vector_same_val_p (rtx op, machine_mode mode) 1764 { 1765 int i, nunits = GET_MODE_NUNITS (mode); 1766 rtx first; 1767 1768 if (GET_CODE (op) != CONST_VECTOR || GET_MODE (op) != mode) 1769 return false; 1770 1771 first = CONST_VECTOR_ELT (op, 0); 1772 for (i = 1; i < nunits; i++) 1773 if (!rtx_equal_p (first, CONST_VECTOR_ELT (op, i))) 1774 return false; 1775 1776 return true; 1777 } 1778 1779 /* Return true if OP is a constant vector with the number of units in MODE, 1780 and each unit has the same value as well as replicated bytes in the value. 1781 */ 1782 1783 bool 1784 loongarch_const_vector_same_bytes_p (rtx op, machine_mode mode) 1785 { 1786 int i, bytes; 1787 HOST_WIDE_INT val, first_byte; 1788 rtx first; 1789 1790 if (!loongarch_const_vector_same_val_p (op, mode)) 1791 return false; 1792 1793 first = CONST_VECTOR_ELT (op, 0); 1794 bytes = GET_MODE_UNIT_SIZE (mode); 1795 val = INTVAL (first); 1796 first_byte = val & 0xff; 1797 for (i = 1; i < bytes; i++) 1798 { 1799 val >>= 8; 1800 if ((val & 0xff) != first_byte) 1801 return false; 1802 } 1803 1804 return true; 1805 } 1806 1807 /* Return true if OP is a constant vector with the number of units in MODE, 1808 and each unit has the same integer value in the range [LOW, HIGH]. */ 1809 1810 bool 1811 loongarch_const_vector_same_int_p (rtx op, machine_mode mode, HOST_WIDE_INT low, 1812 HOST_WIDE_INT high) 1813 { 1814 HOST_WIDE_INT value; 1815 rtx elem0; 1816 1817 if (!loongarch_const_vector_same_val_p (op, mode)) 1818 return false; 1819 1820 elem0 = CONST_VECTOR_ELT (op, 0); 1821 if (!CONST_INT_P (elem0)) 1822 return false; 1823 1824 value = INTVAL (elem0); 1825 return (value >= low && value <= high); 1826 } 1827 1828 /* Return true if OP is a constant vector with repeated 4-element sets 1829 in mode MODE. */ 1830 1831 bool 1832 loongarch_const_vector_shuffle_set_p (rtx op, machine_mode mode) 1833 { 1834 int nunits = GET_MODE_NUNITS (mode); 1835 int nsets = nunits / 4; 1836 int set = 0; 1837 int i, j; 1838 1839 /* Check if we have the same 4-element sets. */ 1840 for (j = 0; j < nsets; j++, set = 4 * j) 1841 for (i = 0; i < 4; i++) 1842 if ((INTVAL (XVECEXP (op, 0, i)) 1843 != (INTVAL (XVECEXP (op, 0, set + i)) - set)) 1844 || !IN_RANGE (INTVAL (XVECEXP (op, 0, set + i)), 0, set + 3)) 1845 return false; 1846 return true; 1847 } 1848 1849 /* Return true if rtx constants of mode MODE should be put into a small 1850 data section. */ 1851 1852 static bool 1853 loongarch_rtx_constant_in_small_data_p (machine_mode mode) 1854 { 1855 return (GET_MODE_SIZE (mode) <= g_switch_value); 1856 } 1857 1858 /* Return the method that should be used to access SYMBOL_REF or 1859 LABEL_REF X. */ 1860 1861 static enum loongarch_symbol_type 1862 loongarch_classify_symbol (const_rtx x) 1863 { 1864 enum loongarch_symbol_type pcrel = 1865 TARGET_CMODEL_EXTREME ? SYMBOL_PCREL64 : SYMBOL_PCREL; 1866 1867 if (!SYMBOL_REF_P (x)) 1868 return pcrel; 1869 1870 if (SYMBOL_REF_TLS_MODEL (x)) 1871 return SYMBOL_TLS; 1872 1873 if (!loongarch_symbol_binds_local_p (x)) 1874 return SYMBOL_GOT_DISP; 1875 1876 tree t = SYMBOL_REF_DECL (x); 1877 if (!t) 1878 return pcrel; 1879 1880 t = lookup_attribute ("model", DECL_ATTRIBUTES (t)); 1881 if (!t) 1882 return pcrel; 1883 1884 t = TREE_VALUE (TREE_VALUE (t)); 1885 1886 /* loongarch_handle_model_attribute should reject other values. */ 1887 gcc_assert (TREE_CODE (t) == STRING_CST); 1888 1889 const char *model = TREE_STRING_POINTER (t); 1890 if (strcmp (model, "normal") == 0) 1891 return SYMBOL_PCREL; 1892 if (strcmp (model, "extreme") == 0) 1893 return SYMBOL_PCREL64; 1894 1895 /* loongarch_handle_model_attribute should reject unknown model 1896 name. */ 1897 gcc_unreachable (); 1898 } 1899 1900 /* Classify the base of symbolic expression X, given that X appears in 1901 context CONTEXT. */ 1902 1903 static enum loongarch_symbol_type 1904 loongarch_classify_symbolic_expression (rtx x) 1905 { 1906 rtx offset; 1907 1908 split_const (x, &x, &offset); 1909 if (UNSPEC_ADDRESS_P (x)) 1910 return UNSPEC_ADDRESS_TYPE (x); 1911 1912 return loongarch_classify_symbol (x); 1913 } 1914 1915 /* Return true if X is a symbolic constant. If it is, 1916 store the type of the symbol in *SYMBOL_TYPE. */ 1917 1918 bool 1919 loongarch_symbolic_constant_p (rtx x, enum loongarch_symbol_type *symbol_type) 1920 { 1921 rtx offset; 1922 1923 split_const (x, &x, &offset); 1924 if (UNSPEC_ADDRESS_P (x)) 1925 { 1926 *symbol_type = UNSPEC_ADDRESS_TYPE (x); 1927 x = UNSPEC_ADDRESS (x); 1928 } 1929 else if (SYMBOL_REF_P (x) || LABEL_REF_P (x)) 1930 *symbol_type = loongarch_classify_symbol (x); 1931 else 1932 return false; 1933 1934 if (offset == const0_rtx) 1935 return true; 1936 1937 /* Check whether a nonzero offset is valid for the underlying 1938 relocations. */ 1939 switch (*symbol_type) 1940 { 1941 case SYMBOL_PCREL64: 1942 /* When the code model is extreme, the non-zero offset situation 1943 has not been handled well, so it is disabled here now. */ 1944 if (!loongarch_explicit_relocs_p (SYMBOL_PCREL64)) 1945 return false; 1946 /* fall through */ 1947 case SYMBOL_PCREL: 1948 /* GAS rejects offsets outside the range [-2^31, 2^31-1]. */ 1949 return sext_hwi (INTVAL (offset), 32) == INTVAL (offset); 1950 1951 /* The following symbol types do not allow non-zero offsets. */ 1952 case SYMBOL_GOT_DISP: 1953 case SYMBOL_TLS_IE: 1954 case SYMBOL_TLSGD: 1955 case SYMBOL_TLSLDM: 1956 case SYMBOL_TLS: 1957 /* From an implementation perspective, tls_le symbols are allowed to 1958 have non-zero offsets, but currently binutils has not added support, 1959 so the generation of non-zero offsets is prohibited here. */ 1960 case SYMBOL_TLS_LE: 1961 return false; 1962 } 1963 gcc_unreachable (); 1964 } 1965 1966 /* If -mexplicit-relocs=auto, we use machine operations with reloc hints 1967 for cases where the linker is unable to relax so we can schedule the 1968 machine operations, otherwise use an assembler pseudo-op so the 1969 assembler will generate R_LARCH_RELAX. */ 1970 1971 bool 1972 loongarch_explicit_relocs_p (enum loongarch_symbol_type type) 1973 { 1974 if (la_opt_explicit_relocs != EXPLICIT_RELOCS_AUTO) 1975 return la_opt_explicit_relocs == EXPLICIT_RELOCS_ALWAYS; 1976 1977 /* The linker don't know how to relax accesses in extreme code model. */ 1978 if (loongarch_symbol_extreme_p (type)) 1979 return true; 1980 1981 switch (type) 1982 { 1983 case SYMBOL_TLS_IE: 1984 case SYMBOL_TLS_LE: 1985 case SYMBOL_PCREL64: 1986 /* TLS IE cannot be relaxed. TLS LE relaxation is different from 1987 the normal R_LARCH_RELAX-based relaxation and it **requires** 1988 using the explicit %le_{lo12,hi20,add}_r relocs. The linker 1989 does not relax 64-bit pc-relative accesses as at now. */ 1990 return true; 1991 case SYMBOL_GOT_DISP: 1992 /* If we are performing LTO for a final link, and we have the 1993 linker plugin so we know the resolution of the symbols, then 1994 all GOT references are binding to external symbols or 1995 preemptable symbols. So the linker cannot relax them. */ 1996 return (in_lto_p 1997 && !flag_incremental_link 1998 && HAVE_LTO_PLUGIN == 2 1999 && (!global_options_set.x_flag_use_linker_plugin 2000 || global_options.x_flag_use_linker_plugin)); 2001 default: 2002 return false; 2003 } 2004 } 2005 2006 /* Returns the number of instructions necessary to reference a symbol. */ 2007 2008 static int 2009 loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode) 2010 { 2011 /* LSX LD.* and ST.* cannot support loading symbols via an immediate 2012 operand. */ 2013 if (mode != MAX_MACHINE_MODE 2014 && (LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode))) 2015 return 0; 2016 2017 switch (type) 2018 { 2019 case SYMBOL_GOT_DISP: 2020 /* The constant will have to be loaded from the GOT before it 2021 is used in an address. */ 2022 if (!loongarch_explicit_relocs_p (type) && mode != MAX_MACHINE_MODE) 2023 return 0; 2024 2025 return 3; 2026 2027 case SYMBOL_PCREL: 2028 case SYMBOL_TLS_IE: 2029 case SYMBOL_TLS_LE: 2030 return 2; 2031 2032 case SYMBOL_TLSGD: 2033 case SYMBOL_TLSLDM: 2034 return TARGET_TLS_DESC ? 4 : 3; 2035 2036 case SYMBOL_PCREL64: 2037 return 5; 2038 2039 case SYMBOL_TLS: 2040 /* We don't treat a bare TLS symbol as a constant. */ 2041 return 0; 2042 } 2043 gcc_unreachable (); 2044 } 2045 2046 /* Implement TARGET_CANNOT_FORCE_CONST_MEM. */ 2047 2048 static bool 2049 loongarch_cannot_force_const_mem (machine_mode mode, rtx x) 2050 { 2051 enum loongarch_symbol_type type; 2052 rtx base, offset; 2053 2054 /* As an optimization, reject constants that loongarch_legitimize_move 2055 can expand inline. 2056 2057 Suppose we have a multi-instruction sequence that loads constant C 2058 into register R. If R does not get allocated a hard register, and 2059 R is used in an operand that allows both registers and memory 2060 references, reload will consider forcing C into memory and using 2061 one of the instruction's memory alternatives. Returning false 2062 here will force it to use an input reload instead. */ 2063 if ((CONST_INT_P (x) || GET_CODE (x) == CONST_VECTOR) 2064 && loongarch_legitimate_constant_p (mode, x)) 2065 return true; 2066 2067 split_const (x, &base, &offset); 2068 if (loongarch_symbolic_constant_p (base, &type)) 2069 { 2070 /* The same optimization as for CONST_INT. */ 2071 if (IMM12_INT (offset) 2072 && loongarch_symbol_insns (type, MAX_MACHINE_MODE) > 0) 2073 return true; 2074 } 2075 2076 /* TLS symbols must be computed by loongarch_legitimize_move. */ 2077 if (tls_referenced_p (x)) 2078 return true; 2079 2080 return false; 2081 } 2082 2083 /* Return true if register REGNO is a valid base register for mode MODE. 2084 STRICT_P is true if REG_OK_STRICT is in effect. */ 2085 2086 int 2087 loongarch_regno_mode_ok_for_base_p (int regno, 2088 machine_mode mode ATTRIBUTE_UNUSED, 2089 bool strict_p) 2090 { 2091 if (!HARD_REGISTER_NUM_P (regno)) 2092 { 2093 if (!strict_p) 2094 return true; 2095 regno = reg_renumber[regno]; 2096 } 2097 2098 /* These fake registers will be eliminated to either the stack or 2099 hard frame pointer, both of which are usually valid base registers. 2100 Reload deals with the cases where the eliminated form isn't valid. */ 2101 if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM) 2102 return true; 2103 2104 return GP_REG_P (regno); 2105 } 2106 2107 /* Return true if X is a valid base register for mode MODE. 2108 STRICT_P is true if REG_OK_STRICT is in effect. */ 2109 2110 static bool 2111 loongarch_valid_base_register_p (rtx x, machine_mode mode, bool strict_p) 2112 { 2113 if (!strict_p && SUBREG_P (x)) 2114 x = SUBREG_REG (x); 2115 2116 return (REG_P (x) 2117 && loongarch_regno_mode_ok_for_base_p (REGNO (x), mode, strict_p)); 2118 } 2119 2120 /* Return true if, for every base register BASE_REG, (plus BASE_REG X) 2121 can address a value of mode MODE. */ 2122 2123 static bool 2124 loongarch_valid_offset_p (rtx x, machine_mode mode) 2125 { 2126 /* Check that X is a signed 12-bit number, 2127 or check that X is a signed 16-bit number 2128 and offset 4 byte aligned. */ 2129 if (!(const_arith_operand (x, Pmode) 2130 || ((mode == E_SImode || mode == E_DImode) 2131 && const_imm16_operand (x, Pmode) 2132 && (loongarch_signed_immediate_p (INTVAL (x), 14, 2))))) 2133 return false; 2134 2135 /* We may need to split multiword moves, so make sure that every word 2136 is accessible. */ 2137 if (!(LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode)) 2138 && GET_MODE_SIZE (mode) > UNITS_PER_WORD 2139 && !IMM12_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode) - UNITS_PER_WORD)) 2140 return false; 2141 2142 return true; 2143 } 2144 2145 /* Should a symbol of type SYMBOL_TYPE should be split in two or more? */ 2146 2147 bool 2148 loongarch_split_symbol_type (enum loongarch_symbol_type symbol_type) 2149 { 2150 switch (symbol_type) 2151 { 2152 case SYMBOL_PCREL: 2153 case SYMBOL_PCREL64: 2154 case SYMBOL_GOT_DISP: 2155 case SYMBOL_TLS_IE: 2156 case SYMBOL_TLS_LE: 2157 case SYMBOL_TLSGD: 2158 case SYMBOL_TLSLDM: 2159 return true; 2160 2161 case SYMBOL_TLS: 2162 return false; 2163 2164 default: 2165 gcc_unreachable (); 2166 } 2167 } 2168 2169 /* Return true if a LO_SUM can address a value of mode MODE when the 2170 LO_SUM symbol has type SYMBOL_TYPE. */ 2171 2172 static bool 2173 loongarch_valid_lo_sum_p (enum loongarch_symbol_type symbol_type, 2174 machine_mode mode, rtx x) 2175 { 2176 int align, size; 2177 2178 /* Check that symbols of type SYMBOL_TYPE can be used to access values 2179 of mode MODE. */ 2180 if (loongarch_symbol_insns (symbol_type, mode) == 0) 2181 return false; 2182 2183 /* Check that there is a known low-part relocation. */ 2184 if (!loongarch_split_symbol_type (symbol_type)) 2185 return false; 2186 2187 /* We can't tell size or alignment when we have BLKmode, so try extracing a 2188 decl from the symbol if possible. */ 2189 if (mode == BLKmode) 2190 { 2191 rtx offset; 2192 2193 /* Extract the symbol from the LO_SUM operand, if any. */ 2194 split_const (x, &x, &offset); 2195 2196 /* Might be a CODE_LABEL. We can compute align but not size for that, 2197 so don't bother trying to handle it. */ 2198 if (!SYMBOL_REF_P (x)) 2199 return false; 2200 2201 /* Use worst case assumptions if we don't have a SYMBOL_REF_DECL. */ 2202 align = (SYMBOL_REF_DECL (x) 2203 ? DECL_ALIGN (SYMBOL_REF_DECL (x)) 2204 : 1); 2205 size = (SYMBOL_REF_DECL (x) && DECL_SIZE (SYMBOL_REF_DECL (x)) 2206 ? tree_to_uhwi (DECL_SIZE (SYMBOL_REF_DECL (x))) 2207 : 2*BITS_PER_WORD); 2208 } 2209 else 2210 { 2211 align = GET_MODE_ALIGNMENT (mode); 2212 size = GET_MODE_BITSIZE (mode); 2213 } 2214 2215 /* We may need to split multiword moves, so make sure that each word 2216 can be accessed without inducing a carry. */ 2217 if (size > BITS_PER_WORD 2218 && (!TARGET_STRICT_ALIGN || size > align)) 2219 return false; 2220 2221 return true; 2222 } 2223 2224 static bool 2225 loongarch_valid_index_p (struct loongarch_address_info *info, rtx x, 2226 machine_mode mode, bool strict_p) 2227 { 2228 rtx index; 2229 2230 if ((REG_P (x) || SUBREG_P (x)) 2231 && GET_MODE (x) == Pmode) 2232 { 2233 index = x; 2234 } 2235 else 2236 return false; 2237 2238 if (!strict_p 2239 && SUBREG_P (index) 2240 && contains_reg_of_mode[GENERAL_REGS][GET_MODE (SUBREG_REG (index))]) 2241 index = SUBREG_REG (index); 2242 2243 if (loongarch_valid_base_register_p (index, mode, strict_p)) 2244 { 2245 info->type = ADDRESS_REG_REG; 2246 info->offset = index; 2247 return true; 2248 } 2249 2250 return false; 2251 } 2252 2253 /* Return true if X is a valid address for machine mode MODE. If it is, 2254 fill in INFO appropriately. STRICT_P is true if REG_OK_STRICT is in 2255 effect. */ 2256 2257 static bool 2258 loongarch_classify_address (struct loongarch_address_info *info, rtx x, 2259 machine_mode mode, bool strict_p) 2260 { 2261 switch (GET_CODE (x)) 2262 { 2263 case REG: 2264 case SUBREG: 2265 info->type = ADDRESS_REG; 2266 info->reg = x; 2267 info->offset = const0_rtx; 2268 return loongarch_valid_base_register_p (info->reg, mode, strict_p); 2269 2270 case PLUS: 2271 if (loongarch_valid_base_register_p (XEXP (x, 0), mode, strict_p) 2272 && loongarch_valid_index_p (info, XEXP (x, 1), mode, strict_p)) 2273 { 2274 info->reg = XEXP (x, 0); 2275 return true; 2276 } 2277 2278 if (loongarch_valid_base_register_p (XEXP (x, 1), mode, strict_p) 2279 && loongarch_valid_index_p (info, XEXP (x, 0), mode, strict_p)) 2280 { 2281 info->reg = XEXP (x, 1); 2282 return true; 2283 } 2284 2285 info->type = ADDRESS_REG; 2286 info->reg = XEXP (x, 0); 2287 info->offset = XEXP (x, 1); 2288 return (loongarch_valid_base_register_p (info->reg, mode, strict_p) 2289 && loongarch_valid_offset_p (info->offset, mode)); 2290 2291 case LO_SUM: 2292 info->type = ADDRESS_LO_SUM; 2293 info->reg = XEXP (x, 0); 2294 info->offset = XEXP (x, 1); 2295 /* We have to trust the creator of the LO_SUM to do something vaguely 2296 sane. Target-independent code that creates a LO_SUM should also 2297 create and verify the matching HIGH. Target-independent code that 2298 adds an offset to a LO_SUM must prove that the offset will not 2299 induce a carry. Failure to do either of these things would be 2300 a bug, and we are not required to check for it here. The MIPS 2301 backend itself should only create LO_SUMs for valid symbolic 2302 constants, with the high part being either a HIGH or a copy 2303 of _gp. */ 2304 info->symbol_type 2305 = loongarch_classify_symbolic_expression (info->offset); 2306 return (loongarch_valid_base_register_p (info->reg, mode, strict_p) 2307 && loongarch_valid_lo_sum_p (info->symbol_type, mode, 2308 info->offset)); 2309 case CONST_INT: 2310 /* Small-integer addresses don't occur very often, but they 2311 are legitimate if $r0 is a valid base register. */ 2312 info->type = ADDRESS_CONST_INT; 2313 return IMM12_OPERAND (INTVAL (x)); 2314 2315 default: 2316 return false; 2317 } 2318 } 2319 2320 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */ 2321 2322 static bool 2323 loongarch_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, 2324 code_helper = ERROR_MARK) 2325 { 2326 struct loongarch_address_info addr; 2327 2328 return loongarch_classify_address (&addr, x, mode, strict_p); 2329 } 2330 2331 /* Return true if ADDR matches the pattern for the indexed address 2332 instruction. */ 2333 2334 static bool 2335 loongarch_index_address_p (rtx addr, machine_mode mode ATTRIBUTE_UNUSED) 2336 { 2337 if (GET_CODE (addr) != PLUS 2338 || !REG_P (XEXP (addr, 0)) 2339 || !REG_P (XEXP (addr, 1))) 2340 return false; 2341 return true; 2342 } 2343 2344 /* Return the number of instructions needed to load or store a value 2345 of mode MODE at address X. Return 0 if X isn't valid for MODE. 2346 Assume that multiword moves may need to be split into word moves 2347 if MIGHT_SPLIT_P, otherwise assume that a single load or store is 2348 enough. */ 2349 2350 int 2351 loongarch_address_insns (rtx x, machine_mode mode, bool might_split_p) 2352 { 2353 struct loongarch_address_info addr; 2354 int factor; 2355 bool lsx_p = (!might_split_p 2356 && (LSX_SUPPORTED_MODE_P (mode) 2357 || LASX_SUPPORTED_MODE_P (mode))); 2358 2359 if (!loongarch_classify_address (&addr, x, mode, false)) 2360 return 0; 2361 2362 /* BLKmode is used for single unaligned loads and stores and should 2363 not count as a multiword mode. (GET_MODE_SIZE (BLKmode) is pretty 2364 meaningless, so we have to single it out as a special case one way 2365 or the other.) */ 2366 if (mode != BLKmode && might_split_p) 2367 factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 2368 else 2369 factor = 1; 2370 2371 if (loongarch_classify_address (&addr, x, mode, false)) 2372 switch (addr.type) 2373 { 2374 case ADDRESS_REG: 2375 if (lsx_p) 2376 { 2377 /* LSX LD.* and ST.* supports 12-bit signed offsets. */ 2378 if (IMM12_OPERAND (INTVAL (addr.offset))) 2379 return 1; 2380 else 2381 return 0; 2382 } 2383 return factor; 2384 2385 case ADDRESS_REG_REG: 2386 return factor; 2387 2388 case ADDRESS_CONST_INT: 2389 return lsx_p ? 0 : factor; 2390 2391 case ADDRESS_LO_SUM: 2392 return factor + 1; 2393 2394 case ADDRESS_SYMBOLIC: 2395 return lsx_p ? 0 2396 : factor * loongarch_symbol_insns (addr.symbol_type, mode); 2397 } 2398 return 0; 2399 } 2400 2401 /* Return true if X fits within an unsigned field of BITS bits that is 2402 shifted left SHIFT bits before being used. */ 2403 2404 bool 2405 loongarch_unsigned_immediate_p (unsigned HOST_WIDE_INT x, int bits, 2406 int shift = 0) 2407 { 2408 return (x & ((1 << shift) - 1)) == 0 && x < ((unsigned) 1 << (shift + bits)); 2409 } 2410 2411 /* Return true if X fits within a signed field of BITS bits that is 2412 shifted left SHIFT bits before being used. */ 2413 2414 bool 2415 loongarch_signed_immediate_p (unsigned HOST_WIDE_INT x, int bits, 2416 int shift = 0) 2417 { 2418 x += 1 << (bits + shift - 1); 2419 return loongarch_unsigned_immediate_p (x, bits, shift); 2420 } 2421 2422 /* Return the scale shift that applied to LSX LD/ST address offset. */ 2423 2424 int 2425 loongarch_ldst_scaled_shift (machine_mode mode) 2426 { 2427 int shift = exact_log2 (GET_MODE_UNIT_SIZE (mode)); 2428 2429 if (shift < 0 || shift > 8) 2430 gcc_unreachable (); 2431 2432 return shift; 2433 } 2434 2435 /* Return true if X is a legitimate address with a 12-bit offset 2436 or addr.type is ADDRESS_LO_SUM. 2437 MODE is the mode of the value being accessed. */ 2438 2439 bool 2440 loongarch_12bit_offset_address_p (rtx x, machine_mode mode) 2441 { 2442 struct loongarch_address_info addr; 2443 2444 return (loongarch_classify_address (&addr, x, mode, false) 2445 && ((addr.type == ADDRESS_REG 2446 && CONST_INT_P (addr.offset) 2447 && LARCH_12BIT_OFFSET_P (INTVAL (addr.offset))) 2448 || addr.type == ADDRESS_LO_SUM)); 2449 } 2450 2451 /* Return true if X is a legitimate address with a 14-bit offset shifted 2. 2452 MODE is the mode of the value being accessed. */ 2453 2454 bool 2455 loongarch_14bit_shifted_offset_address_p (rtx x, machine_mode mode) 2456 { 2457 struct loongarch_address_info addr; 2458 2459 return (loongarch_classify_address (&addr, x, mode, false) 2460 && addr.type == ADDRESS_REG 2461 && CONST_INT_P (addr.offset) 2462 && LARCH_16BIT_OFFSET_P (INTVAL (addr.offset)) 2463 && LARCH_SHIFT_2_OFFSET_P (INTVAL (addr.offset))); 2464 } 2465 2466 /* Return true if X is a legitimate address with base and index. 2467 MODE is the mode of the value being accessed. */ 2468 2469 bool 2470 loongarch_base_index_address_p (rtx x, machine_mode mode) 2471 { 2472 struct loongarch_address_info addr; 2473 2474 return (loongarch_classify_address (&addr, x, mode, false) 2475 && addr.type == ADDRESS_REG_REG 2476 && REG_P (addr.offset)); 2477 } 2478 2479 /* Return the number of instructions needed to load constant X, 2480 Return 0 if X isn't a valid constant. */ 2481 2482 int 2483 loongarch_const_insns (rtx x) 2484 { 2485 enum loongarch_symbol_type symbol_type; 2486 rtx offset; 2487 2488 switch (GET_CODE (x)) 2489 { 2490 case HIGH: 2491 if (!loongarch_symbolic_constant_p (XEXP (x, 0), &symbol_type) 2492 || !loongarch_split_symbol_type (symbol_type)) 2493 return 0; 2494 2495 /* This is simply a PCALAU12I. */ 2496 return 1; 2497 2498 case CONST_INT: 2499 return loongarch_integer_cost (INTVAL (x)); 2500 2501 case CONST_VECTOR: 2502 if ((LSX_SUPPORTED_MODE_P (GET_MODE (x)) 2503 || LASX_SUPPORTED_MODE_P (GET_MODE (x))) 2504 && loongarch_const_vector_same_int_p (x, GET_MODE (x), -512, 511)) 2505 return 1; 2506 /* Fall through. */ 2507 case CONST_DOUBLE: 2508 return x == CONST0_RTX (GET_MODE (x)) ? 1 : 0; 2509 2510 case CONST: 2511 /* See if we can refer to X directly. */ 2512 if (loongarch_symbolic_constant_p (x, &symbol_type)) 2513 return loongarch_symbol_insns (symbol_type, MAX_MACHINE_MODE); 2514 2515 /* Otherwise try splitting the constant into a base and offset. 2516 If the offset is a 12-bit value, we can load the base address 2517 into a register and then use ADDI.{W/D} to add in the offset. 2518 If the offset is larger, we can load the base and offset 2519 into separate registers and add them together with ADD.{W/D}. 2520 However, the latter is only possible before reload; during 2521 and after reload, we must have the option of forcing the 2522 constant into the pool instead. */ 2523 split_const (x, &x, &offset); 2524 if (offset != 0) 2525 { 2526 int n = loongarch_const_insns (x); 2527 if (n != 0) 2528 { 2529 if (IMM12_INT (offset)) 2530 return n + 1; 2531 else if (!targetm.cannot_force_const_mem (GET_MODE (x), x)) 2532 return n + 1 + loongarch_integer_cost (INTVAL (offset)); 2533 } 2534 } 2535 return 0; 2536 2537 case SYMBOL_REF: 2538 case LABEL_REF: 2539 return loongarch_symbol_insns ( 2540 loongarch_classify_symbol (x), MAX_MACHINE_MODE); 2541 2542 default: 2543 return 0; 2544 } 2545 } 2546 2547 /* X is a doubleword constant that can be handled by splitting it into 2548 two words and loading each word separately. Return the number of 2549 instructions required to do this. */ 2550 2551 int 2552 loongarch_split_const_insns (rtx x) 2553 { 2554 unsigned int low, high; 2555 2556 low = loongarch_const_insns (loongarch_subword (x, false)); 2557 high = loongarch_const_insns (loongarch_subword (x, true)); 2558 gcc_assert (low > 0 && high > 0); 2559 return low + high; 2560 } 2561 2562 /* Return one word of 128-bit value OP, taking into account the fixed 2563 endianness of certain registers. BYTE selects from the byte address. */ 2564 2565 rtx 2566 loongarch_subword_at_byte (rtx op, unsigned int byte) 2567 { 2568 machine_mode mode; 2569 2570 mode = GET_MODE (op); 2571 if (mode == VOIDmode) 2572 mode = TImode; 2573 2574 gcc_assert (!FP_REG_RTX_P (op)); 2575 2576 if (MEM_P (op)) 2577 return loongarch_rewrite_small_data (adjust_address (op, word_mode, byte)); 2578 2579 return simplify_gen_subreg (word_mode, op, mode, byte); 2580 } 2581 2582 /* Return the number of instructions needed to implement INSN, 2583 given that it loads from or stores to MEM. */ 2584 2585 int 2586 loongarch_load_store_insns (rtx mem, rtx_insn *insn) 2587 { 2588 machine_mode mode; 2589 bool might_split_p; 2590 rtx set; 2591 2592 gcc_assert (MEM_P (mem)); 2593 mode = GET_MODE (mem); 2594 2595 /* Try to prove that INSN does not need to be split. */ 2596 might_split_p = GET_MODE_SIZE (mode) > UNITS_PER_WORD; 2597 if (might_split_p) 2598 { 2599 set = single_set (insn); 2600 if (set 2601 && !loongarch_split_move_p (SET_DEST (set), SET_SRC (set))) 2602 might_split_p = false; 2603 } 2604 2605 return loongarch_address_insns (XEXP (mem, 0), mode, might_split_p); 2606 } 2607 2608 /* Return true if we need to trap on division by zero. */ 2609 2610 bool 2611 loongarch_check_zero_div_p (void) 2612 { 2613 /* if -m[no-]check-zero-division is given explicitly. */ 2614 if (target_flags_explicit & MASK_CHECK_ZERO_DIV) 2615 return TARGET_CHECK_ZERO_DIV; 2616 2617 /* if not, don't trap for optimized code except -Og. */ 2618 return !optimize || optimize_debug; 2619 } 2620 2621 /* Return the number of instructions needed for an integer division. */ 2622 2623 int 2624 loongarch_idiv_insns (machine_mode mode ATTRIBUTE_UNUSED) 2625 { 2626 int count; 2627 2628 count = 1; 2629 if (loongarch_check_zero_div_p ()) 2630 count += 2; 2631 2632 return count; 2633 } 2634 2635 /* Emit an instruction of the form (set TARGET (CODE OP0 OP1)). */ 2636 2637 void 2638 loongarch_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1) 2639 { 2640 emit_insn (gen_rtx_SET (target, gen_rtx_fmt_ee (code, GET_MODE (target), 2641 op0, op1))); 2642 } 2643 2644 /* Compute (CODE OP0 OP1) and store the result in a new register 2645 of mode MODE. Return that new register. */ 2646 2647 static rtx 2648 loongarch_force_binary (machine_mode mode, enum rtx_code code, rtx op0, 2649 rtx op1) 2650 { 2651 rtx reg; 2652 2653 reg = gen_reg_rtx (mode); 2654 loongarch_emit_binary (code, reg, op0, op1); 2655 return reg; 2656 } 2657 2658 /* Copy VALUE to a register and return that register. If new pseudos 2659 are allowed, copy it into a new register, otherwise use DEST. */ 2660 2661 static rtx 2662 loongarch_force_temporary (rtx dest, rtx value) 2663 { 2664 if (can_create_pseudo_p ()) 2665 return force_reg (Pmode, value); 2666 else 2667 { 2668 loongarch_emit_move (dest, value); 2669 return dest; 2670 } 2671 } 2672 2673 /* Wrap symbol or label BASE in an UNSPEC address of type SYMBOL_TYPE, 2674 then add CONST_INT OFFSET to the result. */ 2675 2676 static rtx 2677 loongarch_unspec_address_offset (rtx base, rtx offset, 2678 enum loongarch_symbol_type symbol_type) 2679 { 2680 base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 2681 UNSPEC_ADDRESS_FIRST + symbol_type); 2682 if (offset != const0_rtx) 2683 base = gen_rtx_PLUS (Pmode, base, offset); 2684 return gen_rtx_CONST (Pmode, base); 2685 } 2686 2687 /* Return an UNSPEC address with underlying address ADDRESS and symbol 2688 type SYMBOL_TYPE. */ 2689 2690 rtx 2691 loongarch_unspec_address (rtx address, enum loongarch_symbol_type symbol_type) 2692 { 2693 rtx base, offset; 2694 2695 split_const (address, &base, &offset); 2696 return loongarch_unspec_address_offset (base, offset, symbol_type); 2697 } 2698 2699 /* Emit an instruction of the form (set TARGET SRC). */ 2700 2701 static rtx 2702 loongarch_emit_set (rtx target, rtx src) 2703 { 2704 emit_insn (gen_rtx_SET (target, src)); 2705 return target; 2706 } 2707 2708 /* If OP is an UNSPEC address, return the address to which it refers, 2709 otherwise return OP itself. */ 2710 2711 rtx 2712 loongarch_strip_unspec_address (rtx op) 2713 { 2714 rtx base, offset; 2715 2716 split_const (op, &base, &offset); 2717 if (UNSPEC_ADDRESS_P (base)) 2718 op = plus_constant (Pmode, UNSPEC_ADDRESS (base), INTVAL (offset)); 2719 return op; 2720 } 2721 2722 /* Return a legitimate address for REG + OFFSET. TEMP is as for 2723 loongarch_force_temporary; it is only needed when OFFSET is not a 2724 IMM12_OPERAND. */ 2725 2726 static rtx 2727 loongarch_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset) 2728 { 2729 if (!IMM12_OPERAND (offset)) 2730 { 2731 rtx high; 2732 2733 /* Leave OFFSET as a 12-bit offset and put the excess in HIGH. 2734 The addition inside the macro CONST_HIGH_PART may cause an 2735 overflow, so we need to force a sign-extension check. */ 2736 high = gen_int_mode (CONST_HIGH_PART (offset), Pmode); 2737 offset = CONST_LOW_PART (offset); 2738 high = loongarch_force_temporary (temp, high); 2739 reg = loongarch_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg)); 2740 } 2741 return plus_constant (Pmode, reg, offset); 2742 } 2743 2744 /* The __tls_get_addr symbol. */ 2745 static GTY (()) rtx loongarch_tls_symbol; 2746 2747 /* Load an entry for a TLS access. */ 2748 2749 static rtx 2750 loongarch_load_tls (rtx dest, rtx sym, enum loongarch_symbol_type type) 2751 { 2752 /* TLS LE gets a 32 or 64 bit offset here, so one register can do it. */ 2753 if (type == SYMBOL_TLS_LE) 2754 return gen_load_tls (Pmode, dest, sym); 2755 2756 return loongarch_symbol_extreme_p (type) 2757 ? gen_movdi_symbolic_off64 (dest, sym, gen_reg_rtx (DImode)) 2758 : gen_load_tls (Pmode, dest, sym); 2759 } 2760 2761 /* Return an instruction sequence that calls __tls_get_addr. SYM is 2762 the TLS symbol we are referencing and TYPE is the symbol type to use 2763 (either global dynamic or local dynamic). V0 is an RTX for the 2764 return value location. */ 2765 2766 static rtx_insn * 2767 loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0) 2768 { 2769 rtx loc, a0; 2770 rtx_insn *insn; 2771 rtx tmp = gen_reg_rtx (Pmode); 2772 2773 a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST); 2774 2775 if (!loongarch_tls_symbol) 2776 loongarch_tls_symbol = init_one_libfunc ("__tls_get_addr"); 2777 2778 loc = loongarch_unspec_address (sym, type); 2779 2780 start_sequence (); 2781 2782 if (loongarch_explicit_relocs_p (type)) 2783 { 2784 if (TARGET_CMODEL_EXTREME) 2785 { 2786 rtx part1 = gen_reg_rtx (Pmode); 2787 rtx part2 = gen_reg_rtx (Pmode); 2788 2789 emit_insn (gen_la_pcrel64_two_parts (part1, part2, loc)); 2790 emit_move_insn (a0, gen_rtx_PLUS (Pmode, part1, part2)); 2791 } 2792 else 2793 { 2794 /* Split tls symbol to high and low. */ 2795 rtx high = gen_rtx_HIGH (Pmode, copy_rtx (loc)); 2796 2797 high = loongarch_force_temporary (tmp, high); 2798 emit_insn (gen_tls_low (Pmode, a0, high, loc)); 2799 } 2800 } 2801 else 2802 emit_insn (loongarch_load_tls (a0, loc, type)); 2803 2804 if (flag_plt) 2805 { 2806 switch (la_target.cmodel) 2807 { 2808 case CMODEL_NORMAL: 2809 insn = emit_call_insn (gen_call_value_internal (v0, 2810 loongarch_tls_symbol, 2811 const0_rtx)); 2812 break; 2813 2814 case CMODEL_MEDIUM: 2815 { 2816 if (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE) 2817 { 2818 rtx call; 2819 2820 if (HAVE_AS_SUPPORT_CALL36) 2821 call = gen_call_value_internal (v0, loongarch_tls_symbol, 2822 const0_rtx); 2823 else 2824 { 2825 rtx reg = gen_reg_rtx (Pmode); 2826 emit_insn (gen_pcalau12i (Pmode, reg, 2827 loongarch_tls_symbol)); 2828 call = gen_call_value_internal_1 (Pmode, v0, reg, 2829 loongarch_tls_symbol, 2830 const0_rtx); 2831 } 2832 insn = emit_call_insn (call); 2833 } 2834 else 2835 { 2836 rtx reg = gen_reg_rtx (Pmode); 2837 emit_move_insn (reg, loongarch_tls_symbol); 2838 insn = emit_call_insn (gen_call_value_internal (v0, 2839 reg, 2840 const0_rtx)); 2841 } 2842 break; 2843 } 2844 2845 /* code model extreme not support plt. */ 2846 case CMODEL_EXTREME: 2847 case CMODEL_LARGE: 2848 case CMODEL_TINY: 2849 case CMODEL_TINY_STATIC: 2850 default: 2851 gcc_unreachable (); 2852 } 2853 } 2854 else 2855 { 2856 rtx dest = gen_reg_rtx (Pmode); 2857 2858 switch (la_target.cmodel) 2859 { 2860 case CMODEL_NORMAL: 2861 case CMODEL_MEDIUM: 2862 { 2863 if (loongarch_explicit_relocs_p (SYMBOL_GOT_DISP)) 2864 { 2865 rtx high = gen_reg_rtx (Pmode); 2866 loongarch_emit_move (high, 2867 gen_rtx_HIGH (Pmode, 2868 loongarch_tls_symbol)); 2869 emit_insn (gen_ld_from_got (Pmode, dest, high, 2870 loongarch_tls_symbol)); 2871 } 2872 else 2873 loongarch_emit_move (dest, loongarch_tls_symbol); 2874 break; 2875 } 2876 2877 case CMODEL_EXTREME: 2878 { 2879 if (loongarch_explicit_relocs_p (SYMBOL_GOT_DISP)) 2880 { 2881 gcc_assert (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE); 2882 2883 rtx part1 = gen_reg_rtx (Pmode); 2884 rtx part2 = gen_reg_rtx (Pmode); 2885 2886 emit_insn (gen_la_pcrel64_two_parts (part1, part2, 2887 loongarch_tls_symbol)); 2888 loongarch_emit_move ( 2889 dest, 2890 gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, 2891 part1, 2892 part2))); 2893 2894 /* Put an REG_EQUAL note here to allow CSE (storing 2895 part1 + part2, i.e. the address of tls_get_addr into 2896 a saved register and use it for multiple TLS 2897 accesses). */ 2898 rtx sum = gen_rtx_UNSPEC ( 2899 Pmode, gen_rtvec (1, loongarch_tls_symbol), 2900 UNSPEC_ADDRESS_FIRST 2901 + loongarch_classify_symbol (loongarch_tls_symbol)); 2902 set_unique_reg_note (get_last_insn (), REG_EQUAL, sum); 2903 } 2904 else 2905 emit_insn (gen_movdi_symbolic_off64 (dest, loongarch_tls_symbol, 2906 gen_reg_rtx (DImode))); 2907 } 2908 break; 2909 2910 case CMODEL_LARGE: 2911 case CMODEL_TINY: 2912 case CMODEL_TINY_STATIC: 2913 default: 2914 gcc_unreachable (); 2915 } 2916 2917 insn = emit_call_insn (gen_call_value_internal (v0, dest, const0_rtx)); 2918 } 2919 2920 RTL_CONST_CALL_P (insn) = 1; 2921 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0); 2922 insn = get_insns (); 2923 2924 end_sequence (); 2925 2926 return insn; 2927 } 2928 2929 /* Generate the code to access LOC, a thread-local SYMBOL_REF, and return 2930 its address. The return value will be both a valid address and a valid 2931 SET_SRC (either a REG or a LO_SUM). */ 2932 2933 static rtx 2934 loongarch_legitimize_tls_address (rtx loc) 2935 { 2936 rtx dest, tp, tmp, tmp1, tmp2, tmp3, a0; 2937 enum tls_model model = SYMBOL_REF_TLS_MODEL (loc); 2938 rtx_insn *insn; 2939 2940 switch (model) 2941 { 2942 case TLS_MODEL_LOCAL_DYNAMIC: 2943 if (!TARGET_TLS_DESC) 2944 { 2945 tmp = gen_rtx_REG (Pmode, GP_RETURN); 2946 dest = gen_reg_rtx (Pmode); 2947 insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp); 2948 emit_libcall_block (insn, dest, tmp, loc); 2949 break; 2950 } 2951 /* Fall through. */ 2952 case TLS_MODEL_GLOBAL_DYNAMIC: 2953 if (TARGET_TLS_DESC) 2954 { 2955 a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST); 2956 dest = gen_reg_rtx (Pmode); 2957 tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); 2958 2959 if (TARGET_CMODEL_EXTREME) 2960 emit_insn (gen_got_load_tls_desc_off64 (loc, gen_reg_rtx (DImode))); 2961 else 2962 emit_insn (gen_got_load_tls_desc (Pmode, loc)); 2963 2964 emit_insn (gen_add3_insn (dest, a0, tp)); 2965 } 2966 else 2967 { 2968 tmp = gen_rtx_REG (Pmode, GP_RETURN); 2969 dest = gen_reg_rtx (Pmode); 2970 insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp); 2971 emit_libcall_block (insn, dest, tmp, loc); 2972 } 2973 break; 2974 2975 case TLS_MODEL_INITIAL_EXEC: 2976 { 2977 /* la.tls.ie; tp-relative add. */ 2978 tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); 2979 tmp1 = gen_reg_rtx (Pmode); 2980 tmp2 = loongarch_unspec_address (loc, SYMBOL_TLS_IE); 2981 dest = gen_reg_rtx (Pmode); 2982 if (loongarch_explicit_relocs_p (SYMBOL_TLS_IE)) 2983 { 2984 if (TARGET_CMODEL_EXTREME) 2985 { 2986 gcc_assert (la_opt_explicit_relocs 2987 != EXPLICIT_RELOCS_NONE); 2988 2989 rtx part1 = gen_reg_rtx (Pmode); 2990 rtx part2 = gen_reg_rtx (Pmode); 2991 2992 emit_insn (gen_la_pcrel64_two_parts (part1, part2, 2993 tmp2)); 2994 emit_move_insn (tmp1, 2995 gen_rtx_MEM (Pmode, 2996 gen_rtx_PLUS (Pmode, 2997 part1, 2998 part2))); 2999 } 3000 else 3001 { 3002 tmp3 = gen_reg_rtx (Pmode); 3003 rtx high = gen_rtx_HIGH (Pmode, copy_rtx (tmp2)); 3004 3005 high = loongarch_force_temporary (tmp3, high); 3006 emit_insn (gen_ld_from_got (Pmode, tmp1, high, tmp2)); 3007 } 3008 } 3009 else 3010 emit_insn (loongarch_load_tls (tmp1, tmp2, SYMBOL_TLS_IE)); 3011 emit_insn (gen_add3_insn (dest, tmp1, tp)); 3012 } 3013 break; 3014 3015 case TLS_MODEL_LOCAL_EXEC: 3016 { 3017 /* la.tls.le; tp-relative add. 3018 3019 normal: 3020 lu12i.w $rd, %le_hi20(sym) 3021 ori $rd, $rd, %le_lo12(sym) 3022 add.{w/d} $rd, $rd, $tp 3023 (st.{w/d}/ld.{w/d} $rs, $rd, 0) 3024 3025 tls le relax: 3026 lu12i.w $rd, %le_hi20_r(sym) 3027 add.{w/d} $rd,$rd,$tp 3028 addi.{w/d} $rd,$rd,%le_lo12_r(sym) 3029 (st.{w/d}/ld.{w/d} $rs, $rd, 0) 3030 3031 extreme (When the code model is set to extreme, the TLS le Relax 3032 instruction sequence is not generated): 3033 lu12i.w $rd, %le_hi20(sym) 3034 ori $rd, $rd, %le_lo12(sym) 3035 lu32i.d $rd, %le64_lo20(sym) 3036 lu52i.d $rd, $rd, %le64_hi12(sym) 3037 add.d $rd, $rd, $tp 3038 (st.{w/d}/ld.{w/d} $rs, $rd, 0) */ 3039 3040 tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); 3041 tmp1 = gen_reg_rtx (Pmode); 3042 tmp2 = loongarch_unspec_address (loc, SYMBOL_TLS_LE); 3043 dest = gen_reg_rtx (Pmode); 3044 3045 if (loongarch_explicit_relocs_p (SYMBOL_TLS_LE)) 3046 { 3047 tmp3 = gen_reg_rtx (Pmode); 3048 rtx high = gen_rtx_HIGH (Pmode, copy_rtx (tmp2)); 3049 high = loongarch_force_temporary (tmp3, high); 3050 3051 /* The assembler does not implement tls le relax support when the 3052 code model is extreme, so when the code model is extreme, the 3053 old symbol address acquisition method is still used. */ 3054 if (HAVE_AS_TLS_LE_RELAXATION && !TARGET_CMODEL_EXTREME) 3055 { 3056 emit_insn (gen_add_tls_le_relax (Pmode, dest, high, 3057 tp, loc)); 3058 loongarch_emit_move (dest, 3059 gen_rtx_LO_SUM (Pmode, dest, tmp2)); 3060 return dest; 3061 } 3062 else 3063 emit_insn (gen_ori_l_lo12 (Pmode, tmp1, high, tmp2)); 3064 3065 if (TARGET_CMODEL_EXTREME) 3066 { 3067 emit_insn (gen_lui_h_lo20 (tmp1, tmp1, tmp2)); 3068 emit_insn (gen_lui_h_hi12 (tmp1, tmp1, tmp2)); 3069 } 3070 } 3071 else 3072 emit_insn (loongarch_load_tls (tmp1, tmp2, SYMBOL_TLS_LE)); 3073 emit_insn (gen_add3_insn (dest, tmp1, tp)); 3074 } 3075 break; 3076 3077 default: 3078 gcc_unreachable (); 3079 } 3080 return dest; 3081 } 3082 3083 rtx 3084 loongarch_legitimize_call_address (rtx addr) 3085 { 3086 if (!call_insn_operand (addr, VOIDmode)) 3087 { 3088 rtx reg = gen_reg_rtx (Pmode); 3089 loongarch_emit_move (reg, addr); 3090 return reg; 3091 } 3092 3093 enum loongarch_symbol_type symbol_type = loongarch_classify_symbol (addr); 3094 3095 /* If add the compilation option '-cmodel=medium', and the assembler does 3096 not support call36. The following sequence of instructions will be 3097 used for the function call: 3098 pcalau12i $rd, %pc_hi20(sym) 3099 jr $rd, %pc_lo12(sym) 3100 */ 3101 3102 if (TARGET_CMODEL_MEDIUM 3103 && !HAVE_AS_SUPPORT_CALL36 3104 && (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE) 3105 && (SYMBOL_REF_P (addr) || LABEL_REF_P (addr)) 3106 && (symbol_type == SYMBOL_PCREL 3107 || (symbol_type == SYMBOL_GOT_DISP && flag_plt))) 3108 { 3109 rtx reg = gen_reg_rtx (Pmode); 3110 emit_insn (gen_pcalau12i (Pmode, reg, addr)); 3111 return gen_rtx_LO_SUM (Pmode, reg, addr); 3112 } 3113 3114 return addr; 3115 } 3116 3117 /* If X is a PLUS of a CONST_INT, return the two terms in *BASE_PTR 3118 and *OFFSET_PTR. Return X in *BASE_PTR and 0 in *OFFSET_PTR otherwise. */ 3119 3120 static void 3121 loongarch_split_plus (rtx x, rtx *base_ptr, HOST_WIDE_INT *offset_ptr) 3122 { 3123 if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1))) 3124 { 3125 *base_ptr = XEXP (x, 0); 3126 *offset_ptr = INTVAL (XEXP (x, 1)); 3127 } 3128 else 3129 { 3130 *base_ptr = x; 3131 *offset_ptr = 0; 3132 } 3133 } 3134 3135 /* If X is not a valid address for mode MODE, force it into a register. */ 3136 3137 static rtx 3138 loongarch_force_address (rtx x, machine_mode mode) 3139 { 3140 if (!loongarch_legitimate_address_p (mode, x, false)) 3141 x = force_reg (Pmode, x); 3142 return x; 3143 } 3144 3145 bool 3146 loongarch_symbol_extreme_p (enum loongarch_symbol_type type) 3147 { 3148 switch (type) 3149 { 3150 case SYMBOL_PCREL: 3151 return false; 3152 case SYMBOL_PCREL64: 3153 return true; 3154 default: 3155 return TARGET_CMODEL_EXTREME; 3156 } 3157 } 3158 3159 /* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise 3160 it appears in a MEM of that mode. Return true if ADDR is a legitimate 3161 constant in that context and can be split into high and low parts. 3162 If so, and if LOW_OUT is nonnull, emit the high part and store the 3163 low part in *LOW_OUT. Leave *LOW_OUT unchanged otherwise. 3164 3165 Return false if build with '-mexplicit-relocs=none'. 3166 3167 TEMP is as for loongarch_force_temporary and is used to load the high 3168 part into a register. 3169 3170 When MODE is MAX_MACHINE_MODE, the low part is guaranteed to be 3171 a legitimize SET_SRC for an .md pattern, otherwise the low part 3172 is guaranteed to be a legitimate address for mode MODE. */ 3173 3174 bool 3175 loongarch_split_symbol (rtx temp, rtx addr, machine_mode mode, rtx *low_out) 3176 { 3177 enum loongarch_symbol_type symbol_type; 3178 3179 if ((GET_CODE (addr) == HIGH && mode == MAX_MACHINE_MODE) 3180 || !loongarch_symbolic_constant_p (addr, &symbol_type) 3181 || !loongarch_explicit_relocs_p (symbol_type) 3182 || loongarch_symbol_insns (symbol_type, mode) == 0 3183 || !loongarch_split_symbol_type (symbol_type)) 3184 return false; 3185 3186 rtx high; 3187 3188 if (temp == NULL) 3189 temp = gen_reg_rtx (Pmode); 3190 3191 if (loongarch_symbol_extreme_p (symbol_type) && can_create_pseudo_p ()) 3192 { 3193 gcc_assert (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE); 3194 3195 high = gen_reg_rtx (Pmode); 3196 emit_insn (gen_la_pcrel64_two_parts (high, temp, addr)); 3197 } 3198 else 3199 { 3200 /* Get the 12-31 bits of the address. */ 3201 high = gen_rtx_HIGH (Pmode, copy_rtx (addr)); 3202 high = loongarch_force_temporary (temp, high); 3203 } 3204 3205 if (low_out) 3206 switch (symbol_type) 3207 { 3208 case SYMBOL_PCREL64: 3209 if (can_create_pseudo_p ()) 3210 { 3211 *low_out = gen_rtx_PLUS (Pmode, high, temp); 3212 break; 3213 } 3214 /* fall through */ 3215 case SYMBOL_PCREL: 3216 *low_out = gen_rtx_LO_SUM (Pmode, high, addr); 3217 break; 3218 3219 case SYMBOL_GOT_DISP: 3220 /* SYMBOL_GOT_DISP symbols are loaded from the GOT. */ 3221 { 3222 if (TARGET_CMODEL_EXTREME && can_create_pseudo_p ()) 3223 *low_out = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, high, 3224 temp)); 3225 else 3226 { 3227 rtx low = gen_rtx_LO_SUM (Pmode, high, addr); 3228 rtx mem = gen_rtx_MEM (Pmode, low); 3229 *low_out = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, mem), 3230 UNSPEC_LOAD_FROM_GOT); 3231 3232 /* Nonzero in a mem, if the memory is statically allocated and 3233 read-only. A common example of the later is a shared librarys 3234 global offset table. */ 3235 MEM_READONLY_P (mem) = 1; 3236 } 3237 3238 break; 3239 } 3240 3241 default: 3242 gcc_unreachable (); 3243 } 3244 3245 return true; 3246 } 3247 3248 /* Helper loongarch_legitimize_address. Given X, return true if it 3249 is a left shift by 1, 2 or 3 positions or a multiply by 2, 4 or 8. 3250 3251 This respectively represent canonical shift-add rtxs or scaled 3252 memory addresses. */ 3253 static bool 3254 mem_shadd_or_shadd_rtx_p (rtx x) 3255 { 3256 return ((GET_CODE (x) == ASHIFT 3257 || GET_CODE (x) == MULT) 3258 && CONST_INT_P (XEXP (x, 1)) 3259 && ((GET_CODE (x) == ASHIFT && IN_RANGE (INTVAL (XEXP (x, 1)), 1, 3)) 3260 || (GET_CODE (x) == MULT 3261 && IN_RANGE (exact_log2 (INTVAL (XEXP (x, 1))), 1, 3)))); 3262 } 3263 3264 /* This function is used to implement LEGITIMIZE_ADDRESS. If X can 3265 be legitimized in a way that the generic machinery might not expect, 3266 return a new address, otherwise return NULL. MODE is the mode of 3267 the memory being accessed. */ 3268 3269 static rtx 3270 loongarch_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, 3271 machine_mode mode) 3272 { 3273 rtx base, addr; 3274 HOST_WIDE_INT offset; 3275 3276 if (loongarch_tls_symbol_p (x)) 3277 return loongarch_legitimize_tls_address (x); 3278 3279 /* See if the address can split into a high part and a LO_SUM. */ 3280 if (loongarch_split_symbol (NULL, x, mode, &addr)) 3281 return loongarch_force_address (addr, mode); 3282 3283 /* Handle BASE + OFFSET using loongarch_add_offset. */ 3284 loongarch_split_plus (x, &base, &offset); 3285 if (offset != 0) 3286 { 3287 /* Handle (plus (plus (mult (a) (mem_shadd_constant)) (fp)) (C)) case. */ 3288 if (GET_CODE (base) == PLUS && mem_shadd_or_shadd_rtx_p (XEXP (base, 0)) 3289 && IMM12_OPERAND (offset)) 3290 { 3291 rtx index = XEXP (base, 0); 3292 rtx fp = XEXP (base, 1); 3293 3294 if (REG_P (fp) && REGNO (fp) == VIRTUAL_STACK_VARS_REGNUM) 3295 { 3296 /* If we were given a MULT, we must fix the constant 3297 as we're going to create the ASHIFT form. */ 3298 int shift_val = INTVAL (XEXP (index, 1)); 3299 if (GET_CODE (index) == MULT) 3300 shift_val = exact_log2 (shift_val); 3301 3302 rtx reg1 = gen_reg_rtx (Pmode); 3303 rtx reg3 = gen_reg_rtx (Pmode); 3304 loongarch_emit_binary (PLUS, reg1, fp, GEN_INT (offset)); 3305 loongarch_emit_binary (PLUS, reg3, 3306 gen_rtx_ASHIFT (Pmode, XEXP (index, 0), 3307 GEN_INT (shift_val)), 3308 reg1); 3309 3310 return reg3; 3311 } 3312 } 3313 3314 if (!loongarch_valid_base_register_p (base, mode, false)) 3315 base = copy_to_mode_reg (Pmode, base); 3316 addr = loongarch_add_offset (NULL, base, offset); 3317 return loongarch_force_address (addr, mode); 3318 } 3319 3320 return x; 3321 } 3322 3323 /* Load VALUE into DEST. TEMP is as for loongarch_force_temporary. */ 3324 3325 void 3326 loongarch_move_integer (rtx temp, rtx dest, unsigned HOST_WIDE_INT value) 3327 { 3328 struct loongarch_integer_op codes[LARCH_MAX_INTEGER_OPS]; 3329 machine_mode mode; 3330 unsigned int i, num_ops; 3331 rtx x; 3332 3333 mode = GET_MODE (dest); 3334 num_ops = loongarch_build_integer (codes, value); 3335 3336 /* Apply each binary operation to X. Invariant: X is a legitimate 3337 source operand for a SET pattern. */ 3338 x = GEN_INT (codes[0].value); 3339 for (i = 1; i < num_ops; i++) 3340 { 3341 if (!can_create_pseudo_p ()) 3342 { 3343 emit_insn (gen_rtx_SET (temp, x)); 3344 x = temp; 3345 } 3346 else 3347 x = force_reg (mode, x); 3348 3349 set_unique_reg_note (get_last_insn (), REG_EQUAL, 3350 GEN_INT (codes[i-1].curr_value)); 3351 3352 switch (codes[i].method) 3353 { 3354 case METHOD_NORMAL: 3355 x = gen_rtx_fmt_ee (codes[i].code, mode, x, 3356 GEN_INT (codes[i].value)); 3357 break; 3358 case METHOD_LU32I: 3359 gcc_assert (mode == DImode); 3360 x = gen_rtx_IOR (DImode, 3361 gen_rtx_ZERO_EXTEND (DImode, 3362 gen_rtx_SUBREG (SImode, x, 0)), 3363 GEN_INT (codes[i].value)); 3364 break; 3365 case METHOD_LU52I: 3366 gcc_assert (mode == DImode); 3367 x = gen_rtx_IOR (DImode, 3368 gen_rtx_AND (DImode, x, GEN_INT (0xfffffffffffff)), 3369 GEN_INT (codes[i].value)); 3370 break; 3371 case METHOD_MIRROR: 3372 gcc_assert (mode == DImode); 3373 emit_insn (gen_insvdi (x, GEN_INT (32), GEN_INT (32), x)); 3374 break; 3375 default: 3376 gcc_unreachable (); 3377 } 3378 } 3379 3380 emit_insn (gen_rtx_SET (dest, x)); 3381 } 3382 3383 /* Subroutine of loongarch_legitimize_move. Move constant SRC into register 3384 DEST given that SRC satisfies immediate_operand but doesn't satisfy 3385 move_operand. */ 3386 3387 static void 3388 loongarch_legitimize_const_move (machine_mode mode, rtx dest, rtx src) 3389 { 3390 rtx base, offset; 3391 3392 /* Split moves of big integers into smaller pieces. */ 3393 if (splittable_const_int_operand (src, mode)) 3394 { 3395 loongarch_move_integer (dest, dest, INTVAL (src)); 3396 return; 3397 } 3398 3399 /* Split moves of symbolic constants into high and low. */ 3400 if (loongarch_split_symbol (dest, src, MAX_MACHINE_MODE, &src)) 3401 { 3402 loongarch_emit_set (dest, src); 3403 return; 3404 } 3405 3406 /* Generate the appropriate access sequences for TLS symbols. */ 3407 if (loongarch_tls_symbol_p (src)) 3408 { 3409 loongarch_emit_move (dest, loongarch_legitimize_tls_address (src)); 3410 return; 3411 } 3412 3413 /* If we have (const (plus symbol offset)), and that expression cannot 3414 be forced into memory, load the symbol first and add in the offset. 3415 prefer to do this even if the constant _can_ be forced into memory, 3416 as it usually produces better code. */ 3417 split_const (src, &base, &offset); 3418 if (offset != const0_rtx 3419 && (targetm.cannot_force_const_mem (mode, src) 3420 || (can_create_pseudo_p ()))) 3421 { 3422 base = loongarch_force_temporary (dest, base); 3423 loongarch_emit_move (dest, 3424 loongarch_add_offset (NULL, base, INTVAL (offset))); 3425 return; 3426 } 3427 3428 src = force_const_mem (mode, src); 3429 3430 loongarch_emit_move (dest, src); 3431 } 3432 3433 /* If (set DEST SRC) is not a valid move instruction, emit an equivalent 3434 sequence that is valid. */ 3435 3436 bool 3437 loongarch_legitimize_move (machine_mode mode, rtx dest, rtx src) 3438 { 3439 if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode)) 3440 { 3441 loongarch_emit_move (dest, force_reg (mode, src)); 3442 return true; 3443 } 3444 3445 /* Both src and dest are non-registers; one special case is supported where 3446 the source is (const_int 0) and the store can source the zero register. 3447 LSX and LASX are never able to source the zero register directly in 3448 memory operations. */ 3449 if (!register_operand (dest, mode) && !register_operand (src, mode) 3450 && (!const_0_operand (src, mode) 3451 || LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode))) 3452 { 3453 loongarch_emit_move (dest, force_reg (mode, src)); 3454 return true; 3455 } 3456 3457 /* We need to deal with constants that would be legitimate 3458 immediate_operands but aren't legitimate move_operands. */ 3459 if (CONSTANT_P (src) && !move_operand (src, mode)) 3460 { 3461 loongarch_legitimize_const_move (mode, dest, src); 3462 set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src)); 3463 return true; 3464 } 3465 3466 /* Obtain the address of the symbol through the macro instruction 3467 of two registers. */ 3468 enum loongarch_symbol_type symbol_type; 3469 if (TARGET_64BIT && register_operand (dest, mode) 3470 && loongarch_symbolic_constant_p (src, &symbol_type) 3471 && loongarch_symbol_extreme_p (symbol_type)) 3472 { 3473 gcc_assert (can_create_pseudo_p ()); 3474 rtx tmp_reg = gen_reg_rtx (DImode); 3475 emit_insn (gen_movdi_symbolic_off64 (dest, src, tmp_reg)); 3476 set_unique_reg_note (get_last_insn (), REG_UNUSED, tmp_reg); 3477 set_unique_reg_note (get_last_insn (), REG_EQUAL, src); 3478 return true; 3479 } 3480 3481 return false; 3482 } 3483 3484 /* Return true if OP refers to small data symbols directly. */ 3485 3486 static int 3487 loongarch_small_data_pattern_1 (rtx x) 3488 { 3489 subrtx_var_iterator::array_type array; 3490 FOR_EACH_SUBRTX_VAR (iter, array, x, ALL) 3491 { 3492 rtx x = *iter; 3493 3494 /* We make no particular guarantee about which symbolic constants are 3495 acceptable as asm operands versus which must be forced into a GPR. */ 3496 if (GET_CODE (x) == ASM_OPERANDS) 3497 iter.skip_subrtxes (); 3498 else if (MEM_P (x)) 3499 { 3500 if (loongarch_small_data_pattern_1 (XEXP (x, 0))) 3501 return true; 3502 iter.skip_subrtxes (); 3503 } 3504 } 3505 return false; 3506 } 3507 3508 /* Return true if OP refers to small data symbols directly. */ 3509 3510 bool 3511 loongarch_small_data_pattern_p (rtx op) 3512 { 3513 return loongarch_small_data_pattern_1 (op); 3514 } 3515 3516 /* Rewrite *LOC so that it refers to small data using explicit 3517 relocations. */ 3518 3519 static void 3520 loongarch_rewrite_small_data_1 (rtx *loc) 3521 { 3522 subrtx_ptr_iterator::array_type array; 3523 FOR_EACH_SUBRTX_PTR (iter, array, loc, ALL) 3524 { 3525 rtx *loc = *iter; 3526 if (MEM_P (*loc)) 3527 { 3528 loongarch_rewrite_small_data_1 (&XEXP (*loc, 0)); 3529 iter.skip_subrtxes (); 3530 } 3531 } 3532 } 3533 3534 /* Rewrite instruction pattern PATTERN so that it refers to small data 3535 using explicit relocations. */ 3536 3537 rtx 3538 loongarch_rewrite_small_data (rtx pattern) 3539 { 3540 pattern = copy_insn (pattern); 3541 loongarch_rewrite_small_data_1 (&pattern); 3542 return pattern; 3543 } 3544 3545 /* The cost of loading values from the constant pool. It should be 3546 larger than the cost of any constant we want to synthesize inline. */ 3547 #define CONSTANT_POOL_COST COSTS_N_INSNS (8) 3548 3549 /* Return true if there is a instruction that implements CODE 3550 and if that instruction accepts X as an immediate operand. */ 3551 3552 static int 3553 loongarch_immediate_operand_p (int code, HOST_WIDE_INT x) 3554 { 3555 switch (code) 3556 { 3557 case ASHIFT: 3558 case ASHIFTRT: 3559 case LSHIFTRT: 3560 /* All shift counts are truncated to a valid constant. */ 3561 return true; 3562 3563 case ROTATE: 3564 case ROTATERT: 3565 return true; 3566 3567 case AND: 3568 case IOR: 3569 case XOR: 3570 /* These instructions take 12-bit unsigned immediates. */ 3571 return IMM12_OPERAND_UNSIGNED (x); 3572 3573 case PLUS: 3574 case LT: 3575 case LTU: 3576 /* These instructions take 12-bit signed immediates. */ 3577 return IMM12_OPERAND (x); 3578 3579 case EQ: 3580 case NE: 3581 case GT: 3582 case GTU: 3583 /* The "immediate" forms of these instructions are really 3584 implemented as comparisons with register 0. */ 3585 return x == 0; 3586 3587 case GE: 3588 case GEU: 3589 /* Likewise, meaning that the only valid immediate operand is 1. */ 3590 return x == 1; 3591 3592 case LE: 3593 /* We add 1 to the immediate and use SLT. */ 3594 return IMM12_OPERAND (x + 1); 3595 3596 case LEU: 3597 /* Likewise SLTU, but reject the always-true case. */ 3598 return IMM12_OPERAND (x + 1) && x + 1 != 0; 3599 3600 case SIGN_EXTRACT: 3601 case ZERO_EXTRACT: 3602 /* The bit position and size are immediate operands. */ 3603 return 1; 3604 3605 default: 3606 /* By default assume that $0 can be used for 0. */ 3607 return x == 0; 3608 } 3609 } 3610 3611 /* Return the cost of binary operation X, given that the instruction 3612 sequence for a word-sized or smaller operation has cost SINGLE_COST 3613 and that the sequence of a double-word operation has cost DOUBLE_COST. 3614 If SPEED is true, optimize for speed otherwise optimize for size. */ 3615 3616 static int 3617 loongarch_binary_cost (rtx x, int single_cost, int double_cost, bool speed) 3618 { 3619 int cost; 3620 3621 if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD * 2) 3622 cost = double_cost; 3623 else 3624 cost = single_cost; 3625 return (cost 3626 + set_src_cost (XEXP (x, 0), GET_MODE (x), speed) 3627 + rtx_cost (XEXP (x, 1), GET_MODE (x), GET_CODE (x), 1, speed)); 3628 } 3629 3630 /* Return the cost of floating-point multiplications of mode MODE. */ 3631 3632 static int 3633 loongarch_fp_mult_cost (machine_mode mode) 3634 { 3635 return mode == DFmode ? loongarch_cost->fp_mult_df 3636 : loongarch_cost->fp_mult_sf; 3637 } 3638 3639 /* Return the cost of floating-point divisions of mode MODE. */ 3640 3641 static int 3642 loongarch_fp_div_cost (machine_mode mode) 3643 { 3644 return mode == DFmode ? loongarch_cost->fp_div_df 3645 : loongarch_cost->fp_div_sf; 3646 } 3647 3648 /* Return the cost of sign-extending OP to mode MODE, not including the 3649 cost of OP itself. */ 3650 3651 static int 3652 loongarch_sign_extend_cost (rtx op) 3653 { 3654 if (MEM_P (op)) 3655 /* Extended loads are as cheap as unextended ones. */ 3656 return 0; 3657 3658 return COSTS_N_INSNS (1); 3659 } 3660 3661 /* Return the cost of zero-extending OP to mode MODE, not including the 3662 cost of OP itself. */ 3663 3664 static int 3665 loongarch_zero_extend_cost (rtx op) 3666 { 3667 if (MEM_P (op)) 3668 /* Extended loads are as cheap as unextended ones. */ 3669 return 0; 3670 3671 /* We can use ANDI. */ 3672 return COSTS_N_INSNS (1); 3673 } 3674 3675 /* Return the cost of moving between two registers of mode MODE, 3676 assuming that the move will be in pieces of at most UNITS bytes. */ 3677 3678 static int 3679 loongarch_set_reg_reg_piece_cost (machine_mode mode, unsigned int units) 3680 { 3681 return COSTS_N_INSNS ((GET_MODE_SIZE (mode) + units - 1) / units); 3682 } 3683 3684 /* Return the cost of moving between two registers of mode MODE. */ 3685 3686 static int 3687 loongarch_set_reg_reg_cost (machine_mode mode) 3688 { 3689 switch (GET_MODE_CLASS (mode)) 3690 { 3691 case MODE_CC: 3692 return loongarch_set_reg_reg_piece_cost (mode, GET_MODE_SIZE (CCmode)); 3693 3694 case MODE_FLOAT: 3695 case MODE_COMPLEX_FLOAT: 3696 case MODE_VECTOR_FLOAT: 3697 if (TARGET_HARD_FLOAT) 3698 return loongarch_set_reg_reg_piece_cost (mode, UNITS_PER_HWFPVALUE); 3699 /* Fall through. */ 3700 3701 default: 3702 return loongarch_set_reg_reg_piece_cost (mode, UNITS_PER_WORD); 3703 } 3704 } 3705 3706 /* Implement TARGET_RTX_COSTS. */ 3707 3708 static bool 3709 loongarch_rtx_costs (rtx x, machine_mode mode, int outer_code, 3710 int opno ATTRIBUTE_UNUSED, int *total, bool speed) 3711 { 3712 int code = GET_CODE (x); 3713 bool float_mode_p = FLOAT_MODE_P (mode); 3714 int cost; 3715 rtx addr; 3716 3717 if (outer_code == COMPARE) 3718 { 3719 gcc_assert (CONSTANT_P (x)); 3720 *total = 0; 3721 return true; 3722 } 3723 3724 switch (code) 3725 { 3726 case CONST_INT: 3727 if (TARGET_64BIT && outer_code == AND && UINTVAL (x) == 0xffffffff) 3728 { 3729 *total = 0; 3730 return true; 3731 } 3732 3733 /* When not optimizing for size, we care more about the cost 3734 of hot code, and hot code is often in a loop. If a constant 3735 operand needs to be forced into a register, we will often be 3736 able to hoist the constant load out of the loop, so the load 3737 should not contribute to the cost. */ 3738 if (speed || loongarch_immediate_operand_p (outer_code, INTVAL (x))) 3739 { 3740 *total = 0; 3741 return true; 3742 } 3743 /* Fall through. */ 3744 3745 case CONST: 3746 case SYMBOL_REF: 3747 case LABEL_REF: 3748 case CONST_DOUBLE: 3749 cost = loongarch_const_insns (x); 3750 if (cost > 0) 3751 { 3752 if (cost == 1 && outer_code == SET 3753 && !(float_mode_p && TARGET_HARD_FLOAT)) 3754 cost = 0; 3755 else if ((outer_code == SET || GET_MODE (x) == VOIDmode)) 3756 cost = 1; 3757 *total = COSTS_N_INSNS (cost); 3758 return true; 3759 } 3760 /* The value will need to be fetched from the constant pool. */ 3761 *total = CONSTANT_POOL_COST; 3762 return true; 3763 3764 case MEM: 3765 /* If the address is legitimate, return the number of 3766 instructions it needs. */ 3767 addr = XEXP (x, 0); 3768 /* Check for a scaled indexed address. */ 3769 if (loongarch_index_address_p (addr, mode)) 3770 { 3771 *total = COSTS_N_INSNS (2); 3772 return true; 3773 } 3774 cost = loongarch_address_insns (addr, mode, true); 3775 if (cost > 0) 3776 { 3777 *total = COSTS_N_INSNS (cost + 1); 3778 return true; 3779 } 3780 /* Otherwise use the default handling. */ 3781 return false; 3782 3783 case FFS: 3784 *total = COSTS_N_INSNS (6); 3785 return false; 3786 3787 case NOT: 3788 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1); 3789 return false; 3790 3791 case AND: 3792 /* Check for a *clear_upper32 pattern and treat it like a zero 3793 extension. See the pattern's comment for details. */ 3794 if (TARGET_64BIT && mode == DImode && CONST_INT_P (XEXP (x, 1)) 3795 && UINTVAL (XEXP (x, 1)) == 0xffffffff) 3796 { 3797 *total = (loongarch_zero_extend_cost (XEXP (x, 0)) 3798 + set_src_cost (XEXP (x, 0), mode, speed)); 3799 return true; 3800 } 3801 /* (AND (NOT op0) (NOT op1) is a nor operation that can be done in 3802 a single instruction. */ 3803 if (GET_CODE (XEXP (x, 0)) == NOT && GET_CODE (XEXP (x, 1)) == NOT) 3804 { 3805 cost = GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1; 3806 *total = (COSTS_N_INSNS (cost) 3807 + set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed) 3808 + set_src_cost (XEXP (XEXP (x, 1), 0), mode, speed)); 3809 return true; 3810 } 3811 3812 /* Fall through. */ 3813 3814 case IOR: 3815 case XOR: 3816 /* Double-word operations use two single-word operations. */ 3817 *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (2), 3818 speed); 3819 return true; 3820 3821 case ASHIFT: 3822 case ASHIFTRT: 3823 case LSHIFTRT: 3824 case ROTATE: 3825 case ROTATERT: 3826 if (CONSTANT_P (XEXP (x, 1))) 3827 *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), 3828 COSTS_N_INSNS (4), speed); 3829 else 3830 *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), 3831 COSTS_N_INSNS (12), speed); 3832 return true; 3833 3834 case ABS: 3835 if (float_mode_p) 3836 *total = loongarch_cost->fp_add; 3837 else 3838 *total = COSTS_N_INSNS (4); 3839 return false; 3840 3841 case LT: 3842 case LTU: 3843 case LE: 3844 case LEU: 3845 case GT: 3846 case GTU: 3847 case GE: 3848 case GEU: 3849 case EQ: 3850 case NE: 3851 case UNORDERED: 3852 case LTGT: 3853 case UNGE: 3854 case UNGT: 3855 case UNLE: 3856 case UNLT: 3857 /* Branch comparisons have VOIDmode, so use the first operand's 3858 mode instead. */ 3859 mode = GET_MODE (XEXP (x, 0)); 3860 if (FLOAT_MODE_P (mode)) 3861 { 3862 *total = loongarch_cost->fp_add; 3863 return false; 3864 } 3865 *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (4), 3866 speed); 3867 return true; 3868 3869 case MINUS: 3870 case PLUS: 3871 if (float_mode_p) 3872 { 3873 *total = loongarch_cost->fp_add; 3874 return false; 3875 } 3876 3877 /* If it's an add + mult (which is equivalent to shift left) and 3878 it's immediate operand satisfies const_immalsl_operand predicate. */ 3879 if ((mode == SImode || (TARGET_64BIT && mode == DImode)) 3880 && GET_CODE (XEXP (x, 0)) == MULT) 3881 { 3882 rtx op2 = XEXP (XEXP (x, 0), 1); 3883 if (const_immalsl_operand (op2, mode)) 3884 { 3885 *total = (COSTS_N_INSNS (1) 3886 + set_src_cost (XEXP (XEXP (x, 0), 0), mode, speed) 3887 + set_src_cost (XEXP (x, 1), mode, speed)); 3888 return true; 3889 } 3890 } 3891 3892 /* Double-word operations require three single-word operations and 3893 an SLTU. */ 3894 *total = loongarch_binary_cost (x, COSTS_N_INSNS (1), COSTS_N_INSNS (4), 3895 speed); 3896 return true; 3897 3898 case NEG: 3899 if (float_mode_p) 3900 *total = loongarch_cost->fp_add; 3901 else 3902 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1); 3903 return false; 3904 3905 case FMA: 3906 *total = loongarch_fp_mult_cost (mode); 3907 return false; 3908 3909 case MULT: 3910 if (float_mode_p) 3911 *total = loongarch_fp_mult_cost (mode); 3912 else if (mode == DImode && !TARGET_64BIT) 3913 *total = (speed 3914 ? loongarch_cost->int_mult_si * 3 + 6 3915 : COSTS_N_INSNS (7)); 3916 else if (mode == DImode) 3917 *total = loongarch_cost->int_mult_di; 3918 else 3919 *total = loongarch_cost->int_mult_si; 3920 return false; 3921 3922 case DIV: 3923 /* Check for a reciprocal. */ 3924 if (float_mode_p 3925 && flag_unsafe_math_optimizations 3926 && XEXP (x, 0) == CONST1_RTX (mode)) 3927 { 3928 if (outer_code == SQRT || GET_CODE (XEXP (x, 1)) == SQRT) 3929 /* An rsqrt<mode>a or rsqrt<mode>b pattern. Count the 3930 division as being free. */ 3931 *total = set_src_cost (XEXP (x, 1), mode, speed); 3932 else 3933 *total = (loongarch_fp_div_cost (mode) 3934 + set_src_cost (XEXP (x, 1), mode, speed)); 3935 return true; 3936 } 3937 /* Fall through. */ 3938 3939 case SQRT: 3940 case MOD: 3941 if (float_mode_p) 3942 { 3943 *total = loongarch_fp_div_cost (mode); 3944 return false; 3945 } 3946 /* Fall through. */ 3947 3948 case UDIV: 3949 case UMOD: 3950 if (mode == DImode) 3951 *total = loongarch_cost->int_div_di; 3952 else 3953 { 3954 *total = loongarch_cost->int_div_si; 3955 if (TARGET_64BIT && !ISA_HAS_DIV32) 3956 *total += COSTS_N_INSNS (2); 3957 } 3958 3959 if (TARGET_CHECK_ZERO_DIV) 3960 *total += COSTS_N_INSNS (2); 3961 3962 return false; 3963 3964 case SIGN_EXTEND: 3965 *total = loongarch_sign_extend_cost (XEXP (x, 0)); 3966 return false; 3967 3968 case ZERO_EXTEND: 3969 *total = loongarch_zero_extend_cost (XEXP (x, 0)); 3970 return false; 3971 case TRUNCATE: 3972 /* Costings for highpart multiplies. Matching patterns of the form: 3973 3974 (lshiftrt:DI (mult:DI (sign_extend:DI (...) 3975 (sign_extend:DI (...)) 3976 (const_int 32) 3977 */ 3978 if ((GET_CODE (XEXP (x, 0)) == ASHIFTRT 3979 || GET_CODE (XEXP (x, 0)) == LSHIFTRT) 3980 && CONST_INT_P (XEXP (XEXP (x, 0), 1)) 3981 && ((INTVAL (XEXP (XEXP (x, 0), 1)) == 32 3982 && GET_MODE (XEXP (x, 0)) == DImode) 3983 || (TARGET_64BIT 3984 && INTVAL (XEXP (XEXP (x, 0), 1)) == 64 3985 && GET_MODE (XEXP (x, 0)) == TImode)) 3986 && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT 3987 && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND 3988 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == SIGN_EXTEND) 3989 || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND 3990 && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) 3991 == ZERO_EXTEND)))) 3992 { 3993 if (mode == DImode) 3994 *total = loongarch_cost->int_mult_di; 3995 else 3996 *total = loongarch_cost->int_mult_si; 3997 3998 /* Sign extension is free, zero extension costs for DImode when 3999 on a 64bit core / when DMUL is present. */ 4000 for (int i = 0; i < 2; ++i) 4001 { 4002 rtx op = XEXP (XEXP (XEXP (x, 0), 0), i); 4003 if (TARGET_64BIT 4004 && GET_CODE (op) == ZERO_EXTEND 4005 && GET_MODE (op) == DImode) 4006 *total += rtx_cost (op, DImode, MULT, i, speed); 4007 else 4008 *total += rtx_cost (XEXP (op, 0), VOIDmode, GET_CODE (op), 0, 4009 speed); 4010 } 4011 4012 return true; 4013 } 4014 return false; 4015 4016 case FLOAT: 4017 case UNSIGNED_FLOAT: 4018 case FIX: 4019 case FLOAT_EXTEND: 4020 case FLOAT_TRUNCATE: 4021 *total = loongarch_cost->fp_add; 4022 return false; 4023 4024 case SET: 4025 if (register_operand (SET_DEST (x), VOIDmode) 4026 && reg_or_0_operand (SET_SRC (x), VOIDmode)) 4027 { 4028 *total = loongarch_set_reg_reg_cost (GET_MODE (SET_DEST (x))); 4029 return true; 4030 } 4031 return false; 4032 4033 default: 4034 return false; 4035 } 4036 } 4037 4038 /* Implement targetm.vectorize.builtin_vectorization_cost. */ 4039 4040 static int 4041 loongarch_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost, 4042 tree vectype, 4043 int misalign ATTRIBUTE_UNUSED) 4044 { 4045 unsigned elements; 4046 machine_mode mode = vectype != NULL ? TYPE_MODE (vectype) : DImode; 4047 4048 switch (type_of_cost) 4049 { 4050 case scalar_stmt: 4051 case scalar_load: 4052 case vector_stmt: 4053 case vec_to_scalar: 4054 case scalar_to_vec: 4055 case scalar_store: 4056 return 1; 4057 4058 case vec_promote_demote: 4059 case vec_perm: 4060 return LASX_SUPPORTED_MODE_P (mode) 4061 && !LSX_SUPPORTED_MODE_P (mode) ? 2 : 1; 4062 4063 case vector_load: 4064 case vector_store: 4065 case unaligned_load: 4066 case unaligned_store: 4067 return 2; 4068 4069 case cond_branch_taken: 4070 return 4; 4071 4072 case cond_branch_not_taken: 4073 return 2; 4074 4075 case vec_construct: 4076 elements = TYPE_VECTOR_SUBPARTS (vectype); 4077 if (ISA_HAS_LASX) 4078 return elements + 1; 4079 else 4080 return elements; 4081 4082 default: 4083 gcc_unreachable (); 4084 } 4085 } 4086 4087 class loongarch_vector_costs : public vector_costs 4088 { 4089 public: 4090 using vector_costs::vector_costs; 4091 4092 unsigned int add_stmt_cost (int count, vect_cost_for_stmt kind, 4093 stmt_vec_info stmt_info, slp_tree, tree vectype, 4094 int misalign, 4095 vect_cost_model_location where) override; 4096 void finish_cost (const vector_costs *) override; 4097 4098 protected: 4099 void count_operations (vect_cost_for_stmt, stmt_vec_info, 4100 vect_cost_model_location, unsigned int); 4101 unsigned int determine_suggested_unroll_factor (loop_vec_info); 4102 /* The number of vectorized stmts in loop. */ 4103 unsigned m_stmts = 0; 4104 /* The number of load and store operations in loop. */ 4105 unsigned m_loads = 0; 4106 unsigned m_stores = 0; 4107 /* Reduction factor for suggesting unroll factor. */ 4108 unsigned m_reduc_factor = 0; 4109 /* True if the loop contains an average operation. */ 4110 bool m_has_avg = false; 4111 /* True if the loop uses approximation instruction sequence. */ 4112 bool m_has_recip = false; 4113 }; 4114 4115 /* Implement TARGET_VECTORIZE_CREATE_COSTS. */ 4116 static vector_costs * 4117 loongarch_vectorize_create_costs (vec_info *vinfo, bool costing_for_scalar) 4118 { 4119 return new loongarch_vector_costs (vinfo, costing_for_scalar); 4120 } 4121 4122 void 4123 loongarch_vector_costs::count_operations (vect_cost_for_stmt kind, 4124 stmt_vec_info stmt_info, 4125 vect_cost_model_location where, 4126 unsigned int count) 4127 { 4128 if (!m_costing_for_scalar 4129 && is_a<loop_vec_info> (m_vinfo) 4130 && where == vect_body) 4131 { 4132 m_stmts += count; 4133 4134 if (kind == scalar_load 4135 || kind == vector_load 4136 || kind == unaligned_load) 4137 m_loads += count; 4138 else if (kind == scalar_store 4139 || kind == vector_store 4140 || kind == unaligned_store) 4141 m_stores += count; 4142 else if ((kind == scalar_stmt 4143 || kind == vector_stmt 4144 || kind == vec_to_scalar) 4145 && stmt_info && vect_is_reduction (stmt_info)) 4146 { 4147 tree lhs = gimple_get_lhs (stmt_info->stmt); 4148 unsigned int base = FLOAT_TYPE_P (TREE_TYPE (lhs)) ? 2 : 1; 4149 m_reduc_factor = MAX (base * count, m_reduc_factor); 4150 } 4151 } 4152 } 4153 4154 unsigned int 4155 loongarch_vector_costs::determine_suggested_unroll_factor (loop_vec_info loop_vinfo) 4156 { 4157 class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); 4158 4159 if (m_has_avg || m_has_recip) 4160 return 1; 4161 4162 /* Don't unroll if it's specified explicitly not to be unrolled. */ 4163 if (loop->unroll == 1 4164 || (OPTION_SET_P (flag_unroll_loops) && !flag_unroll_loops) 4165 || (OPTION_SET_P (flag_unroll_all_loops) && !flag_unroll_all_loops)) 4166 return 1; 4167 4168 unsigned int nstmts_nonldst = m_stmts - m_loads - m_stores; 4169 /* Don't unroll if no vector instructions excepting for memory access. */ 4170 if (nstmts_nonldst == 0) 4171 return 1; 4172 4173 /* Use this simple hardware resource model that how many non vld/vst 4174 vector instructions can be issued per cycle. */ 4175 unsigned int issue_info = la_vect_issue_info; 4176 unsigned int reduc_factor = m_reduc_factor > 1 ? m_reduc_factor : 1; 4177 unsigned int uf = CEIL (reduc_factor * issue_info, nstmts_nonldst); 4178 uf = MIN ((unsigned int) la_vect_unroll_limit, uf); 4179 4180 return 1 << ceil_log2 (uf); 4181 } 4182 4183 /* Check if assign stmt rhs op comes from a multiply-add operation. */ 4184 static bool 4185 loongarch_multiply_add_p (vec_info *vinfo, stmt_vec_info stmt_info) 4186 { 4187 gassign *assign = dyn_cast<gassign *> (stmt_info->stmt); 4188 if (!assign) 4189 return false; 4190 tree_code code = gimple_assign_rhs_code (assign); 4191 if (code != PLUS_EXPR && code != MINUS_EXPR) 4192 return false; 4193 4194 auto is_mul_result = [&](int i) 4195 { 4196 tree rhs = gimple_op (assign, i); 4197 if (TREE_CODE (rhs) != SSA_NAME) 4198 return false; 4199 4200 stmt_vec_info def_stmt_info = vinfo->lookup_def (rhs); 4201 if (!def_stmt_info 4202 || STMT_VINFO_DEF_TYPE (def_stmt_info) != vect_internal_def) 4203 return false; 4204 gassign *rhs_assign = dyn_cast<gassign *> (def_stmt_info->stmt); 4205 if (!rhs_assign || gimple_assign_rhs_code (rhs_assign) != MULT_EXPR) 4206 return false; 4207 4208 return true; 4209 }; 4210 4211 return is_mul_result (1) || is_mul_result (2); 4212 } 4213 4214 unsigned 4215 loongarch_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind, 4216 stmt_vec_info stmt_info, slp_tree, 4217 tree vectype, int misalign, 4218 vect_cost_model_location where) 4219 { 4220 unsigned retval = 0; 4221 4222 if (flag_vect_cost_model) 4223 { 4224 int stmt_cost = loongarch_builtin_vectorization_cost (kind, vectype, 4225 misalign); 4226 if (vectype && stmt_info) 4227 { 4228 gassign *assign = dyn_cast<gassign *> (STMT_VINFO_STMT (stmt_info)); 4229 machine_mode mode = TYPE_MODE (vectype); 4230 4231 /* We found through testing that this strategy (the stmt that 4232 matches the multiply-add pattern) has positive returns only 4233 when applied to the 128-bit vector stmt, so this restriction 4234 is currently made. */ 4235 if (kind == vector_stmt && GET_MODE_SIZE (mode) == 16 && assign) 4236 { 4237 if (!vect_is_reduction (stmt_info) 4238 && loongarch_multiply_add_p (m_vinfo, stmt_info)) 4239 stmt_cost = 0; 4240 } 4241 } 4242 4243 retval = adjust_cost_for_freq (stmt_info, where, count * stmt_cost); 4244 m_costs[where] += retval; 4245 4246 count_operations (kind, stmt_info, where, count); 4247 } 4248 4249 if (stmt_info) 4250 { 4251 /* Detect the use of an averaging operation. */ 4252 gimple *stmt = stmt_info->stmt; 4253 if (is_gimple_call (stmt) 4254 && gimple_call_internal_p (stmt)) 4255 { 4256 switch (gimple_call_internal_fn (stmt)) 4257 { 4258 case IFN_AVG_FLOOR: 4259 case IFN_AVG_CEIL: 4260 m_has_avg = true; 4261 default: 4262 break; 4263 } 4264 } 4265 } 4266 4267 combined_fn cfn; 4268 if (kind == vector_stmt 4269 && stmt_info 4270 && stmt_info->stmt) 4271 { 4272 /* Detect the use of approximate instruction sequence. */ 4273 if ((TARGET_RECIP_VEC_SQRT || TARGET_RECIP_VEC_RSQRT) 4274 && (cfn = gimple_call_combined_fn (stmt_info->stmt)) != CFN_LAST) 4275 switch (cfn) 4276 { 4277 case CFN_BUILT_IN_SQRTF: 4278 m_has_recip = true; 4279 default: 4280 break; 4281 } 4282 else if (TARGET_RECIP_VEC_DIV 4283 && gimple_code (stmt_info->stmt) == GIMPLE_ASSIGN) 4284 { 4285 machine_mode mode = TYPE_MODE (vectype); 4286 switch (gimple_assign_rhs_code (stmt_info->stmt)) 4287 { 4288 case RDIV_EXPR: 4289 if (GET_MODE_INNER (mode) == SFmode) 4290 m_has_recip = true; 4291 default: 4292 break; 4293 } 4294 } 4295 } 4296 4297 return retval; 4298 } 4299 4300 void 4301 loongarch_vector_costs::finish_cost (const vector_costs *scalar_costs) 4302 { 4303 loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (m_vinfo); 4304 if (loop_vinfo) 4305 { 4306 m_suggested_unroll_factor = determine_suggested_unroll_factor (loop_vinfo); 4307 } 4308 4309 vector_costs::finish_cost (scalar_costs); 4310 } 4311 4312 /* Implement TARGET_ADDRESS_COST. */ 4313 4314 static int 4315 loongarch_address_cost (rtx addr, machine_mode mode, 4316 addr_space_t as ATTRIBUTE_UNUSED, 4317 bool speed ATTRIBUTE_UNUSED) 4318 { 4319 return loongarch_address_insns (addr, mode, false); 4320 } 4321 4322 /* Return one word of double-word value OP, taking into account the fixed 4323 endianness of certain registers. HIGH_P is true to select the high part, 4324 false to select the low part. */ 4325 4326 rtx 4327 loongarch_subword (rtx op, bool high_p) 4328 { 4329 unsigned int byte; 4330 machine_mode mode; 4331 4332 byte = high_p ? UNITS_PER_WORD : 0; 4333 mode = GET_MODE (op); 4334 if (mode == VOIDmode) 4335 mode = TARGET_64BIT ? TImode : DImode; 4336 4337 if (FP_REG_RTX_P (op)) 4338 return gen_rtx_REG (word_mode, REGNO (op) + high_p); 4339 4340 if (MEM_P (op)) 4341 return loongarch_rewrite_small_data (adjust_address (op, word_mode, byte)); 4342 4343 return simplify_gen_subreg (word_mode, op, mode, byte); 4344 } 4345 4346 /* Return true if a move from SRC to DEST should be split into two. 4347 SPLIT_TYPE describes the split condition. */ 4348 4349 bool 4350 loongarch_split_move_p (rtx dest, rtx src) 4351 { 4352 /* FPR-to-FPR moves can be done in a single instruction, if they're 4353 allowed at all. */ 4354 unsigned int size = GET_MODE_SIZE (GET_MODE (dest)); 4355 if (size == 8 && FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) 4356 return false; 4357 4358 /* Check for floating-point loads and stores. */ 4359 if (size == 8) 4360 { 4361 if (FP_REG_RTX_P (dest) && MEM_P (src)) 4362 return false; 4363 if (FP_REG_RTX_P (src) && MEM_P (dest)) 4364 return false; 4365 } 4366 4367 /* Check if LSX moves need splitting. */ 4368 if (LSX_SUPPORTED_MODE_P (GET_MODE (dest))) 4369 return loongarch_split_128bit_move_p (dest, src); 4370 4371 /* Check if LASX moves need splitting. */ 4372 if (LASX_SUPPORTED_MODE_P (GET_MODE (dest))) 4373 return loongarch_split_256bit_move_p (dest, src); 4374 4375 /* Otherwise split all multiword moves. */ 4376 return size > UNITS_PER_WORD; 4377 } 4378 4379 /* Split a move from SRC to DEST, given that loongarch_split_move_p holds. 4380 SPLIT_TYPE describes the split condition. */ 4381 4382 void 4383 loongarch_split_move (rtx dest, rtx src) 4384 { 4385 rtx low_dest; 4386 4387 gcc_checking_assert (loongarch_split_move_p (dest, src)); 4388 if (LSX_SUPPORTED_MODE_P (GET_MODE (dest))) 4389 loongarch_split_128bit_move (dest, src); 4390 else if (LASX_SUPPORTED_MODE_P (GET_MODE (dest))) 4391 loongarch_split_256bit_move (dest, src); 4392 else if (FP_REG_RTX_P (dest) || FP_REG_RTX_P (src)) 4393 { 4394 if (!TARGET_64BIT && GET_MODE (dest) == DImode) 4395 emit_insn (gen_move_doubleword_fprdi (dest, src)); 4396 else if (!TARGET_64BIT && GET_MODE (dest) == DFmode) 4397 emit_insn (gen_move_doubleword_fprdf (dest, src)); 4398 else if (TARGET_64BIT && GET_MODE (dest) == TFmode) 4399 emit_insn (gen_move_doubleword_fprtf (dest, src)); 4400 else 4401 gcc_unreachable (); 4402 } 4403 else 4404 { 4405 /* The operation can be split into two normal moves. Decide in 4406 which order to do them. */ 4407 low_dest = loongarch_subword (dest, false); 4408 if (REG_P (low_dest) && reg_overlap_mentioned_p (low_dest, src)) 4409 { 4410 loongarch_emit_move (loongarch_subword (dest, true), 4411 loongarch_subword (src, true)); 4412 loongarch_emit_move (low_dest, loongarch_subword (src, false)); 4413 } 4414 else 4415 { 4416 loongarch_emit_move (low_dest, loongarch_subword (src, false)); 4417 loongarch_emit_move (loongarch_subword (dest, true), 4418 loongarch_subword (src, true)); 4419 } 4420 } 4421 } 4422 4423 /* Check if adding an integer constant value for a specific mode can be 4424 performed with an addu16i.d instruction and an addi.{w/d} 4425 instruction. */ 4426 4427 bool 4428 loongarch_addu16i_imm12_operand_p (HOST_WIDE_INT value, machine_mode mode) 4429 { 4430 /* Not necessary, but avoid unnecessary calculation if !TARGET_64BIT. */ 4431 if (!TARGET_64BIT) 4432 return false; 4433 4434 if ((value & 0xffff) == 0) 4435 return false; 4436 4437 if (IMM12_OPERAND (value)) 4438 return false; 4439 4440 value = (value & ~HWIT_UC_0xFFF) + ((value & 0x800) << 1); 4441 return ADDU16I_OPERAND (trunc_int_for_mode (value, mode)); 4442 } 4443 4444 /* Split one integer constant op[0] into two (op[1] and op[2]) for constant 4445 plus operation in a specific mode. The splitted constants can be added 4446 onto a register with a single instruction (addi.{d/w} or addu16i.d). */ 4447 4448 void 4449 loongarch_split_plus_constant (rtx *op, machine_mode mode) 4450 { 4451 HOST_WIDE_INT v = INTVAL (op[0]), a; 4452 4453 if (DUAL_IMM12_OPERAND (v)) 4454 a = (v > 0 ? 2047 : -2048); 4455 else if (loongarch_addu16i_imm12_operand_p (v, mode)) 4456 a = (v & ~HWIT_UC_0xFFF) + ((v & 0x800) << 1); 4457 else if (mode == DImode && DUAL_ADDU16I_OPERAND (v)) 4458 a = (v > 0 ? 0x7fff0000 : ~0x7fffffff); 4459 else 4460 gcc_unreachable (); 4461 4462 op[1] = gen_int_mode (a, mode); 4463 v = v - (unsigned HOST_WIDE_INT) a; 4464 op[2] = gen_int_mode (v, mode); 4465 } 4466 4467 /* Implement TARGET_CONSTANT_ALIGNMENT. */ 4468 4469 static HOST_WIDE_INT 4470 loongarch_constant_alignment (const_tree exp, HOST_WIDE_INT align) 4471 { 4472 if (TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR) 4473 return MAX (align, BITS_PER_WORD); 4474 return align; 4475 } 4476 4477 const char * 4478 loongarch_output_move_index (rtx x, machine_mode mode, bool ldr) 4479 { 4480 int index = exact_log2 (GET_MODE_SIZE (mode)); 4481 if (!IN_RANGE (index, 0, 3)) 4482 return NULL; 4483 4484 struct loongarch_address_info info; 4485 if ((loongarch_classify_address (&info, x, mode, false) 4486 && !(info.type == ADDRESS_REG_REG)) 4487 || !loongarch_legitimate_address_p (mode, x, false)) 4488 return NULL; 4489 4490 const char *const insn[][4] = 4491 { 4492 { 4493 "stx.b\t%z1,%0", 4494 "stx.h\t%z1,%0", 4495 "stx.w\t%z1,%0", 4496 "stx.d\t%z1,%0", 4497 }, 4498 { 4499 "ldx.bu\t%0,%1", 4500 "ldx.hu\t%0,%1", 4501 "ldx.w\t%0,%1", 4502 "ldx.d\t%0,%1", 4503 } 4504 }; 4505 4506 return insn[ldr][index]; 4507 } 4508 4509 const char * 4510 loongarch_output_move_index_float (rtx x, machine_mode mode, bool ldr) 4511 { 4512 int index = exact_log2 (GET_MODE_SIZE (mode)); 4513 if (!IN_RANGE (index, 2, 5)) 4514 return NULL; 4515 4516 struct loongarch_address_info info; 4517 if ((loongarch_classify_address (&info, x, mode, false) 4518 && !(info.type == ADDRESS_REG_REG)) 4519 || !loongarch_legitimate_address_p (mode, x, false)) 4520 return NULL; 4521 4522 const char *const insn[][4] = 4523 { 4524 { 4525 "fstx.s\t%1,%0", 4526 "fstx.d\t%1,%0", 4527 "vstx\t%w1,%0", 4528 "xvstx\t%u1,%0" 4529 }, 4530 { 4531 "fldx.s\t%0,%1", 4532 "fldx.d\t%0,%1", 4533 "vldx\t%w0,%1", 4534 "xvldx\t%u0,%1" 4535 } 4536 }; 4537 4538 return insn[ldr][index-2]; 4539 } 4540 /* Return true if a 128-bit move from SRC to DEST should be split. */ 4541 4542 bool 4543 loongarch_split_128bit_move_p (rtx dest, rtx src) 4544 { 4545 /* LSX-to-LSX moves can be done in a single instruction. */ 4546 if (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) 4547 return false; 4548 4549 /* Check for LSX loads and stores. */ 4550 if (FP_REG_RTX_P (dest) && MEM_P (src)) 4551 return false; 4552 if (FP_REG_RTX_P (src) && MEM_P (dest)) 4553 return false; 4554 4555 /* Check for LSX set to an immediate const vector with valid replicated 4556 element. */ 4557 if (FP_REG_RTX_P (dest) 4558 && loongarch_const_vector_same_int_p (src, GET_MODE (src), -512, 511)) 4559 return false; 4560 4561 /* Check for LSX load zero immediate. */ 4562 if (FP_REG_RTX_P (dest) && src == CONST0_RTX (GET_MODE (src))) 4563 return false; 4564 4565 return true; 4566 } 4567 4568 /* Return true if a 256-bit move from SRC to DEST should be split. */ 4569 4570 bool 4571 loongarch_split_256bit_move_p (rtx dest, rtx src) 4572 { 4573 /* LSX-to-LSX moves can be done in a single instruction. */ 4574 if (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) 4575 return false; 4576 4577 /* Check for LSX loads and stores. */ 4578 if (FP_REG_RTX_P (dest) && MEM_P (src)) 4579 return false; 4580 if (FP_REG_RTX_P (src) && MEM_P (dest)) 4581 return false; 4582 4583 /* Check for LSX set to an immediate const vector with valid replicated 4584 element. */ 4585 if (FP_REG_RTX_P (dest) 4586 && loongarch_const_vector_same_int_p (src, GET_MODE (src), -512, 511)) 4587 return false; 4588 4589 /* Check for LSX load zero immediate. */ 4590 if (FP_REG_RTX_P (dest) && src == CONST0_RTX (GET_MODE (src))) 4591 return false; 4592 4593 return true; 4594 } 4595 4596 /* Split a 128-bit move from SRC to DEST. */ 4597 4598 void 4599 loongarch_split_128bit_move (rtx dest, rtx src) 4600 { 4601 int byte, index; 4602 rtx low_dest, low_src, d, s; 4603 4604 if (FP_REG_RTX_P (dest)) 4605 { 4606 gcc_assert (!MEM_P (src)); 4607 4608 rtx new_dest = dest; 4609 if (!TARGET_64BIT) 4610 { 4611 if (GET_MODE (dest) != V4SImode) 4612 new_dest = simplify_gen_subreg (V4SImode, dest, GET_MODE (dest), 0); 4613 } 4614 else 4615 { 4616 if (GET_MODE (dest) != V2DImode) 4617 new_dest = simplify_gen_subreg (V2DImode, dest, GET_MODE (dest), 0); 4618 } 4619 4620 for (byte = 0, index = 0; byte < GET_MODE_SIZE (TImode); 4621 byte += UNITS_PER_WORD, index++) 4622 { 4623 s = loongarch_subword_at_byte (src, byte); 4624 if (!TARGET_64BIT) 4625 emit_insn (gen_lsx_vinsgr2vr_w (new_dest, s, new_dest, 4626 GEN_INT (1 << index))); 4627 else 4628 emit_insn (gen_lsx_vinsgr2vr_d (new_dest, s, new_dest, 4629 GEN_INT (1 << index))); 4630 } 4631 } 4632 else if (FP_REG_RTX_P (src)) 4633 { 4634 gcc_assert (!MEM_P (dest)); 4635 4636 rtx new_src = src; 4637 if (!TARGET_64BIT) 4638 { 4639 if (GET_MODE (src) != V4SImode) 4640 new_src = simplify_gen_subreg (V4SImode, src, GET_MODE (src), 0); 4641 } 4642 else 4643 { 4644 if (GET_MODE (src) != V2DImode) 4645 new_src = simplify_gen_subreg (V2DImode, src, GET_MODE (src), 0); 4646 } 4647 4648 for (byte = 0, index = 0; byte < GET_MODE_SIZE (TImode); 4649 byte += UNITS_PER_WORD, index++) 4650 { 4651 d = loongarch_subword_at_byte (dest, byte); 4652 if (!TARGET_64BIT) 4653 emit_insn (gen_lsx_vpickve2gr_w (d, new_src, GEN_INT (index))); 4654 else 4655 emit_insn (gen_lsx_vpickve2gr_d (d, new_src, GEN_INT (index))); 4656 } 4657 } 4658 else 4659 { 4660 low_dest = loongarch_subword_at_byte (dest, 0); 4661 low_src = loongarch_subword_at_byte (src, 0); 4662 gcc_assert (REG_P (low_dest) && REG_P (low_src)); 4663 /* Make sure the source register is not written before reading. */ 4664 if (REGNO (low_dest) <= REGNO (low_src)) 4665 { 4666 for (byte = 0; byte < GET_MODE_SIZE (TImode); 4667 byte += UNITS_PER_WORD) 4668 { 4669 d = loongarch_subword_at_byte (dest, byte); 4670 s = loongarch_subword_at_byte (src, byte); 4671 loongarch_emit_move (d, s); 4672 } 4673 } 4674 else 4675 { 4676 for (byte = GET_MODE_SIZE (TImode) - UNITS_PER_WORD; byte >= 0; 4677 byte -= UNITS_PER_WORD) 4678 { 4679 d = loongarch_subword_at_byte (dest, byte); 4680 s = loongarch_subword_at_byte (src, byte); 4681 loongarch_emit_move (d, s); 4682 } 4683 } 4684 } 4685 } 4686 4687 /* Split a 256-bit move from SRC to DEST. */ 4688 4689 void 4690 loongarch_split_256bit_move (rtx dest, rtx src) 4691 { 4692 int byte, index; 4693 rtx low_dest, low_src, d, s; 4694 4695 if (FP_REG_RTX_P (dest)) 4696 { 4697 gcc_assert (!MEM_P (src)); 4698 4699 rtx new_dest = dest; 4700 if (!TARGET_64BIT) 4701 { 4702 if (GET_MODE (dest) != V8SImode) 4703 new_dest = simplify_gen_subreg (V8SImode, dest, GET_MODE (dest), 0); 4704 } 4705 else 4706 { 4707 if (GET_MODE (dest) != V4DImode) 4708 new_dest = simplify_gen_subreg (V4DImode, dest, GET_MODE (dest), 0); 4709 } 4710 4711 for (byte = 0, index = 0; byte < GET_MODE_SIZE (GET_MODE (dest)); 4712 byte += UNITS_PER_WORD, index++) 4713 { 4714 s = loongarch_subword_at_byte (src, byte); 4715 if (!TARGET_64BIT) 4716 emit_insn (gen_lasx_xvinsgr2vr_w (new_dest, s, new_dest, 4717 GEN_INT (1 << index))); 4718 else 4719 emit_insn (gen_lasx_xvinsgr2vr_d (new_dest, s, new_dest, 4720 GEN_INT (1 << index))); 4721 } 4722 } 4723 else if (FP_REG_RTX_P (src)) 4724 { 4725 gcc_assert (!MEM_P (dest)); 4726 4727 rtx new_src = src; 4728 if (!TARGET_64BIT) 4729 { 4730 if (GET_MODE (src) != V8SImode) 4731 new_src = simplify_gen_subreg (V8SImode, src, GET_MODE (src), 0); 4732 } 4733 else 4734 { 4735 if (GET_MODE (src) != V4DImode) 4736 new_src = simplify_gen_subreg (V4DImode, src, GET_MODE (src), 0); 4737 } 4738 4739 for (byte = 0, index = 0; byte < GET_MODE_SIZE (GET_MODE (src)); 4740 byte += UNITS_PER_WORD, index++) 4741 { 4742 d = loongarch_subword_at_byte (dest, byte); 4743 if (!TARGET_64BIT) 4744 emit_insn (gen_lsx_vpickve2gr_w (d, new_src, GEN_INT (index))); 4745 else 4746 emit_insn (gen_lsx_vpickve2gr_d (d, new_src, GEN_INT (index))); 4747 } 4748 } 4749 else 4750 { 4751 low_dest = loongarch_subword_at_byte (dest, 0); 4752 low_src = loongarch_subword_at_byte (src, 0); 4753 gcc_assert (REG_P (low_dest) && REG_P (low_src)); 4754 /* Make sure the source register is not written before reading. */ 4755 if (REGNO (low_dest) <= REGNO (low_src)) 4756 { 4757 for (byte = 0; byte < GET_MODE_SIZE (TImode); 4758 byte += UNITS_PER_WORD) 4759 { 4760 d = loongarch_subword_at_byte (dest, byte); 4761 s = loongarch_subword_at_byte (src, byte); 4762 loongarch_emit_move (d, s); 4763 } 4764 } 4765 else 4766 { 4767 for (byte = GET_MODE_SIZE (TImode) - UNITS_PER_WORD; byte >= 0; 4768 byte -= UNITS_PER_WORD) 4769 { 4770 d = loongarch_subword_at_byte (dest, byte); 4771 s = loongarch_subword_at_byte (src, byte); 4772 loongarch_emit_move (d, s); 4773 } 4774 } 4775 } 4776 } 4777 4778 /* Return the appropriate instructions to move SRC into DEST. Assume 4779 that SRC is operand 1 and DEST is operand 0. */ 4780 4781 const char * 4782 loongarch_output_move (rtx dest, rtx src) 4783 { 4784 enum rtx_code dest_code = GET_CODE (dest); 4785 enum rtx_code src_code = GET_CODE (src); 4786 machine_mode mode = GET_MODE (dest); 4787 bool dbl_p = (GET_MODE_SIZE (mode) == 8); 4788 bool lsx_p = LSX_SUPPORTED_MODE_P (mode); 4789 bool lasx_p = LASX_SUPPORTED_MODE_P (mode); 4790 4791 if (loongarch_split_move_p (dest, src)) 4792 return "#"; 4793 4794 if ((lsx_p || lasx_p) 4795 && dest_code == REG && FP_REG_P (REGNO (dest)) 4796 && src_code == CONST_VECTOR 4797 && CONST_INT_P (CONST_VECTOR_ELT (src, 0))) 4798 { 4799 gcc_assert (loongarch_const_vector_same_int_p (src, mode, -512, 511)); 4800 switch (GET_MODE_SIZE (mode)) 4801 { 4802 case 16: 4803 return "vrepli.%v0\t%w0,%E1"; 4804 case 32: 4805 return "xvrepli.%v0\t%u0,%E1"; 4806 default: gcc_unreachable (); 4807 } 4808 } 4809 4810 if ((src_code == REG && GP_REG_P (REGNO (src))) 4811 || (src == CONST0_RTX (mode))) 4812 { 4813 if (dest_code == REG) 4814 { 4815 if (GP_REG_P (REGNO (dest))) 4816 return "or\t%0,%z1,$r0"; 4817 4818 if (FP_REG_P (REGNO (dest))) 4819 { 4820 if (lsx_p || lasx_p) 4821 { 4822 gcc_assert (src == CONST0_RTX (GET_MODE (src))); 4823 switch (GET_MODE_SIZE (mode)) 4824 { 4825 case 16: 4826 return "vrepli.b\t%w0,0"; 4827 case 32: 4828 return "xvrepli.b\t%u0,0"; 4829 default: 4830 gcc_unreachable (); 4831 } 4832 } 4833 4834 return dbl_p ? "movgr2fr.d\t%0,%z1" : "movgr2fr.w\t%0,%z1"; 4835 } 4836 } 4837 if (dest_code == MEM) 4838 { 4839 const char *insn = NULL; 4840 insn = loongarch_output_move_index (XEXP (dest, 0), GET_MODE (dest), 4841 false); 4842 if (insn) 4843 return insn; 4844 4845 rtx offset = XEXP (dest, 0); 4846 if (GET_CODE (offset) == PLUS) 4847 offset = XEXP (offset, 1); 4848 switch (GET_MODE_SIZE (mode)) 4849 { 4850 case 1: 4851 return "st.b\t%z1,%0"; 4852 case 2: 4853 return "st.h\t%z1,%0"; 4854 case 4: 4855 /* Matching address type with a 12bit offset and 4856 ADDRESS_LO_SUM. */ 4857 if (const_arith_operand (offset, Pmode) 4858 || GET_CODE (offset) == LO_SUM) 4859 return "st.w\t%z1,%0"; 4860 else 4861 return "stptr.w\t%z1,%0"; 4862 case 8: 4863 if (const_arith_operand (offset, Pmode) 4864 || GET_CODE (offset) == LO_SUM) 4865 return "st.d\t%z1,%0"; 4866 else 4867 return "stptr.d\t%z1,%0"; 4868 default: 4869 gcc_unreachable (); 4870 } 4871 } 4872 } 4873 if (dest_code == REG && GP_REG_P (REGNO (dest))) 4874 { 4875 if (src_code == REG) 4876 if (FP_REG_P (REGNO (src))) 4877 { 4878 gcc_assert (!lsx_p); 4879 return dbl_p ? "movfr2gr.d\t%0,%1" : "movfr2gr.s\t%0,%1"; 4880 } 4881 4882 if (src_code == MEM) 4883 { 4884 const char *insn = NULL; 4885 insn = loongarch_output_move_index (XEXP (src, 0), GET_MODE (src), 4886 true); 4887 if (insn) 4888 return insn; 4889 4890 rtx offset = XEXP (src, 0); 4891 if (GET_CODE (offset) == PLUS) 4892 offset = XEXP (offset, 1); 4893 switch (GET_MODE_SIZE (mode)) 4894 { 4895 case 1: 4896 return "ld.bu\t%0,%1"; 4897 case 2: 4898 return "ld.hu\t%0,%1"; 4899 case 4: 4900 /* Matching address type with a 12bit offset and 4901 ADDRESS_LO_SUM. */ 4902 if (const_arith_operand (offset, Pmode) 4903 || GET_CODE (offset) == LO_SUM) 4904 return "ld.w\t%0,%1"; 4905 else 4906 return "ldptr.w\t%0,%1"; 4907 case 8: 4908 if (const_arith_operand (offset, Pmode) 4909 || GET_CODE (offset) == LO_SUM) 4910 return "ld.d\t%0,%1"; 4911 else 4912 return "ldptr.d\t%0,%1"; 4913 default: 4914 gcc_unreachable (); 4915 } 4916 } 4917 4918 if (src_code == HIGH) 4919 { 4920 rtx offset, x; 4921 split_const (XEXP (src, 0), &x, &offset); 4922 enum loongarch_symbol_type type = SYMBOL_PCREL; 4923 4924 if (UNSPEC_ADDRESS_P (x)) 4925 type = UNSPEC_ADDRESS_TYPE (x); 4926 4927 if (type == SYMBOL_TLS_LE) 4928 return "lu12i.w\t%0,%h1"; 4929 else 4930 return "%Q1pcalau12i\t%0,%h1"; 4931 } 4932 4933 if (src_code == CONST_INT) 4934 { 4935 if (LU12I_INT (src)) 4936 return "lu12i.w\t%0,%1>>12\t\t\t# %X1"; 4937 else if (IMM12_INT (src)) 4938 return "addi.w\t%0,$r0,%1\t\t\t# %X1"; 4939 else if (IMM12_INT_UNSIGNED (src)) 4940 return "ori\t%0,$r0,%1\t\t\t# %X1"; 4941 else if (LU52I_INT (src)) 4942 return "lu52i.d\t%0,$r0,%X1>>52\t\t\t# %1"; 4943 else 4944 gcc_unreachable (); 4945 } 4946 } 4947 4948 if (!loongarch_explicit_relocs_p (loongarch_classify_symbol (src)) 4949 && dest_code == REG && symbolic_operand (src, VOIDmode)) 4950 { 4951 if (loongarch_classify_symbol (src) == SYMBOL_PCREL) 4952 return "la.local\t%0,%1"; 4953 else 4954 return "la.global\t%0,%1"; 4955 } 4956 4957 if (src_code == REG && FP_REG_P (REGNO (src))) 4958 { 4959 if (dest_code == REG && FP_REG_P (REGNO (dest))) 4960 { 4961 if (lsx_p || lasx_p) 4962 { 4963 switch (GET_MODE_SIZE (mode)) 4964 { 4965 case 16: 4966 return "vori.b\t%w0,%w1,0"; 4967 case 32: 4968 return "xvori.b\t%u0,%u1,0"; 4969 default: 4970 gcc_unreachable (); 4971 } 4972 } 4973 4974 return dbl_p ? "fmov.d\t%0,%1" : "fmov.s\t%0,%1"; 4975 } 4976 4977 if (dest_code == MEM) 4978 { 4979 const char *insn = NULL; 4980 insn = loongarch_output_move_index_float (XEXP (dest, 0), 4981 GET_MODE (dest), 4982 false); 4983 if (insn) 4984 return insn; 4985 4986 if (lsx_p || lasx_p) 4987 { 4988 switch (GET_MODE_SIZE (mode)) 4989 { 4990 case 16: 4991 return "vst\t%w1,%0"; 4992 case 32: 4993 return "xvst\t%u1,%0"; 4994 default: 4995 gcc_unreachable (); 4996 } 4997 } 4998 4999 return dbl_p ? "fst.d\t%1,%0" : "fst.s\t%1,%0"; 5000 } 5001 } 5002 5003 if (dest_code == REG && FP_REG_P (REGNO (dest))) 5004 { 5005 if (src_code == MEM) 5006 { 5007 const char *insn = NULL; 5008 insn = loongarch_output_move_index_float (XEXP (src, 0), 5009 GET_MODE (src), 5010 true); 5011 if (insn) 5012 return insn; 5013 5014 if (lsx_p || lasx_p) 5015 { 5016 switch (GET_MODE_SIZE (mode)) 5017 { 5018 case 16: 5019 return "vld\t%w0,%1"; 5020 case 32: 5021 return "xvld\t%u0,%1"; 5022 default: 5023 gcc_unreachable (); 5024 } 5025 } 5026 return dbl_p ? "fld.d\t%0,%1" : "fld.s\t%0,%1"; 5027 } 5028 } 5029 5030 gcc_unreachable (); 5031 } 5032 5033 /* Return true if CMP1 is a suitable second operand for integer ordering 5034 test CODE. */ 5035 5036 static bool 5037 loongarch_int_order_operand_ok_p (enum rtx_code code, rtx cmp1) 5038 { 5039 switch (code) 5040 { 5041 case GT: 5042 case GTU: 5043 return reg_or_0_operand (cmp1, VOIDmode); 5044 5045 case GE: 5046 case GEU: 5047 return cmp1 == const1_rtx; 5048 5049 case LT: 5050 case LTU: 5051 return arith_operand (cmp1, VOIDmode); 5052 5053 case LE: 5054 return sle_operand (cmp1, VOIDmode); 5055 5056 case LEU: 5057 return sleu_operand (cmp1, VOIDmode); 5058 5059 default: 5060 gcc_unreachable (); 5061 } 5062 } 5063 5064 /* Return true if *CMP1 (of mode MODE) is a valid second operand for 5065 integer ordering test *CODE, or if an equivalent combination can 5066 be formed by adjusting *CODE and *CMP1. When returning true, update 5067 *CODE and *CMP1 with the chosen code and operand, otherwise leave 5068 them alone. */ 5069 5070 static bool 5071 loongarch_canonicalize_int_order_test (enum rtx_code *code, rtx *cmp1, 5072 machine_mode mode) 5073 { 5074 HOST_WIDE_INT plus_one; 5075 5076 if (loongarch_int_order_operand_ok_p (*code, *cmp1)) 5077 return true; 5078 5079 if (CONST_INT_P (*cmp1)) 5080 switch (*code) 5081 { 5082 case LE: 5083 plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode); 5084 if (INTVAL (*cmp1) < plus_one) 5085 { 5086 *code = LT; 5087 *cmp1 = force_reg (mode, GEN_INT (plus_one)); 5088 return true; 5089 } 5090 break; 5091 5092 case LEU: 5093 plus_one = trunc_int_for_mode (UINTVAL (*cmp1) + 1, mode); 5094 if (plus_one != 0) 5095 { 5096 *code = LTU; 5097 *cmp1 = force_reg (mode, GEN_INT (plus_one)); 5098 return true; 5099 } 5100 break; 5101 5102 default: 5103 break; 5104 } 5105 return false; 5106 } 5107 5108 /* Compare CMP0 and CMP1 using ordering test CODE and store the result 5109 in TARGET. CMP0 and TARGET are register_operands. If INVERT_PTR 5110 is nonnull, it's OK to set TARGET to the inverse of the result and 5111 flip *INVERT_PTR instead. */ 5112 5113 static void 5114 loongarch_emit_int_order_test (enum rtx_code code, bool *invert_ptr, 5115 rtx target, rtx cmp0, rtx cmp1) 5116 { 5117 machine_mode mode; 5118 5119 /* First see if there is a LoongArch instruction that can do this operation. 5120 If not, try doing the same for the inverse operation. If that also 5121 fails, force CMP1 into a register and try again. */ 5122 mode = GET_MODE (cmp0); 5123 if (loongarch_canonicalize_int_order_test (&code, &cmp1, mode)) 5124 loongarch_emit_binary (code, target, cmp0, cmp1); 5125 else 5126 { 5127 enum rtx_code inv_code = reverse_condition (code); 5128 if (!loongarch_canonicalize_int_order_test (&inv_code, &cmp1, mode)) 5129 { 5130 cmp1 = force_reg (mode, cmp1); 5131 loongarch_emit_int_order_test (code, invert_ptr, target, cmp0, cmp1); 5132 } 5133 else if (invert_ptr == 0) 5134 { 5135 rtx inv_target; 5136 5137 inv_target = loongarch_force_binary (GET_MODE (target), 5138 inv_code, cmp0, cmp1); 5139 loongarch_emit_binary (XOR, target, inv_target, const1_rtx); 5140 } 5141 else 5142 { 5143 *invert_ptr = !*invert_ptr; 5144 loongarch_emit_binary (inv_code, target, cmp0, cmp1); 5145 } 5146 } 5147 } 5148 5149 /* Return a register that is zero if CMP0 and CMP1 are equal. 5150 The register will have the same mode as CMP0. */ 5151 5152 static rtx 5153 loongarch_zero_if_equal (rtx cmp0, rtx cmp1) 5154 { 5155 if (cmp1 == const0_rtx) 5156 return cmp0; 5157 5158 if (uns_arith_operand (cmp1, VOIDmode)) 5159 return expand_binop (GET_MODE (cmp0), xor_optab, cmp0, cmp1, 0, 0, 5160 OPTAB_DIRECT); 5161 5162 return expand_binop (GET_MODE (cmp0), sub_optab, cmp0, cmp1, 0, 0, 5163 OPTAB_DIRECT); 5164 } 5165 5166 /* Sign- or zero-extend OP0 and OP1 for integer comparisons. */ 5167 5168 static void 5169 loongarch_extend_comparands (rtx_code code, rtx *op0, rtx *op1) 5170 { 5171 /* Comparisons consider all GRLEN bits, so extend sub-GRLEN values. */ 5172 if (GET_MODE_SIZE (word_mode) > GET_MODE_SIZE (GET_MODE (*op0))) 5173 { 5174 /* It is more profitable to zero-extend QImode values. But not if the 5175 first operand has already been sign-extended, and the second one is 5176 is a constant or has already been sign-extended also. */ 5177 if (unsigned_condition (code) == code 5178 && (GET_MODE (*op0) == QImode 5179 && ! (GET_CODE (*op0) == SUBREG 5180 && SUBREG_PROMOTED_VAR_P (*op0) 5181 && SUBREG_PROMOTED_SIGNED_P (*op0) 5182 && (CONST_INT_P (*op1) 5183 || (GET_CODE (*op1) == SUBREG 5184 && SUBREG_PROMOTED_VAR_P (*op1) 5185 && SUBREG_PROMOTED_SIGNED_P (*op1)))))) 5186 { 5187 *op0 = gen_rtx_ZERO_EXTEND (word_mode, *op0); 5188 if (CONST_INT_P (*op1)) 5189 *op1 = GEN_INT ((uint8_t) INTVAL (*op1)); 5190 else 5191 *op1 = gen_rtx_ZERO_EXTEND (word_mode, *op1); 5192 } 5193 else 5194 { 5195 *op0 = gen_rtx_SIGN_EXTEND (word_mode, *op0); 5196 if (*op1 != const0_rtx) 5197 *op1 = gen_rtx_SIGN_EXTEND (word_mode, *op1); 5198 } 5199 } 5200 } 5201 5202 5203 /* Convert a comparison into something that can be used in a branch. On 5204 entry, *OP0 and *OP1 are the values being compared and *CODE is the code 5205 used to compare them. Update them to describe the final comparison. */ 5206 5207 static void 5208 loongarch_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1) 5209 { 5210 static const enum rtx_code 5211 mag_comparisons[][2] = {{LEU, LTU}, {GTU, GEU}, {LE, LT}, {GT, GE}}; 5212 5213 if (splittable_const_int_operand (*op1, VOIDmode)) 5214 { 5215 HOST_WIDE_INT rhs = INTVAL (*op1); 5216 5217 if (*code == EQ || *code == NE) 5218 { 5219 /* Convert e.g. OP0 == 2048 into OP0 - 2048 == 0. */ 5220 if (IMM12_OPERAND (-rhs)) 5221 { 5222 *op0 = loongarch_force_binary (GET_MODE (*op0), PLUS, *op0, 5223 GEN_INT (-rhs)); 5224 *op1 = const0_rtx; 5225 } 5226 } 5227 else 5228 { 5229 /* Convert e.g. (OP0 <= 0xFFF) into (OP0 < 0x1000). */ 5230 for (size_t i = 0; i < ARRAY_SIZE (mag_comparisons); i++) 5231 { 5232 HOST_WIDE_INT new_rhs; 5233 bool increment = *code == mag_comparisons[i][0]; 5234 bool decrement = *code == mag_comparisons[i][1]; 5235 if (!increment && !decrement) 5236 continue; 5237 5238 if ((increment && rhs == HOST_WIDE_INT_MAX) 5239 || (decrement && rhs == HOST_WIDE_INT_MIN)) 5240 break; 5241 5242 new_rhs = rhs + (increment ? 1 : -1); 5243 if (loongarch_integer_cost (new_rhs) 5244 < loongarch_integer_cost (rhs)) 5245 { 5246 *op1 = GEN_INT (new_rhs); 5247 *code = mag_comparisons[i][increment]; 5248 } 5249 break; 5250 } 5251 } 5252 } 5253 5254 loongarch_extend_comparands (*code, op0, op1); 5255 5256 *op0 = force_reg (word_mode, *op0); 5257 if (*op1 != const0_rtx) 5258 *op1 = force_reg (word_mode, *op1); 5259 } 5260 5261 /* Like loongarch_emit_int_compare, but for floating-point comparisons. */ 5262 5263 static void 5264 loongarch_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1) 5265 { 5266 rtx cmp_op0 = *op0; 5267 rtx cmp_op1 = *op1; 5268 5269 /* Floating-point tests use a separate FCMP.cond.fmt 5270 comparison to set a register. The branch or conditional move will 5271 then compare that register against zero. 5272 5273 Set CMP_CODE to the code of the comparison instruction and 5274 *CODE to the code that the branch or move should use. */ 5275 enum rtx_code cmp_code = *code; 5276 /* Three FP conditions cannot be implemented by reversing the 5277 operands for FCMP.cond.fmt, instead a reversed condition code is 5278 required and a test for false. */ 5279 *code = NE; 5280 *op0 = gen_reg_rtx (FCCmode); 5281 5282 *op1 = const0_rtx; 5283 loongarch_emit_binary (cmp_code, *op0, cmp_op0, cmp_op1); 5284 } 5285 5286 /* Try performing the comparison in OPERANDS[1], whose arms are OPERANDS[2] 5287 and OPERAND[3]. Store the result in OPERANDS[0]. 5288 5289 On 64-bit targets, the mode of the comparison and target will always be 5290 SImode, thus possibly narrower than that of the comparison's operands. */ 5291 5292 void 5293 loongarch_expand_scc (rtx operands[]) 5294 { 5295 rtx target = operands[0]; 5296 enum rtx_code code = GET_CODE (operands[1]); 5297 rtx op0 = operands[2]; 5298 rtx op1 = operands[3]; 5299 5300 loongarch_extend_comparands (code, &op0, &op1); 5301 op0 = force_reg (word_mode, op0); 5302 5303 gcc_assert (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT); 5304 5305 if (code == EQ || code == NE) 5306 { 5307 rtx zie = loongarch_zero_if_equal (op0, op1); 5308 loongarch_emit_binary (code, target, zie, const0_rtx); 5309 } 5310 else 5311 loongarch_emit_int_order_test (code, 0, target, op0, op1); 5312 } 5313 5314 /* Compare OPERANDS[1] with OPERANDS[2] using comparison code 5315 CODE and jump to OPERANDS[3] if the condition holds. */ 5316 5317 void 5318 loongarch_expand_conditional_branch (rtx *operands) 5319 { 5320 enum rtx_code code = GET_CODE (operands[0]); 5321 rtx op0 = operands[1]; 5322 rtx op1 = operands[2]; 5323 rtx condition; 5324 5325 if (FLOAT_MODE_P (GET_MODE (op1))) 5326 loongarch_emit_float_compare (&code, &op0, &op1); 5327 else 5328 loongarch_emit_int_compare (&code, &op0, &op1); 5329 5330 condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1); 5331 emit_jump_insn (gen_condjump (condition, operands[3])); 5332 } 5333 5334 /* Perform the comparison in OPERANDS[1]. Move OPERANDS[2] into OPERANDS[0] 5335 if the condition holds, otherwise move OPERANDS[3] into OPERANDS[0]. */ 5336 5337 void 5338 loongarch_expand_conditional_move (rtx *operands) 5339 { 5340 enum rtx_code code = GET_CODE (operands[1]); 5341 rtx op0 = XEXP (operands[1], 0); 5342 rtx op1 = XEXP (operands[1], 1); 5343 rtx op0_extend = op0; 5344 rtx op1_extend = op1; 5345 5346 /* Record whether operands[2] and operands[3] modes are promoted to word_mode. */ 5347 bool promote_op[2] = {false, false}; 5348 bool promote_p = false; 5349 machine_mode mode = GET_MODE (operands[0]); 5350 5351 if (FLOAT_MODE_P (GET_MODE (op1))) 5352 loongarch_emit_float_compare (&code, &op0, &op1); 5353 else 5354 { 5355 if (GET_MODE_SIZE (GET_MODE (op0)) < word_mode) 5356 { 5357 promote_op[0] = (REG_P (op0) && REG_P (operands[2]) && 5358 REGNO (op0) == REGNO (operands[2])); 5359 promote_op[1] = (REG_P (op1) && REG_P (operands[3]) && 5360 REGNO (op1) == REGNO (operands[3])); 5361 } 5362 5363 if (promote_op[0] || promote_op[1]) 5364 { 5365 mode = word_mode; 5366 promote_p = true; 5367 } 5368 5369 loongarch_extend_comparands (code, &op0, &op1); 5370 5371 op0 = force_reg (word_mode, op0); 5372 op0_extend = op0; 5373 op1_extend = force_reg (word_mode, op1); 5374 5375 if (code == EQ || code == NE) 5376 { 5377 op0 = loongarch_zero_if_equal (op0, op1); 5378 op1 = const0_rtx; 5379 } 5380 else 5381 { 5382 /* The comparison needs a separate scc instruction. Store the 5383 result of the scc in *OP0 and compare it against zero. */ 5384 bool invert = false; 5385 rtx target = gen_reg_rtx (GET_MODE (op0)); 5386 loongarch_emit_int_order_test (code, &invert, target, op0, op1); 5387 code = invert ? EQ : NE; 5388 op0 = target; 5389 op1 = const0_rtx; 5390 } 5391 } 5392 5393 rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); 5394 /* There is no direct support for general conditional GP move involving 5395 two registers using SEL. */ 5396 if (INTEGRAL_MODE_P (GET_MODE (operands[2])) 5397 && register_operand (operands[2], VOIDmode) 5398 && register_operand (operands[3], VOIDmode)) 5399 { 5400 rtx op2 = operands[2]; 5401 rtx op3 = operands[3]; 5402 5403 if (promote_p) 5404 { 5405 if (promote_op[0]) 5406 op2 = op0_extend; 5407 else 5408 { 5409 loongarch_extend_comparands (code, &op2, &const0_rtx); 5410 op2 = force_reg (mode, op2); 5411 } 5412 5413 if (promote_op[1]) 5414 op3 = op1_extend; 5415 else 5416 { 5417 loongarch_extend_comparands (code, &op3, &const0_rtx); 5418 op3 = force_reg (mode, op3); 5419 } 5420 } 5421 5422 rtx temp = gen_reg_rtx (mode); 5423 rtx temp2 = gen_reg_rtx (mode); 5424 5425 emit_insn (gen_rtx_SET (temp, 5426 gen_rtx_IF_THEN_ELSE (mode, cond, 5427 op2, const0_rtx))); 5428 5429 /* Flip the test for the second operand. */ 5430 cond = gen_rtx_fmt_ee ((code == EQ) ? NE : EQ, GET_MODE (op0), op0, op1); 5431 5432 emit_insn (gen_rtx_SET (temp2, 5433 gen_rtx_IF_THEN_ELSE (mode, cond, 5434 op3, const0_rtx))); 5435 5436 /* Merge the two results, at least one is guaranteed to be zero. */ 5437 if (promote_p) 5438 { 5439 rtx temp3 = gen_reg_rtx (mode); 5440 emit_insn (gen_rtx_SET (temp3, gen_rtx_IOR (mode, temp, temp2))); 5441 temp3 = gen_lowpart (GET_MODE (operands[0]), temp3); 5442 /* Nonzero in a subreg if it was made when accessing an object that 5443 was promoted to a wider mode in accord with the PROMOTED_MODE 5444 machine description macro. */ 5445 SUBREG_PROMOTED_VAR_P (temp3) = 1; 5446 /* Sets promoted mode for SUBREG_PROMOTED_VAR_P. */ 5447 SUBREG_PROMOTED_SET (temp3, SRP_SIGNED); 5448 loongarch_emit_move (operands[0], temp3); 5449 } 5450 else 5451 emit_insn (gen_rtx_SET (operands[0], gen_rtx_IOR (mode, temp, temp2))); 5452 } 5453 else 5454 emit_insn (gen_rtx_SET (operands[0], 5455 gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), cond, 5456 operands[2], operands[3]))); 5457 } 5458 5459 /* Implement TARGET_EXPAND_BUILTIN_VA_START. */ 5460 5461 static void 5462 loongarch_va_start (tree valist, rtx nextarg) 5463 { 5464 nextarg = plus_constant (Pmode, nextarg, -cfun->machine->varargs_size); 5465 std_expand_builtin_va_start (valist, nextarg); 5466 } 5467 5468 /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL. */ 5469 5470 static bool 5471 loongarch_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, 5472 tree exp ATTRIBUTE_UNUSED) 5473 { 5474 /* Always OK. */ 5475 return true; 5476 } 5477 5478 static machine_mode 5479 loongarch_mode_for_move_size (HOST_WIDE_INT size) 5480 { 5481 switch (size) 5482 { 5483 case 32: 5484 return V32QImode; 5485 case 16: 5486 return V16QImode; 5487 } 5488 5489 return int_mode_for_size (size * BITS_PER_UNIT, 0).require (); 5490 } 5491 5492 /* Emit straight-line code to move LENGTH bytes from SRC to DEST. 5493 Assume that the areas do not overlap. */ 5494 5495 static void 5496 loongarch_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length, 5497 HOST_WIDE_INT delta) 5498 { 5499 HOST_WIDE_INT offs, delta_cur; 5500 int i; 5501 machine_mode mode; 5502 rtx *regs; 5503 5504 /* Calculate how many registers we'll need for the block move. 5505 We'll emit length / delta move operations with delta as the size 5506 first. Then we may still have length % delta bytes not copied. 5507 We handle these remaining bytes by move operations with smaller 5508 (halfed) sizes. For example, if length = 21 and delta = 8, we'll 5509 emit two ld.d/st.d pairs, one ld.w/st.w pair, and one ld.b/st.b 5510 pair. For each load/store pair we use a dedicated register to keep 5511 the pipeline as populated as possible. */ 5512 gcc_assert (pow2p_hwi (delta)); 5513 HOST_WIDE_INT num_reg = length / delta + popcount_hwi (length % delta); 5514 5515 /* Allocate a buffer for the temporary registers. */ 5516 regs = XALLOCAVEC (rtx, num_reg); 5517 5518 for (delta_cur = delta, i = 0, offs = 0; offs < length; delta_cur /= 2) 5519 { 5520 mode = loongarch_mode_for_move_size (delta_cur); 5521 5522 for (; offs + delta_cur <= length; offs += delta_cur, i++) 5523 { 5524 regs[i] = gen_reg_rtx (mode); 5525 loongarch_emit_move (regs[i], adjust_address (src, mode, offs)); 5526 } 5527 } 5528 5529 for (delta_cur = delta, i = 0, offs = 0; offs < length; delta_cur /= 2) 5530 { 5531 mode = loongarch_mode_for_move_size (delta_cur); 5532 5533 for (; offs + delta_cur <= length; offs += delta_cur, i++) 5534 loongarch_emit_move (adjust_address (dest, mode, offs), regs[i]); 5535 } 5536 } 5537 5538 /* Helper function for doing a loop-based block operation on memory 5539 reference MEM. Each iteration of the loop will operate on LENGTH 5540 bytes of MEM. 5541 5542 Create a new base register for use within the loop and point it to 5543 the start of MEM. Create a new memory reference that uses this 5544 register. Store them in *LOOP_REG and *LOOP_MEM respectively. */ 5545 5546 static void 5547 loongarch_adjust_block_mem (rtx mem, HOST_WIDE_INT length, rtx *loop_reg, 5548 rtx *loop_mem) 5549 { 5550 *loop_reg = copy_addr_to_reg (XEXP (mem, 0)); 5551 5552 /* Although the new mem does not refer to a known location, 5553 it does keep up to LENGTH bytes of alignment. */ 5554 *loop_mem = change_address (mem, BLKmode, *loop_reg); 5555 set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT)); 5556 } 5557 5558 /* Move LENGTH bytes from SRC to DEST using a loop that moves BYTES_PER_ITER 5559 bytes at a time. LENGTH must be at least BYTES_PER_ITER. Assume that 5560 the memory regions do not overlap. */ 5561 5562 static void 5563 loongarch_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length, 5564 HOST_WIDE_INT align) 5565 { 5566 rtx_code_label *label; 5567 rtx src_reg, dest_reg, final_src, test; 5568 HOST_WIDE_INT bytes_per_iter = align * LARCH_MAX_MOVE_OPS_PER_LOOP_ITER; 5569 HOST_WIDE_INT leftover; 5570 5571 leftover = length % bytes_per_iter; 5572 length -= leftover; 5573 5574 /* Create registers and memory references for use within the loop. */ 5575 loongarch_adjust_block_mem (src, bytes_per_iter, &src_reg, &src); 5576 loongarch_adjust_block_mem (dest, bytes_per_iter, &dest_reg, &dest); 5577 5578 /* Calculate the value that SRC_REG should have after the last iteration 5579 of the loop. */ 5580 final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length), 0, 5581 0, OPTAB_WIDEN); 5582 5583 /* Emit the start of the loop. */ 5584 label = gen_label_rtx (); 5585 emit_label (label); 5586 5587 /* Emit the loop body. */ 5588 loongarch_block_move_straight (dest, src, bytes_per_iter, align); 5589 5590 /* Move on to the next block. */ 5591 loongarch_emit_move (src_reg, 5592 plus_constant (Pmode, src_reg, bytes_per_iter)); 5593 loongarch_emit_move (dest_reg, 5594 plus_constant (Pmode, dest_reg, bytes_per_iter)); 5595 5596 /* Emit the loop condition. */ 5597 test = gen_rtx_NE (VOIDmode, src_reg, final_src); 5598 if (Pmode == DImode) 5599 emit_jump_insn (gen_cbranchdi4 (test, src_reg, final_src, label)); 5600 else 5601 emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label)); 5602 5603 /* Mop up any left-over bytes. */ 5604 if (leftover) 5605 loongarch_block_move_straight (dest, src, leftover, align); 5606 else 5607 /* Temporary fix for PR79150. */ 5608 emit_insn (gen_nop ()); 5609 } 5610 5611 /* Expand a cpymemsi instruction, which copies LENGTH bytes from 5612 memory reference SRC to memory reference DEST. */ 5613 5614 bool 5615 loongarch_expand_block_move (rtx dest, rtx src, rtx r_length, rtx r_align) 5616 { 5617 if (!CONST_INT_P (r_length)) 5618 return false; 5619 5620 HOST_WIDE_INT length = INTVAL (r_length); 5621 if (length > la_max_inline_memcpy_size) 5622 return false; 5623 5624 HOST_WIDE_INT align = INTVAL (r_align); 5625 5626 if (!TARGET_STRICT_ALIGN || align > LARCH_MAX_MOVE_PER_INSN) 5627 align = LARCH_MAX_MOVE_PER_INSN; 5628 5629 if (length <= align * LARCH_MAX_MOVE_OPS_STRAIGHT) 5630 { 5631 loongarch_block_move_straight (dest, src, length, align); 5632 return true; 5633 } 5634 5635 if (optimize) 5636 { 5637 loongarch_block_move_loop (dest, src, length, align); 5638 return true; 5639 } 5640 5641 return false; 5642 } 5643 5644 /* Return true if loongarch_expand_block_move is the preferred 5645 implementation of the 'cpymemsi' template. */ 5646 5647 bool 5648 loongarch_do_optimize_block_move_p (void) 5649 { 5650 /* if -m[no-]memcpy is given explicitly. */ 5651 if (target_flags_explicit & MASK_MEMCPY) 5652 return !TARGET_MEMCPY; 5653 5654 /* if not, don't optimize under -Os. */ 5655 return !optimize_size; 5656 } 5657 5658 /* Expand a QI or HI mode atomic memory operation. 5659 5660 GENERATOR contains a pointer to the gen_* function that generates 5661 the SI mode underlying atomic operation using masks that we 5662 calculate. 5663 5664 RESULT is the return register for the operation. Its value is NULL 5665 if unused. 5666 5667 MEM is the location of the atomic access. 5668 5669 OLDVAL is the first operand for the operation. 5670 5671 NEWVAL is the optional second operand for the operation. Its value 5672 is NULL if unused. */ 5673 5674 void 5675 loongarch_expand_atomic_qihi (union loongarch_gen_fn_ptrs generator, 5676 rtx result, rtx mem, rtx oldval, rtx newval, 5677 rtx model) 5678 { 5679 rtx orig_addr, memsi_addr, memsi, shift, shiftsi, unshifted_mask; 5680 rtx unshifted_mask_reg, mask, inverted_mask, si_op; 5681 rtx res = NULL; 5682 machine_mode mode; 5683 5684 mode = GET_MODE (mem); 5685 5686 /* Compute the address of the containing SImode value. */ 5687 orig_addr = force_reg (Pmode, XEXP (mem, 0)); 5688 memsi_addr = loongarch_force_binary (Pmode, AND, orig_addr, 5689 force_reg (Pmode, GEN_INT (-4))); 5690 5691 /* Create a memory reference for it. */ 5692 memsi = gen_rtx_MEM (SImode, memsi_addr); 5693 set_mem_alias_set (memsi, ALIAS_SET_MEMORY_BARRIER); 5694 MEM_VOLATILE_P (memsi) = MEM_VOLATILE_P (mem); 5695 5696 /* Work out the byte offset of the QImode or HImode value, 5697 counting from the least significant byte. */ 5698 shift = loongarch_force_binary (Pmode, AND, orig_addr, GEN_INT (3)); 5699 /* Multiply by eight to convert the shift value from bytes to bits. */ 5700 loongarch_emit_binary (ASHIFT, shift, shift, GEN_INT (3)); 5701 5702 /* Make the final shift an SImode value, so that it can be used in 5703 SImode operations. */ 5704 shiftsi = force_reg (SImode, gen_lowpart (SImode, shift)); 5705 5706 /* Set MASK to an inclusive mask of the QImode or HImode value. */ 5707 unshifted_mask = GEN_INT (GET_MODE_MASK (mode)); 5708 unshifted_mask_reg = force_reg (SImode, unshifted_mask); 5709 mask = loongarch_force_binary (SImode, ASHIFT, unshifted_mask_reg, shiftsi); 5710 5711 /* Compute the equivalent exclusive mask. */ 5712 inverted_mask = gen_reg_rtx (SImode); 5713 emit_insn (gen_rtx_SET (inverted_mask, gen_rtx_NOT (SImode, mask))); 5714 5715 /* Shift the old value into place. */ 5716 if (oldval != const0_rtx) 5717 { 5718 oldval = convert_modes (SImode, mode, oldval, true); 5719 oldval = force_reg (SImode, oldval); 5720 oldval = loongarch_force_binary (SImode, ASHIFT, oldval, shiftsi); 5721 } 5722 5723 /* Do the same for the new value. */ 5724 if (newval && newval != const0_rtx) 5725 { 5726 newval = convert_modes (SImode, mode, newval, true); 5727 newval = force_reg (SImode, newval); 5728 newval = loongarch_force_binary (SImode, ASHIFT, newval, shiftsi); 5729 } 5730 5731 /* Do the SImode atomic access. */ 5732 if (result) 5733 res = gen_reg_rtx (SImode); 5734 5735 if (newval) 5736 si_op = generator.fn_7 (res, memsi, mask, inverted_mask, oldval, newval, 5737 model); 5738 else if (result) 5739 si_op = generator.fn_6 (res, memsi, mask, inverted_mask, oldval, model); 5740 else 5741 si_op = generator.fn_5 (memsi, mask, inverted_mask, oldval, model); 5742 5743 emit_insn (si_op); 5744 5745 if (result) 5746 { 5747 /* Shift and convert the result. */ 5748 loongarch_emit_binary (AND, res, res, mask); 5749 loongarch_emit_binary (LSHIFTRT, res, res, shiftsi); 5750 loongarch_emit_move (result, gen_lowpart (GET_MODE (result), res)); 5751 } 5752 } 5753 5754 /* Return true if (zero_extract OP WIDTH BITPOS) can be used as the 5755 source of an "ext" instruction or the destination of an "ins" 5756 instruction. OP must be a register operand and the following 5757 conditions must hold: 5758 5759 0 <= BITPOS < GET_MODE_BITSIZE (GET_MODE (op)) 5760 0 < WIDTH <= GET_MODE_BITSIZE (GET_MODE (op)) 5761 0 < BITPOS + WIDTH <= GET_MODE_BITSIZE (GET_MODE (op)) 5762 5763 Also reject lengths equal to a word as they are better handled 5764 by the move patterns. */ 5765 5766 bool 5767 loongarch_use_ins_ext_p (rtx op, HOST_WIDE_INT width, HOST_WIDE_INT bitpos) 5768 { 5769 if (!register_operand (op, VOIDmode) 5770 || GET_MODE_BITSIZE (GET_MODE (op)) > BITS_PER_WORD) 5771 return false; 5772 5773 if (!IN_RANGE (width, 1, GET_MODE_BITSIZE (GET_MODE (op)) - 1)) 5774 return false; 5775 5776 if (bitpos < 0 || bitpos + width > GET_MODE_BITSIZE (GET_MODE (op))) 5777 return false; 5778 5779 return true; 5780 } 5781 5782 /* Predicate for pre-reload splitters with associated instructions, 5783 which can match any time before the split1 pass (usually combine), 5784 then are unconditionally split in that pass and should not be 5785 matched again afterwards. */ 5786 5787 bool loongarch_pre_reload_split (void) 5788 { 5789 return (can_create_pseudo_p () 5790 && !(cfun->curr_properties & PROP_rtl_split_insns)); 5791 } 5792 5793 /* Check if we can use bstrins.<d> for 5794 op0 = (op1 & op2) | (op3 & op4) 5795 where op0, op1, op3 are regs, and op2, op4 are integer constants. */ 5796 int 5797 loongarch_use_bstrins_for_ior_with_mask (machine_mode mode, rtx *op) 5798 { 5799 unsigned HOST_WIDE_INT mask1 = UINTVAL (op[2]); 5800 unsigned HOST_WIDE_INT mask2 = UINTVAL (op[4]); 5801 5802 if (mask1 != ~mask2 || !mask1 || !mask2) 5803 return 0; 5804 5805 /* Try to avoid a right-shift. */ 5806 if (low_bitmask_len (mode, mask1) != -1) 5807 return -1; 5808 5809 if (low_bitmask_len (mode, mask2 >> (ffs_hwi (mask2) - 1)) != -1) 5810 return 1; 5811 5812 if (low_bitmask_len (mode, mask1 >> (ffs_hwi (mask1) - 1)) != -1) 5813 return -1; 5814 5815 return 0; 5816 } 5817 5818 /* Rewrite a MEM for simple load/store under -mexplicit-relocs=auto 5819 -mcmodel={normal/medium}. */ 5820 rtx 5821 loongarch_rewrite_mem_for_simple_ldst (rtx mem) 5822 { 5823 rtx addr = XEXP (mem, 0); 5824 rtx hi = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 5825 UNSPEC_PCALAU12I_GR); 5826 rtx new_mem; 5827 5828 addr = gen_rtx_LO_SUM (Pmode, force_reg (Pmode, hi), addr); 5829 new_mem = gen_rtx_MEM (GET_MODE (mem), addr); 5830 MEM_COPY_ATTRIBUTES (new_mem, mem); 5831 return new_mem; 5832 } 5833 5834 /* Print the text for PRINT_OPERAND punctation character CH to FILE. 5835 The punctuation characters are: 5836 5837 '.' Print the name of the register with a hard-wired zero (zero or $r0). 5838 '$' Print the name of the stack pointer register (sp or $r3). 5839 5840 See also loongarch_init_print_operand_punct. */ 5841 5842 static void 5843 loongarch_print_operand_punctuation (FILE *file, int ch) 5844 { 5845 switch (ch) 5846 { 5847 case '.': 5848 fputs (reg_names[GP_REG_FIRST + 0], file); 5849 break; 5850 5851 case '$': 5852 fputs (reg_names[STACK_POINTER_REGNUM], file); 5853 break; 5854 5855 default: 5856 gcc_unreachable (); 5857 break; 5858 } 5859 } 5860 5861 /* PRINT_OPERAND prefix LETTER refers to the integer branch instruction 5862 associated with condition CODE. Print the condition part of the 5863 opcode to FILE. */ 5864 5865 static void 5866 loongarch_print_int_branch_condition (FILE *file, enum rtx_code code, 5867 int letter) 5868 { 5869 switch (code) 5870 { 5871 case EQ: 5872 case NE: 5873 case GT: 5874 case GE: 5875 case LT: 5876 case LE: 5877 case GTU: 5878 case GEU: 5879 case LTU: 5880 case LEU: 5881 /* Conveniently, the LoongArch names for these conditions are the same 5882 as their RTL equivalents. */ 5883 fputs (GET_RTX_NAME (code), file); 5884 break; 5885 5886 default: 5887 output_operand_lossage ("'%%%c' is not a valid operand prefix", letter); 5888 break; 5889 } 5890 } 5891 5892 /* Likewise floating-point branches. */ 5893 5894 static void 5895 loongarch_print_float_branch_condition (FILE *file, enum rtx_code code, 5896 int letter) 5897 { 5898 switch (code) 5899 { 5900 case EQ: 5901 fputs ("ceqz", file); 5902 break; 5903 5904 case NE: 5905 fputs ("cnez", file); 5906 break; 5907 5908 default: 5909 output_operand_lossage ("'%%%c' is not a valid operand prefix", letter); 5910 break; 5911 } 5912 } 5913 5914 /* Implement TARGET_PRINT_OPERAND_PUNCT_VALID_P. */ 5915 5916 static bool 5917 loongarch_print_operand_punct_valid_p (unsigned char code) 5918 { 5919 return loongarch_print_operand_punct[code]; 5920 } 5921 5922 /* Return true if a FENCE should be emitted to before a memory access to 5923 implement the release portion of memory model MODEL. */ 5924 5925 static bool 5926 loongarch_memmodel_needs_rel_acq_fence (enum memmodel model) 5927 { 5928 switch (memmodel_base (model)) 5929 { 5930 case MEMMODEL_ACQ_REL: 5931 case MEMMODEL_SEQ_CST: 5932 case MEMMODEL_RELEASE: 5933 case MEMMODEL_ACQUIRE: 5934 return true; 5935 5936 case MEMMODEL_RELAXED: 5937 return false; 5938 5939 default: 5940 gcc_unreachable (); 5941 } 5942 } 5943 5944 /* Return true if a FENCE should be emitted after a failed CAS to 5945 implement the acquire semantic of failure_memorder. */ 5946 5947 static bool 5948 loongarch_cas_failure_memorder_needs_acquire (enum memmodel model) 5949 { 5950 switch (memmodel_base (model)) 5951 { 5952 case MEMMODEL_ACQUIRE: 5953 case MEMMODEL_ACQ_REL: 5954 case MEMMODEL_SEQ_CST: 5955 return true; 5956 5957 case MEMMODEL_RELAXED: 5958 case MEMMODEL_RELEASE: 5959 return false; 5960 5961 /* MEMMODEL_CONSUME is deliberately not handled because it's always 5962 replaced by MEMMODEL_ACQUIRE as at now. If you see an ICE caused by 5963 MEMMODEL_CONSUME, read the change (re)introducing it carefully and 5964 decide what to do. See PR 59448 and get_memmodel in builtins.cc. */ 5965 default: 5966 gcc_unreachable (); 5967 } 5968 } 5969 5970 /* Print symbolic operand OP, which is part of a HIGH or LO_SUM 5971 in context CONTEXT. HI_RELOC indicates a high-part reloc. */ 5972 5973 static void 5974 loongarch_print_operand_reloc (FILE *file, rtx op, bool hi64_part, 5975 bool hi_reloc) 5976 { 5977 const char *reloc; 5978 enum loongarch_symbol_type symbol_type = 5979 loongarch_classify_symbolic_expression (op); 5980 5981 if (loongarch_symbol_extreme_p (symbol_type)) 5982 gcc_assert (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE); 5983 5984 switch (symbol_type) 5985 { 5986 case SYMBOL_PCREL64: 5987 if (hi64_part) 5988 { 5989 reloc = hi_reloc ? "%pc64_hi12" : "%pc64_lo20"; 5990 break; 5991 } 5992 /* fall through */ 5993 case SYMBOL_PCREL: 5994 reloc = hi_reloc ? "%pc_hi20" : "%pc_lo12"; 5995 break; 5996 5997 case SYMBOL_GOT_DISP: 5998 if (hi64_part) 5999 { 6000 if (TARGET_CMODEL_EXTREME) 6001 reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20"; 6002 else 6003 gcc_unreachable (); 6004 } 6005 else 6006 reloc = hi_reloc ? "%got_pc_hi20" : "%got_pc_lo12"; 6007 break; 6008 6009 case SYMBOL_TLS_IE: 6010 if (hi64_part) 6011 { 6012 if (TARGET_CMODEL_EXTREME) 6013 reloc = hi_reloc ? "%ie64_pc_hi12" : "%ie64_pc_lo20"; 6014 else 6015 gcc_unreachable (); 6016 } 6017 else 6018 reloc = hi_reloc ? "%ie_pc_hi20" : "%ie_pc_lo12"; 6019 break; 6020 6021 case SYMBOL_TLS_LE: 6022 if (hi64_part) 6023 { 6024 if (TARGET_CMODEL_EXTREME) 6025 reloc = hi_reloc ? "%le64_hi12" : "%le64_lo20"; 6026 else 6027 gcc_unreachable (); 6028 } 6029 else 6030 { 6031 if (HAVE_AS_TLS_LE_RELAXATION && !TARGET_CMODEL_EXTREME) 6032 reloc = hi_reloc ? "%le_hi20_r" : "%le_lo12_r"; 6033 else 6034 reloc = hi_reloc ? "%le_hi20" : "%le_lo12"; 6035 } 6036 break; 6037 6038 case SYMBOL_TLSGD: 6039 if (hi64_part) 6040 { 6041 if (TARGET_CMODEL_EXTREME) 6042 reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20"; 6043 else 6044 gcc_unreachable (); 6045 } 6046 else 6047 reloc = hi_reloc ? "%gd_pc_hi20" : "%got_pc_lo12"; 6048 break; 6049 6050 case SYMBOL_TLSLDM: 6051 if (hi64_part) 6052 { 6053 if (TARGET_CMODEL_EXTREME) 6054 reloc = hi_reloc ? "%got64_pc_hi12" : "%got64_pc_lo20"; 6055 else 6056 gcc_unreachable (); 6057 } 6058 else 6059 reloc = hi_reloc ? "%ld_pc_hi20" : "%got_pc_lo12"; 6060 break; 6061 6062 default: 6063 gcc_unreachable (); 6064 } 6065 6066 fprintf (file, "%s(", reloc); 6067 output_addr_const (file, loongarch_strip_unspec_address (op)); 6068 fputc (')', file); 6069 } 6070 6071 /* Implement TARGET_PRINT_OPERAND. The LoongArch-specific operand codes are: 6072 6073 'A' Print a _DB suffix if the memory model requires a release. 6074 'b' Print the address of a memory operand, without offset. 6075 'B' Print CONST_INT OP element 0 of a replicated CONST_VECTOR 6076 as an unsigned byte [0..255]. 6077 'c' Print an integer. 6078 'C' Print the integer branch condition for comparison OP. 6079 'd' Print CONST_INT OP in decimal. 6080 'E' Print CONST_INT OP element 0 of a replicated CONST_VECTOR in decimal. 6081 'F' Print the FPU branch condition for comparison OP. 6082 'G' Print a DBAR insn for CAS failure (with an acquire semantic if 6083 needed, otherwise a simple load-load barrier). 6084 'H' Print address 52-61bit relocation associated with OP. 6085 'h' Print the high-part relocation associated with OP. 6086 'i' Print i if the operand is not a register. 6087 'L' Print the low-part relocation associated with OP. 6088 'm' Print one less than CONST_INT OP in decimal. 6089 'N' Print the inverse of the integer branch condition for comparison OP. 6090 'Q' Print R_LARCH_RELAX for TLS IE. 6091 'r' Print address 12-31bit relocation associated with OP. 6092 'R' Print address 32-51bit relocation associated with OP. 6093 'T' Print 'f' for (eq:CC ...), 't' for (ne:CC ...), 6094 'z' for (eq:?I ...), 'n' for (ne:?I ...). 6095 't' Like 'T', but with the EQ/NE cases reversed 6096 'F' Print the FPU branch condition for comparison OP. 6097 'W' Print the inverse of the FPU branch condition for comparison OP. 6098 'w' Print a LSX register. 6099 'u' Print a LASX register. 6100 'T' Print 'f' for (eq:CC ...), 't' for (ne:CC ...), 6101 'z' for (eq:?I ...), 'n' for (ne:?I ...). 6102 't' Like 'T', but with the EQ/NE cases reversed 6103 'Y' Print loongarch_fp_conditions[INTVAL (OP)] 6104 'Z' Print OP and a comma for 8CC, otherwise print nothing. 6105 'z' Print $0 if OP is zero, otherwise print OP normally. 6106 'v' Print the insn size suffix b, h, w or d for vector modes V16QI, V8HI, 6107 V4SI, V2SI, and w, d for vector modes V4SF, V2DF respectively. 6108 'V' Print exact log2 of CONST_INT OP element 0 of a replicated 6109 CONST_VECTOR in decimal. 6110 'W' Print the inverse of the FPU branch condition for comparison OP. 6111 'X' Print CONST_INT OP in hexadecimal format. 6112 'x' Print the low 16 bits of CONST_INT OP in hexadecimal format. 6113 'Y' Print loongarch_fp_conditions[INTVAL (OP)] 6114 'y' Print exact log2 of CONST_INT OP in decimal. 6115 'Z' Print OP and a comma for 8CC, otherwise print nothing. 6116 'z' Print $0 if OP is zero, otherwise print OP normally. */ 6117 6118 static void 6119 loongarch_print_operand (FILE *file, rtx op, int letter) 6120 { 6121 enum rtx_code code; 6122 6123 if (loongarch_print_operand_punct_valid_p (letter)) 6124 { 6125 loongarch_print_operand_punctuation (file, letter); 6126 return; 6127 } 6128 6129 gcc_assert (op); 6130 code = GET_CODE (op); 6131 6132 switch (letter) 6133 { 6134 case 'A': 6135 if (loongarch_memmodel_needs_rel_acq_fence ((enum memmodel) INTVAL (op))) 6136 fputs ("_db", file); 6137 break; 6138 case 'E': 6139 if (GET_CODE (op) == CONST_VECTOR) 6140 { 6141 gcc_assert (loongarch_const_vector_same_val_p (op, GET_MODE (op))); 6142 op = CONST_VECTOR_ELT (op, 0); 6143 gcc_assert (CONST_INT_P (op)); 6144 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op)); 6145 } 6146 else 6147 output_operand_lossage ("invalid use of '%%%c'", letter); 6148 break; 6149 6150 6151 case 'c': 6152 if (CONST_INT_P (op)) 6153 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op)); 6154 else 6155 output_operand_lossage ("unsupported operand for code '%c'", letter); 6156 6157 break; 6158 6159 case 'C': 6160 loongarch_print_int_branch_condition (file, code, letter); 6161 break; 6162 6163 case 'd': 6164 if (CONST_INT_P (op)) 6165 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op)); 6166 else 6167 output_operand_lossage ("invalid use of '%%%c'", letter); 6168 break; 6169 6170 case 'F': 6171 loongarch_print_float_branch_condition (file, code, letter); 6172 break; 6173 6174 case 'G': 6175 if (loongarch_cas_failure_memorder_needs_acquire ( 6176 memmodel_from_int (INTVAL (op)))) 6177 fputs ("dbar\t0b10100", file); 6178 else if (!ISA_HAS_LD_SEQ_SA) 6179 fputs ("dbar\t0x700", file); 6180 break; 6181 6182 case 'h': 6183 if (code == HIGH) 6184 op = XEXP (op, 0); 6185 loongarch_print_operand_reloc (file, op, false /* hi64_part */, 6186 true /* hi_reloc */); 6187 break; 6188 6189 case 'H': 6190 loongarch_print_operand_reloc (file, op, true /* hi64_part */, 6191 true /* hi_reloc */); 6192 break; 6193 6194 case 'i': 6195 if (code != REG) 6196 fputs ("i", file); 6197 break; 6198 6199 case 'L': 6200 loongarch_print_operand_reloc (file, op, false /* hi64_part*/, 6201 false /* lo_reloc */); 6202 break; 6203 case 'B': 6204 if (GET_CODE (op) == CONST_VECTOR) 6205 { 6206 gcc_assert (loongarch_const_vector_same_val_p (op, GET_MODE (op))); 6207 op = CONST_VECTOR_ELT (op, 0); 6208 gcc_assert (CONST_INT_P (op)); 6209 unsigned HOST_WIDE_INT val8 = UINTVAL (op) & GET_MODE_MASK (QImode); 6210 fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, val8); 6211 } 6212 else 6213 output_operand_lossage ("invalid use of '%%%c'", letter); 6214 break; 6215 6216 case 'm': 6217 if (CONST_INT_P (op)) 6218 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op) - 1); 6219 else 6220 output_operand_lossage ("invalid use of '%%%c'", letter); 6221 break; 6222 6223 case 'N': 6224 loongarch_print_int_branch_condition (file, reverse_condition (code), 6225 letter); 6226 break; 6227 6228 case 'Q': 6229 if (!TARGET_LINKER_RELAXATION) 6230 break; 6231 6232 if (code == HIGH) 6233 op = XEXP (op, 0); 6234 6235 if (loongarch_classify_symbolic_expression (op) == SYMBOL_TLS_IE) 6236 fprintf (file, ".reloc\t.,R_LARCH_RELAX\n\t"); 6237 6238 break; 6239 6240 case 'r': 6241 loongarch_print_operand_reloc (file, op, false /* hi64_part */, 6242 true /* lo_reloc */); 6243 break; 6244 6245 case 'R': 6246 loongarch_print_operand_reloc (file, op, true /* hi64_part */, 6247 false /* lo_reloc */); 6248 break; 6249 6250 case 't': 6251 case 'T': 6252 { 6253 int truth = (code == NE) == (letter == 'T'); 6254 fputc ("zfnt"[truth * 2 + FCC_REG_P (REGNO (XEXP (op, 0)))], file); 6255 } 6256 break; 6257 6258 case 'V': 6259 if (CONST_VECTOR_P (op)) 6260 { 6261 machine_mode mode = GET_MODE_INNER (GET_MODE (op)); 6262 unsigned HOST_WIDE_INT val = UINTVAL (CONST_VECTOR_ELT (op, 0)); 6263 int vlog2 = exact_log2 (val & GET_MODE_MASK (mode)); 6264 if (vlog2 != -1) 6265 fprintf (file, "%d", vlog2); 6266 else 6267 output_operand_lossage ("invalid use of '%%%c'", letter); 6268 } 6269 else 6270 output_operand_lossage ("invalid use of '%%%c'", letter); 6271 break; 6272 6273 case 'W': 6274 loongarch_print_float_branch_condition (file, reverse_condition (code), 6275 letter); 6276 break; 6277 6278 case 'x': 6279 if (CONST_INT_P (op)) 6280 fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op) & 0xffff); 6281 else 6282 output_operand_lossage ("invalid use of '%%%c'", letter); 6283 break; 6284 6285 case 'X': 6286 if (CONST_INT_P (op)) 6287 fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op)); 6288 else 6289 output_operand_lossage ("invalid use of '%%%c'", letter); 6290 break; 6291 6292 case 'y': 6293 if (CONST_INT_P (op)) 6294 { 6295 int val = exact_log2 (INTVAL (op)); 6296 if (val != -1) 6297 fprintf (file, "%d", val); 6298 else 6299 output_operand_lossage ("invalid use of '%%%c'", letter); 6300 } 6301 else 6302 output_operand_lossage ("invalid use of '%%%c'", letter); 6303 break; 6304 6305 case 'Y': 6306 if (code == CONST_INT 6307 && UINTVAL (op) < ARRAY_SIZE (loongarch_fp_conditions)) 6308 fputs (loongarch_fp_conditions[UINTVAL (op)], file); 6309 else 6310 output_operand_lossage ("'%%%c' is not a valid operand prefix", 6311 letter); 6312 break; 6313 6314 case 'Z': 6315 loongarch_print_operand (file, op, 0); 6316 fputc (',', file); 6317 break; 6318 6319 case 'w': 6320 if (code == REG && LSX_REG_P (REGNO (op))) 6321 fprintf (file, "$vr%s", ®_names[REGNO (op)][2]); 6322 else 6323 output_operand_lossage ("invalid use of '%%%c'", letter); 6324 break; 6325 6326 case 'u': 6327 if (code == REG && LASX_REG_P (REGNO (op))) 6328 fprintf (file, "$xr%s", ®_names[REGNO (op)][2]); 6329 else 6330 output_operand_lossage ("invalid use of '%%%c'", letter); 6331 break; 6332 6333 case 'v': 6334 switch (GET_MODE (op)) 6335 { 6336 case E_V16QImode: 6337 case E_V32QImode: 6338 fprintf (file, "b"); 6339 break; 6340 case E_V8HImode: 6341 case E_V16HImode: 6342 fprintf (file, "h"); 6343 break; 6344 case E_V4SImode: 6345 case E_V4SFmode: 6346 case E_V8SImode: 6347 case E_V8SFmode: 6348 fprintf (file, "w"); 6349 break; 6350 case E_V2DImode: 6351 case E_V2DFmode: 6352 case E_V4DImode: 6353 case E_V4DFmode: 6354 fprintf (file, "d"); 6355 break; 6356 default: 6357 output_operand_lossage ("invalid use of '%%%c'", letter); 6358 } 6359 break; 6360 6361 default: 6362 switch (code) 6363 { 6364 case REG: 6365 { 6366 unsigned int regno = REGNO (op); 6367 if (letter && letter != 'z') 6368 output_operand_lossage ("invalid use of '%%%c'", letter); 6369 fprintf (file, "%s", reg_names[regno]); 6370 } 6371 break; 6372 6373 case MEM: 6374 if (letter == 'D') 6375 output_address (GET_MODE (op), 6376 plus_constant (Pmode, XEXP (op, 0), 4)); 6377 else if (letter == 'b') 6378 { 6379 gcc_assert (REG_P (XEXP (op, 0))); 6380 loongarch_print_operand (file, XEXP (op, 0), 0); 6381 } 6382 else if (letter && letter != 'z') 6383 output_operand_lossage ("invalid use of '%%%c'", letter); 6384 else 6385 output_address (GET_MODE (op), XEXP (op, 0)); 6386 break; 6387 6388 default: 6389 if (letter == 'z' && op == CONST0_RTX (GET_MODE (op))) 6390 fputs (reg_names[GP_REG_FIRST], file); 6391 else if (letter && letter != 'z') 6392 output_operand_lossage ("invalid use of '%%%c'", letter); 6393 else 6394 output_addr_const (file, loongarch_strip_unspec_address (op)); 6395 break; 6396 } 6397 } 6398 } 6399 6400 /* Implement TARGET_PRINT_OPERAND_ADDRESS. */ 6401 6402 static void 6403 loongarch_print_operand_address (FILE *file, machine_mode /* mode */, rtx x) 6404 { 6405 struct loongarch_address_info addr; 6406 6407 if (loongarch_classify_address (&addr, x, word_mode, true)) 6408 switch (addr.type) 6409 { 6410 case ADDRESS_REG: 6411 fprintf (file, "%s,", reg_names[REGNO (addr.reg)]); 6412 loongarch_print_operand (file, addr.offset, 0); 6413 return; 6414 6415 case ADDRESS_REG_REG: 6416 fprintf (file, "%s,%s", reg_names[REGNO (addr.reg)], 6417 reg_names[REGNO (addr.offset)]); 6418 return; 6419 6420 case ADDRESS_LO_SUM: 6421 fprintf (file, "%s,", reg_names[REGNO (addr.reg)]); 6422 loongarch_print_operand_reloc (file, addr.offset, false /* hi64_part */, 6423 false /* hi_reloc */); 6424 return; 6425 6426 case ADDRESS_CONST_INT: 6427 fprintf (file, "%s,", reg_names[GP_REG_FIRST]); 6428 output_addr_const (file, x); 6429 return; 6430 6431 case ADDRESS_SYMBOLIC: 6432 output_addr_const (file, loongarch_strip_unspec_address (x)); 6433 return; 6434 } 6435 if (CONST_INT_P (x)) 6436 output_addr_const (file, x); 6437 else 6438 gcc_unreachable (); 6439 } 6440 6441 /* Implement TARGET_ASM_SELECT_RTX_SECTION. */ 6442 6443 static section * 6444 loongarch_select_rtx_section (machine_mode mode, rtx x, 6445 unsigned HOST_WIDE_INT align) 6446 { 6447 /* ??? Consider using mergeable small data sections. */ 6448 if (loongarch_rtx_constant_in_small_data_p (mode)) 6449 return get_named_section (NULL, ".sdata", 0); 6450 6451 return default_elf_select_rtx_section (mode, x, align); 6452 } 6453 6454 /* Implement TARGET_ASM_FUNCTION_RODATA_SECTION. 6455 6456 The complication here is that jump tables will use absolute addresses, 6457 and should therefore not be included in the read-only part of a DSO. 6458 Handle such cases by selecting a normal data section instead of a 6459 read-only one. The logic apes that in default_function_rodata_section. */ 6460 6461 static section * 6462 loongarch_function_rodata_section (tree decl, bool) 6463 { 6464 return default_function_rodata_section (decl, false); 6465 } 6466 6467 /* Implement TARGET_IN_SMALL_DATA_P. */ 6468 6469 static bool 6470 loongarch_in_small_data_p (const_tree decl) 6471 { 6472 int size; 6473 6474 if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL) 6475 return false; 6476 6477 if (VAR_P (decl) && DECL_SECTION_NAME (decl) != 0) 6478 { 6479 const char *name; 6480 6481 /* Reject anything that isn't in a known small-data section. */ 6482 name = DECL_SECTION_NAME (decl); 6483 if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0) 6484 return false; 6485 6486 /* If a symbol is defined externally, the assembler will use the 6487 usual -G rules when deciding how to implement macros. */ 6488 if (!DECL_EXTERNAL (decl)) 6489 return true; 6490 } 6491 6492 /* We have traditionally not treated zero-sized objects as small data, 6493 so this is now effectively part of the ABI. */ 6494 size = int_size_in_bytes (TREE_TYPE (decl)); 6495 return size > 0 && size <= g_switch_value; 6496 } 6497 6498 /* The LoongArch debug format wants all automatic variables and arguments 6499 to be in terms of the virtual frame pointer (stack pointer before 6500 any adjustment in the function), while the LoongArch linker wants 6501 the frame pointer to be the stack pointer after the initial 6502 adjustment. So, we do the adjustment here. The arg pointer (which 6503 is eliminated) points to the virtual frame pointer, while the frame 6504 pointer (which may be eliminated) points to the stack pointer after 6505 the initial adjustments. */ 6506 6507 HOST_WIDE_INT 6508 loongarch_debugger_offset (rtx addr, HOST_WIDE_INT offset) 6509 { 6510 rtx offset2 = const0_rtx; 6511 rtx reg = eliminate_constant_term (addr, &offset2); 6512 6513 if (offset == 0) 6514 offset = INTVAL (offset2); 6515 6516 if (reg == stack_pointer_rtx 6517 || reg == frame_pointer_rtx 6518 || reg == hard_frame_pointer_rtx) 6519 { 6520 offset -= cfun->machine->frame.total_size; 6521 if (reg == hard_frame_pointer_rtx) 6522 offset += cfun->machine->frame.hard_frame_pointer_offset; 6523 } 6524 6525 return offset; 6526 } 6527 6528 /* Implement ASM_OUTPUT_EXTERNAL. */ 6529 6530 void 6531 loongarch_output_external (FILE *file, tree decl, const char *name) 6532 { 6533 default_elf_asm_output_external (file, decl, name); 6534 6535 /* We output the name if and only if TREE_SYMBOL_REFERENCED is 6536 set in order to avoid putting out names that are never really 6537 used. */ 6538 if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) 6539 { 6540 if (loongarch_in_small_data_p (decl)) 6541 { 6542 /* When using assembler macros, emit .extern directives for 6543 all small-data externs so that the assembler knows how 6544 big they are. 6545 6546 In most cases it would be safe (though pointless) to emit 6547 .externs for other symbols too. One exception is when an 6548 object is within the -G limit but declared by the user to 6549 be in a section other than .sbss or .sdata. */ 6550 fputs ("\t.extern\t", file); 6551 assemble_name (file, name); 6552 fprintf (file, ", " HOST_WIDE_INT_PRINT_DEC "\n", 6553 int_size_in_bytes (TREE_TYPE (decl))); 6554 } 6555 } 6556 } 6557 6558 /* Implement TARGET_ASM_OUTPUT_DWARF_DTPREL. */ 6559 6560 static void ATTRIBUTE_UNUSED 6561 loongarch_output_dwarf_dtprel (FILE *file, int size, rtx x) 6562 { 6563 switch (size) 6564 { 6565 case 4: 6566 fputs ("\t.dtprelword\t", file); 6567 break; 6568 6569 case 8: 6570 fputs ("\t.dtpreldword\t", file); 6571 break; 6572 6573 default: 6574 gcc_unreachable (); 6575 } 6576 output_addr_const (file, x); 6577 fputs ("+0x8000", file); 6578 } 6579 6580 /* Implement ASM_OUTPUT_ASCII. */ 6581 6582 void 6583 loongarch_output_ascii (FILE *stream, const char *string, size_t len) 6584 { 6585 size_t i; 6586 int cur_pos; 6587 6588 cur_pos = 17; 6589 fprintf (stream, "\t.ascii\t\""); 6590 for (i = 0; i < len; i++) 6591 { 6592 int c; 6593 6594 c = (unsigned char) string[i]; 6595 if (ISPRINT (c)) 6596 { 6597 if (c == '\\' || c == '\"') 6598 { 6599 putc ('\\', stream); 6600 cur_pos++; 6601 } 6602 putc (c, stream); 6603 cur_pos++; 6604 } 6605 else 6606 { 6607 fprintf (stream, "\\%03o", c); 6608 cur_pos += 4; 6609 } 6610 6611 if (cur_pos > 72 && i + 1 < len) 6612 { 6613 cur_pos = 17; 6614 fprintf (stream, "\"\n\t.ascii\t\""); 6615 } 6616 } 6617 fprintf (stream, "\"\n"); 6618 } 6619 6620 /* Implement TARGET_FRAME_POINTER_REQUIRED. */ 6621 6622 static bool 6623 loongarch_frame_pointer_required (void) 6624 { 6625 /* If the function contains dynamic stack allocations, we need to 6626 use the frame pointer to access the static parts of the frame. */ 6627 if (cfun->calls_alloca) 6628 return true; 6629 6630 return false; 6631 } 6632 6633 /* Implement TARGET_CAN_ELIMINATE. Make sure that we're not trying 6634 to eliminate to the wrong hard frame pointer. */ 6635 6636 static bool 6637 loongarch_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) 6638 { 6639 return (to == HARD_FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM); 6640 } 6641 6642 /* Implement RETURN_ADDR_RTX. We do not support moving back to a 6643 previous frame. */ 6644 6645 rtx 6646 loongarch_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) 6647 { 6648 if (count != 0) 6649 return const0_rtx; 6650 6651 return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNUM); 6652 } 6653 6654 /* Emit code to change the current function's return address to 6655 ADDRESS. SCRATCH is available as a scratch register, if needed. 6656 ADDRESS and SCRATCH are both word-mode GPRs. */ 6657 6658 void 6659 loongarch_set_return_address (rtx address, rtx scratch) 6660 { 6661 rtx slot_address; 6662 6663 gcc_assert (BITSET_P (cfun->machine->frame.mask, RETURN_ADDR_REGNUM)); 6664 6665 if (frame_pointer_needed) 6666 slot_address = loongarch_add_offset (scratch, hard_frame_pointer_rtx, 6667 -UNITS_PER_WORD); 6668 else 6669 slot_address = loongarch_add_offset (scratch, stack_pointer_rtx, 6670 cfun->machine->frame.gp_sp_offset); 6671 6672 loongarch_emit_move (gen_frame_mem (GET_MODE (address), slot_address), 6673 address); 6674 } 6675 6676 /* Return true if register REGNO can store a value of mode MODE. 6677 The result of this function is cached in loongarch_hard_regno_mode_ok. */ 6678 6679 static bool 6680 loongarch_hard_regno_mode_ok_uncached (unsigned int regno, machine_mode mode) 6681 { 6682 unsigned int size; 6683 enum mode_class mclass; 6684 6685 if (mode == FCCmode) 6686 return FCC_REG_P (regno) || GP_REG_P (regno) || FP_REG_P (regno); 6687 6688 size = GET_MODE_SIZE (mode); 6689 mclass = GET_MODE_CLASS (mode); 6690 6691 if (GP_REG_P (regno) && !LSX_SUPPORTED_MODE_P (mode) 6692 && !LASX_SUPPORTED_MODE_P (mode)) 6693 return ((regno - GP_REG_FIRST) & 1) == 0 || size <= UNITS_PER_WORD; 6694 6695 /* For LSX, allow TImode and 128-bit vector modes in all FPR. */ 6696 if (FP_REG_P (regno) && LSX_SUPPORTED_MODE_P (mode)) 6697 return true; 6698 6699 /* FIXED ME: For LASX, allow TImode and 256-bit vector modes in all FPR. */ 6700 if (FP_REG_P (regno) && LASX_SUPPORTED_MODE_P (mode)) 6701 return true; 6702 6703 if (FP_REG_P (regno)) 6704 { 6705 if (mclass == MODE_FLOAT 6706 || mclass == MODE_COMPLEX_FLOAT 6707 || mclass == MODE_VECTOR_FLOAT) 6708 return size <= UNITS_PER_HWFPVALUE; 6709 6710 /* Allow integer modes that fit into a single register. We need 6711 to put integers into FPRs when using instructions like CVT 6712 and TRUNC. There's no point allowing sizes smaller than a word, 6713 because the FPU has no appropriate load/store instructions. */ 6714 if (mclass == MODE_INT) 6715 return size >= MIN_UNITS_PER_WORD && size <= UNITS_PER_FP_REG; 6716 } 6717 6718 return false; 6719 } 6720 6721 /* Implement TARGET_HARD_REGNO_MODE_OK. */ 6722 6723 static bool 6724 loongarch_hard_regno_mode_ok (unsigned int regno, machine_mode mode) 6725 { 6726 return loongarch_hard_regno_mode_ok_p[mode][regno]; 6727 } 6728 6729 6730 static bool 6731 loongarch_hard_regno_call_part_clobbered (unsigned int, 6732 unsigned int regno, machine_mode mode) 6733 { 6734 if (ISA_HAS_LSX && FP_REG_P (regno) && GET_MODE_SIZE (mode) > 8) 6735 return true; 6736 6737 return false; 6738 } 6739 6740 /* Implement TARGET_HARD_REGNO_NREGS. */ 6741 6742 static unsigned int 6743 loongarch_hard_regno_nregs (unsigned int regno, machine_mode mode) 6744 { 6745 if (FCC_REG_P (regno)) 6746 /* The size of FP status registers is always 4, because they only hold 6747 FCCmode values, and FCCmode is always considered to be 4 bytes wide. */ 6748 return (GET_MODE_SIZE (mode) + 3) / 4; 6749 6750 if (FP_REG_P (regno)) 6751 { 6752 if (LSX_SUPPORTED_MODE_P (mode)) 6753 return 1; 6754 6755 if (LASX_SUPPORTED_MODE_P (mode)) 6756 return 1; 6757 6758 return (GET_MODE_SIZE (mode) + UNITS_PER_FP_REG - 1) / UNITS_PER_FP_REG; 6759 } 6760 6761 /* All other registers are word-sized. */ 6762 return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 6763 } 6764 6765 /* Implement CLASS_MAX_NREGS, taking the maximum of the cases 6766 in loongarch_hard_regno_nregs. */ 6767 6768 int 6769 loongarch_class_max_nregs (enum reg_class rclass, machine_mode mode) 6770 { 6771 int size; 6772 HARD_REG_SET left; 6773 6774 size = 0x8000; 6775 left = reg_class_contents[rclass]; 6776 if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FCC_REGS])) 6777 { 6778 if (loongarch_hard_regno_mode_ok (FCC_REG_FIRST, mode)) 6779 size = MIN (size, 4); 6780 6781 left &= ~reg_class_contents[FCC_REGS]; 6782 } 6783 if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FP_REGS])) 6784 { 6785 if (loongarch_hard_regno_mode_ok (FP_REG_FIRST, mode)) 6786 { 6787 /* Fixed me. */ 6788 if (LASX_SUPPORTED_MODE_P (mode)) 6789 size = MIN (size, UNITS_PER_LASX_REG); 6790 else if (LSX_SUPPORTED_MODE_P (mode)) 6791 size = MIN (size, UNITS_PER_LSX_REG); 6792 else 6793 size = MIN (size, UNITS_PER_FP_REG); 6794 } 6795 left &= ~reg_class_contents[FP_REGS]; 6796 } 6797 if (!hard_reg_set_empty_p (left)) 6798 size = MIN (size, UNITS_PER_WORD); 6799 return (GET_MODE_SIZE (mode) + size - 1) / size; 6800 } 6801 6802 /* Implement TARGET_CAN_CHANGE_MODE_CLASS. */ 6803 6804 static bool 6805 loongarch_can_change_mode_class (machine_mode from, machine_mode to, 6806 reg_class_t rclass) 6807 { 6808 /* Allow conversions between different LSX/LASX vector modes. */ 6809 if (LASX_SUPPORTED_MODE_P (from) && LASX_SUPPORTED_MODE_P (to)) 6810 return true; 6811 6812 /* Allow conversions between different LSX vector modes. */ 6813 if (LSX_SUPPORTED_MODE_P (from) && LSX_SUPPORTED_MODE_P (to)) 6814 return true; 6815 6816 /* Allow conversion between LSX vector mode and scalar fp mode. */ 6817 if ((LSX_SUPPORTED_MODE_P (from) && SCALAR_FLOAT_MODE_P (to)) 6818 || ((SCALAR_FLOAT_MODE_P (from) && LSX_SUPPORTED_MODE_P (to)))) 6819 return true; 6820 6821 return !reg_classes_intersect_p (FP_REGS, rclass); 6822 } 6823 6824 /* Return true if moves in mode MODE can use the FPU's fmov.fmt instruction, 6825 */ 6826 6827 static bool 6828 loongarch_mode_ok_for_mov_fmt_p (machine_mode mode) 6829 { 6830 switch (mode) 6831 { 6832 case E_FCCmode: 6833 case E_SFmode: 6834 return TARGET_HARD_FLOAT; 6835 6836 case E_DFmode: 6837 return TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT; 6838 6839 default: 6840 return ISA_HAS_LASX ? LASX_SUPPORTED_MODE_P (mode) 6841 : LSX_SUPPORTED_MODE_P (mode); 6842 } 6843 } 6844 6845 /* Implement TARGET_MODES_TIEABLE_P. */ 6846 6847 static bool 6848 loongarch_modes_tieable_p (machine_mode mode1, machine_mode mode2) 6849 { 6850 /* FPRs allow no mode punning, so it's not worth tying modes if we'd 6851 prefer to put one of them in FPRs. */ 6852 return (mode1 == mode2 6853 || (!loongarch_mode_ok_for_mov_fmt_p (mode1) 6854 && !loongarch_mode_ok_for_mov_fmt_p (mode2))); 6855 } 6856 6857 /* Implement TARGET_PREFERRED_RELOAD_CLASS. */ 6858 6859 static reg_class_t 6860 loongarch_preferred_reload_class (rtx x, reg_class_t rclass) 6861 { 6862 if (reg_class_subset_p (FP_REGS, rclass) 6863 && loongarch_mode_ok_for_mov_fmt_p (GET_MODE (x))) 6864 return FP_REGS; 6865 6866 if (reg_class_subset_p (GR_REGS, rclass)) 6867 rclass = GR_REGS; 6868 6869 return rclass; 6870 } 6871 6872 /* RCLASS is a class involved in a REGISTER_MOVE_COST calculation. 6873 Return a "canonical" class to represent it in later calculations. */ 6874 6875 static reg_class_t 6876 loongarch_canonicalize_move_class (reg_class_t rclass) 6877 { 6878 if (reg_class_subset_p (rclass, GENERAL_REGS)) 6879 rclass = GENERAL_REGS; 6880 6881 return rclass; 6882 } 6883 6884 /* Return the cost of moving a value from a register of class FROM to a GPR. 6885 Return 0 for classes that are unions of other classes handled by this 6886 function. */ 6887 6888 static int 6889 loongarch_move_to_gpr_cost (reg_class_t from) 6890 { 6891 switch (from) 6892 { 6893 case GENERAL_REGS: 6894 /* MOVE macro. */ 6895 return 2; 6896 6897 case FP_REGS: 6898 /* MOVFR2GR, etc. */ 6899 return 4; 6900 6901 case FCC_REGS: 6902 return loongarch_cost->movcf2gr; 6903 6904 default: 6905 return 0; 6906 } 6907 } 6908 6909 /* Return the cost of moving a value from a GPR to a register of class TO. 6910 Return 0 for classes that are unions of other classes handled by this 6911 function. */ 6912 6913 static int 6914 loongarch_move_from_gpr_cost (reg_class_t to) 6915 { 6916 switch (to) 6917 { 6918 case GENERAL_REGS: 6919 /*MOVE macro. */ 6920 return 2; 6921 6922 case FP_REGS: 6923 /* MOVGR2FR, etc. */ 6924 return 4; 6925 6926 case FCC_REGS: 6927 return loongarch_cost->movgr2cf; 6928 6929 default: 6930 return 0; 6931 } 6932 } 6933 6934 /* Implement TARGET_REGISTER_MOVE_COST. Return 0 for classes that are the 6935 maximum of the move costs for subclasses; regclass will work out 6936 the maximum for us. */ 6937 6938 static int 6939 loongarch_register_move_cost (machine_mode mode, reg_class_t from, 6940 reg_class_t to) 6941 { 6942 reg_class_t dregs; 6943 int cost1, cost2; 6944 6945 from = loongarch_canonicalize_move_class (from); 6946 to = loongarch_canonicalize_move_class (to); 6947 6948 /* Handle moves that can be done without using general-purpose registers. */ 6949 if (from == FP_REGS) 6950 { 6951 if (to == FP_REGS && loongarch_mode_ok_for_mov_fmt_p (mode)) 6952 /* FMOV.FMT. */ 6953 return 4; 6954 } 6955 6956 /* Handle cases in which only one class deviates from the ideal. */ 6957 dregs = GENERAL_REGS; 6958 if (from == dregs) 6959 return loongarch_move_from_gpr_cost (to); 6960 if (to == dregs) 6961 return loongarch_move_to_gpr_cost (from); 6962 6963 /* fcc -> fcc, fcc -> fpr, or fpr -> fcc. */ 6964 if (from == FCC_REGS || to == FCC_REGS) 6965 return COSTS_N_INSNS (from == to ? 2 : 1); 6966 6967 /* Handles cases that require a GPR temporary. */ 6968 cost1 = loongarch_move_to_gpr_cost (from); 6969 if (cost1 != 0) 6970 { 6971 cost2 = loongarch_move_from_gpr_cost (to); 6972 if (cost2 != 0) 6973 return cost1 + cost2; 6974 } 6975 6976 return 0; 6977 } 6978 6979 /* Implement TARGET_MEMORY_MOVE_COST. */ 6980 6981 static int 6982 loongarch_memory_move_cost (machine_mode mode, reg_class_t rclass, bool in) 6983 { 6984 return (loongarch_cost->memory_latency 6985 + memory_move_secondary_cost (mode, rclass, in)); 6986 } 6987 6988 /* Return the register class required for a secondary register when 6989 copying between one of the registers in RCLASS and value X, which 6990 has mode MODE. X is the source of the move if IN_P, otherwise it 6991 is the destination. Return NO_REGS if no secondary register is 6992 needed. */ 6993 6994 static reg_class_t 6995 loongarch_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, 6996 reg_class_t rclass, machine_mode mode, 6997 secondary_reload_info *sri ATTRIBUTE_UNUSED) 6998 { 6999 int regno; 7000 7001 regno = true_regnum (x); 7002 7003 if (mode == FCCmode) 7004 { 7005 if (reg_class_subset_p (rclass, FCC_REGS) && !FP_REG_P (regno)) 7006 { 7007 if (FCC_REG_P (regno)) 7008 return FP_REGS; 7009 7010 auto fn = in_p ? loongarch_move_from_gpr_cost 7011 : loongarch_move_to_gpr_cost; 7012 7013 if (fn (FCC_REGS) > fn (FP_REGS) + COSTS_N_INSNS (1)) 7014 return FP_REGS; 7015 7016 return GP_REG_P (regno) ? NO_REGS : GR_REGS; 7017 } 7018 7019 if (reg_class_subset_p (rclass, GR_REGS) && FCC_REG_P (regno)) 7020 { 7021 auto fn = in_p ? loongarch_move_to_gpr_cost 7022 : loongarch_move_from_gpr_cost; 7023 7024 if (fn (FCC_REGS) > fn (FP_REGS) + COSTS_N_INSNS (1)) 7025 return FP_REGS; 7026 7027 return NO_REGS; 7028 } 7029 7030 if (reg_class_subset_p (rclass, FP_REGS) 7031 && (regno == -1 || MEM_P (x))) 7032 return GR_REGS; 7033 7034 return NO_REGS; 7035 } 7036 7037 if (reg_class_subset_p (rclass, FP_REGS)) 7038 { 7039 if (regno < 0 7040 || (MEM_P (x) 7041 && (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8))) 7042 /* In this case we can use lwc1, swc1, ldc1 or sdc1. We'll use 7043 pairs of lwc1s and swc1s if ldc1 and sdc1 are not supported. */ 7044 return NO_REGS; 7045 7046 if (MEM_P (x) && LSX_SUPPORTED_MODE_P (mode)) 7047 /* In this case we can use LSX LD.* and ST.*. */ 7048 return NO_REGS; 7049 7050 if (GP_REG_P (regno) || x == CONST0_RTX (mode)) 7051 /* In this case we can use movgr2fr.s, movfr2gr.s, movgr2fr.d or 7052 * movfr2gr.d. */ 7053 return NO_REGS; 7054 7055 if (CONSTANT_P (x) && !targetm.cannot_force_const_mem (mode, x)) 7056 /* We can force the constant to memory and use fld.s 7057 and fld.d. As above, we will use pairs of lwc1s if 7058 ldc1 is not supported. */ 7059 return NO_REGS; 7060 7061 if (FP_REG_P (regno) && loongarch_mode_ok_for_mov_fmt_p (mode)) 7062 /* In this case we can use fmov.{s/d}. */ 7063 return NO_REGS; 7064 7065 /* Otherwise, we need to reload through an integer register. */ 7066 return GR_REGS; 7067 } 7068 if (FP_REG_P (regno)) 7069 return reg_class_subset_p (rclass, GR_REGS) ? NO_REGS : GR_REGS; 7070 7071 return NO_REGS; 7072 } 7073 7074 /* Implement TARGET_VALID_POINTER_MODE. */ 7075 7076 static bool 7077 loongarch_valid_pointer_mode (scalar_int_mode mode) 7078 { 7079 return mode == SImode || (TARGET_64BIT && mode == DImode); 7080 } 7081 7082 /* Implement TARGET_VECTOR_MODE_SUPPORTED_P. */ 7083 7084 static bool 7085 loongarch_vector_mode_supported_p (machine_mode mode) 7086 { 7087 return ISA_HAS_LASX ? LASX_SUPPORTED_MODE_P (mode) 7088 : LSX_SUPPORTED_MODE_P (mode); 7089 } 7090 7091 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */ 7092 7093 static bool 7094 loongarch_scalar_mode_supported_p (scalar_mode mode) 7095 { 7096 if (ALL_FIXED_POINT_MODE_P (mode) 7097 && GET_MODE_PRECISION (mode) <= 2 * BITS_PER_WORD) 7098 return true; 7099 7100 return default_scalar_mode_supported_p (mode); 7101 } 7102 7103 /* Implement TARGET_VECTORIZE_PREFERRED_SIMD_MODE. */ 7104 7105 static machine_mode 7106 loongarch_preferred_simd_mode (scalar_mode mode) 7107 { 7108 if (!ISA_HAS_LSX) 7109 return word_mode; 7110 7111 switch (mode) 7112 { 7113 case E_QImode: 7114 return ISA_HAS_LASX ? E_V32QImode : E_V16QImode; 7115 case E_HImode: 7116 return ISA_HAS_LASX ? E_V16HImode : E_V8HImode; 7117 case E_SImode: 7118 return ISA_HAS_LASX ? E_V8SImode : E_V4SImode; 7119 case E_DImode: 7120 return ISA_HAS_LASX ? E_V4DImode : E_V2DImode; 7121 7122 case E_SFmode: 7123 return ISA_HAS_LASX ? E_V8SFmode : E_V4SFmode; 7124 7125 case E_DFmode: 7126 return ISA_HAS_LASX ? E_V4DFmode : E_V2DFmode; 7127 7128 default: 7129 break; 7130 } 7131 return word_mode; 7132 } 7133 7134 static unsigned int 7135 loongarch_autovectorize_vector_modes (vector_modes *modes, bool) 7136 { 7137 if (ISA_HAS_LASX) 7138 { 7139 modes->safe_push (V32QImode); 7140 modes->safe_push (V16QImode); 7141 } 7142 else if (ISA_HAS_LSX) 7143 { 7144 modes->safe_push (V16QImode); 7145 } 7146 7147 return 0; 7148 } 7149 7150 /* Return the assembly code for INSN, which has the operands given by 7151 OPERANDS, and which branches to OPERANDS[0] if some condition is true. 7152 BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[0] 7153 is in range of a direct branch. BRANCH_IF_FALSE is an inverted 7154 version of BRANCH_IF_TRUE. */ 7155 7156 const char * 7157 loongarch_output_conditional_branch (rtx_insn *insn, rtx *operands, 7158 const char *branch_if_true, 7159 const char *branch_if_false) 7160 { 7161 unsigned int length; 7162 rtx taken; 7163 7164 gcc_assert (LABEL_P (operands[0])); 7165 7166 length = get_attr_length (insn); 7167 if (length <= 4) 7168 { 7169 return branch_if_true; 7170 } 7171 7172 /* Generate a reversed branch around a direct jump. */ 7173 rtx_code_label *not_taken = gen_label_rtx (); 7174 taken = operands[0]; 7175 7176 /* Generate the reversed branch to NOT_TAKEN. */ 7177 operands[0] = not_taken; 7178 output_asm_insn (branch_if_false, operands); 7179 7180 output_asm_insn ("b\t%0", &taken); 7181 7182 /* Output NOT_TAKEN. */ 7183 targetm.asm_out.internal_label (asm_out_file, "L", 7184 CODE_LABEL_NUMBER (not_taken)); 7185 return ""; 7186 } 7187 7188 /* Return the assembly code for INSN, which branches to OPERANDS[0] 7189 if some equality condition is true. The condition is given by 7190 OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of 7191 OPERANDS[1]. OPERANDS[2] is the comparison's first operand; 7192 OPERANDS[3] is the second operand and may be zero or a register. */ 7193 7194 const char * 7195 loongarch_output_equal_conditional_branch (rtx_insn *insn, rtx *operands, 7196 bool inverted_p) 7197 { 7198 const char *branch[2]; 7199 if (operands[3] == const0_rtx) 7200 { 7201 branch[!inverted_p] = LARCH_BRANCH ("b%C1z", "%2,%0"); 7202 branch[inverted_p] = LARCH_BRANCH ("b%N1z", "%2,%0"); 7203 } 7204 else 7205 { 7206 branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,%z3,%0"); 7207 branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,%z3,%0"); 7208 } 7209 7210 return loongarch_output_conditional_branch (insn, operands, branch[1], 7211 branch[0]); 7212 } 7213 7214 /* Return the assembly code for INSN, which branches to OPERANDS[0] 7215 if some ordering condition is true. The condition is given by 7216 OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of 7217 OPERANDS[1]. OPERANDS[2] is the comparison's first operand; 7218 OPERANDS[3] is the second operand and may be zero or a register. */ 7219 7220 const char * 7221 loongarch_output_order_conditional_branch (rtx_insn *insn, rtx *operands, 7222 bool inverted_p) 7223 { 7224 const char *branch[2]; 7225 7226 /* Make BRANCH[1] branch to OPERANDS[0] when the condition is true. 7227 Make BRANCH[0] branch on the inverse condition. */ 7228 if (operands[3] != const0_rtx) 7229 { 7230 /* Handle degenerate cases that should not, but do, occur. */ 7231 if (REGNO (operands[2]) == REGNO (operands[3])) 7232 { 7233 switch (GET_CODE (operands[1])) 7234 { 7235 case LT: 7236 case LTU: 7237 case GT: 7238 case GTU: 7239 inverted_p = !inverted_p; 7240 /* Fall through. */ 7241 case LE: 7242 case LEU: 7243 case GE: 7244 case GEU: 7245 branch[!inverted_p] = LARCH_BRANCH ("b", "%0"); 7246 branch[inverted_p] = "\t# branch never"; 7247 break; 7248 default: 7249 gcc_unreachable (); 7250 } 7251 } 7252 else 7253 { 7254 switch (GET_CODE (operands[1])) 7255 { 7256 case LE: 7257 case LEU: 7258 case GT: 7259 case GTU: 7260 case LT: 7261 case LTU: 7262 case GE: 7263 case GEU: 7264 branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,%3,%0"); 7265 branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,%3,%0"); 7266 break; 7267 default: 7268 gcc_unreachable (); 7269 } 7270 } 7271 } 7272 else 7273 { 7274 switch (GET_CODE (operands[1])) 7275 { 7276 /* These cases are equivalent to comparisons against zero. */ 7277 case LEU: 7278 case GTU: 7279 case LTU: 7280 case GEU: 7281 case LE: 7282 case GT: 7283 case LT: 7284 case GE: 7285 branch[!inverted_p] = LARCH_BRANCH ("b%C1", "%2,$r0,%0"); 7286 branch[inverted_p] = LARCH_BRANCH ("b%N1", "%2,$r0,%0"); 7287 break; 7288 default: 7289 gcc_unreachable (); 7290 } 7291 } 7292 return loongarch_output_conditional_branch (insn, operands, branch[1], 7293 branch[0]); 7294 } 7295 7296 /* Return the assembly code for DIV.{W/D} instruction DIVISION, which has 7297 the operands given by OPERANDS. Add in a divide-by-zero check if needed. 7298 */ 7299 7300 const char * 7301 loongarch_output_division (const char *division, rtx *operands) 7302 { 7303 const char *s; 7304 7305 s = division; 7306 if (loongarch_check_zero_div_p ()) 7307 { 7308 output_asm_insn (s, operands); 7309 s = "bne\t%2,%.,1f\n\tbreak\t7\n1:"; 7310 } 7311 return s; 7312 } 7313 7314 /* Return the assembly code for LSX DIV_{S,U}.DF or MOD_{S,U}.DF instructions, 7315 which has the operands given by OPERANDS. Add in a divide-by-zero check 7316 if needed. */ 7317 7318 const char * 7319 loongarch_lsx_output_division (const char *division, rtx *operands) 7320 { 7321 const char *s; 7322 machine_mode mode = GET_MODE (*operands); 7323 7324 s = division; 7325 if (TARGET_CHECK_ZERO_DIV) 7326 { 7327 if (ISA_HAS_LASX && GET_MODE_SIZE (mode) == 32) 7328 { 7329 output_asm_insn ("xvsetallnez.%v0\t$fcc7,%u2",operands); 7330 output_asm_insn (s, operands); 7331 output_asm_insn ("bcnez\t$fcc7,1f", operands); 7332 } 7333 else if (ISA_HAS_LSX) 7334 { 7335 output_asm_insn ("vsetallnez.%v0\t$fcc7,%w2",operands); 7336 output_asm_insn (s, operands); 7337 output_asm_insn ("bcnez\t$fcc7,1f", operands); 7338 } 7339 s = "break\t7\n1:"; 7340 } 7341 return s; 7342 } 7343 7344 /* Implement TARGET_SCHED_ADJUST_COST. We assume that anti and output 7345 dependencies have no cost. */ 7346 7347 static int 7348 loongarch_adjust_cost (rtx_insn *, int dep_type, rtx_insn *, int cost, 7349 unsigned int) 7350 { 7351 if (dep_type != 0 && (dep_type != REG_DEP_OUTPUT)) 7352 return 0; 7353 return cost; 7354 } 7355 7356 /* Return the number of instructions that can be issued per cycle. */ 7357 7358 static int 7359 loongarch_issue_rate (void) 7360 { 7361 if ((unsigned long) la_target.cpu_tune < N_TUNE_TYPES) 7362 return loongarch_cpu_issue_rate[la_target.cpu_tune]; 7363 else 7364 return 1; 7365 } 7366 7367 /* Implement TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD. This should 7368 be as wide as the scheduling freedom in the DFA. */ 7369 7370 static int 7371 loongarch_multipass_dfa_lookahead (void) 7372 { 7373 if ((unsigned long) la_target.cpu_tune < N_ARCH_TYPES) 7374 return loongarch_cpu_multipass_dfa_lookahead[la_target.cpu_tune]; 7375 else 7376 return 0; 7377 } 7378 7379 /* Implement TARGET_SCHED_REORDER. */ 7380 7381 static int 7382 loongarch_sched_reorder (FILE *file ATTRIBUTE_UNUSED, 7383 int verbose ATTRIBUTE_UNUSED, 7384 rtx_insn **ready ATTRIBUTE_UNUSED, 7385 int *nreadyp ATTRIBUTE_UNUSED, 7386 int cycle ATTRIBUTE_UNUSED) 7387 { 7388 return loongarch_issue_rate (); 7389 } 7390 7391 /* Implement TARGET_SCHED_REORDER2. */ 7392 7393 static int 7394 loongarch_sched_reorder2 (FILE *file ATTRIBUTE_UNUSED, 7395 int verbose ATTRIBUTE_UNUSED, 7396 rtx_insn **ready ATTRIBUTE_UNUSED, 7397 int *nreadyp ATTRIBUTE_UNUSED, 7398 int cycle ATTRIBUTE_UNUSED) 7399 { 7400 return cached_can_issue_more; 7401 } 7402 7403 /* Implement TARGET_SCHED_INIT. */ 7404 7405 static void 7406 loongarch_sched_init (FILE *file ATTRIBUTE_UNUSED, 7407 int verbose ATTRIBUTE_UNUSED, 7408 int max_ready ATTRIBUTE_UNUSED) 7409 {} 7410 7411 /* Implement TARGET_SCHED_VARIABLE_ISSUE. */ 7412 7413 static int 7414 loongarch_variable_issue (FILE *file ATTRIBUTE_UNUSED, 7415 int verbose ATTRIBUTE_UNUSED, rtx_insn *insn, 7416 int more) 7417 { 7418 /* Ignore USEs and CLOBBERs; don't count them against the issue rate. */ 7419 if (USEFUL_INSN_P (insn)) 7420 { 7421 if (get_attr_type (insn) != TYPE_GHOST) 7422 more--; 7423 } 7424 7425 /* Instructions of type 'multi' should all be split before 7426 the second scheduling pass. */ 7427 gcc_assert (!reload_completed 7428 || recog_memoized (insn) < 0 7429 || get_attr_type (insn) != TYPE_MULTI); 7430 7431 cached_can_issue_more = more; 7432 return more; 7433 } 7434 7435 /* Given that we have an rtx of the form (prefetch ... WRITE LOCALITY), 7436 return the first operand of the associated PREF or PREFX insn. */ 7437 7438 rtx 7439 loongarch_prefetch_cookie (rtx write, rtx locality) 7440 { 7441 /* store_streamed / load_streamed. */ 7442 if (INTVAL (locality) <= 0) 7443 return GEN_INT (INTVAL (write) + 4); 7444 7445 /* store / load. */ 7446 if (INTVAL (locality) <= 2) 7447 return write; 7448 7449 /* store_retained / load_retained. */ 7450 return GEN_INT (INTVAL (write) + 6); 7451 } 7452 7453 /* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text 7454 in order to avoid duplicating too much logic from elsewhere. */ 7455 7456 static void 7457 loongarch_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, 7458 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, 7459 tree function) 7460 { 7461 const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk_fndecl)); 7462 rtx this_rtx, temp1, temp2, fnaddr; 7463 rtx_insn *insn; 7464 bool use_sibcall_p; 7465 7466 /* Pretend to be a post-reload pass while generating rtl. */ 7467 reload_completed = 1; 7468 7469 /* Mark the end of the (empty) prologue. */ 7470 emit_note (NOTE_INSN_PROLOGUE_END); 7471 7472 /* Determine if we can use a sibcall to call FUNCTION directly. */ 7473 fnaddr = XEXP (DECL_RTL (function), 0); 7474 use_sibcall_p = const_call_insn_operand (fnaddr, Pmode); 7475 7476 /* We need two temporary registers in some cases. */ 7477 temp1 = gen_rtx_REG (Pmode, 12); 7478 temp2 = gen_rtx_REG (Pmode, 13); 7479 7480 /* Find out which register contains the "this" pointer. */ 7481 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) 7482 this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1); 7483 else 7484 this_rtx = gen_rtx_REG (Pmode, GP_ARG_FIRST); 7485 7486 /* Add DELTA to THIS_RTX. */ 7487 if (delta != 0) 7488 { 7489 rtx offset = GEN_INT (delta); 7490 if (!IMM12_OPERAND (delta)) 7491 { 7492 loongarch_emit_move (temp1, offset); 7493 offset = temp1; 7494 } 7495 emit_insn (gen_add3_insn (this_rtx, this_rtx, offset)); 7496 } 7497 7498 /* If needed, add *(*THIS_RTX + VCALL_OFFSET) to THIS_RTX. */ 7499 if (vcall_offset != 0) 7500 { 7501 rtx addr; 7502 7503 /* Set TEMP1 to *THIS_RTX. */ 7504 loongarch_emit_move (temp1, gen_rtx_MEM (Pmode, this_rtx)); 7505 7506 /* Set ADDR to a legitimate address for *THIS_RTX + VCALL_OFFSET. */ 7507 addr = loongarch_add_offset (temp2, temp1, vcall_offset); 7508 7509 /* Load the offset and add it to THIS_RTX. */ 7510 loongarch_emit_move (temp1, gen_rtx_MEM (Pmode, addr)); 7511 emit_insn (gen_add3_insn (this_rtx, this_rtx, temp1)); 7512 } 7513 7514 /* Jump to the target function. Use a sibcall if direct jumps are 7515 allowed, otherwise load the address into a register first. */ 7516 if (use_sibcall_p) 7517 { 7518 /* If TARGET_CMODEL_EXTREME, we cannot do a direct jump at all 7519 and const_call_insn_operand should have returned false. */ 7520 gcc_assert (!TARGET_CMODEL_EXTREME); 7521 7522 insn = emit_call_insn (gen_sibcall_internal (fnaddr, const0_rtx)); 7523 SIBLING_CALL_P (insn) = 1; 7524 } 7525 else 7526 { 7527 if (!TARGET_CMODEL_EXTREME) 7528 loongarch_emit_move (temp1, fnaddr); 7529 else if (la_opt_explicit_relocs == EXPLICIT_RELOCS_NONE) 7530 emit_insn (gen_movdi_symbolic_off64 (temp1, fnaddr, temp2)); 7531 else 7532 { 7533 emit_insn (gen_la_pcrel64_two_parts (temp1, temp2, fnaddr)); 7534 emit_move_insn (temp1, gen_rtx_PLUS (Pmode, temp1, temp2)); 7535 } 7536 7537 emit_jump_insn (gen_indirect_jump (temp1)); 7538 } 7539 7540 /* Run just enough of rest_of_compilation. This sequence was 7541 "borrowed" from alpha.c. */ 7542 insn = get_insns (); 7543 split_all_insns_noflow (); 7544 shorten_branches (insn); 7545 assemble_start_function (thunk_fndecl, fnname); 7546 final_start_function (insn, file, 1); 7547 final (insn, file, 1); 7548 final_end_function (); 7549 assemble_end_function (thunk_fndecl, fnname); 7550 7551 /* Stop pretending to be a post-reload pass. */ 7552 reload_completed = 0; 7553 } 7554 7555 /* Allocate a chunk of memory for per-function machine-dependent data. */ 7556 7557 static struct machine_function * 7558 loongarch_init_machine_status (void) 7559 { 7560 return ggc_cleared_alloc<machine_function> (); 7561 } 7562 7563 static void 7564 loongarch_global_init (void) 7565 { 7566 /* Initialize loongarch_print_operand_punct. */ 7567 for (const char *p = ".$"; *p; p++) 7568 loongarch_print_operand_punct[(unsigned char) *p] = true; 7569 7570 /* Set up array to map GCC register number to debug register number. 7571 Ignore the special purpose register numbers. */ 7572 for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++) 7573 { 7574 if (GP_REG_P (i) || FP_REG_P (i)) 7575 loongarch_dwarf_regno[i] = i; 7576 else 7577 loongarch_dwarf_regno[i] = INVALID_REGNUM; 7578 } 7579 7580 /* Function to allocate machine-dependent function status. */ 7581 init_machine_status = &loongarch_init_machine_status; 7582 }; 7583 7584 static void 7585 loongarch_reg_init (void) 7586 { 7587 /* Set up loongarch_hard_regno_mode_ok. */ 7588 for (int mode = 0; mode < MAX_MACHINE_MODE; mode++) 7589 for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 7590 loongarch_hard_regno_mode_ok_p[mode][regno] 7591 = loongarch_hard_regno_mode_ok_uncached (regno, (machine_mode) mode); 7592 } 7593 7594 static void 7595 loongarch_option_override_internal (struct loongarch_target *target, 7596 struct gcc_options *opts, 7597 struct gcc_options *opts_set) 7598 { 7599 /* Handle options not covered by struct loongarch_target. */ 7600 loongarch_init_misc_options (opts, opts_set); 7601 7602 /* Resolve the target struct. */ 7603 loongarch_init_target (target, 7604 opts->x_la_opt_cpu_arch, 7605 opts->x_la_opt_cpu_tune, 7606 opts->x_la_opt_fpu, 7607 opts->x_la_opt_simd, 7608 opts->x_la_opt_abi_base, 7609 opts->x_la_opt_abi_ext, 7610 opts->x_la_opt_cmodel, 7611 opts->x_la_opt_tls_dialect, 7612 opts->x_la_isa_evolution, 7613 opts_set->x_la_isa_evolution); 7614 7615 loongarch_config_target (target, NULL, 0); 7616 7617 /* Override some options according to the resolved target. */ 7618 loongarch_target_option_override (target, opts, opts_set); 7619 7620 target_option_default_node = target_option_current_node 7621 = build_target_option_node (opts, opts_set); 7622 7623 loongarch_reg_init (); 7624 } 7625 7626 /* Remember the last target of loongarch_set_current_function. */ 7627 7628 static GTY(()) tree loongarch_previous_fndecl; 7629 7630 /* Restore or save the TREE_TARGET_GLOBALS from or to new_tree. 7631 Used by loongarch_set_current_function to 7632 make sure optab availability predicates are recomputed when necessary. */ 7633 7634 static void 7635 loongarch_save_restore_target_globals (tree new_tree) 7636 { 7637 if (TREE_TARGET_GLOBALS (new_tree)) 7638 restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); 7639 else if (new_tree == target_option_default_node) 7640 restore_target_globals (&default_target_globals); 7641 else 7642 TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts (); 7643 } 7644 7645 /* Implement TARGET_SET_CURRENT_FUNCTION. */ 7646 7647 static void 7648 loongarch_set_current_function (tree fndecl) 7649 { 7650 if (fndecl == loongarch_previous_fndecl) 7651 return; 7652 7653 tree old_tree; 7654 if (loongarch_previous_fndecl == NULL_TREE) 7655 old_tree = target_option_current_node; 7656 else if (DECL_FUNCTION_SPECIFIC_TARGET (loongarch_previous_fndecl)) 7657 old_tree = DECL_FUNCTION_SPECIFIC_TARGET (loongarch_previous_fndecl); 7658 else 7659 old_tree = target_option_default_node; 7660 7661 if (fndecl == NULL_TREE) 7662 { 7663 if (old_tree != target_option_current_node) 7664 { 7665 loongarch_previous_fndecl = NULL_TREE; 7666 cl_target_option_restore (&global_options, &global_options_set, 7667 TREE_TARGET_OPTION 7668 (target_option_current_node)); 7669 } 7670 return; 7671 } 7672 7673 tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); 7674 if (new_tree == NULL_TREE) 7675 new_tree = target_option_default_node; 7676 7677 loongarch_previous_fndecl = fndecl; 7678 7679 if (new_tree == old_tree) 7680 return; 7681 7682 cl_target_option_restore (&global_options, &global_options_set, 7683 TREE_TARGET_OPTION (new_tree)); 7684 7685 loongarch_reg_init (); 7686 7687 loongarch_save_restore_target_globals (new_tree); 7688 } 7689 7690 7691 7692 /* Implement TARGET_OPTION_OVERRIDE. */ 7693 7694 static void 7695 loongarch_option_override (void) 7696 { 7697 /* Global initializations. */ 7698 loongarch_global_init (); 7699 7700 /* Setting up the target configuration. */ 7701 loongarch_option_override_internal (&la_target, 7702 &global_options, 7703 &global_options_set); 7704 7705 } 7706 7707 /* Implement TARGET_OPTION_SAVE. */ 7708 static void 7709 loongarch_option_save (struct cl_target_option *, 7710 struct gcc_options *opts, 7711 struct gcc_options *opts_set) 7712 { 7713 loongarch_update_gcc_opt_status (&la_target, opts, opts_set); 7714 } 7715 7716 /* Implement TARGET_OPTION_RESTORE. */ 7717 static void 7718 loongarch_option_restore (struct gcc_options *, 7719 struct gcc_options *, 7720 struct cl_target_option *ptr) 7721 { 7722 la_target.cpu_arch = ptr->x_la_opt_cpu_arch; 7723 la_target.cpu_tune = ptr->x_la_opt_cpu_tune; 7724 7725 la_target.isa.fpu = ptr->x_la_opt_fpu; 7726 la_target.isa.simd = ptr->x_la_opt_simd; 7727 la_target.isa.evolution = ptr->x_la_isa_evolution; 7728 7729 la_target.cmodel = ptr->x_la_opt_cmodel; 7730 la_target.tls_dialect = ptr->x_la_opt_tls_dialect; 7731 } 7732 7733 /* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */ 7734 7735 static void 7736 loongarch_conditional_register_usage (void) 7737 { 7738 if (!TARGET_HARD_FLOAT) 7739 accessible_reg_set &= ~(reg_class_contents[FP_REGS] 7740 | reg_class_contents[FCC_REGS]); 7741 } 7742 7743 /* Implement EH_USES. */ 7744 7745 bool 7746 loongarch_eh_uses (unsigned int regno ATTRIBUTE_UNUSED) 7747 { 7748 return false; 7749 } 7750 7751 /* Implement EPILOGUE_USES. */ 7752 7753 bool 7754 loongarch_epilogue_uses (unsigned int regno) 7755 { 7756 /* Say that the epilogue uses the return address register. Note that 7757 in the case of sibcalls, the values "used by the epilogue" are 7758 considered live at the start of the called function. */ 7759 if (regno == RETURN_ADDR_REGNUM) 7760 return true; 7761 7762 return false; 7763 } 7764 7765 bool 7766 loongarch_load_store_bonding_p (rtx *operands, machine_mode mode, bool load_p) 7767 { 7768 rtx reg1, reg2, mem1, mem2, base1, base2; 7769 enum reg_class rc1, rc2; 7770 HOST_WIDE_INT offset1, offset2; 7771 7772 if (load_p) 7773 { 7774 reg1 = operands[0]; 7775 reg2 = operands[2]; 7776 mem1 = operands[1]; 7777 mem2 = operands[3]; 7778 } 7779 else 7780 { 7781 reg1 = operands[1]; 7782 reg2 = operands[3]; 7783 mem1 = operands[0]; 7784 mem2 = operands[2]; 7785 } 7786 7787 if (loongarch_address_insns (XEXP (mem1, 0), mode, false) == 0 7788 || loongarch_address_insns (XEXP (mem2, 0), mode, false) == 0) 7789 return false; 7790 7791 loongarch_split_plus (XEXP (mem1, 0), &base1, &offset1); 7792 loongarch_split_plus (XEXP (mem2, 0), &base2, &offset2); 7793 7794 /* Base regs do not match. */ 7795 if (!REG_P (base1) || !rtx_equal_p (base1, base2)) 7796 return false; 7797 7798 /* Either of the loads is clobbering base register. It is legitimate to bond 7799 loads if second load clobbers base register. However, hardware does not 7800 support such bonding. */ 7801 if (load_p 7802 && (REGNO (reg1) == REGNO (base1) || (REGNO (reg2) == REGNO (base1)))) 7803 return false; 7804 7805 /* Loading in same registers. */ 7806 if (load_p && REGNO (reg1) == REGNO (reg2)) 7807 return false; 7808 7809 /* The loads/stores are not of same type. */ 7810 rc1 = REGNO_REG_CLASS (REGNO (reg1)); 7811 rc2 = REGNO_REG_CLASS (REGNO (reg2)); 7812 if (rc1 != rc2 && !reg_class_subset_p (rc1, rc2) 7813 && !reg_class_subset_p (rc2, rc1)) 7814 return false; 7815 7816 if (abs (offset1 - offset2) != GET_MODE_SIZE (mode)) 7817 return false; 7818 7819 return true; 7820 } 7821 7822 /* Implement TARGET_TRAMPOLINE_INIT. */ 7823 7824 static void 7825 loongarch_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) 7826 { 7827 rtx addr, end_addr, mem; 7828 rtx trampoline[8]; 7829 unsigned int i, j; 7830 HOST_WIDE_INT end_addr_offset, static_chain_offset, target_function_offset; 7831 7832 /* Work out the offsets of the pointers from the start of the 7833 trampoline code. */ 7834 end_addr_offset = TRAMPOLINE_CODE_SIZE; 7835 static_chain_offset = end_addr_offset; 7836 target_function_offset = static_chain_offset + GET_MODE_SIZE (ptr_mode); 7837 7838 /* Get pointers to the beginning and end of the code block. */ 7839 addr = force_reg (Pmode, XEXP (m_tramp, 0)); 7840 end_addr 7841 = loongarch_force_binary (Pmode, PLUS, addr, GEN_INT (end_addr_offset)); 7842 7843 #define OP(X) gen_int_mode (X, SImode) 7844 7845 /* Build up the code in TRAMPOLINE. */ 7846 i = 0; 7847 /*pcaddi $static_chain,0 7848 ld.[dw] $tmp,$static_chain,target_function_offset 7849 ld.[dw] $static_chain,$static_chain,static_chain_offset 7850 jirl $r0,$tmp,0 */ 7851 trampoline[i++] = OP (0x18000000 | (STATIC_CHAIN_REGNUM - GP_REG_FIRST)); 7852 trampoline[i++] = OP ((ptr_mode == DImode ? 0x28c00000 : 0x28800000) 7853 | 19 /* $t7 */ 7854 | ((STATIC_CHAIN_REGNUM - GP_REG_FIRST) << 5) 7855 | ((target_function_offset & 0xfff) << 10)); 7856 trampoline[i++] = OP ((ptr_mode == DImode ? 0x28c00000 : 0x28800000) 7857 | (STATIC_CHAIN_REGNUM - GP_REG_FIRST) 7858 | ((STATIC_CHAIN_REGNUM - GP_REG_FIRST) << 5) 7859 | ((static_chain_offset & 0xfff) << 10)); 7860 trampoline[i++] = OP (0x4c000000 | (19 << 5)); 7861 #undef OP 7862 7863 for (j = 0; j < i; j++) 7864 { 7865 mem = adjust_address (m_tramp, SImode, j * GET_MODE_SIZE (SImode)); 7866 loongarch_emit_move (mem, trampoline[j]); 7867 } 7868 7869 /* Set up the static chain pointer field. */ 7870 mem = adjust_address (m_tramp, ptr_mode, static_chain_offset); 7871 loongarch_emit_move (mem, chain_value); 7872 7873 /* Set up the target function field. */ 7874 mem = adjust_address (m_tramp, ptr_mode, target_function_offset); 7875 loongarch_emit_move (mem, XEXP (DECL_RTL (fndecl), 0)); 7876 7877 /* Flush the code part of the trampoline. */ 7878 emit_insn (gen_add3_insn (end_addr, addr, GEN_INT (TRAMPOLINE_SIZE))); 7879 emit_insn (gen_clear_cache (addr, end_addr)); 7880 } 7881 7882 /* Generate or test for an insn that supports a constant permutation. */ 7883 7884 #define MAX_VECT_LEN 32 7885 7886 struct expand_vec_perm_d 7887 { 7888 rtx target, op0, op1; 7889 unsigned char perm[MAX_VECT_LEN]; 7890 machine_mode vmode; 7891 unsigned char nelt; 7892 bool one_vector_p; 7893 bool testing_p; 7894 }; 7895 7896 /* Construct (set target (vec_select op0 (parallel perm))) and 7897 return true if that's a valid instruction in the active ISA. */ 7898 7899 static bool 7900 loongarch_expand_vselect (rtx target, rtx op0, 7901 const unsigned char *perm, unsigned nelt, 7902 bool testing_p) 7903 { 7904 rtx rperm[MAX_VECT_LEN], x; 7905 rtx_insn *insn; 7906 unsigned i; 7907 7908 for (i = 0; i < nelt; ++i) 7909 rperm[i] = GEN_INT (perm[i]); 7910 7911 x = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelt, rperm)); 7912 x = gen_rtx_VEC_SELECT (GET_MODE (target), op0, x); 7913 x = gen_rtx_SET (target, x); 7914 7915 insn = emit_insn (x); 7916 if (recog_memoized (insn) < 0) 7917 { 7918 remove_insn (insn); 7919 return false; 7920 } 7921 7922 if (testing_p) 7923 remove_insn (insn); 7924 return true; 7925 } 7926 7927 /* Similar, but generate a vec_concat from op0 and op1 as well. */ 7928 7929 static bool 7930 loongarch_expand_vselect_vconcat (rtx target, rtx op0, rtx op1, 7931 const unsigned char *perm, unsigned nelt, 7932 bool testing_p) 7933 { 7934 machine_mode v2mode; 7935 rtx x; 7936 7937 if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode)) 7938 return false; 7939 x = gen_rtx_VEC_CONCAT (v2mode, op0, op1); 7940 return loongarch_expand_vselect (target, x, perm, nelt, testing_p); 7941 } 7942 7943 static tree 7944 loongarch_handle_model_attribute (tree *node, tree name, tree arg, int, 7945 bool *no_add_attrs) 7946 { 7947 tree decl = *node; 7948 if (VAR_P (decl)) 7949 { 7950 if (DECL_THREAD_LOCAL_P (decl)) 7951 { 7952 error_at (DECL_SOURCE_LOCATION (decl), 7953 "%qE attribute cannot be specified for thread-local " 7954 "variables", name); 7955 *no_add_attrs = true; 7956 return NULL_TREE; 7957 } 7958 if (DECL_CONTEXT (decl) 7959 && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL 7960 && !TREE_STATIC (decl)) 7961 { 7962 error_at (DECL_SOURCE_LOCATION (decl), 7963 "%qE attribute cannot be specified for local " 7964 "variables", name); 7965 *no_add_attrs = true; 7966 return NULL_TREE; 7967 } 7968 if (DECL_REGISTER (decl)) 7969 { 7970 error_at (DECL_SOURCE_LOCATION (decl), 7971 "%qE attribute cannot be specified for register " 7972 "variables", name); 7973 *no_add_attrs = true; 7974 return NULL_TREE; 7975 } 7976 7977 arg = TREE_VALUE (arg); 7978 if (TREE_CODE (arg) != STRING_CST) 7979 { 7980 error_at (DECL_SOURCE_LOCATION (decl), 7981 "invalid argument of %qE attribute", name); 7982 *no_add_attrs = true; 7983 return NULL_TREE; 7984 } 7985 7986 const char *model = TREE_STRING_POINTER (arg); 7987 if (strcmp (model, "normal") != 0 7988 && strcmp (model, "extreme") != 0) 7989 { 7990 error_at (DECL_SOURCE_LOCATION (decl), 7991 "invalid argument of %qE attribute", name); 7992 *no_add_attrs = true; 7993 return NULL_TREE; 7994 } 7995 7996 if (lookup_attribute ("model", DECL_ATTRIBUTES (decl))) 7997 { 7998 error_at (DECL_SOURCE_LOCATION (decl), 7999 "multiple %qE attribute", name); 8000 *no_add_attrs = true; 8001 return NULL_TREE; 8002 } 8003 } 8004 else 8005 { 8006 warning (OPT_Wattributes, "%qE attribute ignored", name); 8007 *no_add_attrs = true; 8008 } 8009 return NULL_TREE; 8010 } 8011 8012 TARGET_GNU_ATTRIBUTES (loongarch_attribute_table, 8013 { 8014 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, 8015 affects_type_identity, handler, exclude } */ 8016 { "model", 1, 1, true, false, false, false, 8017 loongarch_handle_model_attribute, NULL } 8018 }); 8019 8020 bool 8021 loongarch_use_anchors_for_symbol_p (const_rtx symbol) 8022 { 8023 tree decl = SYMBOL_REF_DECL (symbol); 8024 8025 /* The section anchor optimization may break custom address model. */ 8026 if (decl && lookup_attribute ("model", DECL_ATTRIBUTES (decl))) 8027 return false; 8028 8029 return default_use_anchors_for_symbol_p (symbol); 8030 } 8031 8032 /* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */ 8033 8034 static unsigned HOST_WIDE_INT 8035 loongarch_asan_shadow_offset (void) 8036 { 8037 /* We only have libsanitizer support for LOONGARCH64 at present. 8038 This value is taken from the file libsanitizer/asan/asan_mapping.h. */ 8039 return TARGET_64BIT ? (HOST_WIDE_INT_1 << 46) : 0; 8040 } 8041 8042 static sbitmap 8043 loongarch_get_separate_components (void) 8044 { 8045 HOST_WIDE_INT offset; 8046 sbitmap components = sbitmap_alloc (FIRST_PSEUDO_REGISTER); 8047 bitmap_clear (components); 8048 offset = cfun->machine->frame.gp_sp_offset; 8049 8050 /* The stack should be aligned to 16-bytes boundary, so we can make the use 8051 of ldptr instructions. */ 8052 gcc_assert (offset % UNITS_PER_WORD == 0); 8053 8054 for (unsigned int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) 8055 if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST)) 8056 { 8057 /* We can wrap general registers saved at [sp, sp + 32768) using the 8058 ldptr/stptr instructions. For large offsets a pseudo register 8059 might be needed which cannot be created during the shrink 8060 wrapping pass. 8061 8062 TODO: This may need a revise when we add LA32 as ldptr.w is not 8063 guaranteed available by the manual. */ 8064 if (offset < 32768) 8065 bitmap_set_bit (components, regno); 8066 8067 offset -= UNITS_PER_WORD; 8068 } 8069 8070 offset = cfun->machine->frame.fp_sp_offset; 8071 for (unsigned int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) 8072 if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST)) 8073 { 8074 /* We can only wrap FP registers with imm12 offsets. For large 8075 offsets a pseudo register might be needed which cannot be 8076 created during the shrink wrapping pass. */ 8077 if (IMM12_OPERAND (offset)) 8078 bitmap_set_bit (components, regno); 8079 8080 offset -= UNITS_PER_FP_REG; 8081 } 8082 8083 /* Don't mess with the hard frame pointer. */ 8084 if (frame_pointer_needed) 8085 bitmap_clear_bit (components, HARD_FRAME_POINTER_REGNUM); 8086 8087 bitmap_clear_bit (components, RETURN_ADDR_REGNUM); 8088 8089 return components; 8090 } 8091 8092 static sbitmap 8093 loongarch_components_for_bb (basic_block bb) 8094 { 8095 /* Registers are used in a bb if they are in the IN, GEN, or KILL sets. */ 8096 auto_bitmap used; 8097 bitmap_copy (used, DF_LIVE_IN (bb)); 8098 bitmap_ior_into (used, &DF_LIVE_BB_INFO (bb)->gen); 8099 bitmap_ior_into (used, &DF_LIVE_BB_INFO (bb)->kill); 8100 8101 sbitmap components = sbitmap_alloc (FIRST_PSEUDO_REGISTER); 8102 bitmap_clear (components); 8103 8104 function_abi_aggregator callee_abis; 8105 rtx_insn *insn; 8106 FOR_BB_INSNS (bb, insn) 8107 if (CALL_P (insn)) 8108 callee_abis.note_callee_abi (insn_callee_abi (insn)); 8109 8110 HARD_REG_SET extra_caller_saves = 8111 callee_abis.caller_save_regs (*crtl->abi); 8112 8113 for (unsigned int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) 8114 if (!fixed_regs[regno] 8115 && !crtl->abi->clobbers_full_reg_p (regno) 8116 && (TEST_HARD_REG_BIT (extra_caller_saves, regno) || 8117 bitmap_bit_p (used, regno))) 8118 bitmap_set_bit (components, regno); 8119 8120 for (unsigned int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) 8121 if (!fixed_regs[regno] 8122 && !crtl->abi->clobbers_full_reg_p (regno) 8123 && (TEST_HARD_REG_BIT (extra_caller_saves, regno) || 8124 bitmap_bit_p (used, regno))) 8125 bitmap_set_bit (components, regno); 8126 8127 return components; 8128 } 8129 8130 static void 8131 loongarch_disqualify_components (sbitmap, edge, sbitmap, bool) 8132 { 8133 /* Do nothing. */ 8134 } 8135 8136 static void 8137 loongarch_process_components (sbitmap components, loongarch_save_restore_fn fn) 8138 { 8139 HOST_WIDE_INT offset = cfun->machine->frame.gp_sp_offset; 8140 8141 for (unsigned int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) 8142 if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST)) 8143 { 8144 if (bitmap_bit_p (components, regno)) 8145 loongarch_save_restore_reg (word_mode, regno, offset, fn); 8146 8147 offset -= UNITS_PER_WORD; 8148 } 8149 8150 offset = cfun->machine->frame.fp_sp_offset; 8151 machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode; 8152 8153 for (unsigned int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) 8154 if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST)) 8155 { 8156 if (bitmap_bit_p (components, regno)) 8157 loongarch_save_restore_reg (mode, regno, offset, fn); 8158 8159 offset -= UNITS_PER_FP_REG; 8160 } 8161 } 8162 8163 static void 8164 loongarch_emit_prologue_components (sbitmap components) 8165 { 8166 loongarch_process_components (components, loongarch_save_reg); 8167 } 8168 8169 static void 8170 loongarch_emit_epilogue_components (sbitmap components) 8171 { 8172 loongarch_process_components (components, loongarch_restore_reg); 8173 } 8174 8175 static void 8176 loongarch_set_handled_components (sbitmap components) 8177 { 8178 for (unsigned int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) 8179 if (bitmap_bit_p (components, regno)) 8180 cfun->machine->reg_is_wrapped_separately[regno] = true; 8181 8182 for (unsigned int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) 8183 if (bitmap_bit_p (components, regno)) 8184 cfun->machine->reg_is_wrapped_separately[regno] = true; 8185 } 8186 8187 /* Initialize the GCC target structure. */ 8188 #undef TARGET_ASM_ALIGNED_HI_OP 8189 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" 8190 #undef TARGET_ASM_ALIGNED_SI_OP 8191 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" 8192 #undef TARGET_ASM_ALIGNED_DI_OP 8193 #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t" 8194 8195 /* Use the vshuf instruction to implement all 128-bit constant vector 8196 permuatation. */ 8197 8198 static bool 8199 loongarch_try_expand_lsx_vshuf_const (struct expand_vec_perm_d *d) 8200 { 8201 int i; 8202 rtx target, op0, op1, sel, tmp; 8203 rtx rperm[MAX_VECT_LEN]; 8204 8205 if (GET_MODE_SIZE (d->vmode) == 16) 8206 { 8207 target = d->target; 8208 op0 = d->op0; 8209 op1 = d->one_vector_p ? d->op0 : d->op1; 8210 8211 if (GET_MODE (op0) != GET_MODE (op1) 8212 || GET_MODE (op0) != GET_MODE (target)) 8213 return false; 8214 8215 if (d->testing_p) 8216 return true; 8217 8218 for (i = 0; i < d->nelt; i += 1) 8219 rperm[i] = GEN_INT (d->perm[i]); 8220 8221 if (d->vmode == E_V2DFmode) 8222 { 8223 sel = gen_rtx_CONST_VECTOR (E_V2DImode, gen_rtvec_v (d->nelt, rperm)); 8224 tmp = simplify_gen_subreg (E_V2DImode, d->target, d->vmode, 0); 8225 emit_move_insn (tmp, sel); 8226 } 8227 else if (d->vmode == E_V4SFmode) 8228 { 8229 sel = gen_rtx_CONST_VECTOR (E_V4SImode, gen_rtvec_v (d->nelt, rperm)); 8230 tmp = simplify_gen_subreg (E_V4SImode, d->target, d->vmode, 0); 8231 emit_move_insn (tmp, sel); 8232 } 8233 else 8234 { 8235 sel = gen_rtx_CONST_VECTOR (d->vmode, gen_rtvec_v (d->nelt, rperm)); 8236 emit_move_insn (d->target, sel); 8237 } 8238 8239 switch (d->vmode) 8240 { 8241 case E_V2DFmode: 8242 emit_insn (gen_lsx_vshuf_d_f (target, target, op1, op0)); 8243 break; 8244 case E_V2DImode: 8245 emit_insn (gen_lsx_vshuf_d (target, target, op1, op0)); 8246 break; 8247 case E_V4SFmode: 8248 emit_insn (gen_lsx_vshuf_w_f (target, target, op1, op0)); 8249 break; 8250 case E_V4SImode: 8251 emit_insn (gen_lsx_vshuf_w (target, target, op1, op0)); 8252 break; 8253 case E_V8HImode: 8254 emit_insn (gen_lsx_vshuf_h (target, target, op1, op0)); 8255 break; 8256 case E_V16QImode: 8257 emit_insn (gen_lsx_vshuf_b (target, op1, op0, target)); 8258 break; 8259 default: 8260 break; 8261 } 8262 8263 return true; 8264 } 8265 return false; 8266 } 8267 8268 /* Construct (set target (vec_select op0 (parallel selector))) and 8269 return true if that's a valid instruction in the active ISA. 8270 In fact, it matches the special constant vector with repeated 8271 4-element sets. */ 8272 8273 static bool 8274 loongarch_is_imm_set_shuffle (struct expand_vec_perm_d *d) 8275 { 8276 rtx x, elts[MAX_VECT_LEN]; 8277 rtvec v; 8278 rtx_insn *insn; 8279 unsigned i; 8280 8281 if (!ISA_HAS_LSX && !ISA_HAS_LASX) 8282 return false; 8283 8284 for (i = 0; i < d->nelt; i++) 8285 elts[i] = GEN_INT (d->perm[i]); 8286 8287 v = gen_rtvec_v (d->nelt, elts); 8288 x = gen_rtx_PARALLEL (VOIDmode, v); 8289 8290 if (!loongarch_const_vector_shuffle_set_p (x, d->vmode)) 8291 return false; 8292 8293 if (d->testing_p) 8294 return true; 8295 8296 x = gen_rtx_VEC_SELECT (d->vmode, d->op0, x); 8297 x = gen_rtx_SET (d->target, x); 8298 8299 insn = emit_insn (x); 8300 if (recog_memoized (insn) < 0) 8301 { 8302 remove_insn (insn); 8303 return false; 8304 } 8305 return true; 8306 } 8307 8308 static bool 8309 loongarch_expand_vec_perm_even_odd (struct expand_vec_perm_d *); 8310 8311 /* Try to match and expand all kinds of 128-bit const vector permutation 8312 cases. */ 8313 8314 static bool 8315 loongarch_expand_lsx_shuffle (struct expand_vec_perm_d *d) 8316 { 8317 if (!ISA_HAS_LSX && GET_MODE_SIZE (d->vmode) != 16) 8318 return false; 8319 8320 if (loongarch_is_imm_set_shuffle (d)) 8321 return true; 8322 8323 if (loongarch_expand_vec_perm_even_odd (d)) 8324 return true; 8325 8326 return loongarch_try_expand_lsx_vshuf_const (d); 8327 } 8328 8329 /* Try to simplify a two vector permutation using 2 intra-lane interleave 8330 insns and cross-lane shuffle for 32-byte vectors. */ 8331 8332 static bool 8333 loongarch_expand_vec_perm_interleave (struct expand_vec_perm_d *d) 8334 { 8335 unsigned i, nelt; 8336 rtx t1,t2,t3; 8337 rtx (*gen_high) (rtx, rtx, rtx); 8338 rtx (*gen_low) (rtx, rtx, rtx); 8339 machine_mode mode = GET_MODE (d->target); 8340 8341 if (d->one_vector_p) 8342 return false; 8343 if (ISA_HAS_LASX && GET_MODE_SIZE (d->vmode) == 32) 8344 ; 8345 else 8346 return false; 8347 8348 nelt = d->nelt; 8349 if (d->perm[0] != 0 && d->perm[0] != nelt / 2) 8350 return false; 8351 for (i = 0; i < nelt; i += 2) 8352 if (d->perm[i] != d->perm[0] + i / 2 8353 || d->perm[i + 1] != d->perm[0] + i / 2 + nelt) 8354 return false; 8355 8356 if (d->testing_p) 8357 return true; 8358 8359 switch (d->vmode) 8360 { 8361 case E_V32QImode: 8362 gen_high = gen_lasx_xvilvh_b; 8363 gen_low = gen_lasx_xvilvl_b; 8364 break; 8365 case E_V16HImode: 8366 gen_high = gen_lasx_xvilvh_h; 8367 gen_low = gen_lasx_xvilvl_h; 8368 break; 8369 case E_V8SImode: 8370 gen_high = gen_lasx_xvilvh_w; 8371 gen_low = gen_lasx_xvilvl_w; 8372 break; 8373 case E_V4DImode: 8374 gen_high = gen_lasx_xvilvh_d; 8375 gen_low = gen_lasx_xvilvl_d; 8376 break; 8377 case E_V8SFmode: 8378 gen_high = gen_lasx_xvilvh_w_f; 8379 gen_low = gen_lasx_xvilvl_w_f; 8380 break; 8381 case E_V4DFmode: 8382 gen_high = gen_lasx_xvilvh_d_f; 8383 gen_low = gen_lasx_xvilvl_d_f; 8384 break; 8385 default: 8386 gcc_unreachable (); 8387 } 8388 8389 t1 = gen_reg_rtx (mode); 8390 t2 = gen_reg_rtx (mode); 8391 emit_insn (gen_high (t1, d->op0, d->op1)); 8392 emit_insn (gen_low (t2, d->op0, d->op1)); 8393 if (mode == V4DFmode || mode == V8SFmode) 8394 { 8395 t3 = gen_reg_rtx (V4DFmode); 8396 if (d->perm[0]) 8397 emit_insn (gen_lasx_xvpermi_q_v4df (t3, gen_lowpart (V4DFmode, t1), 8398 gen_lowpart (V4DFmode, t2), 8399 GEN_INT (0x31))); 8400 else 8401 emit_insn (gen_lasx_xvpermi_q_v4df (t3, gen_lowpart (V4DFmode, t1), 8402 gen_lowpart (V4DFmode, t2), 8403 GEN_INT (0x20))); 8404 } 8405 else 8406 { 8407 t3 = gen_reg_rtx (V4DImode); 8408 if (d->perm[0]) 8409 emit_insn (gen_lasx_xvpermi_q_v4di (t3, gen_lowpart (V4DImode, t1), 8410 gen_lowpart (V4DImode, t2), 8411 GEN_INT (0x31))); 8412 else 8413 emit_insn (gen_lasx_xvpermi_q_v4di (t3, gen_lowpart (V4DImode, t1), 8414 gen_lowpart (V4DImode, t2), 8415 GEN_INT (0x20))); 8416 } 8417 emit_move_insn (d->target, gen_lowpart (mode, t3)); 8418 return true; 8419 } 8420 8421 /* Implement 128-bit and 256-bit extract-even and extract-odd permutations. */ 8422 8423 static bool 8424 loongarch_expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd) 8425 { 8426 rtx t1; 8427 machine_mode mode = GET_MODE (d->target); 8428 8429 if (d->testing_p) 8430 return true; 8431 8432 t1 = gen_reg_rtx (mode); 8433 8434 switch (d->vmode) 8435 { 8436 /* 128 bit. */ 8437 case E_V2DFmode: 8438 if (odd) 8439 emit_insn (gen_lsx_vilvh_d_f (d->target, d->op0, d->op1)); 8440 else 8441 emit_insn (gen_lsx_vilvl_d_f (d->target, d->op0, d->op1)); 8442 break; 8443 8444 case E_V2DImode: 8445 if (odd) 8446 emit_insn (gen_lsx_vilvh_d (d->target, d->op0, d->op1)); 8447 else 8448 emit_insn (gen_lsx_vilvl_d (d->target, d->op0, d->op1)); 8449 break; 8450 8451 case E_V4SFmode: 8452 if (odd) 8453 emit_insn (gen_lsx_vpickod_w_f (d->target, d->op0, d->op1)); 8454 else 8455 emit_insn (gen_lsx_vpickev_w_f (d->target, d->op0, d->op1)); 8456 break; 8457 8458 case E_V4SImode: 8459 if (odd) 8460 emit_insn (gen_lsx_vpickod_w (d->target, d->op0, d->op1)); 8461 else 8462 emit_insn (gen_lsx_vpickev_w (d->target, d->op0, d->op1)); 8463 break; 8464 8465 case E_V8HImode: 8466 if (odd) 8467 emit_insn (gen_lsx_vpickod_h (d->target, d->op0, d->op1)); 8468 else 8469 emit_insn (gen_lsx_vpickev_h (d->target, d->op0, d->op1)); 8470 break; 8471 8472 case E_V16QImode: 8473 if (odd) 8474 emit_insn (gen_lsx_vpickod_b (d->target, d->op0, d->op1)); 8475 else 8476 emit_insn (gen_lsx_vpickev_b (d->target, d->op0, d->op1)); 8477 break; 8478 8479 /* 256 bit. */ 8480 case E_V4DFmode: 8481 /* Shuffle the lanes around into { 0 4 2 6 } and { 1 5 3 7 }. */ 8482 if (odd) 8483 emit_insn (gen_lasx_xvilvh_d_f (t1, d->op0, d->op1)); 8484 else 8485 emit_insn (gen_lasx_xvilvl_d_f (t1, d->op0, d->op1)); 8486 8487 /* Shuffle within the 256-bit lanes to produce the result required. 8488 { 0 2 4 6 } | { 1 3 5 7 }. */ 8489 emit_insn (gen_lasx_xvpermi_d_v4df (d->target, t1, GEN_INT (0xd8))); 8490 break; 8491 8492 case E_V4DImode: 8493 if (odd) 8494 emit_insn (gen_lasx_xvilvh_d (t1, d->op0, d->op1)); 8495 else 8496 emit_insn (gen_lasx_xvilvl_d (t1, d->op0, d->op1)); 8497 8498 emit_insn (gen_lasx_xvpermi_d_v4di (d->target, t1, GEN_INT (0xd8))); 8499 break; 8500 8501 case E_V8SFmode: 8502 /* Shuffle the lanes around into: 8503 { 0 2 8 a 4 6 c e } | { 1 3 9 b 5 7 d f }. */ 8504 if (odd) 8505 emit_insn (gen_lasx_xvpickod_w_f (t1, d->op0, d->op1)); 8506 else 8507 emit_insn (gen_lasx_xvpickev_w_f (t1, d->op0, d->op1)); 8508 8509 /* Shuffle within the 256-bit lanes to produce the result required. 8510 { 0 2 4 6 8 a c e } | { 1 3 5 7 9 b d f }. */ 8511 emit_insn (gen_lasx_xvpermi_d_v8sf (d->target, t1, GEN_INT (0xd8))); 8512 break; 8513 8514 case E_V8SImode: 8515 if (odd) 8516 emit_insn (gen_lasx_xvpickod_w (t1, d->op0, d->op1)); 8517 else 8518 emit_insn (gen_lasx_xvpickev_w (t1, d->op0, d->op1)); 8519 8520 emit_insn (gen_lasx_xvpermi_d_v8si (d->target, t1, GEN_INT (0xd8))); 8521 break; 8522 8523 case E_V16HImode: 8524 if (odd) 8525 emit_insn (gen_lasx_xvpickod_h (t1, d->op0, d->op1)); 8526 else 8527 emit_insn (gen_lasx_xvpickev_h (t1, d->op0, d->op1)); 8528 8529 emit_insn (gen_lasx_xvpermi_d_v16hi (d->target, t1, GEN_INT (0xd8))); 8530 break; 8531 8532 case E_V32QImode: 8533 if (odd) 8534 emit_insn (gen_lasx_xvpickod_b (t1, d->op0, d->op1)); 8535 else 8536 emit_insn (gen_lasx_xvpickev_b (t1, d->op0, d->op1)); 8537 8538 emit_insn (gen_lasx_xvpermi_d_v32qi (d->target, t1, GEN_INT (0xd8))); 8539 break; 8540 8541 default: 8542 gcc_unreachable (); 8543 } 8544 8545 return true; 8546 } 8547 8548 /* Pattern match extract-even and extract-odd permutations. */ 8549 8550 static bool 8551 loongarch_expand_vec_perm_even_odd (struct expand_vec_perm_d *d) 8552 { 8553 unsigned i, odd, nelt = d->nelt; 8554 if (!ISA_HAS_LASX && !ISA_HAS_LSX) 8555 return false; 8556 8557 odd = d->perm[0]; 8558 if (odd != 0 && odd != 1) 8559 return false; 8560 8561 for (i = 1; i < nelt; ++i) 8562 if (d->perm[i] != 2 * i + odd) 8563 return false; 8564 8565 return loongarch_expand_vec_perm_even_odd_1 (d, odd); 8566 } 8567 8568 static void 8569 loongarch_expand_vec_interleave (rtx target, rtx op0, rtx op1, bool high_p) 8570 { 8571 struct expand_vec_perm_d d; 8572 unsigned i, nelt, base; 8573 bool ok; 8574 8575 d.target = target; 8576 d.op0 = op0; 8577 d.op1 = op1; 8578 d.vmode = GET_MODE (target); 8579 d.nelt = nelt = GET_MODE_NUNITS (d.vmode); 8580 d.one_vector_p = false; 8581 d.testing_p = false; 8582 8583 base = high_p ? nelt / 2 : 0; 8584 for (i = 0; i < nelt / 2; ++i) 8585 { 8586 d.perm[i * 2] = i + base; 8587 d.perm[i * 2 + 1] = i + base + nelt; 8588 } 8589 8590 ok = loongarch_expand_vec_perm_interleave (&d); 8591 gcc_assert (ok); 8592 } 8593 8594 /* The loongarch lasx instructions xvmulwev and xvmulwod return the even or odd 8595 parts of the double sized result elements in the corresponding elements of 8596 the target register. That's NOT what the vec_widen_umult_lo/hi patterns are 8597 expected to do. We emulate the widening lo/hi multiplies with the even/odd 8598 versions followed by a vector merge. */ 8599 8600 void 8601 loongarch_expand_vec_widen_hilo (rtx dest, rtx op1, rtx op2, 8602 bool uns_p, bool high_p, const char *optab) 8603 { 8604 machine_mode wmode = GET_MODE (dest); 8605 machine_mode mode = GET_MODE (op1); 8606 rtx t1, t2, t3; 8607 8608 t1 = gen_reg_rtx (wmode); 8609 t2 = gen_reg_rtx (wmode); 8610 t3 = gen_reg_rtx (wmode); 8611 switch (mode) 8612 { 8613 case V16HImode: 8614 if (!strcmp (optab, "add")) 8615 { 8616 if (!uns_p) 8617 { 8618 emit_insn (gen_lasx_xvaddwev_w_h (t1, op1, op2)); 8619 emit_insn (gen_lasx_xvaddwod_w_h (t2, op1, op2)); 8620 } 8621 else 8622 { 8623 emit_insn (gen_lasx_xvaddwev_w_hu (t1, op1, op2)); 8624 emit_insn (gen_lasx_xvaddwod_w_hu (t2, op1, op2)); 8625 } 8626 } 8627 else if (!strcmp (optab, "mult")) 8628 { 8629 if (!uns_p) 8630 { 8631 emit_insn (gen_lasx_xvmulwev_w_h (t1, op1, op2)); 8632 emit_insn (gen_lasx_xvmulwod_w_h (t2, op1, op2)); 8633 } 8634 else 8635 { 8636 emit_insn (gen_lasx_xvmulwev_w_hu (t1, op1, op2)); 8637 emit_insn (gen_lasx_xvmulwod_w_hu (t2, op1, op2)); 8638 } 8639 } 8640 else if (!strcmp (optab, "sub")) 8641 { 8642 if (!uns_p) 8643 { 8644 emit_insn (gen_lasx_xvsubwev_w_h (t1, op1, op2)); 8645 emit_insn (gen_lasx_xvsubwod_w_h (t2, op1, op2)); 8646 } 8647 else 8648 { 8649 emit_insn (gen_lasx_xvsubwev_w_hu (t1, op1, op2)); 8650 emit_insn (gen_lasx_xvsubwod_w_hu (t2, op1, op2)); 8651 } 8652 } 8653 break; 8654 8655 case V32QImode: 8656 if (!strcmp (optab, "add")) 8657 { 8658 if (!uns_p) 8659 { 8660 emit_insn (gen_lasx_xvaddwev_h_b (t1, op1, op2)); 8661 emit_insn (gen_lasx_xvaddwod_h_b (t2, op1, op2)); 8662 } 8663 else 8664 { 8665 emit_insn (gen_lasx_xvaddwev_h_bu (t1, op1, op2)); 8666 emit_insn (gen_lasx_xvaddwod_h_bu (t2, op1, op2)); 8667 } 8668 } 8669 else if (!strcmp (optab, "mult")) 8670 { 8671 if (!uns_p) 8672 { 8673 emit_insn (gen_lasx_xvmulwev_h_b (t1, op1, op2)); 8674 emit_insn (gen_lasx_xvmulwod_h_b (t2, op1, op2)); 8675 } 8676 else 8677 { 8678 emit_insn (gen_lasx_xvmulwev_h_bu (t1, op1, op2)); 8679 emit_insn (gen_lasx_xvmulwod_h_bu (t2, op1, op2)); 8680 } 8681 } 8682 else if (!strcmp (optab, "sub")) 8683 { 8684 if (!uns_p) 8685 { 8686 emit_insn (gen_lasx_xvsubwev_h_b (t1, op1, op2)); 8687 emit_insn (gen_lasx_xvsubwod_h_b (t2, op1, op2)); 8688 } 8689 else 8690 { 8691 emit_insn (gen_lasx_xvsubwev_h_bu (t1, op1, op2)); 8692 emit_insn (gen_lasx_xvsubwod_h_bu (t2, op1, op2)); 8693 } 8694 } 8695 break; 8696 8697 default: 8698 gcc_unreachable (); 8699 } 8700 8701 loongarch_expand_vec_interleave (t3, t1, t2, high_p); 8702 emit_move_insn (dest, gen_lowpart (wmode, t3)); 8703 } 8704 8705 /* Expand a variable vector permutation for LASX. */ 8706 8707 void 8708 loongarch_expand_vec_perm_1 (rtx operands[]) 8709 { 8710 rtx target = operands[0]; 8711 rtx op0 = operands[1]; 8712 rtx op1 = operands[2]; 8713 rtx mask = operands[3]; 8714 8715 bool one_operand_shuffle = rtx_equal_p (op0, op1); 8716 rtx t1 = NULL; 8717 rtx t2 = NULL; 8718 rtx t3, t4, t5, t6, vt = NULL; 8719 rtx vec[32] = {NULL}; 8720 machine_mode mode = GET_MODE (op0); 8721 machine_mode maskmode = GET_MODE (mask); 8722 int w, i; 8723 8724 /* Number of elements in the vector. */ 8725 w = GET_MODE_NUNITS (mode); 8726 8727 rtx round_data[MAX_VECT_LEN]; 8728 rtx round_reg, round_data_rtx; 8729 8730 if (mode != E_V32QImode) 8731 { 8732 for (int i = 0; i < w; i += 1) 8733 { 8734 round_data[i] = GEN_INT (0x1f); 8735 } 8736 8737 if (mode == E_V4DFmode) 8738 { 8739 round_data_rtx = gen_rtx_CONST_VECTOR (E_V4DImode, 8740 gen_rtvec_v (w, round_data)); 8741 round_reg = gen_reg_rtx (E_V4DImode); 8742 } 8743 else if (mode == E_V8SFmode) 8744 { 8745 8746 round_data_rtx = gen_rtx_CONST_VECTOR (E_V8SImode, 8747 gen_rtvec_v (w, round_data)); 8748 round_reg = gen_reg_rtx (E_V8SImode); 8749 } 8750 else 8751 { 8752 round_data_rtx = gen_rtx_CONST_VECTOR (mode, 8753 gen_rtvec_v (w, round_data)); 8754 round_reg = gen_reg_rtx (mode); 8755 } 8756 8757 emit_move_insn (round_reg, round_data_rtx); 8758 switch (mode) 8759 { 8760 case E_V32QImode: 8761 emit_insn (gen_andv32qi3 (mask, mask, round_reg)); 8762 break; 8763 case E_V16HImode: 8764 emit_insn (gen_andv16hi3 (mask, mask, round_reg)); 8765 break; 8766 case E_V8SImode: 8767 case E_V8SFmode: 8768 emit_insn (gen_andv8si3 (mask, mask, round_reg)); 8769 break; 8770 case E_V4DImode: 8771 case E_V4DFmode: 8772 emit_insn (gen_andv4di3 (mask, mask, round_reg)); 8773 break; 8774 default: 8775 gcc_unreachable (); 8776 break; 8777 } 8778 } 8779 8780 if (mode == V4DImode || mode == V4DFmode) 8781 { 8782 maskmode = mode = V8SImode; 8783 w = 8; 8784 t1 = gen_reg_rtx (maskmode); 8785 8786 /* Replicate the low bits of the V4DImode mask into V8SImode: 8787 mask = { A B C D } 8788 t1 = { A A B B C C D D }. */ 8789 for (i = 0; i < w / 2; ++i) 8790 vec[i*2 + 1] = vec[i*2] = GEN_INT (i * 2); 8791 vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec)); 8792 vt = force_reg (maskmode, vt); 8793 mask = gen_lowpart (maskmode, mask); 8794 emit_insn (gen_lasx_xvperm_w (t1, mask, vt)); 8795 8796 /* Multiply the shuffle indicies by two. */ 8797 t1 = expand_simple_binop (maskmode, PLUS, t1, t1, t1, 1, 8798 OPTAB_DIRECT); 8799 8800 /* Add one to the odd shuffle indicies: 8801 t1 = { A*2, A*2+1, B*2, B*2+1, ... }. */ 8802 for (i = 0; i < w / 2; ++i) 8803 { 8804 vec[i * 2] = const0_rtx; 8805 vec[i * 2 + 1] = const1_rtx; 8806 } 8807 vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec)); 8808 vt = validize_mem (force_const_mem (maskmode, vt)); 8809 t1 = expand_simple_binop (maskmode, PLUS, t1, vt, t1, 1, 8810 OPTAB_DIRECT); 8811 8812 /* Continue as if V8SImode (resp. V32QImode) was used initially. */ 8813 operands[3] = mask = t1; 8814 target = gen_reg_rtx (mode); 8815 op0 = gen_lowpart (mode, op0); 8816 op1 = gen_lowpart (mode, op1); 8817 } 8818 8819 switch (mode) 8820 { 8821 case E_V8SImode: 8822 if (one_operand_shuffle) 8823 { 8824 emit_insn (gen_lasx_xvperm_w (target, op0, mask)); 8825 if (target != operands[0]) 8826 emit_move_insn (operands[0], 8827 gen_lowpart (GET_MODE (operands[0]), target)); 8828 } 8829 else 8830 { 8831 t1 = gen_reg_rtx (V8SImode); 8832 t2 = gen_reg_rtx (V8SImode); 8833 emit_insn (gen_lasx_xvperm_w (t1, op0, mask)); 8834 emit_insn (gen_lasx_xvperm_w (t2, op1, mask)); 8835 goto merge_two; 8836 } 8837 return; 8838 8839 case E_V8SFmode: 8840 mask = gen_lowpart (V8SImode, mask); 8841 if (one_operand_shuffle) 8842 emit_insn (gen_lasx_xvperm_w_f (target, op0, mask)); 8843 else 8844 { 8845 t1 = gen_reg_rtx (V8SFmode); 8846 t2 = gen_reg_rtx (V8SFmode); 8847 emit_insn (gen_lasx_xvperm_w_f (t1, op0, mask)); 8848 emit_insn (gen_lasx_xvperm_w_f (t2, op1, mask)); 8849 goto merge_two; 8850 } 8851 return; 8852 8853 case E_V16HImode: 8854 if (one_operand_shuffle) 8855 { 8856 t1 = gen_reg_rtx (V16HImode); 8857 t2 = gen_reg_rtx (V16HImode); 8858 emit_insn (gen_lasx_xvpermi_d_v16hi (t1, op0, GEN_INT (0x44))); 8859 emit_insn (gen_lasx_xvpermi_d_v16hi (t2, op0, GEN_INT (0xee))); 8860 emit_insn (gen_lasx_xvshuf_h (target, mask, t2, t1)); 8861 } 8862 else 8863 { 8864 t1 = gen_reg_rtx (V16HImode); 8865 t2 = gen_reg_rtx (V16HImode); 8866 t3 = gen_reg_rtx (V16HImode); 8867 t4 = gen_reg_rtx (V16HImode); 8868 t5 = gen_reg_rtx (V16HImode); 8869 t6 = gen_reg_rtx (V16HImode); 8870 emit_insn (gen_lasx_xvpermi_d_v16hi (t3, op0, GEN_INT (0x44))); 8871 emit_insn (gen_lasx_xvpermi_d_v16hi (t4, op0, GEN_INT (0xee))); 8872 emit_insn (gen_lasx_xvshuf_h (t1, mask, t4, t3)); 8873 emit_insn (gen_lasx_xvpermi_d_v16hi (t5, op1, GEN_INT (0x44))); 8874 emit_insn (gen_lasx_xvpermi_d_v16hi (t6, op1, GEN_INT (0xee))); 8875 emit_insn (gen_lasx_xvshuf_h (t2, mask, t6, t5)); 8876 goto merge_two; 8877 } 8878 return; 8879 8880 case E_V32QImode: 8881 if (one_operand_shuffle) 8882 { 8883 t1 = gen_reg_rtx (V32QImode); 8884 t2 = gen_reg_rtx (V32QImode); 8885 emit_insn (gen_lasx_xvpermi_d_v32qi (t1, op0, GEN_INT (0x44))); 8886 emit_insn (gen_lasx_xvpermi_d_v32qi (t2, op0, GEN_INT (0xee))); 8887 emit_insn (gen_lasx_xvshuf_b (target, t2, t1, mask)); 8888 } 8889 else 8890 { 8891 t1 = gen_reg_rtx (V32QImode); 8892 t2 = gen_reg_rtx (V32QImode); 8893 t3 = gen_reg_rtx (V32QImode); 8894 t4 = gen_reg_rtx (V32QImode); 8895 t5 = gen_reg_rtx (V32QImode); 8896 t6 = gen_reg_rtx (V32QImode); 8897 emit_insn (gen_lasx_xvpermi_d_v32qi (t3, op0, GEN_INT (0x44))); 8898 emit_insn (gen_lasx_xvpermi_d_v32qi (t4, op0, GEN_INT (0xee))); 8899 emit_insn (gen_lasx_xvshuf_b (t1, t4, t3, mask)); 8900 emit_insn (gen_lasx_xvpermi_d_v32qi (t5, op1, GEN_INT (0x44))); 8901 emit_insn (gen_lasx_xvpermi_d_v32qi (t6, op1, GEN_INT (0xee))); 8902 emit_insn (gen_lasx_xvshuf_b (t2, t6, t5, mask)); 8903 goto merge_two; 8904 } 8905 return; 8906 8907 default: 8908 gcc_assert (GET_MODE_SIZE (mode) == 32); 8909 break; 8910 } 8911 8912 merge_two: 8913 /* Then merge them together. The key is whether any given control 8914 element contained a bit set that indicates the second word. */ 8915 rtx xops[6]; 8916 mask = operands[3]; 8917 vt = GEN_INT (w); 8918 vt = gen_const_vec_duplicate (maskmode, vt); 8919 vt = force_reg (maskmode, vt); 8920 mask = expand_simple_binop (maskmode, AND, mask, vt, 8921 NULL_RTX, 0, OPTAB_DIRECT); 8922 if (GET_MODE (target) != mode) 8923 target = gen_reg_rtx (mode); 8924 xops[0] = target; 8925 xops[1] = gen_lowpart (mode, t2); 8926 xops[2] = gen_lowpart (mode, t1); 8927 xops[3] = gen_rtx_EQ (maskmode, mask, vt); 8928 xops[4] = mask; 8929 xops[5] = vt; 8930 8931 loongarch_expand_vec_cond_expr (mode, maskmode, xops); 8932 if (target != operands[0]) 8933 emit_move_insn (operands[0], 8934 gen_lowpart (GET_MODE (operands[0]), target)); 8935 } 8936 8937 void 8938 loongarch_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel) 8939 { 8940 machine_mode vmode = GET_MODE (target); 8941 machine_mode vimode = GET_MODE (sel); 8942 auto nelt = GET_MODE_NUNITS (vmode); 8943 auto round_reg = gen_reg_rtx (vimode); 8944 rtx round_data[MAX_VECT_LEN]; 8945 8946 for (int i = 0; i < nelt; i += 1) 8947 { 8948 round_data[i] = GEN_INT (0x1f); 8949 } 8950 8951 rtx round_data_rtx = gen_rtx_CONST_VECTOR (vimode, gen_rtvec_v (nelt, round_data)); 8952 emit_move_insn (round_reg, round_data_rtx); 8953 8954 if (vmode != vimode) 8955 { 8956 target = lowpart_subreg (vimode, target, vmode); 8957 op0 = lowpart_subreg (vimode, op0, vmode); 8958 op1 = lowpart_subreg (vimode, op1, vmode); 8959 } 8960 8961 switch (vmode) 8962 { 8963 case E_V16QImode: 8964 emit_insn (gen_andv16qi3 (sel, sel, round_reg)); 8965 emit_insn (gen_lsx_vshuf_b (target, op1, op0, sel)); 8966 break; 8967 case E_V2DFmode: 8968 case E_V2DImode: 8969 emit_insn (gen_andv2di3 (sel, sel, round_reg)); 8970 emit_insn (gen_lsx_vshuf_d (target, sel, op1, op0)); 8971 break; 8972 case E_V4SFmode: 8973 case E_V4SImode: 8974 emit_insn (gen_andv4si3 (sel, sel, round_reg)); 8975 emit_insn (gen_lsx_vshuf_w (target, sel, op1, op0)); 8976 break; 8977 case E_V8HImode: 8978 emit_insn (gen_andv8hi3 (sel, sel, round_reg)); 8979 emit_insn (gen_lsx_vshuf_h (target, sel, op1, op0)); 8980 break; 8981 default: 8982 break; 8983 } 8984 } 8985 8986 /* Following are the assist function for const vector permutation support. */ 8987 static bool 8988 loongarch_is_quad_duplicate (struct expand_vec_perm_d *d) 8989 { 8990 if (d->perm[0] >= d->nelt / 2) 8991 return false; 8992 8993 bool result = true; 8994 unsigned char lhs = d->perm[0]; 8995 unsigned char rhs = d->perm[d->nelt / 2]; 8996 8997 if ((rhs - lhs) != d->nelt / 2) 8998 return false; 8999 9000 for (int i = 1; i < d->nelt; i += 1) 9001 { 9002 if ((i < d->nelt / 2) && (d->perm[i] != lhs)) 9003 { 9004 result = false; 9005 break; 9006 } 9007 if ((i > d->nelt / 2) && (d->perm[i] != rhs)) 9008 { 9009 result = false; 9010 break; 9011 } 9012 } 9013 9014 return result; 9015 } 9016 9017 static bool 9018 loongarch_is_extraction_permutation (struct expand_vec_perm_d *d) 9019 { 9020 bool result = true; 9021 unsigned char buf = d->perm[0]; 9022 9023 if (buf != 0 || buf != d->nelt) 9024 return false; 9025 9026 for (int i = 0; i < d->nelt; i += 1) 9027 { 9028 if (buf != d->perm[i]) 9029 { 9030 result = false; 9031 break; 9032 } 9033 buf += 1; 9034 } 9035 9036 return result; 9037 } 9038 9039 static bool 9040 loongarch_is_lasx_lowpart_interleave (struct expand_vec_perm_d *d) 9041 { 9042 bool result = true; 9043 unsigned char buf = 0; 9044 9045 for (int i = 0;i < d->nelt; i += 2) 9046 { 9047 if (buf != d->perm[i]) 9048 { 9049 result = false; 9050 break; 9051 } 9052 buf += 1; 9053 } 9054 9055 if (result) 9056 { 9057 buf = d->nelt; 9058 for (int i = 1; i < d->nelt; i += 2) 9059 { 9060 if (buf != d->perm[i]) 9061 { 9062 result = false; 9063 break; 9064 } 9065 buf += 1; 9066 } 9067 } 9068 9069 return result; 9070 } 9071 9072 static bool 9073 loongarch_is_lasx_lowpart_interleave_2 (struct expand_vec_perm_d *d) 9074 { 9075 if (d->vmode != E_V32QImode) 9076 return false; 9077 bool result = true; 9078 unsigned char buf = 0; 9079 9080 #define COMPARE_SELECTOR(INIT, BEGIN, END) \ 9081 buf = INIT; \ 9082 for (int i = BEGIN; i < END && result; i += 1) \ 9083 { \ 9084 if (buf != d->perm[i]) \ 9085 { \ 9086 result = false; \ 9087 break; \ 9088 } \ 9089 buf += 1; \ 9090 } 9091 9092 COMPARE_SELECTOR (0, 0, 8); 9093 COMPARE_SELECTOR (32, 8, 16); 9094 COMPARE_SELECTOR (8, 16, 24); 9095 COMPARE_SELECTOR (40, 24, 32); 9096 9097 #undef COMPARE_SELECTOR 9098 return result; 9099 } 9100 9101 static bool 9102 loongarch_is_lasx_highpart_interleave (expand_vec_perm_d *d) 9103 { 9104 bool result = true; 9105 unsigned char buf = d->nelt / 2; 9106 9107 for (int i = 0; i < d->nelt; i += 2) 9108 { 9109 if (buf != d->perm[i]) 9110 { 9111 result = false; 9112 break; 9113 } 9114 buf += 1; 9115 } 9116 9117 if (result) 9118 { 9119 buf = d->nelt + d->nelt / 2; 9120 for (int i = 1; i < d->nelt;i += 2) 9121 { 9122 if (buf != d->perm[i]) 9123 { 9124 result = false; 9125 break; 9126 } 9127 buf += 1; 9128 } 9129 } 9130 9131 return result; 9132 } 9133 9134 static bool 9135 loongarch_is_lasx_highpart_interleave_2 (struct expand_vec_perm_d *d) 9136 { 9137 if (d->vmode != E_V32QImode) 9138 return false; 9139 9140 bool result = true; 9141 unsigned char buf = 0; 9142 9143 #define COMPARE_SELECTOR(INIT, BEGIN, END) \ 9144 buf = INIT; \ 9145 for (int i = BEGIN; i < END && result; i += 1) \ 9146 { \ 9147 if (buf != d->perm[i]) \ 9148 { \ 9149 result = false; \ 9150 break; \ 9151 } \ 9152 buf += 1; \ 9153 } 9154 9155 COMPARE_SELECTOR (16, 0, 8); 9156 COMPARE_SELECTOR (48, 8, 16); 9157 COMPARE_SELECTOR (24, 16, 24); 9158 COMPARE_SELECTOR (56, 24, 32); 9159 9160 #undef COMPARE_SELECTOR 9161 return result; 9162 } 9163 9164 static bool 9165 loongarch_is_elem_duplicate (struct expand_vec_perm_d *d) 9166 { 9167 bool result = true; 9168 unsigned char buf = d->perm[0]; 9169 9170 for (int i = 0; i < d->nelt; i += 1) 9171 { 9172 if (buf != d->perm[i]) 9173 { 9174 result = false; 9175 break; 9176 } 9177 } 9178 9179 return result; 9180 } 9181 9182 /* In LASX, some permutation insn does not have the behavior that gcc expects 9183 when compiler wants to emit a vector permutation. 9184 9185 1. What GCC provides via vectorize_vec_perm_const ()'s paramater: 9186 When GCC wants to performs a vector permutation, it provides two op 9187 reigster, one target register, and a selector. 9188 In const vector permutation case, GCC provides selector as a char array 9189 that contains original value; in variable vector permuatation 9190 (performs via vec_perm<mode> insn template), it provides a vector register. 9191 We assume that nelt is the elements numbers inside single vector in current 9192 256bit vector mode. 9193 9194 2. What GCC expects to perform: 9195 Two op registers (op0, op1) will "combine" into a 512bit temp vector storage 9196 that has 2*nelt elements inside it; the low 256bit is op0, and high 256bit 9197 is op1, then the elements are indexed as below: 9198 0 ~ nelt - 1 nelt ~ 2 * nelt - 1 9199 |-------------------------|-------------------------| 9200 Low 256bit (op0) High 256bit (op1) 9201 For example, the second element in op1 (V8SImode) will be indexed with 9. 9202 Selector is a vector that has the same mode and number of elements with 9203 op0,op1 and target, it's look like this: 9204 0 ~ nelt - 1 9205 |-------------------------| 9206 256bit (selector) 9207 It describes which element from 512bit temp vector storage will fit into 9208 target's every element slot. 9209 GCC expects that every element in selector can be ANY indices of 512bit 9210 vector storage (Selector can pick literally any element from op0 and op1, and 9211 then fits into any place of target register). This is also what LSX 128bit 9212 vshuf.* instruction do similarly, so we can handle 128bit vector permutation 9213 by single instruction easily. 9214 9215 3. What LASX permutation instruction does: 9216 In short, it just execute two independent 128bit vector permuatation, and 9217 it's the reason that we need to do the jobs below. We will explain it. 9218 op0, op1, target, and selector will be separate into high 128bit and low 9219 128bit, and do permutation as the description below: 9220 9221 a) op0's low 128bit and op1's low 128bit "combines" into a 256bit temp 9222 vector storage (TVS1), elements are indexed as below: 9223 0 ~ nelt / 2 - 1 nelt / 2 ~ nelt - 1 9224 |---------------------|---------------------| TVS1 9225 op0's low 128bit op1's low 128bit 9226 op0's high 128bit and op1's high 128bit are "combined" into TVS2 in the 9227 same way. 9228 0 ~ nelt / 2 - 1 nelt / 2 ~ nelt - 1 9229 |---------------------|---------------------| TVS2 9230 op0's high 128bit op1's high 128bit 9231 b) Selector's low 128bit describes which elements from TVS1 will fit into 9232 target vector's low 128bit. No TVS2 elements are allowed. 9233 c) Selector's high 128bit describes which elements from TVS2 will fit into 9234 target vector's high 128bit. No TVS1 elements are allowed. 9235 9236 As we can see, if we want to handle vector permutation correctly, we can 9237 achieve it in three ways: 9238 a) Modify selector's elements, to make sure that every elements can inform 9239 correct value that will put into target vector. 9240 b) Generate extra instruction before/after permutation instruction, for 9241 adjusting op vector or target vector, to make sure target vector's value is 9242 what GCC expects. 9243 c) Use other instructions to process op and put correct result into target. 9244 */ 9245 9246 /* Implementation of constant vector permuatation. This function identifies 9247 recognized pattern of permuation selector argument, and use one or more 9248 instruction (s) to finish the permutation job correctly. For unsupported 9249 patterns, it will return false. */ 9250 9251 static bool 9252 loongarch_expand_vec_perm_const (struct expand_vec_perm_d *d) 9253 { 9254 bool flag = false; 9255 unsigned int i; 9256 unsigned char idx; 9257 rtx target, op0, op1, sel, tmp; 9258 rtx rperm[MAX_VECT_LEN]; 9259 unsigned int remapped[MAX_VECT_LEN]; 9260 unsigned char perm2[MAX_VECT_LEN]; 9261 9262 if (GET_MODE_SIZE (d->vmode) == 16) 9263 return loongarch_expand_lsx_shuffle (d); 9264 else 9265 { 9266 if (d->one_vector_p) 9267 { 9268 /* Try interleave with alternating operands. */ 9269 memcpy (perm2, d->perm, sizeof (perm2)); 9270 for (i = 1; i < d->nelt; i += 2) 9271 perm2[i] += d->nelt; 9272 if (loongarch_expand_vselect_vconcat (d->target, d->op0, d->op1, 9273 perm2, d->nelt, d->testing_p)) 9274 return true; 9275 } 9276 else 9277 { 9278 if (loongarch_expand_vselect_vconcat (d->target, d->op0, d->op1, 9279 d->perm, d->nelt, 9280 d->testing_p)) 9281 return true; 9282 9283 /* Try again with swapped operands. */ 9284 for (i = 0; i < d->nelt; ++i) 9285 perm2[i] = (d->perm[i] + d->nelt) & (2 * d->nelt - 1); 9286 if (loongarch_expand_vselect_vconcat (d->target, d->op1, d->op0, 9287 perm2, d->nelt, d->testing_p)) 9288 return true; 9289 } 9290 9291 if (loongarch_is_imm_set_shuffle (d)) 9292 return true; 9293 9294 if (loongarch_expand_vec_perm_even_odd (d)) 9295 return true; 9296 9297 if (loongarch_is_lasx_lowpart_interleave (d) 9298 || loongarch_is_lasx_lowpart_interleave_2 (d) 9299 || loongarch_is_lasx_highpart_interleave (d) 9300 || loongarch_is_lasx_highpart_interleave_2 (d)) 9301 { 9302 if (loongarch_expand_vec_perm_interleave (d)) 9303 return true; 9304 } 9305 9306 if (loongarch_is_quad_duplicate (d)) 9307 { 9308 if (d->testing_p) 9309 return true; 9310 /* Selector example: E_V8SImode, { 0, 0, 0, 0, 4, 4, 4, 4 }. */ 9311 for (i = 0; i < d->nelt; i += 1) 9312 { 9313 rperm[i] = GEN_INT (d->perm[0]); 9314 } 9315 /* Selector after: { 0, 0, 0, 0, 0, 0, 0, 0 }. */ 9316 flag = true; 9317 goto expand_perm_const_end; 9318 } 9319 9320 if (loongarch_is_extraction_permutation (d)) 9321 { 9322 if (d->testing_p) 9323 return true; 9324 /* Selector sample: E_V8SImode, { 0, 1, 2, 3, 4, 5, 6, 7 }. */ 9325 if (d->perm[0] == 0) 9326 { 9327 for (i = 0; i < d->nelt / 2; i += 1) 9328 { 9329 remapped[i] = i; 9330 remapped[i + d->nelt / 2] = i; 9331 } 9332 } 9333 else 9334 { 9335 /* { 8, 9, 10, 11, 12, 13, 14, 15 }. */ 9336 for (i = 0; i < d->nelt / 2; i += 1) 9337 { 9338 idx = i + d->nelt / 2; 9339 remapped[i] = idx; 9340 remapped[i + d->nelt / 2] = idx; 9341 } 9342 } 9343 /* Selector after: { 0, 1, 2, 3, 0, 1, 2, 3 } 9344 { 8, 9, 10, 11, 8, 9, 10, 11 } */ 9345 9346 /* Convert remapped selector array to RTL array. */ 9347 for (i = 0; i < d->nelt; i += 1) 9348 { 9349 rperm[i] = GEN_INT (remapped[i]); 9350 } 9351 9352 flag = true; 9353 goto expand_perm_const_end; 9354 } 9355 9356 if (loongarch_is_elem_duplicate (d)) 9357 { 9358 if (d->testing_p) 9359 return true; 9360 /* Brocast single element (from op0 or op1) to all slot of target 9361 register. 9362 Selector sample:E_V8SImode, { 2, 2, 2, 2, 2, 2, 2, 2 } */ 9363 rtx conv_op1 = simplify_gen_subreg (E_V4DImode, d->op1, d->vmode, 0); 9364 rtx conv_op0 = simplify_gen_subreg (E_V4DImode, d->op0, d->vmode, 0); 9365 rtx temp_reg = gen_reg_rtx (d->vmode); 9366 rtx conv_temp = simplify_gen_subreg (E_V4DImode, temp_reg, 9367 d->vmode, 0); 9368 emit_move_insn (temp_reg, d->op0); 9369 9370 idx = d->perm[0]; 9371 /* We will use xvrepl128vei.* insn to achieve the result, but we need 9372 to make the high/low 128bit has the same contents that contain the 9373 value that we need to broardcast, because xvrepl128vei does the 9374 broardcast job from every 128bit of source register to 9375 corresponded part of target register! (A deep sigh.) */ 9376 if (idx < d->nelt / 2) 9377 { 9378 emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp, 9379 conv_op0, GEN_INT (0x0))); 9380 } 9381 else if (idx >= d->nelt / 2 && idx < d->nelt) 9382 { 9383 emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp, 9384 conv_op0, GEN_INT (0x11))); 9385 idx -= d->nelt / 2; 9386 } 9387 else if (idx >= d->nelt && idx < (d->nelt + d->nelt / 2)) 9388 { 9389 emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp, 9390 conv_op1, GEN_INT (0x0))); 9391 } 9392 else if (idx >= (d->nelt + d->nelt / 2) && idx < d->nelt * 2) 9393 { 9394 emit_insn (gen_lasx_xvpermi_q_v4di (conv_temp, conv_temp, 9395 conv_op1, GEN_INT (0x11))); 9396 idx -= d->nelt / 2; 9397 } 9398 9399 /* Then we can finally generate this insn. */ 9400 switch (d->vmode) 9401 { 9402 case E_V4DImode: 9403 emit_insn (gen_lasx_xvrepl128vei_d (d->target, temp_reg, 9404 GEN_INT (idx))); 9405 break; 9406 case E_V4DFmode: 9407 emit_insn (gen_lasx_xvrepl128vei_d_f (d->target, temp_reg, 9408 GEN_INT (idx))); 9409 break; 9410 case E_V8SImode: 9411 emit_insn (gen_lasx_xvrepl128vei_w (d->target, temp_reg, 9412 GEN_INT (idx))); 9413 break; 9414 case E_V8SFmode: 9415 emit_insn (gen_lasx_xvrepl128vei_w_f (d->target, temp_reg, 9416 GEN_INT (idx))); 9417 break; 9418 case E_V16HImode: 9419 emit_insn (gen_lasx_xvrepl128vei_h (d->target, temp_reg, 9420 GEN_INT (idx))); 9421 break; 9422 case E_V32QImode: 9423 emit_insn (gen_lasx_xvrepl128vei_b (d->target, temp_reg, 9424 GEN_INT (idx))); 9425 break; 9426 default: 9427 gcc_unreachable (); 9428 break; 9429 } 9430 9431 return true; 9432 } 9433 9434 expand_perm_const_end: 9435 if (flag) 9436 { 9437 /* Copy selector vector from memory to vector register for later insn 9438 gen function. 9439 If vector's element in floating point value, we cannot fit 9440 selector argument into insn gen function directly, because of the 9441 insn template definition. As a solution, generate a integral mode 9442 subreg of target, then copy selector vector (that is in integral 9443 mode) to this subreg. */ 9444 switch (d->vmode) 9445 { 9446 case E_V4DFmode: 9447 sel = gen_rtx_CONST_VECTOR (E_V4DImode, gen_rtvec_v (d->nelt, 9448 rperm)); 9449 tmp = simplify_gen_subreg (E_V4DImode, d->target, d->vmode, 0); 9450 emit_move_insn (tmp, sel); 9451 break; 9452 case E_V8SFmode: 9453 sel = gen_rtx_CONST_VECTOR (E_V8SImode, gen_rtvec_v (d->nelt, 9454 rperm)); 9455 tmp = simplify_gen_subreg (E_V8SImode, d->target, d->vmode, 0); 9456 emit_move_insn (tmp, sel); 9457 break; 9458 default: 9459 sel = gen_rtx_CONST_VECTOR (d->vmode, gen_rtvec_v (d->nelt, 9460 rperm)); 9461 emit_move_insn (d->target, sel); 9462 break; 9463 } 9464 9465 target = d->target; 9466 op0 = d->op0; 9467 op1 = d->one_vector_p ? d->op0 : d->op1; 9468 9469 /* We FINALLY can generate xvshuf.* insn. */ 9470 switch (d->vmode) 9471 { 9472 case E_V4DFmode: 9473 emit_insn (gen_lasx_xvshuf_d_f (target, target, op1, op0)); 9474 break; 9475 case E_V4DImode: 9476 emit_insn (gen_lasx_xvshuf_d (target, target, op1, op0)); 9477 break; 9478 case E_V8SFmode: 9479 emit_insn (gen_lasx_xvshuf_w_f (target, target, op1, op0)); 9480 break; 9481 case E_V8SImode: 9482 emit_insn (gen_lasx_xvshuf_w (target, target, op1, op0)); 9483 break; 9484 case E_V16HImode: 9485 emit_insn (gen_lasx_xvshuf_h (target, target, op1, op0)); 9486 break; 9487 case E_V32QImode: 9488 emit_insn (gen_lasx_xvshuf_b (target, op1, op0, target)); 9489 break; 9490 default: 9491 gcc_unreachable (); 9492 break; 9493 } 9494 9495 return true; 9496 } 9497 } 9498 9499 return false; 9500 } 9501 9502 /* Implement TARGET_VECTORIZE_VEC_PERM_CONST. */ 9503 9504 static bool 9505 loongarch_vectorize_vec_perm_const (machine_mode vmode, machine_mode op_mode, 9506 rtx target, rtx op0, rtx op1, 9507 const vec_perm_indices &sel) 9508 { 9509 if (vmode != op_mode) 9510 return false; 9511 9512 struct expand_vec_perm_d d; 9513 int i, nelt, which; 9514 unsigned char orig_perm[MAX_VECT_LEN]; 9515 bool ok; 9516 9517 d.target = target; 9518 if (op0) 9519 { 9520 rtx nop0 = force_reg (vmode, op0); 9521 if (op0 == op1) 9522 op1 = nop0; 9523 op0 = nop0; 9524 } 9525 if (op1) 9526 op1 = force_reg (vmode, op1); 9527 d.op0 = op0; 9528 d.op1 = op1; 9529 9530 d.vmode = vmode; 9531 gcc_assert (VECTOR_MODE_P (vmode)); 9532 d.nelt = nelt = GET_MODE_NUNITS (vmode); 9533 d.testing_p = !target; 9534 9535 /* This is overly conservative, but ensures we don't get an 9536 uninitialized warning on ORIG_PERM. */ 9537 memset (orig_perm, 0, MAX_VECT_LEN); 9538 for (i = which = 0; i < nelt; ++i) 9539 { 9540 int ei = sel[i] & (2 * nelt - 1); 9541 which |= (ei < nelt ? 1 : 2); 9542 orig_perm[i] = ei; 9543 } 9544 memcpy (d.perm, orig_perm, MAX_VECT_LEN); 9545 9546 switch (which) 9547 { 9548 default: 9549 gcc_unreachable (); 9550 9551 case 3: 9552 d.one_vector_p = false; 9553 if (d.testing_p || !rtx_equal_p (d.op0, d.op1)) 9554 break; 9555 /* FALLTHRU */ 9556 9557 case 2: 9558 for (i = 0; i < nelt; ++i) 9559 d.perm[i] &= nelt - 1; 9560 d.op0 = d.op1; 9561 d.one_vector_p = true; 9562 break; 9563 9564 case 1: 9565 d.op1 = d.op0; 9566 d.one_vector_p = true; 9567 break; 9568 } 9569 9570 // Do rounding for selector to avoid vshuf undefined behavior. 9571 for (i = 0; i < d.nelt; i += 1) 9572 { 9573 d.perm[i] %= (d.nelt * 2); 9574 } 9575 9576 if (d.testing_p) 9577 { 9578 d.target = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 1); 9579 d.op1 = d.op0 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 2); 9580 if (!d.one_vector_p) 9581 d.op1 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 3); 9582 9583 start_sequence (); 9584 ok = loongarch_expand_vec_perm_const (&d); 9585 end_sequence (); 9586 return ok; 9587 } 9588 9589 ok = loongarch_expand_vec_perm_const (&d); 9590 9591 /* If we were given a two-vector permutation which just happened to 9592 have both input vectors equal, we folded this into a one-vector 9593 permutation. There are several loongson patterns that are matched 9594 via direct vec_select+vec_concat expansion, but we do not have 9595 support in loongarch_expand_vec_perm_const to guess the adjustment 9596 that should be made for a single operand. Just try again with 9597 the original permutation. */ 9598 if (!ok && which == 3) 9599 { 9600 d.op0 = op0; 9601 d.op1 = op1; 9602 d.one_vector_p = false; 9603 memcpy (d.perm, orig_perm, MAX_VECT_LEN); 9604 ok = loongarch_expand_vec_perm_const (&d); 9605 } 9606 9607 return ok; 9608 } 9609 9610 static int 9611 loongarch_cpu_sched_reassociation_width (struct loongarch_target *target, 9612 unsigned int opc, machine_mode mode) 9613 { 9614 /* unreferenced argument */ 9615 (void) opc; 9616 9617 switch (target->cpu_tune) 9618 { 9619 case TUNE_GENERIC: 9620 case TUNE_LOONGARCH64: 9621 case TUNE_LA464: 9622 case TUNE_LA664: 9623 /* Vector part. */ 9624 if (LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode)) 9625 { 9626 /* Integer vector instructions execute in FP unit. 9627 The width of integer/float-point vector instructions is 3. */ 9628 return 3; 9629 } 9630 9631 /* Scalar part. */ 9632 else if (INTEGRAL_MODE_P (mode)) 9633 return 1; 9634 else if (FLOAT_MODE_P (mode)) 9635 { 9636 if (opc == PLUS_EXPR) 9637 { 9638 return 2; 9639 } 9640 return 4; 9641 } 9642 break; 9643 default: 9644 break; 9645 } 9646 9647 /* default is 1 */ 9648 return 1; 9649 } 9650 9651 /* Implement TARGET_SCHED_REASSOCIATION_WIDTH. */ 9652 9653 static int 9654 loongarch_sched_reassociation_width (unsigned int opc, machine_mode mode) 9655 { 9656 return loongarch_cpu_sched_reassociation_width (&la_target, opc, mode); 9657 } 9658 9659 /* Implement extract a scalar element from vecotr register */ 9660 9661 void 9662 loongarch_expand_vector_extract (rtx target, rtx vec, int elt) 9663 { 9664 machine_mode mode = GET_MODE (vec); 9665 machine_mode inner_mode = GET_MODE_INNER (mode); 9666 rtx tmp; 9667 9668 switch (mode) 9669 { 9670 case E_V8HImode: 9671 case E_V16QImode: 9672 break; 9673 9674 case E_V32QImode: 9675 if (ISA_HAS_LASX) 9676 { 9677 if (elt >= 16) 9678 { 9679 tmp = gen_reg_rtx (V32QImode); 9680 emit_insn (gen_lasx_xvpermi_d_v32qi (tmp, vec, GEN_INT (0xe))); 9681 loongarch_expand_vector_extract (target, 9682 gen_lowpart (V16QImode, tmp), 9683 elt & 15); 9684 } 9685 else 9686 loongarch_expand_vector_extract (target, 9687 gen_lowpart (V16QImode, vec), 9688 elt & 15); 9689 return; 9690 } 9691 break; 9692 9693 case E_V16HImode: 9694 if (ISA_HAS_LASX) 9695 { 9696 if (elt >= 8) 9697 { 9698 tmp = gen_reg_rtx (V16HImode); 9699 emit_insn (gen_lasx_xvpermi_d_v16hi (tmp, vec, GEN_INT (0xe))); 9700 loongarch_expand_vector_extract (target, 9701 gen_lowpart (V8HImode, tmp), 9702 elt & 7); 9703 } 9704 else 9705 loongarch_expand_vector_extract (target, 9706 gen_lowpart (V8HImode, vec), 9707 elt & 7); 9708 return; 9709 } 9710 break; 9711 9712 default: 9713 break; 9714 } 9715 9716 tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (1, GEN_INT (elt))); 9717 tmp = gen_rtx_VEC_SELECT (inner_mode, vec, tmp); 9718 9719 /* Let the rtl optimizers know about the zero extension performed. */ 9720 if (inner_mode == QImode || inner_mode == HImode) 9721 { 9722 tmp = gen_rtx_ZERO_EXTEND (SImode, tmp); 9723 target = gen_lowpart (SImode, target); 9724 } 9725 if (inner_mode == SImode || inner_mode == DImode) 9726 { 9727 tmp = gen_rtx_SIGN_EXTEND (inner_mode, tmp); 9728 } 9729 9730 emit_insn (gen_rtx_SET (target, tmp)); 9731 } 9732 9733 /* Generate code to copy vector bits i / 2 ... i - 1 from vector SRC 9734 to bits 0 ... i / 2 - 1 of vector DEST, which has the same mode. 9735 The upper bits of DEST are undefined, though they shouldn't cause 9736 exceptions (some bits from src or all zeros are ok). */ 9737 9738 static void 9739 emit_reduc_half (rtx dest, rtx src, int i) 9740 { 9741 rtx tem, d = dest; 9742 switch (GET_MODE (src)) 9743 { 9744 case E_V4SFmode: 9745 tem = gen_lsx_vbsrl_w_f (dest, src, GEN_INT (i == 128 ? 8 : 4)); 9746 break; 9747 case E_V2DFmode: 9748 tem = gen_lsx_vbsrl_d_f (dest, src, GEN_INT (8)); 9749 break; 9750 case E_V8SFmode: 9751 if (i == 256) 9752 tem = gen_lasx_xvpermi_d_v8sf (dest, src, GEN_INT (0xe)); 9753 else 9754 tem = gen_lasx_xvshuf4i_w_f (dest, src, 9755 GEN_INT (i == 128 ? 2 + (3 << 2) : 1)); 9756 break; 9757 case E_V4DFmode: 9758 if (i == 256) 9759 tem = gen_lasx_xvpermi_d_v4df (dest, src, GEN_INT (0xe)); 9760 else 9761 tem = gen_lasx_xvpermi_d_v4df (dest, src, const1_rtx); 9762 break; 9763 case E_V32QImode: 9764 case E_V16HImode: 9765 case E_V8SImode: 9766 case E_V4DImode: 9767 d = gen_reg_rtx (V4DImode); 9768 if (i == 256) 9769 tem = gen_lasx_xvpermi_d_v4di (d, gen_lowpart (V4DImode, src), 9770 GEN_INT (0xe)); 9771 else 9772 tem = gen_lasx_xvbsrl_d (d, gen_lowpart (V4DImode, src), 9773 GEN_INT (i/16)); 9774 break; 9775 case E_V16QImode: 9776 case E_V8HImode: 9777 case E_V4SImode: 9778 case E_V2DImode: 9779 d = gen_reg_rtx (V2DImode); 9780 tem = gen_lsx_vbsrl_d (d, gen_lowpart (V2DImode, src), GEN_INT (i/16)); 9781 break; 9782 default: 9783 gcc_unreachable (); 9784 } 9785 emit_insn (tem); 9786 if (d != dest) 9787 emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d)); 9788 } 9789 9790 /* Expand a vector reduction. FN is the binary pattern to reduce; 9791 DEST is the destination; IN is the input vector. */ 9792 9793 void 9794 loongarch_expand_vector_reduc (rtx (*fn) (rtx, rtx, rtx), rtx dest, rtx in) 9795 { 9796 rtx half, dst, vec = in; 9797 machine_mode mode = GET_MODE (in); 9798 int i; 9799 9800 for (i = GET_MODE_BITSIZE (mode); 9801 i > GET_MODE_UNIT_BITSIZE (mode); 9802 i >>= 1) 9803 { 9804 half = gen_reg_rtx (mode); 9805 emit_reduc_half (half, vec, i); 9806 if (i == GET_MODE_UNIT_BITSIZE (mode) * 2) 9807 dst = dest; 9808 else 9809 dst = gen_reg_rtx (mode); 9810 emit_insn (fn (dst, half, vec)); 9811 vec = dst; 9812 } 9813 } 9814 9815 /* Expand an integral vector unpack operation. */ 9816 9817 void 9818 loongarch_expand_vec_unpack (rtx operands[2], bool unsigned_p, bool high_p) 9819 { 9820 machine_mode imode = GET_MODE (operands[1]); 9821 rtx (*unpack) (rtx, rtx, rtx); 9822 rtx (*extend) (rtx, rtx); 9823 rtx (*cmpFunc) (rtx, rtx, rtx); 9824 rtx (*swap_hi_lo) (rtx, rtx, rtx, rtx); 9825 rtx tmp, dest; 9826 9827 if (ISA_HAS_LASX && GET_MODE_SIZE (imode) == 32) 9828 { 9829 switch (imode) 9830 { 9831 case E_V8SImode: 9832 if (unsigned_p) 9833 extend = gen_lasx_vext2xv_du_wu; 9834 else 9835 extend = gen_lasx_vext2xv_d_w; 9836 swap_hi_lo = gen_lasx_xvpermi_q_v8si; 9837 break; 9838 9839 case E_V16HImode: 9840 if (unsigned_p) 9841 extend = gen_lasx_vext2xv_wu_hu; 9842 else 9843 extend = gen_lasx_vext2xv_w_h; 9844 swap_hi_lo = gen_lasx_xvpermi_q_v16hi; 9845 break; 9846 9847 case E_V32QImode: 9848 if (unsigned_p) 9849 extend = gen_lasx_vext2xv_hu_bu; 9850 else 9851 extend = gen_lasx_vext2xv_h_b; 9852 swap_hi_lo = gen_lasx_xvpermi_q_v32qi; 9853 break; 9854 9855 default: 9856 gcc_unreachable (); 9857 break; 9858 } 9859 9860 if (high_p) 9861 { 9862 tmp = gen_reg_rtx (imode); 9863 emit_insn (swap_hi_lo (tmp, tmp, operands[1], const1_rtx)); 9864 emit_insn (extend (operands[0], tmp)); 9865 return; 9866 } 9867 9868 emit_insn (extend (operands[0], operands[1])); 9869 return; 9870 9871 } 9872 else if (ISA_HAS_LSX) 9873 { 9874 switch (imode) 9875 { 9876 case E_V4SImode: 9877 if (high_p != 0) 9878 unpack = gen_lsx_vilvh_w; 9879 else 9880 unpack = gen_lsx_vilvl_w; 9881 9882 cmpFunc = gen_lsx_vslt_w; 9883 break; 9884 9885 case E_V8HImode: 9886 if (high_p != 0) 9887 unpack = gen_lsx_vilvh_h; 9888 else 9889 unpack = gen_lsx_vilvl_h; 9890 9891 cmpFunc = gen_lsx_vslt_h; 9892 break; 9893 9894 case E_V16QImode: 9895 if (high_p != 0) 9896 unpack = gen_lsx_vilvh_b; 9897 else 9898 unpack = gen_lsx_vilvl_b; 9899 9900 cmpFunc = gen_lsx_vslt_b; 9901 break; 9902 9903 default: 9904 gcc_unreachable (); 9905 break; 9906 } 9907 9908 if (!unsigned_p) 9909 { 9910 /* Extract sign extention for each element comparing each element 9911 with immediate zero. */ 9912 tmp = gen_reg_rtx (imode); 9913 emit_insn (cmpFunc (tmp, operands[1], CONST0_RTX (imode))); 9914 } 9915 else 9916 tmp = force_reg (imode, CONST0_RTX (imode)); 9917 9918 dest = gen_reg_rtx (imode); 9919 9920 emit_insn (unpack (dest, operands[1], tmp)); 9921 emit_move_insn (operands[0], gen_lowpart (GET_MODE (operands[0]), dest)); 9922 return; 9923 } 9924 gcc_unreachable (); 9925 } 9926 9927 /* Construct and return PARALLEL RTX with CONST_INTs for HIGH (high_p == TRUE) 9928 or LOW (high_p == FALSE) half of a vector for mode MODE. */ 9929 9930 rtx 9931 loongarch_lsx_vec_parallel_const_half (machine_mode mode, bool high_p) 9932 { 9933 int nunits = GET_MODE_NUNITS (mode); 9934 rtvec v = rtvec_alloc (nunits / 2); 9935 int base; 9936 int i; 9937 9938 base = high_p ? nunits / 2 : 0; 9939 9940 for (i = 0; i < nunits / 2; i++) 9941 RTVEC_ELT (v, i) = GEN_INT (base + i); 9942 9943 return gen_rtx_PARALLEL (VOIDmode, v); 9944 } 9945 9946 /* A subroutine of loongarch_expand_vec_init, match constant vector 9947 elements. */ 9948 9949 static inline bool 9950 loongarch_constant_elt_p (rtx x) 9951 { 9952 return CONST_INT_P (x) || GET_CODE (x) == CONST_DOUBLE; 9953 } 9954 9955 rtx 9956 loongarch_gen_const_int_vector_shuffle (machine_mode mode, int val) 9957 { 9958 int nunits = GET_MODE_NUNITS (mode); 9959 int nsets = nunits / 4; 9960 rtx elts[MAX_VECT_LEN]; 9961 int set = 0; 9962 int i, j; 9963 9964 /* Generate a const_int vector replicating the same 4-element set 9965 from an immediate. */ 9966 for (j = 0; j < nsets; j++, set = 4 * j) 9967 for (i = 0; i < 4; i++) 9968 elts[set + i] = GEN_INT (set + ((val >> (2 * i)) & 0x3)); 9969 9970 return gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nunits, elts)); 9971 } 9972 9973 9974 /* Expand a vector initialization. */ 9975 9976 void 9977 loongarch_expand_vector_group_init (rtx target, rtx vals) 9978 { 9979 machine_mode vmode = GET_MODE (target); 9980 machine_mode half_mode = VOIDmode; 9981 rtx low = XVECEXP (vals, 0, 0); 9982 rtx high = XVECEXP (vals, 0, 1); 9983 9984 switch (vmode) 9985 { 9986 case E_V32QImode: 9987 half_mode = V16QImode; 9988 break; 9989 case E_V16HImode: 9990 half_mode = V8HImode; 9991 break; 9992 case E_V8SImode: 9993 half_mode = V4SImode; 9994 break; 9995 case E_V4DImode: 9996 half_mode = V2DImode; 9997 break; 9998 case E_V8SFmode: 9999 half_mode = V4SFmode; 10000 break; 10001 case E_V4DFmode: 10002 half_mode = V2DFmode; 10003 break; 10004 default: 10005 gcc_unreachable (); 10006 } 10007 10008 if (!register_operand (low, half_mode)) 10009 low = force_reg (half_mode, low); 10010 if (!register_operand (high, half_mode)) 10011 high = force_reg (half_mode, high); 10012 emit_insn (gen_rtx_SET (target, 10013 gen_rtx_VEC_CONCAT (vmode, low, high))); 10014 } 10015 10016 /* Expand initialization of a vector which has all same elements. */ 10017 10018 void 10019 loongarch_expand_vector_init_same (rtx target, rtx vals, unsigned nvar) 10020 { 10021 machine_mode vmode = GET_MODE (target); 10022 machine_mode imode = GET_MODE_INNER (vmode); 10023 rtx same = XVECEXP (vals, 0, 0); 10024 rtx temp; 10025 10026 if (CONST_INT_P (same) && nvar == 0 10027 && loongarch_signed_immediate_p (INTVAL (same), 10, 0)) 10028 { 10029 switch (vmode) 10030 { 10031 case E_V32QImode: 10032 case E_V16HImode: 10033 case E_V8SImode: 10034 case E_V4DImode: 10035 case E_V16QImode: 10036 case E_V8HImode: 10037 case E_V4SImode: 10038 case E_V2DImode: 10039 temp = gen_rtx_CONST_VECTOR (vmode, XVEC (vals, 0)); 10040 emit_move_insn (target, temp); 10041 return; 10042 default: 10043 gcc_unreachable (); 10044 } 10045 } 10046 10047 if (imode == GET_MODE (same)) 10048 temp = same; 10049 else if (GET_MODE_SIZE (imode) >= UNITS_PER_WORD) 10050 { 10051 if (GET_CODE (same) == MEM) 10052 { 10053 rtx reg_tmp = gen_reg_rtx (GET_MODE (same)); 10054 loongarch_emit_move (reg_tmp, same); 10055 temp = simplify_gen_subreg (imode, reg_tmp, GET_MODE (reg_tmp), 0); 10056 } 10057 else 10058 temp = simplify_gen_subreg (imode, same, GET_MODE (same), 0); 10059 } 10060 else 10061 { 10062 if (GET_CODE (same) == MEM) 10063 { 10064 rtx reg_tmp = gen_reg_rtx (GET_MODE (same)); 10065 loongarch_emit_move (reg_tmp, same); 10066 temp = lowpart_subreg (imode, reg_tmp, GET_MODE (reg_tmp)); 10067 } 10068 else 10069 temp = lowpart_subreg (imode, same, GET_MODE (same)); 10070 } 10071 10072 temp = force_reg (imode, temp); 10073 10074 switch (vmode) 10075 { 10076 case E_V32QImode: 10077 case E_V16HImode: 10078 case E_V8SImode: 10079 case E_V4DImode: 10080 case E_V16QImode: 10081 case E_V8HImode: 10082 case E_V4SImode: 10083 case E_V2DImode: 10084 loongarch_emit_move (target, gen_rtx_VEC_DUPLICATE (vmode, temp)); 10085 break; 10086 10087 case E_V8SFmode: 10088 emit_insn (gen_lasx_xvreplve0_w_f_scalar (target, temp)); 10089 break; 10090 10091 case E_V4DFmode: 10092 emit_insn (gen_lasx_xvreplve0_d_f_scalar (target, temp)); 10093 break; 10094 10095 case E_V4SFmode: 10096 emit_insn (gen_lsx_vreplvei_w_f_scalar (target, temp)); 10097 break; 10098 10099 case E_V2DFmode: 10100 emit_insn (gen_lsx_vreplvei_d_f_scalar (target, temp)); 10101 break; 10102 10103 default: 10104 gcc_unreachable (); 10105 } 10106 } 10107 10108 /* Expand a vector initialization. */ 10109 10110 void 10111 loongarch_expand_vector_init (rtx target, rtx vals) 10112 { 10113 machine_mode vmode = GET_MODE (target); 10114 machine_mode imode = GET_MODE_INNER (vmode); 10115 unsigned i, nelt = GET_MODE_NUNITS (vmode); 10116 /* VALS is divided into high and low half-part. */ 10117 /* Number of non constant elements in corresponding parts of VALS. */ 10118 unsigned nvar = 0, hi_nvar = 0, lo_nvar = 0; 10119 /* all_same : true if all elements of VALS are the same. 10120 hi_same : true if all elements of the high half-part are the same. 10121 lo_same : true if all elements of the low half-part are the same. 10122 half_same : true if the high half-part is the same as the low one. */ 10123 bool all_same = false, hi_same = true, lo_same = true, half_same = true; 10124 rtx val[32], val_hi[32], val_lo[16]; 10125 rtx x, op0, op1; 10126 /* Copy one element of vals to per element of target vector. */ 10127 typedef rtx (*loongarch_vec_repl1_fn) (rtx, rtx); 10128 /* Copy two elements of vals to target vector. */ 10129 typedef rtx (*loongarch_vec_repl2_fn) (rtx, rtx, rtx); 10130 /* Insert scalar operands into the specified position of the vector. */ 10131 typedef rtx (*loongarch_vec_set_fn) (rtx, rtx, rtx); 10132 /* Copy 64bit lowpart to highpart. */ 10133 typedef rtx (*loongarch_vec_mirror_fn) (rtx, rtx, rtx); 10134 /* Merge lowpart and highpart into target. */ 10135 typedef rtx (*loongarch_vec_merge_fn) (rtx, rtx, rtx, rtx); 10136 10137 loongarch_vec_repl1_fn loongarch_vec_repl1_128 = NULL, 10138 loongarch_vec_repl1_256 = NULL; 10139 loongarch_vec_repl2_fn loongarch_vec_repl2_128 = NULL, 10140 loongarch_vec_repl2_256 = NULL; 10141 loongarch_vec_set_fn loongarch_vec_set128 = NULL, loongarch_vec_set256 = NULL; 10142 loongarch_vec_mirror_fn loongarch_vec_mirror = NULL; 10143 loongarch_vec_merge_fn loongarch_lasx_vecinit_merge = NULL; 10144 machine_mode half_mode = VOIDmode; 10145 10146 /* Check whether elements of each part are the same. */ 10147 for (i = 0; i < nelt / 2; ++i) 10148 { 10149 val_hi[i] = val_hi[i + nelt / 2] = val[i + nelt / 2] 10150 = XVECEXP (vals, 0, i + nelt / 2); 10151 val_lo[i] = val[i] = XVECEXP (vals, 0, i); 10152 if (!loongarch_constant_elt_p (val_hi[i])) 10153 hi_nvar++; 10154 if (!loongarch_constant_elt_p (val_lo[i])) 10155 lo_nvar++; 10156 if (i > 0 && !rtx_equal_p (val_hi[i], val_hi[0])) 10157 hi_same = false; 10158 if (i > 0 && !rtx_equal_p (val_lo[i], val_lo[0])) 10159 lo_same = false; 10160 if (!rtx_equal_p (val_hi[i], val_lo[i])) 10161 half_same = false; 10162 } 10163 10164 /* If all elements are the same, set all_same true. */ 10165 if (hi_same && lo_same && half_same) 10166 all_same = true; 10167 10168 nvar = hi_nvar + lo_nvar; 10169 10170 switch (vmode) 10171 { 10172 case E_V32QImode: 10173 half_mode = E_V16QImode; 10174 loongarch_vec_set256 = gen_vec_setv32qi_internal; 10175 loongarch_vec_repl1_256 = gen_lasx_xvreplgr2vr_b; 10176 loongarch_lasx_vecinit_merge 10177 = half_same ? gen_lasx_xvpermi_q_v32qi : gen_lasx_vecinit_merge_v32qi; 10178 /* FALLTHRU. */ 10179 case E_V16QImode: 10180 loongarch_vec_set128 = gen_vec_setv16qi; 10181 loongarch_vec_repl1_128 = gen_lsx_vreplgr2vr_b; 10182 loongarch_vec_mirror = gen_lsx_vreplvei_mirror_b; 10183 break; 10184 10185 case E_V16HImode: 10186 half_mode = E_V8HImode; 10187 loongarch_vec_set256 = gen_vec_setv16hi_internal; 10188 loongarch_vec_repl1_256 = gen_lasx_xvreplgr2vr_h; 10189 loongarch_lasx_vecinit_merge 10190 = half_same ? gen_lasx_xvpermi_q_v16hi : gen_lasx_vecinit_merge_v16hi; 10191 /* FALLTHRU. */ 10192 case E_V8HImode: 10193 loongarch_vec_set128 = gen_vec_setv8hi; 10194 loongarch_vec_repl1_128 = gen_lsx_vreplgr2vr_h; 10195 loongarch_vec_mirror = gen_lsx_vreplvei_mirror_h; 10196 break; 10197 10198 case E_V8SImode: 10199 half_mode = V4SImode; 10200 loongarch_vec_set256 = gen_vec_setv8si; 10201 loongarch_vec_repl1_256 = gen_lasx_xvreplgr2vr_w; 10202 loongarch_lasx_vecinit_merge 10203 = half_same ? gen_lasx_xvpermi_q_v8si : gen_lasx_vecinit_merge_v8si; 10204 /* FALLTHRU. */ 10205 case E_V4SImode: 10206 loongarch_vec_set128 = gen_vec_setv4si; 10207 loongarch_vec_repl1_128 = gen_lsx_vreplgr2vr_w; 10208 loongarch_vec_mirror = gen_lsx_vreplvei_mirror_w; 10209 break; 10210 10211 case E_V4DImode: 10212 half_mode = E_V2DImode; 10213 loongarch_vec_set256 = gen_vec_setv4di; 10214 loongarch_vec_repl1_256 = gen_lasx_xvreplgr2vr_d; 10215 loongarch_lasx_vecinit_merge 10216 = half_same ? gen_lasx_xvpermi_q_v4di : gen_lasx_vecinit_merge_v4di; 10217 /* FALLTHRU. */ 10218 case E_V2DImode: 10219 loongarch_vec_set128 = gen_vec_setv2di; 10220 loongarch_vec_repl1_128 = gen_lsx_vreplgr2vr_d; 10221 loongarch_vec_mirror = gen_lsx_vreplvei_mirror_d; 10222 break; 10223 10224 case E_V8SFmode: 10225 half_mode = E_V4SFmode; 10226 loongarch_vec_set256 = gen_vec_setv8sf; 10227 loongarch_vec_repl1_128 = gen_lsx_vreplvei_w_f_scalar; 10228 loongarch_vec_repl2_256 = gen_lasx_xvilvl_w_f_internal; 10229 loongarch_lasx_vecinit_merge 10230 = half_same ? gen_lasx_xvpermi_q_v8sf : gen_lasx_vecinit_merge_v8sf; 10231 /* FALLTHRU. */ 10232 case E_V4SFmode: 10233 loongarch_vec_set128 = gen_vec_setv4sf; 10234 loongarch_vec_repl2_128 = gen_lsx_vilvl_w_f_internal; 10235 loongarch_vec_mirror = gen_lsx_vreplvei_mirror_w_f; 10236 break; 10237 10238 case E_V4DFmode: 10239 half_mode = E_V2DFmode; 10240 loongarch_vec_set256 = gen_vec_setv4df; 10241 loongarch_vec_repl1_128 = gen_lsx_vreplvei_d_f_scalar; 10242 loongarch_vec_repl2_256 = gen_lasx_xvilvl_d_f_internal; 10243 loongarch_lasx_vecinit_merge 10244 = half_same ? gen_lasx_xvpermi_q_v4df : gen_lasx_vecinit_merge_v4df; 10245 /* FALLTHRU. */ 10246 case E_V2DFmode: 10247 loongarch_vec_set128 = gen_vec_setv2df; 10248 loongarch_vec_repl2_128 = gen_lsx_vilvl_d_f_internal; 10249 loongarch_vec_mirror = gen_lsx_vreplvei_mirror_d_f; 10250 break; 10251 10252 default: 10253 gcc_unreachable (); 10254 } 10255 10256 if (ISA_HAS_LASX && GET_MODE_SIZE (vmode) == 32) 10257 { 10258 /* If all elements are the same, just do a broadcost. */ 10259 if (all_same) 10260 loongarch_expand_vector_init_same (target, vals, nvar); 10261 else 10262 { 10263 gcc_assert (nelt >= 4); 10264 10265 rtx target_hi, target_lo; 10266 /* Write elements of high half-part in target directly. */ 10267 target_hi = target; 10268 target_lo = gen_reg_rtx (half_mode); 10269 10270 /* If all elements of high half-part are the same, 10271 just do a broadcost. Also applicable to low half-part. */ 10272 if (hi_same) 10273 { 10274 rtx vtmp = gen_rtx_PARALLEL (vmode, gen_rtvec_v (nelt, val_hi)); 10275 loongarch_expand_vector_init_same (target_hi, vtmp, hi_nvar); 10276 } 10277 if (lo_same) 10278 { 10279 rtx vtmp 10280 = gen_rtx_PARALLEL (half_mode, gen_rtvec_v (nelt / 2, val_lo)); 10281 loongarch_expand_vector_init_same (target_lo, vtmp, lo_nvar); 10282 } 10283 10284 for (i = 0; i < nelt / 2; ++i) 10285 { 10286 if (!hi_same) 10287 { 10288 if (vmode == E_V8SFmode || vmode == E_V4DFmode) 10289 { 10290 /* Using xvilvl to load lowest 2 elements simultaneously 10291 to reduce the number of instructions. */ 10292 if (i == 1) 10293 { 10294 op0 = force_reg (imode, val_hi[0]); 10295 op1 = force_reg (imode, val_hi[1]); 10296 emit_insn ( 10297 loongarch_vec_repl2_256 (target_hi, op0, op1)); 10298 } 10299 else if (i > 1) 10300 { 10301 op0 = force_reg (imode, val_hi[i]); 10302 emit_insn ( 10303 loongarch_vec_set256 (target_hi, op0, GEN_INT (i))); 10304 } 10305 } 10306 else 10307 { 10308 op0 = force_reg (imode, val_hi[i]); 10309 /* Assign the lowest element of val_hi to all elements 10310 of target_hi. */ 10311 if (i == 0) 10312 { 10313 emit_insn (loongarch_vec_repl1_256 (target_hi, op0)); 10314 } 10315 else if (!rtx_equal_p (val_hi[i], val_hi[0])) 10316 { 10317 emit_insn ( 10318 loongarch_vec_set256 (target_hi, op0, GEN_INT (i))); 10319 } 10320 } 10321 } 10322 if (!lo_same && !half_same) 10323 { 10324 op0 = force_reg (imode, val_lo[i]); 10325 /* Assign the lowest element of val_lo to all elements 10326 of target_lo. */ 10327 if (i == 0) 10328 { 10329 emit_insn (loongarch_vec_repl1_128 (target_lo, op0)); 10330 } 10331 else if (!rtx_equal_p (val_lo[i], val_lo[0])) 10332 { 10333 emit_insn ( 10334 loongarch_vec_set128 (target_lo, op0, GEN_INT (i))); 10335 } 10336 } 10337 } 10338 if (half_same) 10339 { 10340 emit_insn (loongarch_lasx_vecinit_merge (target, target_hi, 10341 target_hi, const0_rtx)); 10342 return; 10343 } 10344 emit_insn (loongarch_lasx_vecinit_merge (target, target_hi, target_lo, 10345 GEN_INT (0x20))); 10346 } 10347 return; 10348 } 10349 10350 if (ISA_HAS_LSX) 10351 { 10352 if (all_same) 10353 loongarch_expand_vector_init_same (target, vals, nvar); 10354 else 10355 { 10356 for (i = 0; i < nelt; ++i) 10357 { 10358 if (vmode == E_V4SFmode || vmode == E_V2DFmode) 10359 { 10360 /* Using vilvl to load lowest 2 elements simultaneously to 10361 reduce the number of instructions. */ 10362 if (i == 1) 10363 { 10364 op0 = force_reg (imode, val[0]); 10365 op1 = force_reg (imode, val[1]); 10366 emit_insn (loongarch_vec_repl2_128 (target, op0, op1)); 10367 } 10368 else if (i > 1) 10369 { 10370 op0 = force_reg (imode, val[i]); 10371 emit_insn ( 10372 loongarch_vec_set128 (target, op0, GEN_INT (i))); 10373 } 10374 } 10375 else 10376 { 10377 if (half_same && i == nelt / 2) 10378 { 10379 emit_insn ( 10380 loongarch_vec_mirror (target, target, const0_rtx)); 10381 return; 10382 } 10383 op0 = force_reg (imode, val[i]); 10384 /* Assign the lowest element of val to all elements of 10385 target. */ 10386 if (i == 0) 10387 { 10388 emit_insn (loongarch_vec_repl1_128 (target, op0)); 10389 } 10390 else if (!rtx_equal_p (val[i], val[0])) 10391 { 10392 emit_insn ( 10393 loongarch_vec_set128 (target, op0, GEN_INT (i))); 10394 } 10395 } 10396 } 10397 } 10398 return; 10399 } 10400 10401 /* Load constants from the pool, or whatever's handy. */ 10402 if (nvar == 0) 10403 { 10404 emit_move_insn (target, gen_rtx_CONST_VECTOR (vmode, XVEC (vals, 0))); 10405 return; 10406 } 10407 10408 /* For two-part initialization, always use CONCAT. */ 10409 if (nelt == 2) 10410 { 10411 rtx op0 = force_reg (imode, val[0]); 10412 rtx op1 = force_reg (imode, val[1]); 10413 x = gen_rtx_VEC_CONCAT (vmode, op0, op1); 10414 emit_insn (gen_rtx_SET (target, x)); 10415 return; 10416 } 10417 10418 /* No LoongArch CPU supports vectors with more elements as at now. */ 10419 gcc_unreachable (); 10420 } 10421 10422 /* Implement HARD_REGNO_CALLER_SAVE_MODE. */ 10423 10424 machine_mode 10425 loongarch_hard_regno_caller_save_mode (unsigned int regno, unsigned int nregs, 10426 machine_mode mode) 10427 { 10428 /* For performance, avoid saving/restoring upper parts of a register 10429 by returning MODE as save mode when the mode is known. */ 10430 if (mode == VOIDmode) 10431 return choose_hard_reg_mode (regno, nregs, NULL); 10432 else 10433 return mode; 10434 } 10435 10436 /* Generate RTL for comparing CMP_OP0 and CMP_OP1 using condition COND and 10437 store the result -1 or 0 in DEST. */ 10438 10439 static void 10440 loongarch_expand_lsx_cmp (rtx dest, enum rtx_code cond, rtx op0, rtx op1) 10441 { 10442 machine_mode cmp_mode = GET_MODE (op0); 10443 bool negate = false; 10444 10445 switch (cmp_mode) 10446 { 10447 case E_V16QImode: 10448 case E_V32QImode: 10449 case E_V8HImode: 10450 case E_V16HImode: 10451 case E_V4SImode: 10452 case E_V8SImode: 10453 case E_V2DImode: 10454 case E_V4DImode: 10455 switch (cond) 10456 { 10457 case NE: 10458 cond = reverse_condition (cond); 10459 negate = true; 10460 break; 10461 case EQ: 10462 case LT: 10463 case LE: 10464 case LTU: 10465 case LEU: 10466 break; 10467 case GE: 10468 case GT: 10469 case GEU: 10470 case GTU: 10471 std::swap (op0, op1); 10472 cond = swap_condition (cond); 10473 break; 10474 default: 10475 gcc_unreachable (); 10476 } 10477 loongarch_emit_binary (cond, dest, op0, op1); 10478 if (negate) 10479 emit_move_insn (dest, gen_rtx_NOT (GET_MODE (dest), dest)); 10480 break; 10481 10482 case E_V4SFmode: 10483 case E_V2DFmode: 10484 case E_V8SFmode: 10485 case E_V4DFmode: 10486 loongarch_emit_binary (cond, dest, op0, op1); 10487 break; 10488 10489 default: 10490 gcc_unreachable (); 10491 break; 10492 } 10493 } 10494 10495 /* Expand VEC_COND_EXPR, where: 10496 MODE is mode of the result 10497 VIMODE equivalent integer mode 10498 OPERANDS operands of VEC_COND_EXPR. */ 10499 10500 void 10501 loongarch_expand_vec_cond_expr (machine_mode mode, machine_mode vimode, 10502 rtx *operands) 10503 { 10504 rtx cond = operands[3]; 10505 rtx cmp_op0 = operands[4]; 10506 rtx cmp_op1 = operands[5]; 10507 rtx cmp_res = gen_reg_rtx (vimode); 10508 10509 loongarch_expand_lsx_cmp (cmp_res, GET_CODE (cond), cmp_op0, cmp_op1); 10510 10511 /* We handle the following cases: 10512 1) r = a CMP b ? -1 : 0 10513 2) r = a CMP b ? -1 : v 10514 3) r = a CMP b ? v : 0 10515 4) r = a CMP b ? v1 : v2 */ 10516 10517 /* Case (1) above. We only move the results. */ 10518 if (operands[1] == CONSTM1_RTX (vimode) 10519 && operands[2] == CONST0_RTX (vimode)) 10520 emit_move_insn (operands[0], cmp_res); 10521 else 10522 { 10523 rtx src1 = gen_reg_rtx (vimode); 10524 rtx src2 = gen_reg_rtx (vimode); 10525 rtx mask = gen_reg_rtx (vimode); 10526 rtx bsel; 10527 10528 /* Move the vector result to use it as a mask. */ 10529 emit_move_insn (mask, cmp_res); 10530 10531 if (register_operand (operands[1], mode)) 10532 { 10533 rtx xop1 = operands[1]; 10534 if (mode != vimode) 10535 { 10536 xop1 = gen_reg_rtx (vimode); 10537 emit_move_insn (xop1, 10538 simplify_gen_subreg (vimode, operands[1], 10539 mode, 0)); 10540 } 10541 emit_move_insn (src1, xop1); 10542 } 10543 else 10544 { 10545 gcc_assert (operands[1] == CONSTM1_RTX (vimode)); 10546 /* Case (2) if the below doesn't move the mask to src2. */ 10547 emit_move_insn (src1, mask); 10548 } 10549 10550 if (register_operand (operands[2], mode)) 10551 { 10552 rtx xop2 = operands[2]; 10553 if (mode != vimode) 10554 { 10555 xop2 = gen_reg_rtx (vimode); 10556 emit_move_insn (xop2, 10557 simplify_gen_subreg (vimode, operands[2], 10558 mode, 0)); 10559 } 10560 emit_move_insn (src2, xop2); 10561 } 10562 else 10563 { 10564 gcc_assert (operands[2] == CONST0_RTX (mode)); 10565 /* Case (3) if the above didn't move the mask to src1. */ 10566 emit_move_insn (src2, mask); 10567 } 10568 10569 /* We deal with case (4) if the mask wasn't moved to either src1 or src2. 10570 In any case, we eventually do vector mask-based copy. */ 10571 bsel = gen_rtx_IOR (vimode, 10572 gen_rtx_AND (vimode, 10573 gen_rtx_NOT (vimode, mask), src2), 10574 gen_rtx_AND (vimode, mask, src1)); 10575 /* The result is placed back to a register with the mask. */ 10576 emit_insn (gen_rtx_SET (mask, bsel)); 10577 emit_move_insn (operands[0], 10578 simplify_gen_subreg (mode, mask, vimode, 0)); 10579 } 10580 } 10581 10582 void 10583 loongarch_expand_vec_cond_mask_expr (machine_mode mode, machine_mode vimode, 10584 rtx *operands) 10585 { 10586 rtx cmp_res = operands[3]; 10587 10588 /* We handle the following cases: 10589 1) r = a CMP b ? -1 : 0 10590 2) r = a CMP b ? -1 : v 10591 3) r = a CMP b ? v : 0 10592 4) r = a CMP b ? v1 : v2 */ 10593 10594 /* Case (1) above. We only move the results. */ 10595 if (operands[1] == CONSTM1_RTX (vimode) 10596 && operands[2] == CONST0_RTX (vimode)) 10597 emit_move_insn (operands[0], cmp_res); 10598 else 10599 { 10600 rtx src1 = gen_reg_rtx (vimode); 10601 rtx src2 = gen_reg_rtx (vimode); 10602 rtx mask = gen_reg_rtx (vimode); 10603 rtx bsel; 10604 10605 /* Move the vector result to use it as a mask. */ 10606 emit_move_insn (mask, cmp_res); 10607 10608 if (register_operand (operands[1], mode)) 10609 { 10610 rtx xop1 = operands[1]; 10611 if (mode != vimode) 10612 { 10613 xop1 = gen_reg_rtx (vimode); 10614 emit_move_insn (xop1, 10615 simplify_gen_subreg (vimode, operands[1], 10616 mode, 0)); 10617 } 10618 emit_move_insn (src1, xop1); 10619 } 10620 else 10621 { 10622 gcc_assert (operands[1] == CONSTM1_RTX (vimode)); 10623 /* Case (2) if the below doesn't move the mask to src2. */ 10624 emit_move_insn (src1, mask); 10625 } 10626 10627 if (register_operand (operands[2], mode)) 10628 { 10629 rtx xop2 = operands[2]; 10630 if (mode != vimode) 10631 { 10632 xop2 = gen_reg_rtx (vimode); 10633 emit_move_insn (xop2, 10634 simplify_gen_subreg (vimode, operands[2], 10635 mode, 0)); 10636 } 10637 emit_move_insn (src2, xop2); 10638 } 10639 else 10640 { 10641 gcc_assert (operands[2] == CONST0_RTX (mode)); 10642 /* Case (3) if the above didn't move the mask to src1. */ 10643 emit_move_insn (src2, mask); 10644 } 10645 10646 /* We deal with case (4) if the mask wasn't moved to either src1 or src2. 10647 In any case, we eventually do vector mask-based copy. */ 10648 bsel = gen_rtx_IOR (vimode, 10649 gen_rtx_AND (vimode, 10650 gen_rtx_NOT (vimode, mask), src2), 10651 gen_rtx_AND (vimode, mask, src1)); 10652 /* The result is placed back to a register with the mask. */ 10653 emit_insn (gen_rtx_SET (mask, bsel)); 10654 emit_move_insn (operands[0], simplify_gen_subreg (mode, mask, 10655 vimode, 0)); 10656 } 10657 } 10658 10659 /* Expand integer vector comparison */ 10660 void 10661 loongarch_expand_vec_cmp (rtx operands[]) 10662 { 10663 10664 rtx_code code = GET_CODE (operands[1]); 10665 loongarch_expand_lsx_cmp (operands[0], code, operands[2], operands[3]); 10666 } 10667 10668 /* Implement TARGET_PROMOTE_FUNCTION_MODE. */ 10669 10670 /* This function is equivalent to default_promote_function_mode_always_promote 10671 except that it returns a promoted mode even if type is NULL_TREE. This is 10672 needed by libcalls which have no type (only a mode) such as fixed conversion 10673 routines that take a signed or unsigned char/short argument and convert it 10674 to a fixed type. */ 10675 10676 static machine_mode 10677 loongarch_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, 10678 machine_mode mode, 10679 int *punsignedp ATTRIBUTE_UNUSED, 10680 const_tree fntype ATTRIBUTE_UNUSED, 10681 int for_return ATTRIBUTE_UNUSED) 10682 { 10683 int unsignedp; 10684 10685 if (type != NULL_TREE) 10686 return promote_mode (type, mode, punsignedp); 10687 10688 unsignedp = *punsignedp; 10689 PROMOTE_MODE (mode, unsignedp, type); 10690 *punsignedp = unsignedp; 10691 return mode; 10692 } 10693 10694 /* Implement TARGET_STARTING_FRAME_OFFSET. See loongarch_compute_frame_info 10695 for details about the frame layout. */ 10696 10697 static HOST_WIDE_INT 10698 loongarch_starting_frame_offset (void) 10699 { 10700 if (FRAME_GROWS_DOWNWARD) 10701 return 0; 10702 return crtl->outgoing_args_size; 10703 } 10704 10705 /* A subroutine of loongarch_build_signbit_mask. If VECT is true, 10706 then replicate the value for all elements of the vector 10707 register. */ 10708 10709 rtx 10710 loongarch_build_const_vector (machine_mode mode, bool vect, rtx value) 10711 { 10712 int i, n_elt; 10713 rtvec v; 10714 machine_mode scalar_mode; 10715 10716 switch (mode) 10717 { 10718 case E_V32QImode: 10719 case E_V16QImode: 10720 case E_V32HImode: 10721 case E_V16HImode: 10722 case E_V8HImode: 10723 case E_V8SImode: 10724 case E_V4SImode: 10725 case E_V8DImode: 10726 case E_V4DImode: 10727 case E_V2DImode: 10728 gcc_assert (vect); 10729 /* FALLTHRU */ 10730 case E_V8SFmode: 10731 case E_V4SFmode: 10732 case E_V8DFmode: 10733 case E_V4DFmode: 10734 case E_V2DFmode: 10735 n_elt = GET_MODE_NUNITS (mode); 10736 v = rtvec_alloc (n_elt); 10737 scalar_mode = GET_MODE_INNER (mode); 10738 10739 RTVEC_ELT (v, 0) = value; 10740 10741 for (i = 1; i < n_elt; ++i) 10742 RTVEC_ELT (v, i) = vect ? value : CONST0_RTX (scalar_mode); 10743 10744 return gen_rtx_CONST_VECTOR (mode, v); 10745 10746 default: 10747 gcc_unreachable (); 10748 } 10749 } 10750 10751 /* Create a mask for the sign bit in MODE 10752 for an register. If VECT is true, then replicate the mask for 10753 all elements of the vector register. If INVERT is true, then create 10754 a mask excluding the sign bit. */ 10755 10756 rtx 10757 loongarch_build_signbit_mask (machine_mode mode, bool vect, bool invert) 10758 { 10759 machine_mode vec_mode, imode; 10760 wide_int w; 10761 rtx mask, v; 10762 10763 switch (mode) 10764 { 10765 case E_V16SImode: 10766 case E_V16SFmode: 10767 case E_V8SImode: 10768 case E_V4SImode: 10769 case E_V8SFmode: 10770 case E_V4SFmode: 10771 vec_mode = mode; 10772 imode = SImode; 10773 break; 10774 10775 case E_V8DImode: 10776 case E_V4DImode: 10777 case E_V2DImode: 10778 case E_V8DFmode: 10779 case E_V4DFmode: 10780 case E_V2DFmode: 10781 vec_mode = mode; 10782 imode = DImode; 10783 break; 10784 10785 case E_TImode: 10786 case E_TFmode: 10787 vec_mode = VOIDmode; 10788 imode = TImode; 10789 break; 10790 10791 default: 10792 gcc_unreachable (); 10793 } 10794 10795 machine_mode inner_mode = GET_MODE_INNER (mode); 10796 w = wi::set_bit_in_zero (GET_MODE_BITSIZE (inner_mode) - 1, 10797 GET_MODE_BITSIZE (inner_mode)); 10798 if (invert) 10799 w = wi::bit_not (w); 10800 10801 /* Force this value into the low part of a fp vector constant. */ 10802 mask = immed_wide_int_const (w, imode); 10803 mask = gen_lowpart (inner_mode, mask); 10804 10805 if (vec_mode == VOIDmode) 10806 return force_reg (inner_mode, mask); 10807 10808 v = loongarch_build_const_vector (vec_mode, vect, mask); 10809 return force_reg (vec_mode, v); 10810 } 10811 10812 /* Use rsqrte instruction and Newton-Rhapson to compute the approximation of 10813 a single precision floating point [reciprocal] square root. */ 10814 10815 void loongarch_emit_swrsqrtsf (rtx res, rtx a, machine_mode mode, bool recip) 10816 { 10817 rtx x0, e0, e1, e2, mhalf, monehalf; 10818 REAL_VALUE_TYPE r; 10819 int unspec; 10820 10821 x0 = gen_reg_rtx (mode); 10822 e0 = gen_reg_rtx (mode); 10823 e1 = gen_reg_rtx (mode); 10824 e2 = gen_reg_rtx (mode); 10825 10826 real_arithmetic (&r, ABS_EXPR, &dconsthalf, NULL); 10827 mhalf = const_double_from_real_value (r, SFmode); 10828 10829 real_arithmetic (&r, PLUS_EXPR, &dconsthalf, &dconst1); 10830 monehalf = const_double_from_real_value (r, SFmode); 10831 unspec = UNSPEC_RSQRTE; 10832 10833 if (VECTOR_MODE_P (mode)) 10834 { 10835 mhalf = loongarch_build_const_vector (mode, true, mhalf); 10836 monehalf = loongarch_build_const_vector (mode, true, monehalf); 10837 unspec = GET_MODE_SIZE (mode) == 32 ? UNSPEC_LASX_XVFRSQRTE 10838 : UNSPEC_LSX_VFRSQRTE; 10839 } 10840 10841 /* rsqrt(a) = rsqrte(a) * (1.5 - 0.5 * a * rsqrte(a) * rsqrte(a)) 10842 sqrt(a) = a * rsqrte(a) * (1.5 - 0.5 * a * rsqrte(a) * rsqrte(a)) */ 10843 10844 a = force_reg (mode, a); 10845 10846 /* x0 = rsqrt(a) estimate. */ 10847 emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, a), 10848 unspec))); 10849 10850 /* If (a == 0.0) Filter out infinity to prevent NaN for sqrt(0.0). */ 10851 if (!recip) 10852 { 10853 rtx zero = force_reg (mode, CONST0_RTX (mode)); 10854 10855 if (VECTOR_MODE_P (mode)) 10856 { 10857 machine_mode imode = related_int_vector_mode (mode).require (); 10858 rtx mask = gen_reg_rtx (imode); 10859 emit_insn (gen_rtx_SET (mask, gen_rtx_NE (imode, a, zero))); 10860 emit_insn (gen_rtx_SET (x0, gen_rtx_AND (mode, x0, 10861 gen_lowpart (mode, mask)))); 10862 } 10863 else 10864 { 10865 rtx target = emit_conditional_move (x0, { GT, a, zero, mode }, 10866 x0, zero, mode, 0); 10867 if (target != x0) 10868 emit_move_insn (x0, target); 10869 } 10870 } 10871 10872 /* e0 = x0 * a */ 10873 emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a))); 10874 /* e1 = e0 * x0 */ 10875 emit_insn (gen_rtx_SET (e1, gen_rtx_MULT (mode, e0, x0))); 10876 10877 /* e2 = 1.5 - e1 * 0.5 */ 10878 mhalf = force_reg (mode, mhalf); 10879 monehalf = force_reg (mode, monehalf); 10880 emit_insn (gen_rtx_SET (e2, gen_rtx_FMA (mode, 10881 gen_rtx_NEG (mode, e1), 10882 mhalf, monehalf))); 10883 10884 if (recip) 10885 /* res = e2 * x0 */ 10886 emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, x0, e2))); 10887 else 10888 /* res = e2 * e0 */ 10889 emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, e2, e0))); 10890 } 10891 10892 /* Use recipe instruction and Newton-Rhapson to compute the approximation of 10893 a single precision floating point divide. */ 10894 10895 void loongarch_emit_swdivsf (rtx res, rtx a, rtx b, machine_mode mode) 10896 { 10897 rtx x0, e0, mtwo; 10898 REAL_VALUE_TYPE r; 10899 x0 = gen_reg_rtx (mode); 10900 e0 = gen_reg_rtx (mode); 10901 int unspec = UNSPEC_RECIPE; 10902 10903 real_arithmetic (&r, ABS_EXPR, &dconst2, NULL); 10904 mtwo = const_double_from_real_value (r, SFmode); 10905 10906 if (VECTOR_MODE_P (mode)) 10907 { 10908 mtwo = loongarch_build_const_vector (mode, true, mtwo); 10909 unspec = GET_MODE_SIZE (mode) == 32 ? UNSPEC_LASX_XVFRECIPE 10910 : UNSPEC_LSX_VFRECIPE; 10911 } 10912 10913 mtwo = force_reg (mode, mtwo); 10914 10915 /* a / b = a * recipe(b) * (2.0 - b * recipe(b)) */ 10916 10917 /* x0 = 1./b estimate. */ 10918 emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b), 10919 unspec))); 10920 /* e0 = 2.0 - b * x0. */ 10921 emit_insn (gen_rtx_SET (e0, gen_rtx_FMA (mode, 10922 gen_rtx_NEG (mode, b), x0, mtwo))); 10923 10924 if (a != CONST1_RTX (mode)) 10925 { 10926 rtx e1 = gen_reg_rtx (mode); 10927 /* e1 = a * x0. */ 10928 emit_insn (gen_rtx_SET (e1, gen_rtx_MULT (mode, a, x0))); 10929 /* res = e0 * e1. */ 10930 emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, e0, e1))); 10931 } 10932 else 10933 { 10934 /* res = e0 * x0. */ 10935 emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, e0, x0))); 10936 } 10937 } 10938 10939 static bool 10940 loongarch_builtin_support_vector_misalignment (machine_mode mode, 10941 const_tree type, 10942 int misalignment, 10943 bool is_packed) 10944 { 10945 if ((ISA_HAS_LSX || ISA_HAS_LASX) && STRICT_ALIGNMENT) 10946 { 10947 if (optab_handler (movmisalign_optab, mode) == CODE_FOR_nothing) 10948 return false; 10949 if (misalignment == -1) 10950 return false; 10951 } 10952 return default_builtin_support_vector_misalignment (mode, type, misalignment, 10953 is_packed); 10954 } 10955 10956 static bool 10957 use_rsqrt_p (void) 10958 { 10959 return (flag_finite_math_only 10960 && !flag_trapping_math 10961 && flag_unsafe_math_optimizations); 10962 } 10963 10964 /* Implement the TARGET_OPTAB_SUPPORTED_P hook. */ 10965 10966 static bool 10967 loongarch_optab_supported_p (int op, machine_mode, machine_mode, 10968 optimization_type opt_type) 10969 { 10970 switch (op) 10971 { 10972 case rsqrt_optab: 10973 return opt_type == OPTIMIZE_FOR_SPEED && use_rsqrt_p (); 10974 10975 default: 10976 return true; 10977 } 10978 } 10979 10980 /* If -fverbose-asm, dump some info for debugging. */ 10981 static void 10982 loongarch_asm_code_end (void) 10983 { 10984 #define DUMP_FEATURE(PRED) \ 10985 fprintf (asm_out_file, "%s %s: %s\n", ASM_COMMENT_START, #PRED, \ 10986 (PRED) ? "enabled" : "disabled") 10987 10988 if (flag_verbose_asm) 10989 { 10990 fprintf (asm_out_file, "\n%s CPU: %s\n", ASM_COMMENT_START, 10991 loongarch_arch_strings[la_target.cpu_arch]); 10992 fprintf (asm_out_file, "%s Tune: %s\n", ASM_COMMENT_START, 10993 loongarch_tune_strings[la_target.cpu_tune]); 10994 fprintf (asm_out_file, "%s Base ISA: %s\n", ASM_COMMENT_START, 10995 loongarch_isa_base_strings [la_target.isa.base]); 10996 DUMP_FEATURE (ISA_HAS_FRECIPE); 10997 DUMP_FEATURE (ISA_HAS_DIV32); 10998 DUMP_FEATURE (ISA_HAS_LAM_BH); 10999 DUMP_FEATURE (ISA_HAS_LAMCAS); 11000 DUMP_FEATURE (ISA_HAS_LD_SEQ_SA); 11001 } 11002 11003 fputs ("\n\n", asm_out_file); 11004 #undef DUMP_FEATURE 11005 } 11006 11007 /* Target hook for c_mode_for_suffix. */ 11008 static machine_mode 11009 loongarch_c_mode_for_suffix (char suffix) 11010 { 11011 if (suffix == 'q') 11012 return TFmode; 11013 11014 return VOIDmode; 11015 } 11016 11017 /* Initialize the GCC target structure. */ 11018 #undef TARGET_ASM_ALIGNED_HI_OP 11019 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" 11020 #undef TARGET_ASM_ALIGNED_SI_OP 11021 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" 11022 #undef TARGET_ASM_ALIGNED_DI_OP 11023 #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t" 11024 11025 #undef TARGET_OPTION_OVERRIDE 11026 #define TARGET_OPTION_OVERRIDE loongarch_option_override 11027 #undef TARGET_OPTION_SAVE 11028 #define TARGET_OPTION_SAVE loongarch_option_save 11029 #undef TARGET_OPTION_RESTORE 11030 #define TARGET_OPTION_RESTORE loongarch_option_restore 11031 11032 #undef TARGET_SET_CURRENT_FUNCTION 11033 #define TARGET_SET_CURRENT_FUNCTION loongarch_set_current_function 11034 11035 #undef TARGET_LEGITIMIZE_ADDRESS 11036 #define TARGET_LEGITIMIZE_ADDRESS loongarch_legitimize_address 11037 11038 #undef TARGET_ASM_SELECT_RTX_SECTION 11039 #define TARGET_ASM_SELECT_RTX_SECTION loongarch_select_rtx_section 11040 #undef TARGET_ASM_FUNCTION_RODATA_SECTION 11041 #define TARGET_ASM_FUNCTION_RODATA_SECTION loongarch_function_rodata_section 11042 11043 #undef TARGET_ASM_CODE_END 11044 #define TARGET_ASM_CODE_END loongarch_asm_code_end 11045 11046 #undef TARGET_SCHED_INIT 11047 #define TARGET_SCHED_INIT loongarch_sched_init 11048 #undef TARGET_SCHED_REORDER 11049 #define TARGET_SCHED_REORDER loongarch_sched_reorder 11050 #undef TARGET_SCHED_REORDER2 11051 #define TARGET_SCHED_REORDER2 loongarch_sched_reorder2 11052 #undef TARGET_SCHED_VARIABLE_ISSUE 11053 #define TARGET_SCHED_VARIABLE_ISSUE loongarch_variable_issue 11054 #undef TARGET_SCHED_ADJUST_COST 11055 #define TARGET_SCHED_ADJUST_COST loongarch_adjust_cost 11056 #undef TARGET_SCHED_ISSUE_RATE 11057 #define TARGET_SCHED_ISSUE_RATE loongarch_issue_rate 11058 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD 11059 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \ 11060 loongarch_multipass_dfa_lookahead 11061 11062 #undef TARGET_FUNCTION_OK_FOR_SIBCALL 11063 #define TARGET_FUNCTION_OK_FOR_SIBCALL loongarch_function_ok_for_sibcall 11064 11065 #undef TARGET_VALID_POINTER_MODE 11066 #define TARGET_VALID_POINTER_MODE loongarch_valid_pointer_mode 11067 #undef TARGET_REGISTER_MOVE_COST 11068 #define TARGET_REGISTER_MOVE_COST loongarch_register_move_cost 11069 #undef TARGET_MEMORY_MOVE_COST 11070 #define TARGET_MEMORY_MOVE_COST loongarch_memory_move_cost 11071 #undef TARGET_RTX_COSTS 11072 #define TARGET_RTX_COSTS loongarch_rtx_costs 11073 #undef TARGET_ADDRESS_COST 11074 #define TARGET_ADDRESS_COST loongarch_address_cost 11075 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST 11076 #define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST \ 11077 loongarch_builtin_vectorization_cost 11078 #undef TARGET_VECTORIZE_CREATE_COSTS 11079 #define TARGET_VECTORIZE_CREATE_COSTS loongarch_vectorize_create_costs 11080 11081 11082 #undef TARGET_IN_SMALL_DATA_P 11083 #define TARGET_IN_SMALL_DATA_P loongarch_in_small_data_p 11084 11085 #undef TARGET_PREFERRED_RELOAD_CLASS 11086 #define TARGET_PREFERRED_RELOAD_CLASS loongarch_preferred_reload_class 11087 11088 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE 11089 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true 11090 11091 #undef TARGET_EXPAND_BUILTIN_VA_START 11092 #define TARGET_EXPAND_BUILTIN_VA_START loongarch_va_start 11093 11094 #undef TARGET_PROMOTE_FUNCTION_MODE 11095 #define TARGET_PROMOTE_FUNCTION_MODE loongarch_promote_function_mode 11096 #undef TARGET_RETURN_IN_MEMORY 11097 #define TARGET_RETURN_IN_MEMORY loongarch_return_in_memory 11098 11099 #undef TARGET_FUNCTION_VALUE 11100 #define TARGET_FUNCTION_VALUE loongarch_function_value 11101 #undef TARGET_LIBCALL_VALUE 11102 #define TARGET_LIBCALL_VALUE loongarch_libcall_value 11103 11104 #undef TARGET_ASM_OUTPUT_MI_THUNK 11105 #define TARGET_ASM_OUTPUT_MI_THUNK loongarch_output_mi_thunk 11106 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK 11107 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \ 11108 hook_bool_const_tree_hwi_hwi_const_tree_true 11109 11110 #undef TARGET_PRINT_OPERAND 11111 #define TARGET_PRINT_OPERAND loongarch_print_operand 11112 #undef TARGET_PRINT_OPERAND_ADDRESS 11113 #define TARGET_PRINT_OPERAND_ADDRESS loongarch_print_operand_address 11114 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P 11115 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P \ 11116 loongarch_print_operand_punct_valid_p 11117 11118 #undef TARGET_SETUP_INCOMING_VARARGS 11119 #define TARGET_SETUP_INCOMING_VARARGS loongarch_setup_incoming_varargs 11120 #undef TARGET_STRICT_ARGUMENT_NAMING 11121 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true 11122 #undef TARGET_MUST_PASS_IN_STACK 11123 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size 11124 #undef TARGET_PASS_BY_REFERENCE 11125 #define TARGET_PASS_BY_REFERENCE loongarch_pass_by_reference 11126 #undef TARGET_ARG_PARTIAL_BYTES 11127 #define TARGET_ARG_PARTIAL_BYTES loongarch_arg_partial_bytes 11128 #undef TARGET_FUNCTION_ARG 11129 #define TARGET_FUNCTION_ARG loongarch_function_arg 11130 #undef TARGET_FUNCTION_ARG_ADVANCE 11131 #define TARGET_FUNCTION_ARG_ADVANCE loongarch_function_arg_advance 11132 #undef TARGET_FUNCTION_ARG_BOUNDARY 11133 #define TARGET_FUNCTION_ARG_BOUNDARY loongarch_function_arg_boundary 11134 11135 #undef TARGET_VECTOR_MODE_SUPPORTED_P 11136 #define TARGET_VECTOR_MODE_SUPPORTED_P loongarch_vector_mode_supported_p 11137 11138 #undef TARGET_SCALAR_MODE_SUPPORTED_P 11139 #define TARGET_SCALAR_MODE_SUPPORTED_P loongarch_scalar_mode_supported_p 11140 11141 #undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE 11142 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE loongarch_preferred_simd_mode 11143 11144 #undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES 11145 #define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES \ 11146 loongarch_autovectorize_vector_modes 11147 11148 #undef TARGET_OPTAB_SUPPORTED_P 11149 #define TARGET_OPTAB_SUPPORTED_P loongarch_optab_supported_p 11150 11151 #undef TARGET_INIT_BUILTINS 11152 #define TARGET_INIT_BUILTINS loongarch_init_builtins 11153 #undef TARGET_BUILTIN_DECL 11154 #define TARGET_BUILTIN_DECL loongarch_builtin_decl 11155 #undef TARGET_EXPAND_BUILTIN 11156 #define TARGET_EXPAND_BUILTIN loongarch_expand_builtin 11157 11158 /* The generic ELF target does not always have TLS support. */ 11159 #ifdef HAVE_AS_TLS 11160 #undef TARGET_HAVE_TLS 11161 #define TARGET_HAVE_TLS HAVE_AS_TLS 11162 #endif 11163 11164 #undef TARGET_CANNOT_FORCE_CONST_MEM 11165 #define TARGET_CANNOT_FORCE_CONST_MEM loongarch_cannot_force_const_mem 11166 11167 #undef TARGET_LEGITIMATE_CONSTANT_P 11168 #define TARGET_LEGITIMATE_CONSTANT_P loongarch_legitimate_constant_p 11169 11170 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P 11171 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true 11172 11173 #ifdef HAVE_AS_DTPRELWORD 11174 #undef TARGET_ASM_OUTPUT_DWARF_DTPREL 11175 #define TARGET_ASM_OUTPUT_DWARF_DTPREL loongarch_output_dwarf_dtprel 11176 #endif 11177 11178 #undef TARGET_LEGITIMATE_ADDRESS_P 11179 #define TARGET_LEGITIMATE_ADDRESS_P loongarch_legitimate_address_p 11180 11181 #undef TARGET_FRAME_POINTER_REQUIRED 11182 #define TARGET_FRAME_POINTER_REQUIRED loongarch_frame_pointer_required 11183 11184 #undef TARGET_CAN_ELIMINATE 11185 #define TARGET_CAN_ELIMINATE loongarch_can_eliminate 11186 11187 #undef TARGET_CONDITIONAL_REGISTER_USAGE 11188 #define TARGET_CONDITIONAL_REGISTER_USAGE loongarch_conditional_register_usage 11189 11190 #undef TARGET_TRAMPOLINE_INIT 11191 #define TARGET_TRAMPOLINE_INIT loongarch_trampoline_init 11192 11193 #undef TARGET_MIN_ANCHOR_OFFSET 11194 #define TARGET_MIN_ANCHOR_OFFSET (-IMM_REACH/2) 11195 11196 #undef TARGET_MAX_ANCHOR_OFFSET 11197 #define TARGET_MAX_ANCHOR_OFFSET (IMM_REACH/2-1) 11198 #undef TARGET_VECTORIZE_VEC_PERM_CONST 11199 #define TARGET_VECTORIZE_VEC_PERM_CONST loongarch_vectorize_vec_perm_const 11200 11201 #undef TARGET_SCHED_REASSOCIATION_WIDTH 11202 #define TARGET_SCHED_REASSOCIATION_WIDTH loongarch_sched_reassociation_width 11203 11204 #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV 11205 #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV loongarch_atomic_assign_expand_fenv 11206 11207 #undef TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS 11208 #define TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS true 11209 11210 #undef TARGET_HARD_REGNO_NREGS 11211 #define TARGET_HARD_REGNO_NREGS loongarch_hard_regno_nregs 11212 #undef TARGET_HARD_REGNO_MODE_OK 11213 #define TARGET_HARD_REGNO_MODE_OK loongarch_hard_regno_mode_ok 11214 11215 #undef TARGET_MODES_TIEABLE_P 11216 #define TARGET_MODES_TIEABLE_P loongarch_modes_tieable_p 11217 11218 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED 11219 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \ 11220 loongarch_hard_regno_call_part_clobbered 11221 11222 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS 11223 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 2 11224 11225 #undef TARGET_CAN_CHANGE_MODE_CLASS 11226 #define TARGET_CAN_CHANGE_MODE_CLASS loongarch_can_change_mode_class 11227 11228 #undef TARGET_CONSTANT_ALIGNMENT 11229 #define TARGET_CONSTANT_ALIGNMENT loongarch_constant_alignment 11230 11231 #undef TARGET_STARTING_FRAME_OFFSET 11232 #define TARGET_STARTING_FRAME_OFFSET loongarch_starting_frame_offset 11233 11234 #undef TARGET_SECONDARY_RELOAD 11235 #define TARGET_SECONDARY_RELOAD loongarch_secondary_reload 11236 11237 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE 11238 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed 11239 11240 #undef TARGET_ATTRIBUTE_TABLE 11241 #define TARGET_ATTRIBUTE_TABLE loongarch_attribute_table 11242 11243 #undef TARGET_USE_ANCHORS_FOR_SYMBOL_P 11244 #define TARGET_USE_ANCHORS_FOR_SYMBOL_P loongarch_use_anchors_for_symbol_p 11245 11246 #undef TARGET_ASAN_SHADOW_OFFSET 11247 #define TARGET_ASAN_SHADOW_OFFSET loongarch_asan_shadow_offset 11248 11249 #undef TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS 11250 #define TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS \ 11251 loongarch_get_separate_components 11252 11253 #undef TARGET_SHRINK_WRAP_COMPONENTS_FOR_BB 11254 #define TARGET_SHRINK_WRAP_COMPONENTS_FOR_BB loongarch_components_for_bb 11255 11256 #undef TARGET_SHRINK_WRAP_DISQUALIFY_COMPONENTS 11257 #define TARGET_SHRINK_WRAP_DISQUALIFY_COMPONENTS \ 11258 loongarch_disqualify_components 11259 11260 #undef TARGET_SHRINK_WRAP_EMIT_PROLOGUE_COMPONENTS 11261 #define TARGET_SHRINK_WRAP_EMIT_PROLOGUE_COMPONENTS \ 11262 loongarch_emit_prologue_components 11263 11264 #undef TARGET_SHRINK_WRAP_EMIT_EPILOGUE_COMPONENTS 11265 #define TARGET_SHRINK_WRAP_EMIT_EPILOGUE_COMPONENTS \ 11266 loongarch_emit_epilogue_components 11267 11268 #undef TARGET_SHRINK_WRAP_SET_HANDLED_COMPONENTS 11269 #define TARGET_SHRINK_WRAP_SET_HANDLED_COMPONENTS \ 11270 loongarch_set_handled_components 11271 11272 #undef TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT 11273 #define TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT \ 11274 loongarch_builtin_support_vector_misalignment 11275 11276 #undef TARGET_C_MODE_FOR_SUFFIX 11277 #define TARGET_C_MODE_FOR_SUFFIX loongarch_c_mode_for_suffix 11278 11279 struct gcc_target targetm = TARGET_INITIALIZER; 11280 11281 #include "gt-loongarch.h" 11282