1 /* Machine description for AArch64 architecture. 2 Copyright (C) 2009-2022 Free Software Foundation, Inc. 3 Contributed by ARM Ltd. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GCC is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #define IN_TARGET_CODE 1 22 23 #define INCLUDE_STRING 24 #define INCLUDE_ALGORITHM 25 #include "config.h" 26 #include "system.h" 27 #include "coretypes.h" 28 #include "backend.h" 29 #include "target.h" 30 #include "rtl.h" 31 #include "tree.h" 32 #include "memmodel.h" 33 #include "gimple.h" 34 #include "cfghooks.h" 35 #include "cfgloop.h" 36 #include "df.h" 37 #include "tm_p.h" 38 #include "stringpool.h" 39 #include "attribs.h" 40 #include "optabs.h" 41 #include "regs.h" 42 #include "emit-rtl.h" 43 #include "recog.h" 44 #include "cgraph.h" 45 #include "diagnostic.h" 46 #include "insn-attr.h" 47 #include "alias.h" 48 #include "fold-const.h" 49 #include "stor-layout.h" 50 #include "calls.h" 51 #include "varasm.h" 52 #include "output.h" 53 #include "flags.h" 54 #include "explow.h" 55 #include "expr.h" 56 #include "reload.h" 57 #include "langhooks.h" 58 #include "opts.h" 59 #include "gimplify.h" 60 #include "dwarf2.h" 61 #include "gimple-iterator.h" 62 #include "tree-vectorizer.h" 63 #include "aarch64-cost-tables.h" 64 #include "dumpfile.h" 65 #include "builtins.h" 66 #include "rtl-iter.h" 67 #include "tm-constrs.h" 68 #include "sched-int.h" 69 #include "target-globals.h" 70 #include "common/common-target.h" 71 #include "cfgrtl.h" 72 #include "selftest.h" 73 #include "selftest-rtl.h" 74 #include "rtx-vector-builder.h" 75 #include "intl.h" 76 #include "expmed.h" 77 #include "function-abi.h" 78 #include "gimple-pretty-print.h" 79 #include "tree-ssa-loop-niter.h" 80 #include "fractional-cost.h" 81 #include "rtlanal.h" 82 #include "tree-dfa.h" 83 #include "asan.h" 84 85 /* This file should be included last. */ 86 #include "target-def.h" 87 88 /* Defined for convenience. */ 89 #define POINTER_BYTES (POINTER_SIZE / BITS_PER_UNIT) 90 91 /* Information about a legitimate vector immediate operand. */ 92 struct simd_immediate_info 93 { 94 enum insn_type { MOV, MVN, INDEX, PTRUE }; 95 enum modifier_type { LSL, MSL }; 96 97 simd_immediate_info () {} 98 simd_immediate_info (scalar_float_mode, rtx); 99 simd_immediate_info (scalar_int_mode, unsigned HOST_WIDE_INT, 100 insn_type = MOV, modifier_type = LSL, 101 unsigned int = 0); 102 simd_immediate_info (scalar_mode, rtx, rtx); 103 simd_immediate_info (scalar_int_mode, aarch64_svpattern); 104 105 /* The mode of the elements. */ 106 scalar_mode elt_mode; 107 108 /* The instruction to use to move the immediate into a vector. */ 109 insn_type insn; 110 111 union 112 { 113 /* For MOV and MVN. */ 114 struct 115 { 116 /* The value of each element. */ 117 rtx value; 118 119 /* The kind of shift modifier to use, and the number of bits to shift. 120 This is (LSL, 0) if no shift is needed. */ 121 modifier_type modifier; 122 unsigned int shift; 123 } mov; 124 125 /* For INDEX. */ 126 struct 127 { 128 /* The value of the first element and the step to be added for each 129 subsequent element. */ 130 rtx base, step; 131 } index; 132 133 /* For PTRUE. */ 134 aarch64_svpattern pattern; 135 } u; 136 }; 137 138 /* Construct a floating-point immediate in which each element has mode 139 ELT_MODE_IN and value VALUE_IN. */ 140 inline simd_immediate_info 141 ::simd_immediate_info (scalar_float_mode elt_mode_in, rtx value_in) 142 : elt_mode (elt_mode_in), insn (MOV) 143 { 144 u.mov.value = value_in; 145 u.mov.modifier = LSL; 146 u.mov.shift = 0; 147 } 148 149 /* Construct an integer immediate in which each element has mode ELT_MODE_IN 150 and value VALUE_IN. The other parameters are as for the structure 151 fields. */ 152 inline simd_immediate_info 153 ::simd_immediate_info (scalar_int_mode elt_mode_in, 154 unsigned HOST_WIDE_INT value_in, 155 insn_type insn_in, modifier_type modifier_in, 156 unsigned int shift_in) 157 : elt_mode (elt_mode_in), insn (insn_in) 158 { 159 u.mov.value = gen_int_mode (value_in, elt_mode_in); 160 u.mov.modifier = modifier_in; 161 u.mov.shift = shift_in; 162 } 163 164 /* Construct an integer immediate in which each element has mode ELT_MODE_IN 165 and where element I is equal to BASE_IN + I * STEP_IN. */ 166 inline simd_immediate_info 167 ::simd_immediate_info (scalar_mode elt_mode_in, rtx base_in, rtx step_in) 168 : elt_mode (elt_mode_in), insn (INDEX) 169 { 170 u.index.base = base_in; 171 u.index.step = step_in; 172 } 173 174 /* Construct a predicate that controls elements of mode ELT_MODE_IN 175 and has PTRUE pattern PATTERN_IN. */ 176 inline simd_immediate_info 177 ::simd_immediate_info (scalar_int_mode elt_mode_in, 178 aarch64_svpattern pattern_in) 179 : elt_mode (elt_mode_in), insn (PTRUE) 180 { 181 u.pattern = pattern_in; 182 } 183 184 namespace { 185 186 /* Describes types that map to Pure Scalable Types (PSTs) in the AAPCS64. */ 187 class pure_scalable_type_info 188 { 189 public: 190 /* Represents the result of analyzing a type. All values are nonzero, 191 in the possibly forlorn hope that accidental conversions to bool 192 trigger a warning. */ 193 enum analysis_result 194 { 195 /* The type does not have an ABI identity; i.e. it doesn't contain 196 at least one object whose type is a Fundamental Data Type. */ 197 NO_ABI_IDENTITY = 1, 198 199 /* The type is definitely a Pure Scalable Type. */ 200 IS_PST, 201 202 /* The type is definitely not a Pure Scalable Type. */ 203 ISNT_PST, 204 205 /* It doesn't matter for PCS purposes whether the type is a Pure 206 Scalable Type or not, since the type will be handled the same 207 way regardless. 208 209 Specifically, this means that if the type is a Pure Scalable Type, 210 there aren't enough argument registers to hold it, and so it will 211 need to be passed or returned in memory. If the type isn't a 212 Pure Scalable Type, it's too big to be passed or returned in core 213 or SIMD&FP registers, and so again will need to go in memory. */ 214 DOESNT_MATTER 215 }; 216 217 /* Aggregates of 17 bytes or more are normally passed and returned 218 in memory, so aggregates of that size can safely be analyzed as 219 DOESNT_MATTER. We need to be able to collect enough pieces to 220 represent a PST that is smaller than that. Since predicates are 221 2 bytes in size for -msve-vector-bits=128, that means we need to be 222 able to store at least 8 pieces. 223 224 We also need to be able to store enough pieces to represent 225 a single vector in each vector argument register and a single 226 predicate in each predicate argument register. This means that 227 we need at least 12 pieces. */ 228 static const unsigned int MAX_PIECES = NUM_FP_ARG_REGS + NUM_PR_ARG_REGS; 229 static_assert (MAX_PIECES >= 8, "Need to store at least 8 predicates"); 230 231 /* Describes one piece of a PST. Each piece is one of: 232 233 - a single Scalable Vector Type (SVT) 234 - a single Scalable Predicate Type (SPT) 235 - a PST containing 2, 3 or 4 SVTs, with no padding 236 237 It either represents a single built-in type or a PST formed from 238 multiple homogeneous built-in types. */ 239 struct piece 240 { 241 rtx get_rtx (unsigned int, unsigned int) const; 242 243 /* The number of vector and predicate registers that the piece 244 occupies. One of the two is always zero. */ 245 unsigned int num_zr; 246 unsigned int num_pr; 247 248 /* The mode of the registers described above. */ 249 machine_mode mode; 250 251 /* If this piece is formed from multiple homogeneous built-in types, 252 this is the mode of the built-in types, otherwise it is MODE. */ 253 machine_mode orig_mode; 254 255 /* The offset in bytes of the piece from the start of the type. */ 256 poly_uint64_pod offset; 257 }; 258 259 /* Divides types analyzed as IS_PST into individual pieces. The pieces 260 are in memory order. */ 261 auto_vec<piece, MAX_PIECES> pieces; 262 263 unsigned int num_zr () const; 264 unsigned int num_pr () const; 265 266 rtx get_rtx (machine_mode mode, unsigned int, unsigned int) const; 267 268 analysis_result analyze (const_tree); 269 bool analyze_registers (const_tree); 270 271 private: 272 analysis_result analyze_array (const_tree); 273 analysis_result analyze_record (const_tree); 274 void add_piece (const piece &); 275 }; 276 } 277 278 /* The current code model. */ 279 enum aarch64_code_model aarch64_cmodel; 280 281 /* The number of 64-bit elements in an SVE vector. */ 282 poly_uint16 aarch64_sve_vg; 283 284 #ifdef HAVE_AS_TLS 285 #undef TARGET_HAVE_TLS 286 #define TARGET_HAVE_TLS 1 287 #endif 288 289 static bool aarch64_composite_type_p (const_tree, machine_mode); 290 static bool aarch64_return_in_memory_1 (const_tree); 291 static bool aarch64_vfp_is_call_or_return_candidate (machine_mode, 292 const_tree, 293 machine_mode *, int *, 294 bool *, bool); 295 static void aarch64_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED; 296 static void aarch64_elf_asm_destructor (rtx, int) ATTRIBUTE_UNUSED; 297 static void aarch64_override_options_after_change (void); 298 static bool aarch64_vector_mode_supported_p (machine_mode); 299 static int aarch64_address_cost (rtx, machine_mode, addr_space_t, bool); 300 static bool aarch64_builtin_support_vector_misalignment (machine_mode mode, 301 const_tree type, 302 int misalignment, 303 bool is_packed); 304 static machine_mode aarch64_simd_container_mode (scalar_mode, poly_int64); 305 static bool aarch64_print_address_internal (FILE*, machine_mode, rtx, 306 aarch64_addr_query_type); 307 static HOST_WIDE_INT aarch64_clamp_to_uimm12_shift (HOST_WIDE_INT val); 308 309 /* Major revision number of the ARM Architecture implemented by the target. */ 310 unsigned aarch64_architecture_version; 311 312 /* The processor for which instructions should be scheduled. */ 313 enum aarch64_processor aarch64_tune = cortexa53; 314 315 /* Mask to specify which instruction scheduling options should be used. */ 316 uint64_t aarch64_tune_flags = 0; 317 318 /* Global flag for PC relative loads. */ 319 bool aarch64_pcrelative_literal_loads; 320 321 /* Global flag for whether frame pointer is enabled. */ 322 bool aarch64_use_frame_pointer; 323 324 #define BRANCH_PROTECT_STR_MAX 255 325 char *accepted_branch_protection_string = NULL; 326 327 static enum aarch64_parse_opt_result 328 aarch64_parse_branch_protection (const char*, char**); 329 330 /* Support for command line parsing of boolean flags in the tuning 331 structures. */ 332 struct aarch64_flag_desc 333 { 334 const char* name; 335 unsigned int flag; 336 }; 337 338 #define AARCH64_FUSION_PAIR(name, internal_name) \ 339 { name, AARCH64_FUSE_##internal_name }, 340 static const struct aarch64_flag_desc aarch64_fusible_pairs[] = 341 { 342 { "none", AARCH64_FUSE_NOTHING }, 343 #include "aarch64-fusion-pairs.def" 344 { "all", AARCH64_FUSE_ALL }, 345 { NULL, AARCH64_FUSE_NOTHING } 346 }; 347 348 #define AARCH64_EXTRA_TUNING_OPTION(name, internal_name) \ 349 { name, AARCH64_EXTRA_TUNE_##internal_name }, 350 static const struct aarch64_flag_desc aarch64_tuning_flags[] = 351 { 352 { "none", AARCH64_EXTRA_TUNE_NONE }, 353 #include "aarch64-tuning-flags.def" 354 { "all", AARCH64_EXTRA_TUNE_ALL }, 355 { NULL, AARCH64_EXTRA_TUNE_NONE } 356 }; 357 358 /* Tuning parameters. */ 359 360 static const struct cpu_addrcost_table generic_addrcost_table = 361 { 362 { 363 1, /* hi */ 364 0, /* si */ 365 0, /* di */ 366 1, /* ti */ 367 }, 368 0, /* pre_modify */ 369 0, /* post_modify */ 370 0, /* post_modify_ld3_st3 */ 371 0, /* post_modify_ld4_st4 */ 372 0, /* register_offset */ 373 0, /* register_sextend */ 374 0, /* register_zextend */ 375 0 /* imm_offset */ 376 }; 377 378 static const struct cpu_addrcost_table exynosm1_addrcost_table = 379 { 380 { 381 0, /* hi */ 382 0, /* si */ 383 0, /* di */ 384 2, /* ti */ 385 }, 386 0, /* pre_modify */ 387 0, /* post_modify */ 388 0, /* post_modify_ld3_st3 */ 389 0, /* post_modify_ld4_st4 */ 390 1, /* register_offset */ 391 1, /* register_sextend */ 392 2, /* register_zextend */ 393 0, /* imm_offset */ 394 }; 395 396 static const struct cpu_addrcost_table xgene1_addrcost_table = 397 { 398 { 399 1, /* hi */ 400 0, /* si */ 401 0, /* di */ 402 1, /* ti */ 403 }, 404 1, /* pre_modify */ 405 1, /* post_modify */ 406 1, /* post_modify_ld3_st3 */ 407 1, /* post_modify_ld4_st4 */ 408 0, /* register_offset */ 409 1, /* register_sextend */ 410 1, /* register_zextend */ 411 0, /* imm_offset */ 412 }; 413 414 static const struct cpu_addrcost_table thunderx2t99_addrcost_table = 415 { 416 { 417 1, /* hi */ 418 1, /* si */ 419 1, /* di */ 420 2, /* ti */ 421 }, 422 0, /* pre_modify */ 423 0, /* post_modify */ 424 0, /* post_modify_ld3_st3 */ 425 0, /* post_modify_ld4_st4 */ 426 2, /* register_offset */ 427 3, /* register_sextend */ 428 3, /* register_zextend */ 429 0, /* imm_offset */ 430 }; 431 432 static const struct cpu_addrcost_table thunderx3t110_addrcost_table = 433 { 434 { 435 1, /* hi */ 436 1, /* si */ 437 1, /* di */ 438 2, /* ti */ 439 }, 440 0, /* pre_modify */ 441 0, /* post_modify */ 442 0, /* post_modify_ld3_st3 */ 443 0, /* post_modify_ld4_st4 */ 444 2, /* register_offset */ 445 3, /* register_sextend */ 446 3, /* register_zextend */ 447 0, /* imm_offset */ 448 }; 449 450 static const struct cpu_addrcost_table tsv110_addrcost_table = 451 { 452 { 453 1, /* hi */ 454 0, /* si */ 455 0, /* di */ 456 1, /* ti */ 457 }, 458 0, /* pre_modify */ 459 0, /* post_modify */ 460 0, /* post_modify_ld3_st3 */ 461 0, /* post_modify_ld4_st4 */ 462 0, /* register_offset */ 463 1, /* register_sextend */ 464 1, /* register_zextend */ 465 0, /* imm_offset */ 466 }; 467 468 static const struct cpu_addrcost_table qdf24xx_addrcost_table = 469 { 470 { 471 1, /* hi */ 472 1, /* si */ 473 1, /* di */ 474 2, /* ti */ 475 }, 476 1, /* pre_modify */ 477 1, /* post_modify */ 478 1, /* post_modify_ld3_st3 */ 479 1, /* post_modify_ld4_st4 */ 480 3, /* register_offset */ 481 3, /* register_sextend */ 482 3, /* register_zextend */ 483 2, /* imm_offset */ 484 }; 485 486 static const struct cpu_addrcost_table a64fx_addrcost_table = 487 { 488 { 489 1, /* hi */ 490 1, /* si */ 491 1, /* di */ 492 2, /* ti */ 493 }, 494 0, /* pre_modify */ 495 0, /* post_modify */ 496 0, /* post_modify_ld3_st3 */ 497 0, /* post_modify_ld4_st4 */ 498 2, /* register_offset */ 499 3, /* register_sextend */ 500 3, /* register_zextend */ 501 0, /* imm_offset */ 502 }; 503 504 static const struct cpu_addrcost_table neoversev1_addrcost_table = 505 { 506 { 507 1, /* hi */ 508 0, /* si */ 509 0, /* di */ 510 1, /* ti */ 511 }, 512 0, /* pre_modify */ 513 0, /* post_modify */ 514 3, /* post_modify_ld3_st3 */ 515 3, /* post_modify_ld4_st4 */ 516 0, /* register_offset */ 517 0, /* register_sextend */ 518 0, /* register_zextend */ 519 0 /* imm_offset */ 520 }; 521 522 static const struct cpu_addrcost_table neoversen2_addrcost_table = 523 { 524 { 525 1, /* hi */ 526 0, /* si */ 527 0, /* di */ 528 1, /* ti */ 529 }, 530 0, /* pre_modify */ 531 0, /* post_modify */ 532 2, /* post_modify_ld3_st3 */ 533 2, /* post_modify_ld4_st4 */ 534 0, /* register_offset */ 535 0, /* register_sextend */ 536 0, /* register_zextend */ 537 0 /* imm_offset */ 538 }; 539 540 static const struct cpu_addrcost_table neoversev2_addrcost_table = 541 { 542 { 543 1, /* hi */ 544 0, /* si */ 545 0, /* di */ 546 1, /* ti */ 547 }, 548 0, /* pre_modify */ 549 0, /* post_modify */ 550 2, /* post_modify_ld3_st3 */ 551 2, /* post_modify_ld4_st4 */ 552 0, /* register_offset */ 553 0, /* register_sextend */ 554 0, /* register_zextend */ 555 0 /* imm_offset */ 556 }; 557 558 static const struct cpu_regmove_cost generic_regmove_cost = 559 { 560 1, /* GP2GP */ 561 /* Avoid the use of slow int<->fp moves for spilling by setting 562 their cost higher than memmov_cost. */ 563 5, /* GP2FP */ 564 5, /* FP2GP */ 565 2 /* FP2FP */ 566 }; 567 568 static const struct cpu_regmove_cost cortexa57_regmove_cost = 569 { 570 1, /* GP2GP */ 571 /* Avoid the use of slow int<->fp moves for spilling by setting 572 their cost higher than memmov_cost. */ 573 5, /* GP2FP */ 574 5, /* FP2GP */ 575 2 /* FP2FP */ 576 }; 577 578 static const struct cpu_regmove_cost cortexa53_regmove_cost = 579 { 580 1, /* GP2GP */ 581 /* Avoid the use of slow int<->fp moves for spilling by setting 582 their cost higher than memmov_cost. */ 583 5, /* GP2FP */ 584 5, /* FP2GP */ 585 2 /* FP2FP */ 586 }; 587 588 static const struct cpu_regmove_cost exynosm1_regmove_cost = 589 { 590 1, /* GP2GP */ 591 /* Avoid the use of slow int<->fp moves for spilling by setting 592 their cost higher than memmov_cost (actual, 4 and 9). */ 593 9, /* GP2FP */ 594 9, /* FP2GP */ 595 1 /* FP2FP */ 596 }; 597 598 static const struct cpu_regmove_cost thunderx_regmove_cost = 599 { 600 2, /* GP2GP */ 601 2, /* GP2FP */ 602 6, /* FP2GP */ 603 4 /* FP2FP */ 604 }; 605 606 static const struct cpu_regmove_cost xgene1_regmove_cost = 607 { 608 1, /* GP2GP */ 609 /* Avoid the use of slow int<->fp moves for spilling by setting 610 their cost higher than memmov_cost. */ 611 8, /* GP2FP */ 612 8, /* FP2GP */ 613 2 /* FP2FP */ 614 }; 615 616 static const struct cpu_regmove_cost qdf24xx_regmove_cost = 617 { 618 2, /* GP2GP */ 619 /* Avoid the use of int<->fp moves for spilling. */ 620 6, /* GP2FP */ 621 6, /* FP2GP */ 622 4 /* FP2FP */ 623 }; 624 625 static const struct cpu_regmove_cost thunderx2t99_regmove_cost = 626 { 627 1, /* GP2GP */ 628 /* Avoid the use of int<->fp moves for spilling. */ 629 5, /* GP2FP */ 630 6, /* FP2GP */ 631 3, /* FP2FP */ 632 }; 633 634 static const struct cpu_regmove_cost thunderx3t110_regmove_cost = 635 { 636 1, /* GP2GP */ 637 /* Avoid the use of int<->fp moves for spilling. */ 638 4, /* GP2FP */ 639 5, /* FP2GP */ 640 4 /* FP2FP */ 641 }; 642 643 static const struct cpu_regmove_cost tsv110_regmove_cost = 644 { 645 1, /* GP2GP */ 646 /* Avoid the use of slow int<->fp moves for spilling by setting 647 their cost higher than memmov_cost. */ 648 2, /* GP2FP */ 649 3, /* FP2GP */ 650 2 /* FP2FP */ 651 }; 652 653 static const struct cpu_regmove_cost a64fx_regmove_cost = 654 { 655 1, /* GP2GP */ 656 /* Avoid the use of slow int<->fp moves for spilling by setting 657 their cost higher than memmov_cost. */ 658 5, /* GP2FP */ 659 7, /* FP2GP */ 660 2 /* FP2FP */ 661 }; 662 663 static const struct cpu_regmove_cost neoversen2_regmove_cost = 664 { 665 1, /* GP2GP */ 666 /* Spilling to int<->fp instead of memory is recommended so set 667 realistic costs compared to memmov_cost. */ 668 3, /* GP2FP */ 669 2, /* FP2GP */ 670 2 /* FP2FP */ 671 }; 672 673 static const struct cpu_regmove_cost neoversev1_regmove_cost = 674 { 675 1, /* GP2GP */ 676 /* Spilling to int<->fp instead of memory is recommended so set 677 realistic costs compared to memmov_cost. */ 678 3, /* GP2FP */ 679 2, /* FP2GP */ 680 2 /* FP2FP */ 681 }; 682 683 static const struct cpu_regmove_cost neoversev2_regmove_cost = 684 { 685 1, /* GP2GP */ 686 /* Spilling to int<->fp instead of memory is recommended so set 687 realistic costs compared to memmov_cost. */ 688 3, /* GP2FP */ 689 2, /* FP2GP */ 690 2 /* FP2FP */ 691 }; 692 693 /* Generic costs for Advanced SIMD vector operations. */ 694 static const advsimd_vec_cost generic_advsimd_vector_cost = 695 { 696 1, /* int_stmt_cost */ 697 1, /* fp_stmt_cost */ 698 0, /* ld2_st2_permute_cost */ 699 0, /* ld3_st3_permute_cost */ 700 0, /* ld4_st4_permute_cost */ 701 2, /* permute_cost */ 702 2, /* reduc_i8_cost */ 703 2, /* reduc_i16_cost */ 704 2, /* reduc_i32_cost */ 705 2, /* reduc_i64_cost */ 706 2, /* reduc_f16_cost */ 707 2, /* reduc_f32_cost */ 708 2, /* reduc_f64_cost */ 709 2, /* store_elt_extra_cost */ 710 2, /* vec_to_scalar_cost */ 711 1, /* scalar_to_vec_cost */ 712 1, /* align_load_cost */ 713 1, /* unalign_load_cost */ 714 1, /* unalign_store_cost */ 715 1 /* store_cost */ 716 }; 717 718 /* Generic costs for SVE vector operations. */ 719 static const sve_vec_cost generic_sve_vector_cost = 720 { 721 { 722 1, /* int_stmt_cost */ 723 1, /* fp_stmt_cost */ 724 0, /* ld2_st2_permute_cost */ 725 0, /* ld3_st3_permute_cost */ 726 0, /* ld4_st4_permute_cost */ 727 2, /* permute_cost */ 728 2, /* reduc_i8_cost */ 729 2, /* reduc_i16_cost */ 730 2, /* reduc_i32_cost */ 731 2, /* reduc_i64_cost */ 732 2, /* reduc_f16_cost */ 733 2, /* reduc_f32_cost */ 734 2, /* reduc_f64_cost */ 735 2, /* store_elt_extra_cost */ 736 2, /* vec_to_scalar_cost */ 737 1, /* scalar_to_vec_cost */ 738 1, /* align_load_cost */ 739 1, /* unalign_load_cost */ 740 1, /* unalign_store_cost */ 741 1 /* store_cost */ 742 }, 743 2, /* clast_cost */ 744 2, /* fadda_f16_cost */ 745 2, /* fadda_f32_cost */ 746 2, /* fadda_f64_cost */ 747 4, /* gather_load_x32_cost */ 748 2, /* gather_load_x64_cost */ 749 1 /* scatter_store_elt_cost */ 750 }; 751 752 /* Generic costs for vector insn classes. */ 753 static const struct cpu_vector_cost generic_vector_cost = 754 { 755 1, /* scalar_int_stmt_cost */ 756 1, /* scalar_fp_stmt_cost */ 757 1, /* scalar_load_cost */ 758 1, /* scalar_store_cost */ 759 3, /* cond_taken_branch_cost */ 760 1, /* cond_not_taken_branch_cost */ 761 &generic_advsimd_vector_cost, /* advsimd */ 762 &generic_sve_vector_cost, /* sve */ 763 nullptr /* issue_info */ 764 }; 765 766 static const advsimd_vec_cost a64fx_advsimd_vector_cost = 767 { 768 2, /* int_stmt_cost */ 769 5, /* fp_stmt_cost */ 770 0, /* ld2_st2_permute_cost */ 771 0, /* ld3_st3_permute_cost */ 772 0, /* ld4_st4_permute_cost */ 773 3, /* permute_cost */ 774 13, /* reduc_i8_cost */ 775 13, /* reduc_i16_cost */ 776 13, /* reduc_i32_cost */ 777 13, /* reduc_i64_cost */ 778 13, /* reduc_f16_cost */ 779 13, /* reduc_f32_cost */ 780 13, /* reduc_f64_cost */ 781 13, /* store_elt_extra_cost */ 782 13, /* vec_to_scalar_cost */ 783 4, /* scalar_to_vec_cost */ 784 6, /* align_load_cost */ 785 6, /* unalign_load_cost */ 786 1, /* unalign_store_cost */ 787 1 /* store_cost */ 788 }; 789 790 static const sve_vec_cost a64fx_sve_vector_cost = 791 { 792 { 793 2, /* int_stmt_cost */ 794 5, /* fp_stmt_cost */ 795 0, /* ld2_st2_permute_cost */ 796 0, /* ld3_st3_permute_cost */ 797 0, /* ld4_st4_permute_cost */ 798 3, /* permute_cost */ 799 13, /* reduc_i8_cost */ 800 13, /* reduc_i16_cost */ 801 13, /* reduc_i32_cost */ 802 13, /* reduc_i64_cost */ 803 13, /* reduc_f16_cost */ 804 13, /* reduc_f32_cost */ 805 13, /* reduc_f64_cost */ 806 13, /* store_elt_extra_cost */ 807 13, /* vec_to_scalar_cost */ 808 4, /* scalar_to_vec_cost */ 809 6, /* align_load_cost */ 810 6, /* unalign_load_cost */ 811 1, /* unalign_store_cost */ 812 1 /* store_cost */ 813 }, 814 13, /* clast_cost */ 815 13, /* fadda_f16_cost */ 816 13, /* fadda_f32_cost */ 817 13, /* fadda_f64_cost */ 818 64, /* gather_load_x32_cost */ 819 32, /* gather_load_x64_cost */ 820 1 /* scatter_store_elt_cost */ 821 }; 822 823 static const struct cpu_vector_cost a64fx_vector_cost = 824 { 825 1, /* scalar_int_stmt_cost */ 826 5, /* scalar_fp_stmt_cost */ 827 4, /* scalar_load_cost */ 828 1, /* scalar_store_cost */ 829 3, /* cond_taken_branch_cost */ 830 1, /* cond_not_taken_branch_cost */ 831 &a64fx_advsimd_vector_cost, /* advsimd */ 832 &a64fx_sve_vector_cost, /* sve */ 833 nullptr /* issue_info */ 834 }; 835 836 static const advsimd_vec_cost qdf24xx_advsimd_vector_cost = 837 { 838 1, /* int_stmt_cost */ 839 3, /* fp_stmt_cost */ 840 0, /* ld2_st2_permute_cost */ 841 0, /* ld3_st3_permute_cost */ 842 0, /* ld4_st4_permute_cost */ 843 2, /* permute_cost */ 844 1, /* reduc_i8_cost */ 845 1, /* reduc_i16_cost */ 846 1, /* reduc_i32_cost */ 847 1, /* reduc_i64_cost */ 848 1, /* reduc_f16_cost */ 849 1, /* reduc_f32_cost */ 850 1, /* reduc_f64_cost */ 851 1, /* store_elt_extra_cost */ 852 1, /* vec_to_scalar_cost */ 853 1, /* scalar_to_vec_cost */ 854 1, /* align_load_cost */ 855 1, /* unalign_load_cost */ 856 1, /* unalign_store_cost */ 857 1 /* store_cost */ 858 }; 859 860 /* QDF24XX costs for vector insn classes. */ 861 static const struct cpu_vector_cost qdf24xx_vector_cost = 862 { 863 1, /* scalar_int_stmt_cost */ 864 1, /* scalar_fp_stmt_cost */ 865 1, /* scalar_load_cost */ 866 1, /* scalar_store_cost */ 867 3, /* cond_taken_branch_cost */ 868 1, /* cond_not_taken_branch_cost */ 869 &qdf24xx_advsimd_vector_cost, /* advsimd */ 870 nullptr, /* sve */ 871 nullptr /* issue_info */ 872 }; 873 874 875 static const advsimd_vec_cost thunderx_advsimd_vector_cost = 876 { 877 4, /* int_stmt_cost */ 878 1, /* fp_stmt_cost */ 879 0, /* ld2_st2_permute_cost */ 880 0, /* ld3_st3_permute_cost */ 881 0, /* ld4_st4_permute_cost */ 882 4, /* permute_cost */ 883 2, /* reduc_i8_cost */ 884 2, /* reduc_i16_cost */ 885 2, /* reduc_i32_cost */ 886 2, /* reduc_i64_cost */ 887 2, /* reduc_f16_cost */ 888 2, /* reduc_f32_cost */ 889 2, /* reduc_f64_cost */ 890 2, /* store_elt_extra_cost */ 891 2, /* vec_to_scalar_cost */ 892 2, /* scalar_to_vec_cost */ 893 3, /* align_load_cost */ 894 5, /* unalign_load_cost */ 895 5, /* unalign_store_cost */ 896 1 /* store_cost */ 897 }; 898 899 /* ThunderX costs for vector insn classes. */ 900 static const struct cpu_vector_cost thunderx_vector_cost = 901 { 902 1, /* scalar_int_stmt_cost */ 903 1, /* scalar_fp_stmt_cost */ 904 3, /* scalar_load_cost */ 905 1, /* scalar_store_cost */ 906 3, /* cond_taken_branch_cost */ 907 3, /* cond_not_taken_branch_cost */ 908 &thunderx_advsimd_vector_cost, /* advsimd */ 909 nullptr, /* sve */ 910 nullptr /* issue_info */ 911 }; 912 913 static const advsimd_vec_cost tsv110_advsimd_vector_cost = 914 { 915 2, /* int_stmt_cost */ 916 2, /* fp_stmt_cost */ 917 0, /* ld2_st2_permute_cost */ 918 0, /* ld3_st3_permute_cost */ 919 0, /* ld4_st4_permute_cost */ 920 2, /* permute_cost */ 921 3, /* reduc_i8_cost */ 922 3, /* reduc_i16_cost */ 923 3, /* reduc_i32_cost */ 924 3, /* reduc_i64_cost */ 925 3, /* reduc_f16_cost */ 926 3, /* reduc_f32_cost */ 927 3, /* reduc_f64_cost */ 928 3, /* store_elt_extra_cost */ 929 3, /* vec_to_scalar_cost */ 930 2, /* scalar_to_vec_cost */ 931 5, /* align_load_cost */ 932 5, /* unalign_load_cost */ 933 1, /* unalign_store_cost */ 934 1 /* store_cost */ 935 }; 936 937 static const struct cpu_vector_cost tsv110_vector_cost = 938 { 939 1, /* scalar_int_stmt_cost */ 940 1, /* scalar_fp_stmt_cost */ 941 5, /* scalar_load_cost */ 942 1, /* scalar_store_cost */ 943 1, /* cond_taken_branch_cost */ 944 1, /* cond_not_taken_branch_cost */ 945 &tsv110_advsimd_vector_cost, /* advsimd */ 946 nullptr, /* sve */ 947 nullptr /* issue_info */ 948 }; 949 950 static const advsimd_vec_cost cortexa57_advsimd_vector_cost = 951 { 952 2, /* int_stmt_cost */ 953 2, /* fp_stmt_cost */ 954 0, /* ld2_st2_permute_cost */ 955 0, /* ld3_st3_permute_cost */ 956 0, /* ld4_st4_permute_cost */ 957 3, /* permute_cost */ 958 8, /* reduc_i8_cost */ 959 8, /* reduc_i16_cost */ 960 8, /* reduc_i32_cost */ 961 8, /* reduc_i64_cost */ 962 8, /* reduc_f16_cost */ 963 8, /* reduc_f32_cost */ 964 8, /* reduc_f64_cost */ 965 8, /* store_elt_extra_cost */ 966 8, /* vec_to_scalar_cost */ 967 8, /* scalar_to_vec_cost */ 968 4, /* align_load_cost */ 969 4, /* unalign_load_cost */ 970 1, /* unalign_store_cost */ 971 1 /* store_cost */ 972 }; 973 974 /* Cortex-A57 costs for vector insn classes. */ 975 static const struct cpu_vector_cost cortexa57_vector_cost = 976 { 977 1, /* scalar_int_stmt_cost */ 978 1, /* scalar_fp_stmt_cost */ 979 4, /* scalar_load_cost */ 980 1, /* scalar_store_cost */ 981 1, /* cond_taken_branch_cost */ 982 1, /* cond_not_taken_branch_cost */ 983 &cortexa57_advsimd_vector_cost, /* advsimd */ 984 nullptr, /* sve */ 985 nullptr /* issue_info */ 986 }; 987 988 static const advsimd_vec_cost exynosm1_advsimd_vector_cost = 989 { 990 3, /* int_stmt_cost */ 991 3, /* fp_stmt_cost */ 992 0, /* ld2_st2_permute_cost */ 993 0, /* ld3_st3_permute_cost */ 994 0, /* ld4_st4_permute_cost */ 995 3, /* permute_cost */ 996 3, /* reduc_i8_cost */ 997 3, /* reduc_i16_cost */ 998 3, /* reduc_i32_cost */ 999 3, /* reduc_i64_cost */ 1000 3, /* reduc_f16_cost */ 1001 3, /* reduc_f32_cost */ 1002 3, /* reduc_f64_cost */ 1003 3, /* store_elt_extra_cost */ 1004 3, /* vec_to_scalar_cost */ 1005 3, /* scalar_to_vec_cost */ 1006 5, /* align_load_cost */ 1007 5, /* unalign_load_cost */ 1008 1, /* unalign_store_cost */ 1009 1 /* store_cost */ 1010 }; 1011 1012 static const struct cpu_vector_cost exynosm1_vector_cost = 1013 { 1014 1, /* scalar_int_stmt_cost */ 1015 1, /* scalar_fp_stmt_cost */ 1016 5, /* scalar_load_cost */ 1017 1, /* scalar_store_cost */ 1018 1, /* cond_taken_branch_cost */ 1019 1, /* cond_not_taken_branch_cost */ 1020 &exynosm1_advsimd_vector_cost, /* advsimd */ 1021 nullptr, /* sve */ 1022 nullptr /* issue_info */ 1023 }; 1024 1025 static const advsimd_vec_cost xgene1_advsimd_vector_cost = 1026 { 1027 2, /* int_stmt_cost */ 1028 2, /* fp_stmt_cost */ 1029 0, /* ld2_st2_permute_cost */ 1030 0, /* ld3_st3_permute_cost */ 1031 0, /* ld4_st4_permute_cost */ 1032 2, /* permute_cost */ 1033 4, /* reduc_i8_cost */ 1034 4, /* reduc_i16_cost */ 1035 4, /* reduc_i32_cost */ 1036 4, /* reduc_i64_cost */ 1037 4, /* reduc_f16_cost */ 1038 4, /* reduc_f32_cost */ 1039 4, /* reduc_f64_cost */ 1040 4, /* store_elt_extra_cost */ 1041 4, /* vec_to_scalar_cost */ 1042 4, /* scalar_to_vec_cost */ 1043 10, /* align_load_cost */ 1044 10, /* unalign_load_cost */ 1045 2, /* unalign_store_cost */ 1046 2 /* store_cost */ 1047 }; 1048 1049 /* Generic costs for vector insn classes. */ 1050 static const struct cpu_vector_cost xgene1_vector_cost = 1051 { 1052 1, /* scalar_int_stmt_cost */ 1053 1, /* scalar_fp_stmt_cost */ 1054 5, /* scalar_load_cost */ 1055 1, /* scalar_store_cost */ 1056 2, /* cond_taken_branch_cost */ 1057 1, /* cond_not_taken_branch_cost */ 1058 &xgene1_advsimd_vector_cost, /* advsimd */ 1059 nullptr, /* sve */ 1060 nullptr /* issue_info */ 1061 }; 1062 1063 static const advsimd_vec_cost thunderx2t99_advsimd_vector_cost = 1064 { 1065 4, /* int_stmt_cost */ 1066 5, /* fp_stmt_cost */ 1067 0, /* ld2_st2_permute_cost */ 1068 0, /* ld3_st3_permute_cost */ 1069 0, /* ld4_st4_permute_cost */ 1070 10, /* permute_cost */ 1071 6, /* reduc_i8_cost */ 1072 6, /* reduc_i16_cost */ 1073 6, /* reduc_i32_cost */ 1074 6, /* reduc_i64_cost */ 1075 6, /* reduc_f16_cost */ 1076 6, /* reduc_f32_cost */ 1077 6, /* reduc_f64_cost */ 1078 6, /* store_elt_extra_cost */ 1079 6, /* vec_to_scalar_cost */ 1080 5, /* scalar_to_vec_cost */ 1081 4, /* align_load_cost */ 1082 4, /* unalign_load_cost */ 1083 1, /* unalign_store_cost */ 1084 1 /* store_cost */ 1085 }; 1086 1087 /* Costs for vector insn classes for Vulcan. */ 1088 static const struct cpu_vector_cost thunderx2t99_vector_cost = 1089 { 1090 1, /* scalar_int_stmt_cost */ 1091 6, /* scalar_fp_stmt_cost */ 1092 4, /* scalar_load_cost */ 1093 1, /* scalar_store_cost */ 1094 2, /* cond_taken_branch_cost */ 1095 1, /* cond_not_taken_branch_cost */ 1096 &thunderx2t99_advsimd_vector_cost, /* advsimd */ 1097 nullptr, /* sve */ 1098 nullptr /* issue_info */ 1099 }; 1100 1101 static const advsimd_vec_cost thunderx3t110_advsimd_vector_cost = 1102 { 1103 5, /* int_stmt_cost */ 1104 5, /* fp_stmt_cost */ 1105 0, /* ld2_st2_permute_cost */ 1106 0, /* ld3_st3_permute_cost */ 1107 0, /* ld4_st4_permute_cost */ 1108 10, /* permute_cost */ 1109 5, /* reduc_i8_cost */ 1110 5, /* reduc_i16_cost */ 1111 5, /* reduc_i32_cost */ 1112 5, /* reduc_i64_cost */ 1113 5, /* reduc_f16_cost */ 1114 5, /* reduc_f32_cost */ 1115 5, /* reduc_f64_cost */ 1116 5, /* store_elt_extra_cost */ 1117 5, /* vec_to_scalar_cost */ 1118 5, /* scalar_to_vec_cost */ 1119 4, /* align_load_cost */ 1120 4, /* unalign_load_cost */ 1121 4, /* unalign_store_cost */ 1122 4 /* store_cost */ 1123 }; 1124 1125 static const struct cpu_vector_cost thunderx3t110_vector_cost = 1126 { 1127 1, /* scalar_int_stmt_cost */ 1128 5, /* scalar_fp_stmt_cost */ 1129 4, /* scalar_load_cost */ 1130 1, /* scalar_store_cost */ 1131 2, /* cond_taken_branch_cost */ 1132 1, /* cond_not_taken_branch_cost */ 1133 &thunderx3t110_advsimd_vector_cost, /* advsimd */ 1134 nullptr, /* sve */ 1135 nullptr /* issue_info */ 1136 }; 1137 1138 static const advsimd_vec_cost ampere1_advsimd_vector_cost = 1139 { 1140 1, /* int_stmt_cost */ 1141 3, /* fp_stmt_cost */ 1142 0, /* ld2_st2_permute_cost */ 1143 0, /* ld3_st3_permute_cost */ 1144 0, /* ld4_st4_permute_cost */ 1145 2, /* permute_cost */ 1146 12, /* reduc_i8_cost */ 1147 9, /* reduc_i16_cost */ 1148 6, /* reduc_i32_cost */ 1149 5, /* reduc_i64_cost */ 1150 9, /* reduc_f16_cost */ 1151 6, /* reduc_f32_cost */ 1152 5, /* reduc_f64_cost */ 1153 8, /* store_elt_extra_cost */ 1154 6, /* vec_to_scalar_cost */ 1155 7, /* scalar_to_vec_cost */ 1156 4, /* align_load_cost */ 1157 4, /* unalign_load_cost */ 1158 1, /* unalign_store_cost */ 1159 1 /* store_cost */ 1160 }; 1161 1162 /* Ampere-1 costs for vector insn classes. */ 1163 static const struct cpu_vector_cost ampere1_vector_cost = 1164 { 1165 1, /* scalar_int_stmt_cost */ 1166 3, /* scalar_fp_stmt_cost */ 1167 4, /* scalar_load_cost */ 1168 1, /* scalar_store_cost */ 1169 1, /* cond_taken_branch_cost */ 1170 1, /* cond_not_taken_branch_cost */ 1171 &ere1_advsimd_vector_cost, /* advsimd */ 1172 nullptr, /* sve */ 1173 nullptr /* issue_info */ 1174 }; 1175 1176 /* Generic costs for branch instructions. */ 1177 static const struct cpu_branch_cost generic_branch_cost = 1178 { 1179 1, /* Predictable. */ 1180 3 /* Unpredictable. */ 1181 }; 1182 1183 /* Generic approximation modes. */ 1184 static const cpu_approx_modes generic_approx_modes = 1185 { 1186 AARCH64_APPROX_NONE, /* division */ 1187 AARCH64_APPROX_NONE, /* sqrt */ 1188 AARCH64_APPROX_NONE /* recip_sqrt */ 1189 }; 1190 1191 /* Approximation modes for Exynos M1. */ 1192 static const cpu_approx_modes exynosm1_approx_modes = 1193 { 1194 AARCH64_APPROX_NONE, /* division */ 1195 AARCH64_APPROX_ALL, /* sqrt */ 1196 AARCH64_APPROX_ALL /* recip_sqrt */ 1197 }; 1198 1199 /* Approximation modes for X-Gene 1. */ 1200 static const cpu_approx_modes xgene1_approx_modes = 1201 { 1202 AARCH64_APPROX_NONE, /* division */ 1203 AARCH64_APPROX_NONE, /* sqrt */ 1204 AARCH64_APPROX_ALL /* recip_sqrt */ 1205 }; 1206 1207 /* Generic prefetch settings (which disable prefetch). */ 1208 static const cpu_prefetch_tune generic_prefetch_tune = 1209 { 1210 0, /* num_slots */ 1211 -1, /* l1_cache_size */ 1212 -1, /* l1_cache_line_size */ 1213 -1, /* l2_cache_size */ 1214 true, /* prefetch_dynamic_strides */ 1215 -1, /* minimum_stride */ 1216 -1 /* default_opt_level */ 1217 }; 1218 1219 static const cpu_prefetch_tune exynosm1_prefetch_tune = 1220 { 1221 0, /* num_slots */ 1222 -1, /* l1_cache_size */ 1223 64, /* l1_cache_line_size */ 1224 -1, /* l2_cache_size */ 1225 true, /* prefetch_dynamic_strides */ 1226 -1, /* minimum_stride */ 1227 -1 /* default_opt_level */ 1228 }; 1229 1230 static const cpu_prefetch_tune qdf24xx_prefetch_tune = 1231 { 1232 4, /* num_slots */ 1233 32, /* l1_cache_size */ 1234 64, /* l1_cache_line_size */ 1235 512, /* l2_cache_size */ 1236 false, /* prefetch_dynamic_strides */ 1237 2048, /* minimum_stride */ 1238 3 /* default_opt_level */ 1239 }; 1240 1241 static const cpu_prefetch_tune thunderxt88_prefetch_tune = 1242 { 1243 8, /* num_slots */ 1244 32, /* l1_cache_size */ 1245 128, /* l1_cache_line_size */ 1246 16*1024, /* l2_cache_size */ 1247 true, /* prefetch_dynamic_strides */ 1248 -1, /* minimum_stride */ 1249 3 /* default_opt_level */ 1250 }; 1251 1252 static const cpu_prefetch_tune thunderx_prefetch_tune = 1253 { 1254 8, /* num_slots */ 1255 32, /* l1_cache_size */ 1256 128, /* l1_cache_line_size */ 1257 -1, /* l2_cache_size */ 1258 true, /* prefetch_dynamic_strides */ 1259 -1, /* minimum_stride */ 1260 -1 /* default_opt_level */ 1261 }; 1262 1263 static const cpu_prefetch_tune thunderx2t99_prefetch_tune = 1264 { 1265 8, /* num_slots */ 1266 32, /* l1_cache_size */ 1267 64, /* l1_cache_line_size */ 1268 256, /* l2_cache_size */ 1269 true, /* prefetch_dynamic_strides */ 1270 -1, /* minimum_stride */ 1271 -1 /* default_opt_level */ 1272 }; 1273 1274 static const cpu_prefetch_tune thunderx3t110_prefetch_tune = 1275 { 1276 8, /* num_slots */ 1277 32, /* l1_cache_size */ 1278 64, /* l1_cache_line_size */ 1279 256, /* l2_cache_size */ 1280 true, /* prefetch_dynamic_strides */ 1281 -1, /* minimum_stride */ 1282 -1 /* default_opt_level */ 1283 }; 1284 1285 static const cpu_prefetch_tune tsv110_prefetch_tune = 1286 { 1287 0, /* num_slots */ 1288 64, /* l1_cache_size */ 1289 64, /* l1_cache_line_size */ 1290 512, /* l2_cache_size */ 1291 true, /* prefetch_dynamic_strides */ 1292 -1, /* minimum_stride */ 1293 -1 /* default_opt_level */ 1294 }; 1295 1296 static const cpu_prefetch_tune xgene1_prefetch_tune = 1297 { 1298 8, /* num_slots */ 1299 32, /* l1_cache_size */ 1300 64, /* l1_cache_line_size */ 1301 256, /* l2_cache_size */ 1302 true, /* prefetch_dynamic_strides */ 1303 -1, /* minimum_stride */ 1304 -1 /* default_opt_level */ 1305 }; 1306 1307 static const cpu_prefetch_tune a64fx_prefetch_tune = 1308 { 1309 8, /* num_slots */ 1310 64, /* l1_cache_size */ 1311 256, /* l1_cache_line_size */ 1312 32768, /* l2_cache_size */ 1313 true, /* prefetch_dynamic_strides */ 1314 -1, /* minimum_stride */ 1315 -1 /* default_opt_level */ 1316 }; 1317 1318 static const cpu_prefetch_tune ampere1_prefetch_tune = 1319 { 1320 0, /* num_slots */ 1321 64, /* l1_cache_size */ 1322 64, /* l1_cache_line_size */ 1323 2048, /* l2_cache_size */ 1324 true, /* prefetch_dynamic_strides */ 1325 -1, /* minimum_stride */ 1326 -1 /* default_opt_level */ 1327 }; 1328 1329 static const struct tune_params generic_tunings = 1330 { 1331 &cortexa57_extra_costs, 1332 &generic_addrcost_table, 1333 &generic_regmove_cost, 1334 &generic_vector_cost, 1335 &generic_branch_cost, 1336 &generic_approx_modes, 1337 SVE_NOT_IMPLEMENTED, /* sve_width */ 1338 { 4, /* load_int. */ 1339 4, /* store_int. */ 1340 4, /* load_fp. */ 1341 4, /* store_fp. */ 1342 4, /* load_pred. */ 1343 4 /* store_pred. */ 1344 }, /* memmov_cost. */ 1345 2, /* issue_rate */ 1346 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ 1347 "16:12", /* function_align. */ 1348 "4", /* jump_align. */ 1349 "8", /* loop_align. */ 1350 2, /* int_reassoc_width. */ 1351 4, /* fp_reassoc_width. */ 1352 1, /* vec_reassoc_width. */ 1353 2, /* min_div_recip_mul_sf. */ 1354 2, /* min_div_recip_mul_df. */ 1355 0, /* max_case_values. */ 1356 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1357 /* Enabling AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS significantly benefits 1358 Neoverse V1. It does not have a noticeable effect on A64FX and should 1359 have at most a very minor effect on SVE2 cores. */ 1360 (AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS), /* tune_flags. */ 1361 &generic_prefetch_tune 1362 }; 1363 1364 static const struct tune_params cortexa35_tunings = 1365 { 1366 &cortexa53_extra_costs, 1367 &generic_addrcost_table, 1368 &cortexa53_regmove_cost, 1369 &generic_vector_cost, 1370 &generic_branch_cost, 1371 &generic_approx_modes, 1372 SVE_NOT_IMPLEMENTED, /* sve_width */ 1373 { 4, /* load_int. */ 1374 4, /* store_int. */ 1375 4, /* load_fp. */ 1376 4, /* store_fp. */ 1377 4, /* load_pred. */ 1378 4 /* store_pred. */ 1379 }, /* memmov_cost. */ 1380 1, /* issue_rate */ 1381 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD 1382 | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ 1383 "16", /* function_align. */ 1384 "4", /* jump_align. */ 1385 "8", /* loop_align. */ 1386 2, /* int_reassoc_width. */ 1387 4, /* fp_reassoc_width. */ 1388 1, /* vec_reassoc_width. */ 1389 2, /* min_div_recip_mul_sf. */ 1390 2, /* min_div_recip_mul_df. */ 1391 0, /* max_case_values. */ 1392 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1393 (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ 1394 &generic_prefetch_tune 1395 }; 1396 1397 static const struct tune_params cortexa53_tunings = 1398 { 1399 &cortexa53_extra_costs, 1400 &generic_addrcost_table, 1401 &cortexa53_regmove_cost, 1402 &generic_vector_cost, 1403 &generic_branch_cost, 1404 &generic_approx_modes, 1405 SVE_NOT_IMPLEMENTED, /* sve_width */ 1406 { 4, /* load_int. */ 1407 4, /* store_int. */ 1408 4, /* load_fp. */ 1409 4, /* store_fp. */ 1410 4, /* load_pred. */ 1411 4 /* store_pred. */ 1412 }, /* memmov_cost. */ 1413 2, /* issue_rate */ 1414 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD 1415 | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ 1416 "16", /* function_align. */ 1417 "4", /* jump_align. */ 1418 "8", /* loop_align. */ 1419 2, /* int_reassoc_width. */ 1420 4, /* fp_reassoc_width. */ 1421 1, /* vec_reassoc_width. */ 1422 2, /* min_div_recip_mul_sf. */ 1423 2, /* min_div_recip_mul_df. */ 1424 0, /* max_case_values. */ 1425 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1426 (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ 1427 &generic_prefetch_tune 1428 }; 1429 1430 static const struct tune_params cortexa57_tunings = 1431 { 1432 &cortexa57_extra_costs, 1433 &generic_addrcost_table, 1434 &cortexa57_regmove_cost, 1435 &cortexa57_vector_cost, 1436 &generic_branch_cost, 1437 &generic_approx_modes, 1438 SVE_NOT_IMPLEMENTED, /* sve_width */ 1439 { 4, /* load_int. */ 1440 4, /* store_int. */ 1441 4, /* load_fp. */ 1442 4, /* store_fp. */ 1443 4, /* load_pred. */ 1444 4 /* store_pred. */ 1445 }, /* memmov_cost. */ 1446 3, /* issue_rate */ 1447 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD 1448 | AARCH64_FUSE_MOVK_MOVK), /* fusible_ops */ 1449 "16", /* function_align. */ 1450 "4", /* jump_align. */ 1451 "8", /* loop_align. */ 1452 2, /* int_reassoc_width. */ 1453 4, /* fp_reassoc_width. */ 1454 1, /* vec_reassoc_width. */ 1455 2, /* min_div_recip_mul_sf. */ 1456 2, /* min_div_recip_mul_df. */ 1457 0, /* max_case_values. */ 1458 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1459 (AARCH64_EXTRA_TUNE_RENAME_FMA_REGS), /* tune_flags. */ 1460 &generic_prefetch_tune 1461 }; 1462 1463 static const struct tune_params cortexa72_tunings = 1464 { 1465 &cortexa57_extra_costs, 1466 &generic_addrcost_table, 1467 &cortexa57_regmove_cost, 1468 &cortexa57_vector_cost, 1469 &generic_branch_cost, 1470 &generic_approx_modes, 1471 SVE_NOT_IMPLEMENTED, /* sve_width */ 1472 { 4, /* load_int. */ 1473 4, /* store_int. */ 1474 4, /* load_fp. */ 1475 4, /* store_fp. */ 1476 4, /* load_pred. */ 1477 4 /* store_pred. */ 1478 }, /* memmov_cost. */ 1479 3, /* issue_rate */ 1480 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD 1481 | AARCH64_FUSE_MOVK_MOVK), /* fusible_ops */ 1482 "16", /* function_align. */ 1483 "4", /* jump_align. */ 1484 "8", /* loop_align. */ 1485 2, /* int_reassoc_width. */ 1486 4, /* fp_reassoc_width. */ 1487 1, /* vec_reassoc_width. */ 1488 2, /* min_div_recip_mul_sf. */ 1489 2, /* min_div_recip_mul_df. */ 1490 0, /* max_case_values. */ 1491 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1492 (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ 1493 &generic_prefetch_tune 1494 }; 1495 1496 static const struct tune_params cortexa73_tunings = 1497 { 1498 &cortexa57_extra_costs, 1499 &generic_addrcost_table, 1500 &cortexa57_regmove_cost, 1501 &cortexa57_vector_cost, 1502 &generic_branch_cost, 1503 &generic_approx_modes, 1504 SVE_NOT_IMPLEMENTED, /* sve_width */ 1505 { 4, /* load_int. */ 1506 4, /* store_int. */ 1507 4, /* load_fp. */ 1508 4, /* store_fp. */ 1509 4, /* load_pred. */ 1510 4 /* store_pred. */ 1511 }, /* memmov_cost. */ 1512 2, /* issue_rate. */ 1513 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD 1514 | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR), /* fusible_ops */ 1515 "16", /* function_align. */ 1516 "4", /* jump_align. */ 1517 "8", /* loop_align. */ 1518 2, /* int_reassoc_width. */ 1519 4, /* fp_reassoc_width. */ 1520 1, /* vec_reassoc_width. */ 1521 2, /* min_div_recip_mul_sf. */ 1522 2, /* min_div_recip_mul_df. */ 1523 0, /* max_case_values. */ 1524 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1525 (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ 1526 &generic_prefetch_tune 1527 }; 1528 1529 1530 1531 static const struct tune_params exynosm1_tunings = 1532 { 1533 &exynosm1_extra_costs, 1534 &exynosm1_addrcost_table, 1535 &exynosm1_regmove_cost, 1536 &exynosm1_vector_cost, 1537 &generic_branch_cost, 1538 &exynosm1_approx_modes, 1539 SVE_NOT_IMPLEMENTED, /* sve_width */ 1540 { 4, /* load_int. */ 1541 4, /* store_int. */ 1542 4, /* load_fp. */ 1543 4, /* store_fp. */ 1544 4, /* load_pred. */ 1545 4 /* store_pred. */ 1546 }, /* memmov_cost. */ 1547 3, /* issue_rate */ 1548 (AARCH64_FUSE_AES_AESMC), /* fusible_ops */ 1549 "4", /* function_align. */ 1550 "4", /* jump_align. */ 1551 "4", /* loop_align. */ 1552 2, /* int_reassoc_width. */ 1553 4, /* fp_reassoc_width. */ 1554 1, /* vec_reassoc_width. */ 1555 2, /* min_div_recip_mul_sf. */ 1556 2, /* min_div_recip_mul_df. */ 1557 48, /* max_case_values. */ 1558 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1559 (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ 1560 &exynosm1_prefetch_tune 1561 }; 1562 1563 static const struct tune_params thunderxt88_tunings = 1564 { 1565 &thunderx_extra_costs, 1566 &generic_addrcost_table, 1567 &thunderx_regmove_cost, 1568 &thunderx_vector_cost, 1569 &generic_branch_cost, 1570 &generic_approx_modes, 1571 SVE_NOT_IMPLEMENTED, /* sve_width */ 1572 { 6, /* load_int. */ 1573 6, /* store_int. */ 1574 6, /* load_fp. */ 1575 6, /* store_fp. */ 1576 6, /* load_pred. */ 1577 6 /* store_pred. */ 1578 }, /* memmov_cost. */ 1579 2, /* issue_rate */ 1580 AARCH64_FUSE_ALU_BRANCH, /* fusible_ops */ 1581 "8", /* function_align. */ 1582 "8", /* jump_align. */ 1583 "8", /* loop_align. */ 1584 2, /* int_reassoc_width. */ 1585 4, /* fp_reassoc_width. */ 1586 1, /* vec_reassoc_width. */ 1587 2, /* min_div_recip_mul_sf. */ 1588 2, /* min_div_recip_mul_df. */ 1589 0, /* max_case_values. */ 1590 tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ 1591 (AARCH64_EXTRA_TUNE_SLOW_UNALIGNED_LDPW), /* tune_flags. */ 1592 &thunderxt88_prefetch_tune 1593 }; 1594 1595 static const struct tune_params thunderx_tunings = 1596 { 1597 &thunderx_extra_costs, 1598 &generic_addrcost_table, 1599 &thunderx_regmove_cost, 1600 &thunderx_vector_cost, 1601 &generic_branch_cost, 1602 &generic_approx_modes, 1603 SVE_NOT_IMPLEMENTED, /* sve_width */ 1604 { 6, /* load_int. */ 1605 6, /* store_int. */ 1606 6, /* load_fp. */ 1607 6, /* store_fp. */ 1608 6, /* load_pred. */ 1609 6 /* store_pred. */ 1610 }, /* memmov_cost. */ 1611 2, /* issue_rate */ 1612 AARCH64_FUSE_ALU_BRANCH, /* fusible_ops */ 1613 "8", /* function_align. */ 1614 "8", /* jump_align. */ 1615 "8", /* loop_align. */ 1616 2, /* int_reassoc_width. */ 1617 4, /* fp_reassoc_width. */ 1618 1, /* vec_reassoc_width. */ 1619 2, /* min_div_recip_mul_sf. */ 1620 2, /* min_div_recip_mul_df. */ 1621 0, /* max_case_values. */ 1622 tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ 1623 (AARCH64_EXTRA_TUNE_SLOW_UNALIGNED_LDPW 1624 | AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ 1625 &thunderx_prefetch_tune 1626 }; 1627 1628 static const struct tune_params tsv110_tunings = 1629 { 1630 &tsv110_extra_costs, 1631 &tsv110_addrcost_table, 1632 &tsv110_regmove_cost, 1633 &tsv110_vector_cost, 1634 &generic_branch_cost, 1635 &generic_approx_modes, 1636 SVE_NOT_IMPLEMENTED, /* sve_width */ 1637 { 4, /* load_int. */ 1638 4, /* store_int. */ 1639 4, /* load_fp. */ 1640 4, /* store_fp. */ 1641 4, /* load_pred. */ 1642 4 /* store_pred. */ 1643 }, /* memmov_cost. */ 1644 4, /* issue_rate */ 1645 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_ALU_BRANCH 1646 | AARCH64_FUSE_ALU_CBZ), /* fusible_ops */ 1647 "16", /* function_align. */ 1648 "4", /* jump_align. */ 1649 "8", /* loop_align. */ 1650 2, /* int_reassoc_width. */ 1651 4, /* fp_reassoc_width. */ 1652 1, /* vec_reassoc_width. */ 1653 2, /* min_div_recip_mul_sf. */ 1654 2, /* min_div_recip_mul_df. */ 1655 0, /* max_case_values. */ 1656 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1657 (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ 1658 &tsv110_prefetch_tune 1659 }; 1660 1661 static const struct tune_params xgene1_tunings = 1662 { 1663 &xgene1_extra_costs, 1664 &xgene1_addrcost_table, 1665 &xgene1_regmove_cost, 1666 &xgene1_vector_cost, 1667 &generic_branch_cost, 1668 &xgene1_approx_modes, 1669 SVE_NOT_IMPLEMENTED, /* sve_width */ 1670 { 6, /* load_int. */ 1671 6, /* store_int. */ 1672 6, /* load_fp. */ 1673 6, /* store_fp. */ 1674 6, /* load_pred. */ 1675 6 /* store_pred. */ 1676 }, /* memmov_cost. */ 1677 4, /* issue_rate */ 1678 AARCH64_FUSE_NOTHING, /* fusible_ops */ 1679 "16", /* function_align. */ 1680 "16", /* jump_align. */ 1681 "16", /* loop_align. */ 1682 2, /* int_reassoc_width. */ 1683 4, /* fp_reassoc_width. */ 1684 1, /* vec_reassoc_width. */ 1685 2, /* min_div_recip_mul_sf. */ 1686 2, /* min_div_recip_mul_df. */ 1687 17, /* max_case_values. */ 1688 tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ 1689 (AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS), /* tune_flags. */ 1690 &xgene1_prefetch_tune 1691 }; 1692 1693 static const struct tune_params emag_tunings = 1694 { 1695 &xgene1_extra_costs, 1696 &xgene1_addrcost_table, 1697 &xgene1_regmove_cost, 1698 &xgene1_vector_cost, 1699 &generic_branch_cost, 1700 &xgene1_approx_modes, 1701 SVE_NOT_IMPLEMENTED, 1702 { 6, /* load_int. */ 1703 6, /* store_int. */ 1704 6, /* load_fp. */ 1705 6, /* store_fp. */ 1706 6, /* load_pred. */ 1707 6 /* store_pred. */ 1708 }, /* memmov_cost. */ 1709 4, /* issue_rate */ 1710 AARCH64_FUSE_NOTHING, /* fusible_ops */ 1711 "16", /* function_align. */ 1712 "16", /* jump_align. */ 1713 "16", /* loop_align. */ 1714 2, /* int_reassoc_width. */ 1715 4, /* fp_reassoc_width. */ 1716 1, /* vec_reassoc_width. */ 1717 2, /* min_div_recip_mul_sf. */ 1718 2, /* min_div_recip_mul_df. */ 1719 17, /* max_case_values. */ 1720 tune_params::AUTOPREFETCHER_OFF, /* autoprefetcher_model. */ 1721 (AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS), /* tune_flags. */ 1722 &xgene1_prefetch_tune 1723 }; 1724 1725 static const struct tune_params qdf24xx_tunings = 1726 { 1727 &qdf24xx_extra_costs, 1728 &qdf24xx_addrcost_table, 1729 &qdf24xx_regmove_cost, 1730 &qdf24xx_vector_cost, 1731 &generic_branch_cost, 1732 &generic_approx_modes, 1733 SVE_NOT_IMPLEMENTED, /* sve_width */ 1734 { 4, /* load_int. */ 1735 4, /* store_int. */ 1736 4, /* load_fp. */ 1737 4, /* store_fp. */ 1738 4, /* load_pred. */ 1739 4 /* store_pred. */ 1740 }, /* memmov_cost. */ 1741 4, /* issue_rate */ 1742 (AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD 1743 | AARCH64_FUSE_MOVK_MOVK), /* fuseable_ops */ 1744 "16", /* function_align. */ 1745 "8", /* jump_align. */ 1746 "16", /* loop_align. */ 1747 2, /* int_reassoc_width. */ 1748 4, /* fp_reassoc_width. */ 1749 1, /* vec_reassoc_width. */ 1750 2, /* min_div_recip_mul_sf. */ 1751 2, /* min_div_recip_mul_df. */ 1752 0, /* max_case_values. */ 1753 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1754 AARCH64_EXTRA_TUNE_RENAME_LOAD_REGS, /* tune_flags. */ 1755 &qdf24xx_prefetch_tune 1756 }; 1757 1758 /* Tuning structure for the Qualcomm Saphira core. Default to falkor values 1759 for now. */ 1760 static const struct tune_params saphira_tunings = 1761 { 1762 &generic_extra_costs, 1763 &generic_addrcost_table, 1764 &generic_regmove_cost, 1765 &generic_vector_cost, 1766 &generic_branch_cost, 1767 &generic_approx_modes, 1768 SVE_NOT_IMPLEMENTED, /* sve_width */ 1769 { 4, /* load_int. */ 1770 4, /* store_int. */ 1771 4, /* load_fp. */ 1772 4, /* store_fp. */ 1773 4, /* load_pred. */ 1774 4 /* store_pred. */ 1775 }, /* memmov_cost. */ 1776 4, /* issue_rate */ 1777 (AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD 1778 | AARCH64_FUSE_MOVK_MOVK), /* fuseable_ops */ 1779 "16", /* function_align. */ 1780 "8", /* jump_align. */ 1781 "16", /* loop_align. */ 1782 2, /* int_reassoc_width. */ 1783 4, /* fp_reassoc_width. */ 1784 1, /* vec_reassoc_width. */ 1785 2, /* min_div_recip_mul_sf. */ 1786 2, /* min_div_recip_mul_df. */ 1787 0, /* max_case_values. */ 1788 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1789 (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ 1790 &generic_prefetch_tune 1791 }; 1792 1793 static const struct tune_params thunderx2t99_tunings = 1794 { 1795 &thunderx2t99_extra_costs, 1796 &thunderx2t99_addrcost_table, 1797 &thunderx2t99_regmove_cost, 1798 &thunderx2t99_vector_cost, 1799 &generic_branch_cost, 1800 &generic_approx_modes, 1801 SVE_NOT_IMPLEMENTED, /* sve_width */ 1802 { 4, /* load_int. */ 1803 4, /* store_int. */ 1804 4, /* load_fp. */ 1805 4, /* store_fp. */ 1806 4, /* load_pred. */ 1807 4 /* store_pred. */ 1808 }, /* memmov_cost. */ 1809 4, /* issue_rate. */ 1810 (AARCH64_FUSE_ALU_BRANCH | AARCH64_FUSE_AES_AESMC 1811 | AARCH64_FUSE_ALU_CBZ), /* fusible_ops */ 1812 "16", /* function_align. */ 1813 "8", /* jump_align. */ 1814 "16", /* loop_align. */ 1815 3, /* int_reassoc_width. */ 1816 2, /* fp_reassoc_width. */ 1817 2, /* vec_reassoc_width. */ 1818 2, /* min_div_recip_mul_sf. */ 1819 2, /* min_div_recip_mul_df. */ 1820 0, /* max_case_values. */ 1821 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1822 (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ 1823 &thunderx2t99_prefetch_tune 1824 }; 1825 1826 static const struct tune_params thunderx3t110_tunings = 1827 { 1828 &thunderx3t110_extra_costs, 1829 &thunderx3t110_addrcost_table, 1830 &thunderx3t110_regmove_cost, 1831 &thunderx3t110_vector_cost, 1832 &generic_branch_cost, 1833 &generic_approx_modes, 1834 SVE_NOT_IMPLEMENTED, /* sve_width */ 1835 { 4, /* load_int. */ 1836 4, /* store_int. */ 1837 4, /* load_fp. */ 1838 4, /* store_fp. */ 1839 4, /* load_pred. */ 1840 4 /* store_pred. */ 1841 }, /* memmov_cost. */ 1842 6, /* issue_rate. */ 1843 (AARCH64_FUSE_ALU_BRANCH | AARCH64_FUSE_AES_AESMC 1844 | AARCH64_FUSE_ALU_CBZ), /* fusible_ops */ 1845 "16", /* function_align. */ 1846 "8", /* jump_align. */ 1847 "16", /* loop_align. */ 1848 3, /* int_reassoc_width. */ 1849 2, /* fp_reassoc_width. */ 1850 2, /* vec_reassoc_width. */ 1851 2, /* min_div_recip_mul_sf. */ 1852 2, /* min_div_recip_mul_df. */ 1853 0, /* max_case_values. */ 1854 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1855 (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ 1856 &thunderx3t110_prefetch_tune 1857 }; 1858 1859 static const struct tune_params neoversen1_tunings = 1860 { 1861 &cortexa76_extra_costs, 1862 &generic_addrcost_table, 1863 &generic_regmove_cost, 1864 &cortexa57_vector_cost, 1865 &generic_branch_cost, 1866 &generic_approx_modes, 1867 SVE_NOT_IMPLEMENTED, /* sve_width */ 1868 { 4, /* load_int. */ 1869 2, /* store_int. */ 1870 5, /* load_fp. */ 1871 2, /* store_fp. */ 1872 4, /* load_pred. */ 1873 4 /* store_pred. */ 1874 }, /* memmov_cost. */ 1875 3, /* issue_rate */ 1876 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ 1877 "32:16", /* function_align. */ 1878 "4", /* jump_align. */ 1879 "32:16", /* loop_align. */ 1880 2, /* int_reassoc_width. */ 1881 4, /* fp_reassoc_width. */ 1882 2, /* vec_reassoc_width. */ 1883 2, /* min_div_recip_mul_sf. */ 1884 2, /* min_div_recip_mul_df. */ 1885 0, /* max_case_values. */ 1886 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1887 (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ 1888 &generic_prefetch_tune 1889 }; 1890 1891 static const struct tune_params ampere1_tunings = 1892 { 1893 &ere1_extra_costs, 1894 &generic_addrcost_table, 1895 &generic_regmove_cost, 1896 &ere1_vector_cost, 1897 &generic_branch_cost, 1898 &generic_approx_modes, 1899 SVE_NOT_IMPLEMENTED, /* sve_width */ 1900 { 4, /* load_int. */ 1901 4, /* store_int. */ 1902 4, /* load_fp. */ 1903 4, /* store_fp. */ 1904 4, /* load_pred. */ 1905 4 /* store_pred. */ 1906 }, /* memmov_cost. */ 1907 4, /* issue_rate */ 1908 (AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_AES_AESMC | 1909 AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_MOVK_MOVK | 1910 AARCH64_FUSE_ALU_BRANCH /* adds, ands, bics, ccmp, ccmn */ | 1911 AARCH64_FUSE_CMP_BRANCH), 1912 /* fusible_ops */ 1913 "32", /* function_align. */ 1914 "4", /* jump_align. */ 1915 "32:16", /* loop_align. */ 1916 2, /* int_reassoc_width. */ 1917 4, /* fp_reassoc_width. */ 1918 2, /* vec_reassoc_width. */ 1919 2, /* min_div_recip_mul_sf. */ 1920 2, /* min_div_recip_mul_df. */ 1921 0, /* max_case_values. */ 1922 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1923 (AARCH64_EXTRA_TUNE_NO_LDP_COMBINE), /* tune_flags. */ 1924 &ere1_prefetch_tune 1925 }; 1926 1927 static const struct tune_params ampere1a_tunings = 1928 { 1929 &ere1a_extra_costs, 1930 &generic_addrcost_table, 1931 &generic_regmove_cost, 1932 &ere1_vector_cost, 1933 &generic_branch_cost, 1934 &generic_approx_modes, 1935 SVE_NOT_IMPLEMENTED, /* sve_width */ 1936 { 4, /* load_int. */ 1937 4, /* store_int. */ 1938 4, /* load_fp. */ 1939 4, /* store_fp. */ 1940 4, /* load_pred. */ 1941 4 /* store_pred. */ 1942 }, /* memmov_cost. */ 1943 4, /* issue_rate */ 1944 (AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_AES_AESMC | 1945 AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_MOVK_MOVK | 1946 AARCH64_FUSE_ALU_BRANCH /* adds, ands, bics, ccmp, ccmn */ | 1947 AARCH64_FUSE_CMP_BRANCH | AARCH64_FUSE_ALU_CBZ | 1948 AARCH64_FUSE_ADDSUB_2REG_CONST1), 1949 /* fusible_ops */ 1950 "32", /* function_align. */ 1951 "4", /* jump_align. */ 1952 "32:16", /* loop_align. */ 1953 2, /* int_reassoc_width. */ 1954 4, /* fp_reassoc_width. */ 1955 2, /* vec_reassoc_width. */ 1956 2, /* min_div_recip_mul_sf. */ 1957 2, /* min_div_recip_mul_df. */ 1958 0, /* max_case_values. */ 1959 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 1960 (AARCH64_EXTRA_TUNE_NO_LDP_COMBINE), /* tune_flags. */ 1961 &ere1_prefetch_tune 1962 }; 1963 1964 static const advsimd_vec_cost neoversev1_advsimd_vector_cost = 1965 { 1966 2, /* int_stmt_cost */ 1967 2, /* fp_stmt_cost */ 1968 4, /* ld2_st2_permute_cost */ 1969 4, /* ld3_st3_permute_cost */ 1970 5, /* ld4_st4_permute_cost */ 1971 3, /* permute_cost */ 1972 4, /* reduc_i8_cost */ 1973 4, /* reduc_i16_cost */ 1974 2, /* reduc_i32_cost */ 1975 2, /* reduc_i64_cost */ 1976 6, /* reduc_f16_cost */ 1977 3, /* reduc_f32_cost */ 1978 2, /* reduc_f64_cost */ 1979 2, /* store_elt_extra_cost */ 1980 /* This value is just inherited from the Cortex-A57 table. */ 1981 8, /* vec_to_scalar_cost */ 1982 /* This depends very much on what the scalar value is and 1983 where it comes from. E.g. some constants take two dependent 1984 instructions or a load, while others might be moved from a GPR. 1985 4 seems to be a reasonable compromise in practice. */ 1986 4, /* scalar_to_vec_cost */ 1987 4, /* align_load_cost */ 1988 4, /* unalign_load_cost */ 1989 /* Although stores have a latency of 2 and compete for the 1990 vector pipes, in practice it's better not to model that. */ 1991 1, /* unalign_store_cost */ 1992 1 /* store_cost */ 1993 }; 1994 1995 static const sve_vec_cost neoversev1_sve_vector_cost = 1996 { 1997 { 1998 2, /* int_stmt_cost */ 1999 2, /* fp_stmt_cost */ 2000 4, /* ld2_st2_permute_cost */ 2001 7, /* ld3_st3_permute_cost */ 2002 8, /* ld4_st4_permute_cost */ 2003 3, /* permute_cost */ 2004 /* Theoretically, a reduction involving 31 scalar ADDs could 2005 complete in ~9 cycles and would have a cost of 31. [SU]ADDV 2006 completes in 14 cycles, so give it a cost of 31 + 5. */ 2007 36, /* reduc_i8_cost */ 2008 /* Likewise for 15 scalar ADDs (~5 cycles) vs. 12: 15 + 7. */ 2009 22, /* reduc_i16_cost */ 2010 /* Likewise for 7 scalar ADDs (~3 cycles) vs. 10: 7 + 7. */ 2011 14, /* reduc_i32_cost */ 2012 /* Likewise for 3 scalar ADDs (~2 cycles) vs. 10: 3 + 8. */ 2013 11, /* reduc_i64_cost */ 2014 /* Theoretically, a reduction involving 15 scalar FADDs could 2015 complete in ~9 cycles and would have a cost of 30. FADDV 2016 completes in 13 cycles, so give it a cost of 30 + 4. */ 2017 34, /* reduc_f16_cost */ 2018 /* Likewise for 7 scalar FADDs (~6 cycles) vs. 11: 14 + 5. */ 2019 19, /* reduc_f32_cost */ 2020 /* Likewise for 3 scalar FADDs (~4 cycles) vs. 9: 6 + 5. */ 2021 11, /* reduc_f64_cost */ 2022 2, /* store_elt_extra_cost */ 2023 /* This value is just inherited from the Cortex-A57 table. */ 2024 8, /* vec_to_scalar_cost */ 2025 /* See the comment above the Advanced SIMD versions. */ 2026 4, /* scalar_to_vec_cost */ 2027 4, /* align_load_cost */ 2028 4, /* unalign_load_cost */ 2029 /* Although stores have a latency of 2 and compete for the 2030 vector pipes, in practice it's better not to model that. */ 2031 1, /* unalign_store_cost */ 2032 1 /* store_cost */ 2033 }, 2034 3, /* clast_cost */ 2035 19, /* fadda_f16_cost */ 2036 11, /* fadda_f32_cost */ 2037 8, /* fadda_f64_cost */ 2038 32, /* gather_load_x32_cost */ 2039 16, /* gather_load_x64_cost */ 2040 3 /* scatter_store_elt_cost */ 2041 }; 2042 2043 static const aarch64_scalar_vec_issue_info neoversev1_scalar_issue_info = 2044 { 2045 3, /* loads_stores_per_cycle */ 2046 2, /* stores_per_cycle */ 2047 4, /* general_ops_per_cycle */ 2048 0, /* fp_simd_load_general_ops */ 2049 1 /* fp_simd_store_general_ops */ 2050 }; 2051 2052 static const aarch64_advsimd_vec_issue_info neoversev1_advsimd_issue_info = 2053 { 2054 { 2055 3, /* loads_stores_per_cycle */ 2056 2, /* stores_per_cycle */ 2057 4, /* general_ops_per_cycle */ 2058 0, /* fp_simd_load_general_ops */ 2059 1 /* fp_simd_store_general_ops */ 2060 }, 2061 2, /* ld2_st2_general_ops */ 2062 2, /* ld3_st3_general_ops */ 2063 3 /* ld4_st4_general_ops */ 2064 }; 2065 2066 static const aarch64_sve_vec_issue_info neoversev1_sve_issue_info = 2067 { 2068 { 2069 { 2070 2, /* loads_per_cycle */ 2071 2, /* stores_per_cycle */ 2072 2, /* general_ops_per_cycle */ 2073 0, /* fp_simd_load_general_ops */ 2074 1 /* fp_simd_store_general_ops */ 2075 }, 2076 2, /* ld2_st2_general_ops */ 2077 2, /* ld3_st3_general_ops */ 2078 3 /* ld4_st4_general_ops */ 2079 }, 2080 1, /* pred_ops_per_cycle */ 2081 2, /* while_pred_ops */ 2082 2, /* int_cmp_pred_ops */ 2083 1, /* fp_cmp_pred_ops */ 2084 1, /* gather_scatter_pair_general_ops */ 2085 1 /* gather_scatter_pair_pred_ops */ 2086 }; 2087 2088 static const aarch64_vec_issue_info neoversev1_vec_issue_info = 2089 { 2090 &neoversev1_scalar_issue_info, 2091 &neoversev1_advsimd_issue_info, 2092 &neoversev1_sve_issue_info 2093 }; 2094 2095 /* Neoverse V1 costs for vector insn classes. */ 2096 static const struct cpu_vector_cost neoversev1_vector_cost = 2097 { 2098 1, /* scalar_int_stmt_cost */ 2099 2, /* scalar_fp_stmt_cost */ 2100 4, /* scalar_load_cost */ 2101 1, /* scalar_store_cost */ 2102 1, /* cond_taken_branch_cost */ 2103 1, /* cond_not_taken_branch_cost */ 2104 &neoversev1_advsimd_vector_cost, /* advsimd */ 2105 &neoversev1_sve_vector_cost, /* sve */ 2106 &neoversev1_vec_issue_info /* issue_info */ 2107 }; 2108 2109 static const struct tune_params neoversev1_tunings = 2110 { 2111 &cortexa76_extra_costs, 2112 &neoversev1_addrcost_table, 2113 &neoversev1_regmove_cost, 2114 &neoversev1_vector_cost, 2115 &generic_branch_cost, 2116 &generic_approx_modes, 2117 SVE_256, /* sve_width */ 2118 { 4, /* load_int. */ 2119 2, /* store_int. */ 2120 6, /* load_fp. */ 2121 2, /* store_fp. */ 2122 6, /* load_pred. */ 2123 1 /* store_pred. */ 2124 }, /* memmov_cost. */ 2125 3, /* issue_rate */ 2126 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ 2127 "32:16", /* function_align. */ 2128 "4", /* jump_align. */ 2129 "32:16", /* loop_align. */ 2130 2, /* int_reassoc_width. */ 2131 4, /* fp_reassoc_width. */ 2132 2, /* vec_reassoc_width. */ 2133 2, /* min_div_recip_mul_sf. */ 2134 2, /* min_div_recip_mul_df. */ 2135 0, /* max_case_values. */ 2136 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 2137 (AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS 2138 | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS 2139 | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT 2140 | AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND), /* tune_flags. */ 2141 &generic_prefetch_tune 2142 }; 2143 2144 static const sve_vec_cost neoverse512tvb_sve_vector_cost = 2145 { 2146 { 2147 2, /* int_stmt_cost */ 2148 2, /* fp_stmt_cost */ 2149 4, /* ld2_st2_permute_cost */ 2150 5, /* ld3_st3_permute_cost */ 2151 5, /* ld4_st4_permute_cost */ 2152 3, /* permute_cost */ 2153 /* Theoretically, a reduction involving 15 scalar ADDs could 2154 complete in ~5 cycles and would have a cost of 15. Assume that 2155 [SU]ADDV completes in 11 cycles and so give it a cost of 15 + 6. */ 2156 21, /* reduc_i8_cost */ 2157 /* Likewise for 7 scalar ADDs (~3 cycles) vs. 9: 7 + 6. */ 2158 13, /* reduc_i16_cost */ 2159 /* Likewise for 3 scalar ADDs (~2 cycles) vs. 8: 3 + 6. */ 2160 9, /* reduc_i32_cost */ 2161 /* Likewise for 1 scalar ADD (1 cycle) vs. 8: 1 + 7. */ 2162 8, /* reduc_i64_cost */ 2163 /* Theoretically, a reduction involving 7 scalar FADDs could 2164 complete in ~6 cycles and would have a cost of 14. Assume that 2165 FADDV completes in 8 cycles and so give it a cost of 14 + 2. */ 2166 16, /* reduc_f16_cost */ 2167 /* Likewise for 3 scalar FADDs (~4 cycles) vs. 6: 6 + 2. */ 2168 8, /* reduc_f32_cost */ 2169 /* Likewise for 1 scalar FADD (2 cycles) vs. 4: 2 + 2. */ 2170 4, /* reduc_f64_cost */ 2171 2, /* store_elt_extra_cost */ 2172 /* This value is just inherited from the Cortex-A57 table. */ 2173 8, /* vec_to_scalar_cost */ 2174 /* This depends very much on what the scalar value is and 2175 where it comes from. E.g. some constants take two dependent 2176 instructions or a load, while others might be moved from a GPR. 2177 4 seems to be a reasonable compromise in practice. */ 2178 4, /* scalar_to_vec_cost */ 2179 4, /* align_load_cost */ 2180 4, /* unalign_load_cost */ 2181 /* Although stores generally have a latency of 2 and compete for the 2182 vector pipes, in practice it's better not to model that. */ 2183 1, /* unalign_store_cost */ 2184 1 /* store_cost */ 2185 }, 2186 3, /* clast_cost */ 2187 10, /* fadda_f16_cost */ 2188 6, /* fadda_f32_cost */ 2189 4, /* fadda_f64_cost */ 2190 /* A strided Advanced SIMD x64 load would take two parallel FP loads 2191 (6 cycles) plus an insertion (2 cycles). Assume a 64-bit SVE gather 2192 is 1 cycle more. The Advanced SIMD version is costed as 2 scalar loads 2193 (cost 8) and a vec_construct (cost 2). Add a full vector operation 2194 (cost 2) to that, to avoid the difference being lost in rounding. 2195 2196 There is no easy comparison between a strided Advanced SIMD x32 load 2197 and an SVE 32-bit gather, but cost an SVE 32-bit gather as 1 vector 2198 operation more than a 64-bit gather. */ 2199 14, /* gather_load_x32_cost */ 2200 12, /* gather_load_x64_cost */ 2201 3 /* scatter_store_elt_cost */ 2202 }; 2203 2204 static const aarch64_sve_vec_issue_info neoverse512tvb_sve_issue_info = 2205 { 2206 { 2207 { 2208 3, /* loads_per_cycle */ 2209 2, /* stores_per_cycle */ 2210 4, /* general_ops_per_cycle */ 2211 0, /* fp_simd_load_general_ops */ 2212 1 /* fp_simd_store_general_ops */ 2213 }, 2214 2, /* ld2_st2_general_ops */ 2215 2, /* ld3_st3_general_ops */ 2216 3 /* ld4_st4_general_ops */ 2217 }, 2218 2, /* pred_ops_per_cycle */ 2219 2, /* while_pred_ops */ 2220 2, /* int_cmp_pred_ops */ 2221 1, /* fp_cmp_pred_ops */ 2222 1, /* gather_scatter_pair_general_ops */ 2223 1 /* gather_scatter_pair_pred_ops */ 2224 }; 2225 2226 static const aarch64_vec_issue_info neoverse512tvb_vec_issue_info = 2227 { 2228 &neoversev1_scalar_issue_info, 2229 &neoversev1_advsimd_issue_info, 2230 &neoverse512tvb_sve_issue_info 2231 }; 2232 2233 static const struct cpu_vector_cost neoverse512tvb_vector_cost = 2234 { 2235 1, /* scalar_int_stmt_cost */ 2236 2, /* scalar_fp_stmt_cost */ 2237 4, /* scalar_load_cost */ 2238 1, /* scalar_store_cost */ 2239 1, /* cond_taken_branch_cost */ 2240 1, /* cond_not_taken_branch_cost */ 2241 &neoversev1_advsimd_vector_cost, /* advsimd */ 2242 &neoverse512tvb_sve_vector_cost, /* sve */ 2243 &neoverse512tvb_vec_issue_info /* issue_info */ 2244 }; 2245 2246 static const struct tune_params neoverse512tvb_tunings = 2247 { 2248 &cortexa76_extra_costs, 2249 &neoversev1_addrcost_table, 2250 &neoversev1_regmove_cost, 2251 &neoverse512tvb_vector_cost, 2252 &generic_branch_cost, 2253 &generic_approx_modes, 2254 SVE_128 | SVE_256, /* sve_width */ 2255 { 4, /* load_int. */ 2256 2, /* store_int. */ 2257 6, /* load_fp. */ 2258 2, /* store_fp. */ 2259 6, /* load_pred. */ 2260 1 /* store_pred. */ 2261 }, /* memmov_cost. */ 2262 3, /* issue_rate */ 2263 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ 2264 "32:16", /* function_align. */ 2265 "4", /* jump_align. */ 2266 "32:16", /* loop_align. */ 2267 2, /* int_reassoc_width. */ 2268 4, /* fp_reassoc_width. */ 2269 2, /* vec_reassoc_width. */ 2270 2, /* min_div_recip_mul_sf. */ 2271 2, /* min_div_recip_mul_df. */ 2272 0, /* max_case_values. */ 2273 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 2274 (AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS 2275 | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS 2276 | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ 2277 &generic_prefetch_tune 2278 }; 2279 2280 static const advsimd_vec_cost neoversen2_advsimd_vector_cost = 2281 { 2282 2, /* int_stmt_cost */ 2283 2, /* fp_stmt_cost */ 2284 2, /* ld2_st2_permute_cost */ 2285 2, /* ld3_st3_permute_cost */ 2286 3, /* ld4_st4_permute_cost */ 2287 3, /* permute_cost */ 2288 4, /* reduc_i8_cost */ 2289 4, /* reduc_i16_cost */ 2290 2, /* reduc_i32_cost */ 2291 2, /* reduc_i64_cost */ 2292 6, /* reduc_f16_cost */ 2293 4, /* reduc_f32_cost */ 2294 2, /* reduc_f64_cost */ 2295 2, /* store_elt_extra_cost */ 2296 /* This value is just inherited from the Cortex-A57 table. */ 2297 8, /* vec_to_scalar_cost */ 2298 /* This depends very much on what the scalar value is and 2299 where it comes from. E.g. some constants take two dependent 2300 instructions or a load, while others might be moved from a GPR. 2301 4 seems to be a reasonable compromise in practice. */ 2302 4, /* scalar_to_vec_cost */ 2303 4, /* align_load_cost */ 2304 4, /* unalign_load_cost */ 2305 /* Although stores have a latency of 2 and compete for the 2306 vector pipes, in practice it's better not to model that. */ 2307 1, /* unalign_store_cost */ 2308 1 /* store_cost */ 2309 }; 2310 2311 static const sve_vec_cost neoversen2_sve_vector_cost = 2312 { 2313 { 2314 2, /* int_stmt_cost */ 2315 2, /* fp_stmt_cost */ 2316 3, /* ld2_st2_permute_cost */ 2317 4, /* ld3_st3_permute_cost */ 2318 4, /* ld4_st4_permute_cost */ 2319 3, /* permute_cost */ 2320 /* Theoretically, a reduction involving 15 scalar ADDs could 2321 complete in ~5 cycles and would have a cost of 15. [SU]ADDV 2322 completes in 11 cycles, so give it a cost of 15 + 6. */ 2323 21, /* reduc_i8_cost */ 2324 /* Likewise for 7 scalar ADDs (~3 cycles) vs. 9: 7 + 6. */ 2325 13, /* reduc_i16_cost */ 2326 /* Likewise for 3 scalar ADDs (~2 cycles) vs. 8: 3 + 6. */ 2327 9, /* reduc_i32_cost */ 2328 /* Likewise for 1 scalar ADD (~1 cycles) vs. 2: 1 + 1. */ 2329 2, /* reduc_i64_cost */ 2330 /* Theoretically, a reduction involving 7 scalar FADDs could 2331 complete in ~8 cycles and would have a cost of 14. FADDV 2332 completes in 6 cycles, so give it a cost of 14 - 2. */ 2333 12, /* reduc_f16_cost */ 2334 /* Likewise for 3 scalar FADDs (~4 cycles) vs. 4: 6 - 0. */ 2335 6, /* reduc_f32_cost */ 2336 /* Likewise for 1 scalar FADD (~2 cycles) vs. 2: 2 - 0. */ 2337 2, /* reduc_f64_cost */ 2338 2, /* store_elt_extra_cost */ 2339 /* This value is just inherited from the Cortex-A57 table. */ 2340 8, /* vec_to_scalar_cost */ 2341 /* See the comment above the Advanced SIMD versions. */ 2342 4, /* scalar_to_vec_cost */ 2343 4, /* align_load_cost */ 2344 4, /* unalign_load_cost */ 2345 /* Although stores have a latency of 2 and compete for the 2346 vector pipes, in practice it's better not to model that. */ 2347 1, /* unalign_store_cost */ 2348 1 /* store_cost */ 2349 }, 2350 3, /* clast_cost */ 2351 10, /* fadda_f16_cost */ 2352 6, /* fadda_f32_cost */ 2353 4, /* fadda_f64_cost */ 2354 /* A strided Advanced SIMD x64 load would take two parallel FP loads 2355 (8 cycles) plus an insertion (2 cycles). Assume a 64-bit SVE gather 2356 is 1 cycle more. The Advanced SIMD version is costed as 2 scalar loads 2357 (cost 8) and a vec_construct (cost 2). Add a full vector operation 2358 (cost 2) to that, to avoid the difference being lost in rounding. 2359 2360 There is no easy comparison between a strided Advanced SIMD x32 load 2361 and an SVE 32-bit gather, but cost an SVE 32-bit gather as 1 vector 2362 operation more than a 64-bit gather. */ 2363 14, /* gather_load_x32_cost */ 2364 12, /* gather_load_x64_cost */ 2365 3 /* scatter_store_elt_cost */ 2366 }; 2367 2368 static const aarch64_scalar_vec_issue_info neoversen2_scalar_issue_info = 2369 { 2370 3, /* loads_stores_per_cycle */ 2371 2, /* stores_per_cycle */ 2372 4, /* general_ops_per_cycle */ 2373 0, /* fp_simd_load_general_ops */ 2374 1 /* fp_simd_store_general_ops */ 2375 }; 2376 2377 static const aarch64_advsimd_vec_issue_info neoversen2_advsimd_issue_info = 2378 { 2379 { 2380 3, /* loads_stores_per_cycle */ 2381 2, /* stores_per_cycle */ 2382 2, /* general_ops_per_cycle */ 2383 0, /* fp_simd_load_general_ops */ 2384 1 /* fp_simd_store_general_ops */ 2385 }, 2386 2, /* ld2_st2_general_ops */ 2387 2, /* ld3_st3_general_ops */ 2388 3 /* ld4_st4_general_ops */ 2389 }; 2390 2391 static const aarch64_sve_vec_issue_info neoversen2_sve_issue_info = 2392 { 2393 { 2394 { 2395 3, /* loads_per_cycle */ 2396 2, /* stores_per_cycle */ 2397 2, /* general_ops_per_cycle */ 2398 0, /* fp_simd_load_general_ops */ 2399 1 /* fp_simd_store_general_ops */ 2400 }, 2401 2, /* ld2_st2_general_ops */ 2402 3, /* ld3_st3_general_ops */ 2403 3 /* ld4_st4_general_ops */ 2404 }, 2405 2, /* pred_ops_per_cycle */ 2406 2, /* while_pred_ops */ 2407 2, /* int_cmp_pred_ops */ 2408 1, /* fp_cmp_pred_ops */ 2409 1, /* gather_scatter_pair_general_ops */ 2410 1 /* gather_scatter_pair_pred_ops */ 2411 }; 2412 2413 static const aarch64_vec_issue_info neoversen2_vec_issue_info = 2414 { 2415 &neoversen2_scalar_issue_info, 2416 &neoversen2_advsimd_issue_info, 2417 &neoversen2_sve_issue_info 2418 }; 2419 2420 /* Neoverse N2 costs for vector insn classes. */ 2421 static const struct cpu_vector_cost neoversen2_vector_cost = 2422 { 2423 1, /* scalar_int_stmt_cost */ 2424 2, /* scalar_fp_stmt_cost */ 2425 4, /* scalar_load_cost */ 2426 1, /* scalar_store_cost */ 2427 1, /* cond_taken_branch_cost */ 2428 1, /* cond_not_taken_branch_cost */ 2429 &neoversen2_advsimd_vector_cost, /* advsimd */ 2430 &neoversen2_sve_vector_cost, /* sve */ 2431 &neoversen2_vec_issue_info /* issue_info */ 2432 }; 2433 2434 static const struct tune_params neoversen2_tunings = 2435 { 2436 &cortexa76_extra_costs, 2437 &neoversen2_addrcost_table, 2438 &neoversen2_regmove_cost, 2439 &neoversen2_vector_cost, 2440 &generic_branch_cost, 2441 &generic_approx_modes, 2442 SVE_128, /* sve_width */ 2443 { 4, /* load_int. */ 2444 1, /* store_int. */ 2445 6, /* load_fp. */ 2446 2, /* store_fp. */ 2447 6, /* load_pred. */ 2448 1 /* store_pred. */ 2449 }, /* memmov_cost. */ 2450 3, /* issue_rate */ 2451 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ 2452 "32:16", /* function_align. */ 2453 "4", /* jump_align. */ 2454 "32:16", /* loop_align. */ 2455 2, /* int_reassoc_width. */ 2456 4, /* fp_reassoc_width. */ 2457 2, /* vec_reassoc_width. */ 2458 2, /* min_div_recip_mul_sf. */ 2459 2, /* min_div_recip_mul_df. */ 2460 0, /* max_case_values. */ 2461 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 2462 (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND 2463 | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS 2464 | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS 2465 | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ 2466 &generic_prefetch_tune 2467 }; 2468 2469 static const advsimd_vec_cost neoversev2_advsimd_vector_cost = 2470 { 2471 2, /* int_stmt_cost */ 2472 2, /* fp_stmt_cost */ 2473 2, /* ld2_st2_permute_cost */ 2474 2, /* ld3_st3_permute_cost */ 2475 3, /* ld4_st4_permute_cost */ 2476 3, /* permute_cost */ 2477 4, /* reduc_i8_cost */ 2478 4, /* reduc_i16_cost */ 2479 2, /* reduc_i32_cost */ 2480 2, /* reduc_i64_cost */ 2481 6, /* reduc_f16_cost */ 2482 3, /* reduc_f32_cost */ 2483 2, /* reduc_f64_cost */ 2484 2, /* store_elt_extra_cost */ 2485 /* This value is just inherited from the Cortex-A57 table. */ 2486 8, /* vec_to_scalar_cost */ 2487 /* This depends very much on what the scalar value is and 2488 where it comes from. E.g. some constants take two dependent 2489 instructions or a load, while others might be moved from a GPR. 2490 4 seems to be a reasonable compromise in practice. */ 2491 4, /* scalar_to_vec_cost */ 2492 4, /* align_load_cost */ 2493 4, /* unalign_load_cost */ 2494 /* Although stores have a latency of 2 and compete for the 2495 vector pipes, in practice it's better not to model that. */ 2496 1, /* unalign_store_cost */ 2497 1 /* store_cost */ 2498 }; 2499 2500 static const sve_vec_cost neoversev2_sve_vector_cost = 2501 { 2502 { 2503 2, /* int_stmt_cost */ 2504 2, /* fp_stmt_cost */ 2505 3, /* ld2_st2_permute_cost */ 2506 3, /* ld3_st3_permute_cost */ 2507 4, /* ld4_st4_permute_cost */ 2508 3, /* permute_cost */ 2509 /* Theoretically, a reduction involving 15 scalar ADDs could 2510 complete in ~3 cycles and would have a cost of 15. [SU]ADDV 2511 completes in 11 cycles, so give it a cost of 15 + 8. */ 2512 21, /* reduc_i8_cost */ 2513 /* Likewise for 7 scalar ADDs (~2 cycles) vs. 9: 7 + 7. */ 2514 14, /* reduc_i16_cost */ 2515 /* Likewise for 3 scalar ADDs (~2 cycles) vs. 8: 3 + 4. */ 2516 7, /* reduc_i32_cost */ 2517 /* Likewise for 1 scalar ADD (~1 cycles) vs. 2: 1 + 1. */ 2518 2, /* reduc_i64_cost */ 2519 /* Theoretically, a reduction involving 7 scalar FADDs could 2520 complete in ~6 cycles and would have a cost of 14. FADDV 2521 completes in 8 cycles, so give it a cost of 14 + 2. */ 2522 16, /* reduc_f16_cost */ 2523 /* Likewise for 3 scalar FADDs (~4 cycles) vs. 6: 6 + 2. */ 2524 8, /* reduc_f32_cost */ 2525 /* Likewise for 1 scalar FADD (~2 cycles) vs. 4: 2 + 2. */ 2526 4, /* reduc_f64_cost */ 2527 2, /* store_elt_extra_cost */ 2528 /* This value is just inherited from the Cortex-A57 table. */ 2529 8, /* vec_to_scalar_cost */ 2530 /* See the comment above the Advanced SIMD versions. */ 2531 4, /* scalar_to_vec_cost */ 2532 4, /* align_load_cost */ 2533 4, /* unalign_load_cost */ 2534 /* Although stores have a latency of 2 and compete for the 2535 vector pipes, in practice it's better not to model that. */ 2536 1, /* unalign_store_cost */ 2537 1 /* store_cost */ 2538 }, 2539 3, /* clast_cost */ 2540 10, /* fadda_f16_cost */ 2541 6, /* fadda_f32_cost */ 2542 4, /* fadda_f64_cost */ 2543 /* A strided Advanced SIMD x64 load would take two parallel FP loads 2544 (8 cycles) plus an insertion (2 cycles). Assume a 64-bit SVE gather 2545 is 1 cycle more. The Advanced SIMD version is costed as 2 scalar loads 2546 (cost 8) and a vec_construct (cost 2). Add a full vector operation 2547 (cost 2) to that, to avoid the difference being lost in rounding. 2548 2549 There is no easy comparison between a strided Advanced SIMD x32 load 2550 and an SVE 32-bit gather, but cost an SVE 32-bit gather as 1 vector 2551 operation more than a 64-bit gather. */ 2552 14, /* gather_load_x32_cost */ 2553 12, /* gather_load_x64_cost */ 2554 3 /* scatter_store_elt_cost */ 2555 }; 2556 2557 static const aarch64_scalar_vec_issue_info neoversev2_scalar_issue_info = 2558 { 2559 3, /* loads_stores_per_cycle */ 2560 2, /* stores_per_cycle */ 2561 6, /* general_ops_per_cycle */ 2562 0, /* fp_simd_load_general_ops */ 2563 1 /* fp_simd_store_general_ops */ 2564 }; 2565 2566 static const aarch64_advsimd_vec_issue_info neoversev2_advsimd_issue_info = 2567 { 2568 { 2569 3, /* loads_stores_per_cycle */ 2570 2, /* stores_per_cycle */ 2571 4, /* general_ops_per_cycle */ 2572 0, /* fp_simd_load_general_ops */ 2573 1 /* fp_simd_store_general_ops */ 2574 }, 2575 2, /* ld2_st2_general_ops */ 2576 2, /* ld3_st3_general_ops */ 2577 3 /* ld4_st4_general_ops */ 2578 }; 2579 2580 static const aarch64_sve_vec_issue_info neoversev2_sve_issue_info = 2581 { 2582 { 2583 { 2584 3, /* loads_per_cycle */ 2585 2, /* stores_per_cycle */ 2586 4, /* general_ops_per_cycle */ 2587 0, /* fp_simd_load_general_ops */ 2588 1 /* fp_simd_store_general_ops */ 2589 }, 2590 2, /* ld2_st2_general_ops */ 2591 3, /* ld3_st3_general_ops */ 2592 3 /* ld4_st4_general_ops */ 2593 }, 2594 2, /* pred_ops_per_cycle */ 2595 2, /* while_pred_ops */ 2596 2, /* int_cmp_pred_ops */ 2597 1, /* fp_cmp_pred_ops */ 2598 1, /* gather_scatter_pair_general_ops */ 2599 1 /* gather_scatter_pair_pred_ops */ 2600 }; 2601 2602 static const aarch64_vec_issue_info neoversev2_vec_issue_info = 2603 { 2604 &neoversev2_scalar_issue_info, 2605 &neoversev2_advsimd_issue_info, 2606 &neoversev2_sve_issue_info 2607 }; 2608 2609 /* Demeter costs for vector insn classes. */ 2610 static const struct cpu_vector_cost neoversev2_vector_cost = 2611 { 2612 1, /* scalar_int_stmt_cost */ 2613 2, /* scalar_fp_stmt_cost */ 2614 4, /* scalar_load_cost */ 2615 1, /* scalar_store_cost */ 2616 1, /* cond_taken_branch_cost */ 2617 1, /* cond_not_taken_branch_cost */ 2618 &neoversev2_advsimd_vector_cost, /* advsimd */ 2619 &neoversev2_sve_vector_cost, /* sve */ 2620 &neoversev2_vec_issue_info /* issue_info */ 2621 }; 2622 2623 static const struct tune_params neoversev2_tunings = 2624 { 2625 &cortexa76_extra_costs, 2626 &neoversev2_addrcost_table, 2627 &neoversev2_regmove_cost, 2628 &neoversev2_vector_cost, 2629 &generic_branch_cost, 2630 &generic_approx_modes, 2631 SVE_128, /* sve_width */ 2632 { 4, /* load_int. */ 2633 2, /* store_int. */ 2634 6, /* load_fp. */ 2635 1, /* store_fp. */ 2636 6, /* load_pred. */ 2637 2 /* store_pred. */ 2638 }, /* memmov_cost. */ 2639 5, /* issue_rate */ 2640 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ 2641 "32:16", /* function_align. */ 2642 "4", /* jump_align. */ 2643 "32:16", /* loop_align. */ 2644 3, /* int_reassoc_width. */ 2645 6, /* fp_reassoc_width. */ 2646 3, /* vec_reassoc_width. */ 2647 2, /* min_div_recip_mul_sf. */ 2648 2, /* min_div_recip_mul_df. */ 2649 0, /* max_case_values. */ 2650 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 2651 (AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND 2652 | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS 2653 | AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS 2654 | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT), /* tune_flags. */ 2655 &generic_prefetch_tune 2656 }; 2657 2658 static const struct tune_params a64fx_tunings = 2659 { 2660 &a64fx_extra_costs, 2661 &a64fx_addrcost_table, 2662 &a64fx_regmove_cost, 2663 &a64fx_vector_cost, 2664 &generic_branch_cost, 2665 &generic_approx_modes, 2666 SVE_512, /* sve_width */ 2667 { 4, /* load_int. */ 2668 4, /* store_int. */ 2669 4, /* load_fp. */ 2670 4, /* store_fp. */ 2671 4, /* load_pred. */ 2672 4 /* store_pred. */ 2673 }, /* memmov_cost. */ 2674 7, /* issue_rate */ 2675 (AARCH64_FUSE_AES_AESMC | AARCH64_FUSE_CMP_BRANCH), /* fusible_ops */ 2676 "32", /* function_align. */ 2677 "16", /* jump_align. */ 2678 "32", /* loop_align. */ 2679 4, /* int_reassoc_width. */ 2680 2, /* fp_reassoc_width. */ 2681 2, /* vec_reassoc_width. */ 2682 2, /* min_div_recip_mul_sf. */ 2683 2, /* min_div_recip_mul_df. */ 2684 0, /* max_case_values. */ 2685 tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */ 2686 (AARCH64_EXTRA_TUNE_NONE), /* tune_flags. */ 2687 &a64fx_prefetch_tune 2688 }; 2689 2690 /* Support for fine-grained override of the tuning structures. */ 2691 struct aarch64_tuning_override_function 2692 { 2693 const char* name; 2694 void (*parse_override)(const char*, struct tune_params*); 2695 }; 2696 2697 static void aarch64_parse_fuse_string (const char*, struct tune_params*); 2698 static void aarch64_parse_tune_string (const char*, struct tune_params*); 2699 static void aarch64_parse_sve_width_string (const char*, struct tune_params*); 2700 2701 static const struct aarch64_tuning_override_function 2702 aarch64_tuning_override_functions[] = 2703 { 2704 { "fuse", aarch64_parse_fuse_string }, 2705 { "tune", aarch64_parse_tune_string }, 2706 { "sve_width", aarch64_parse_sve_width_string }, 2707 { NULL, NULL } 2708 }; 2709 2710 /* A processor implementing AArch64. */ 2711 struct processor 2712 { 2713 const char *const name; 2714 enum aarch64_processor ident; 2715 enum aarch64_processor sched_core; 2716 enum aarch64_arch arch; 2717 unsigned architecture_version; 2718 const uint64_t flags; 2719 const struct tune_params *const tune; 2720 }; 2721 2722 /* Architectures implementing AArch64. */ 2723 static const struct processor all_architectures[] = 2724 { 2725 #define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH_REV, FLAGS) \ 2726 {NAME, CORE, CORE, AARCH64_ARCH_##ARCH_IDENT, ARCH_REV, FLAGS, NULL}, 2727 #include "aarch64-arches.def" 2728 {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, 0, NULL} 2729 }; 2730 2731 /* Processor cores implementing AArch64. */ 2732 static const struct processor all_cores[] = 2733 { 2734 #define AARCH64_CORE(NAME, IDENT, SCHED, ARCH, FLAGS, COSTS, IMP, PART, VARIANT) \ 2735 {NAME, IDENT, SCHED, AARCH64_ARCH_##ARCH, \ 2736 all_architectures[AARCH64_ARCH_##ARCH].architecture_version, \ 2737 FLAGS, &COSTS##_tunings}, 2738 #include "aarch64-cores.def" 2739 {"generic", generic, cortexa53, AARCH64_ARCH_8A, 8, 2740 AARCH64_FL_FOR_ARCH8, &generic_tunings}, 2741 {NULL, aarch64_none, aarch64_none, aarch64_no_arch, 0, 0, NULL} 2742 }; 2743 2744 2745 /* Target specification. These are populated by the -march, -mtune, -mcpu 2746 handling code or by target attributes. */ 2747 static const struct processor *selected_arch; 2748 static const struct processor *selected_cpu; 2749 static const struct processor *selected_tune; 2750 2751 enum aarch64_key_type aarch64_ra_sign_key = AARCH64_KEY_A; 2752 2753 /* The current tuning set. */ 2754 struct tune_params aarch64_tune_params = generic_tunings; 2755 2756 /* Check whether an 'aarch64_vector_pcs' attribute is valid. */ 2757 2758 static tree 2759 handle_aarch64_vector_pcs_attribute (tree *node, tree name, tree, 2760 int, bool *no_add_attrs) 2761 { 2762 /* Since we set fn_type_req to true, the caller should have checked 2763 this for us. */ 2764 gcc_assert (FUNC_OR_METHOD_TYPE_P (*node)); 2765 switch ((arm_pcs) fntype_abi (*node).id ()) 2766 { 2767 case ARM_PCS_AAPCS64: 2768 case ARM_PCS_SIMD: 2769 return NULL_TREE; 2770 2771 case ARM_PCS_SVE: 2772 error ("the %qE attribute cannot be applied to an SVE function type", 2773 name); 2774 *no_add_attrs = true; 2775 return NULL_TREE; 2776 2777 case ARM_PCS_TLSDESC: 2778 case ARM_PCS_UNKNOWN: 2779 break; 2780 } 2781 gcc_unreachable (); 2782 } 2783 2784 /* Table of machine attributes. */ 2785 static const struct attribute_spec aarch64_attribute_table[] = 2786 { 2787 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, 2788 affects_type_identity, handler, exclude } */ 2789 { "aarch64_vector_pcs", 0, 0, false, true, true, true, 2790 handle_aarch64_vector_pcs_attribute, NULL }, 2791 { "arm_sve_vector_bits", 1, 1, false, true, false, true, 2792 aarch64_sve::handle_arm_sve_vector_bits_attribute, 2793 NULL }, 2794 { "Advanced SIMD type", 1, 1, false, true, false, true, NULL, NULL }, 2795 { "SVE type", 3, 3, false, true, false, true, NULL, NULL }, 2796 { "SVE sizeless type", 0, 0, false, true, false, true, NULL, NULL }, 2797 { NULL, 0, 0, false, false, false, false, NULL, NULL } 2798 }; 2799 2800 #define AARCH64_CPU_DEFAULT_FLAGS ((selected_cpu) ? selected_cpu->flags : 0) 2801 2802 /* An ISA extension in the co-processor and main instruction set space. */ 2803 struct aarch64_option_extension 2804 { 2805 const char *const name; 2806 const unsigned long flags_on; 2807 const unsigned long flags_off; 2808 }; 2809 2810 typedef enum aarch64_cond_code 2811 { 2812 AARCH64_EQ = 0, AARCH64_NE, AARCH64_CS, AARCH64_CC, AARCH64_MI, AARCH64_PL, 2813 AARCH64_VS, AARCH64_VC, AARCH64_HI, AARCH64_LS, AARCH64_GE, AARCH64_LT, 2814 AARCH64_GT, AARCH64_LE, AARCH64_AL, AARCH64_NV 2815 } 2816 aarch64_cc; 2817 2818 #define AARCH64_INVERSE_CONDITION_CODE(X) ((aarch64_cc) (((int) X) ^ 1)) 2819 2820 struct aarch64_branch_protect_type 2821 { 2822 /* The type's name that the user passes to the branch-protection option 2823 string. */ 2824 const char* name; 2825 /* Function to handle the protection type and set global variables. 2826 First argument is the string token corresponding with this type and the 2827 second argument is the next token in the option string. 2828 Return values: 2829 * AARCH64_PARSE_OK: Handling was sucessful. 2830 * AARCH64_INVALID_ARG: The type is invalid in this context and the caller 2831 should print an error. 2832 * AARCH64_INVALID_FEATURE: The type is invalid and the handler prints its 2833 own error. */ 2834 enum aarch64_parse_opt_result (*handler)(char*, char*); 2835 /* A list of types that can follow this type in the option string. */ 2836 const aarch64_branch_protect_type* subtypes; 2837 unsigned int num_subtypes; 2838 }; 2839 2840 static enum aarch64_parse_opt_result 2841 aarch64_handle_no_branch_protection (char* str, char* rest) 2842 { 2843 aarch64_ra_sign_scope = AARCH64_FUNCTION_NONE; 2844 aarch64_enable_bti = 0; 2845 if (rest) 2846 { 2847 error ("unexpected %<%s%> after %<%s%>", rest, str); 2848 return AARCH64_PARSE_INVALID_FEATURE; 2849 } 2850 return AARCH64_PARSE_OK; 2851 } 2852 2853 static enum aarch64_parse_opt_result 2854 aarch64_handle_standard_branch_protection (char* str, char* rest) 2855 { 2856 aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF; 2857 aarch64_ra_sign_key = AARCH64_KEY_A; 2858 aarch64_enable_bti = 1; 2859 if (rest) 2860 { 2861 error ("unexpected %<%s%> after %<%s%>", rest, str); 2862 return AARCH64_PARSE_INVALID_FEATURE; 2863 } 2864 return AARCH64_PARSE_OK; 2865 } 2866 2867 static enum aarch64_parse_opt_result 2868 aarch64_handle_pac_ret_protection (char* str ATTRIBUTE_UNUSED, 2869 char* rest ATTRIBUTE_UNUSED) 2870 { 2871 aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF; 2872 aarch64_ra_sign_key = AARCH64_KEY_A; 2873 return AARCH64_PARSE_OK; 2874 } 2875 2876 static enum aarch64_parse_opt_result 2877 aarch64_handle_pac_ret_leaf (char* str ATTRIBUTE_UNUSED, 2878 char* rest ATTRIBUTE_UNUSED) 2879 { 2880 aarch64_ra_sign_scope = AARCH64_FUNCTION_ALL; 2881 return AARCH64_PARSE_OK; 2882 } 2883 2884 static enum aarch64_parse_opt_result 2885 aarch64_handle_pac_ret_b_key (char* str ATTRIBUTE_UNUSED, 2886 char* rest ATTRIBUTE_UNUSED) 2887 { 2888 aarch64_ra_sign_key = AARCH64_KEY_B; 2889 return AARCH64_PARSE_OK; 2890 } 2891 2892 static enum aarch64_parse_opt_result 2893 aarch64_handle_bti_protection (char* str ATTRIBUTE_UNUSED, 2894 char* rest ATTRIBUTE_UNUSED) 2895 { 2896 aarch64_enable_bti = 1; 2897 return AARCH64_PARSE_OK; 2898 } 2899 2900 static const struct aarch64_branch_protect_type aarch64_pac_ret_subtypes[] = { 2901 { "leaf", aarch64_handle_pac_ret_leaf, NULL, 0 }, 2902 { "b-key", aarch64_handle_pac_ret_b_key, NULL, 0 }, 2903 { NULL, NULL, NULL, 0 } 2904 }; 2905 2906 static const struct aarch64_branch_protect_type aarch64_branch_protect_types[] = { 2907 { "none", aarch64_handle_no_branch_protection, NULL, 0 }, 2908 { "standard", aarch64_handle_standard_branch_protection, NULL, 0 }, 2909 { "pac-ret", aarch64_handle_pac_ret_protection, aarch64_pac_ret_subtypes, 2910 ARRAY_SIZE (aarch64_pac_ret_subtypes) }, 2911 { "bti", aarch64_handle_bti_protection, NULL, 0 }, 2912 { NULL, NULL, NULL, 0 } 2913 }; 2914 2915 /* The condition codes of the processor, and the inverse function. */ 2916 static const char * const aarch64_condition_codes[] = 2917 { 2918 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", 2919 "hi", "ls", "ge", "lt", "gt", "le", "al", "nv" 2920 }; 2921 2922 /* The preferred condition codes for SVE conditions. */ 2923 static const char *const aarch64_sve_condition_codes[] = 2924 { 2925 "none", "any", "nlast", "last", "first", "nfrst", "vs", "vc", 2926 "pmore", "plast", "tcont", "tstop", "gt", "le", "al", "nv" 2927 }; 2928 2929 /* Return the assembly token for svpattern value VALUE. */ 2930 2931 static const char * 2932 svpattern_token (enum aarch64_svpattern pattern) 2933 { 2934 switch (pattern) 2935 { 2936 #define CASE(UPPER, LOWER, VALUE) case AARCH64_SV_##UPPER: return #LOWER; 2937 AARCH64_FOR_SVPATTERN (CASE) 2938 #undef CASE 2939 case AARCH64_NUM_SVPATTERNS: 2940 break; 2941 } 2942 gcc_unreachable (); 2943 } 2944 2945 /* Return the location of a piece that is known to be passed or returned 2946 in registers. FIRST_ZR is the first unused vector argument register 2947 and FIRST_PR is the first unused predicate argument register. */ 2948 2949 rtx 2950 pure_scalable_type_info::piece::get_rtx (unsigned int first_zr, 2951 unsigned int first_pr) const 2952 { 2953 gcc_assert (VECTOR_MODE_P (mode) 2954 && first_zr + num_zr <= V0_REGNUM + NUM_FP_ARG_REGS 2955 && first_pr + num_pr <= P0_REGNUM + NUM_PR_ARG_REGS); 2956 2957 if (num_zr > 0 && num_pr == 0) 2958 return gen_rtx_REG (mode, first_zr); 2959 2960 if (num_zr == 0 && num_pr == 1) 2961 return gen_rtx_REG (mode, first_pr); 2962 2963 gcc_unreachable (); 2964 } 2965 2966 /* Return the total number of vector registers required by the PST. */ 2967 2968 unsigned int 2969 pure_scalable_type_info::num_zr () const 2970 { 2971 unsigned int res = 0; 2972 for (unsigned int i = 0; i < pieces.length (); ++i) 2973 res += pieces[i].num_zr; 2974 return res; 2975 } 2976 2977 /* Return the total number of predicate registers required by the PST. */ 2978 2979 unsigned int 2980 pure_scalable_type_info::num_pr () const 2981 { 2982 unsigned int res = 0; 2983 for (unsigned int i = 0; i < pieces.length (); ++i) 2984 res += pieces[i].num_pr; 2985 return res; 2986 } 2987 2988 /* Return the location of a PST that is known to be passed or returned 2989 in registers. FIRST_ZR is the first unused vector argument register 2990 and FIRST_PR is the first unused predicate argument register. */ 2991 2992 rtx 2993 pure_scalable_type_info::get_rtx (machine_mode mode, 2994 unsigned int first_zr, 2995 unsigned int first_pr) const 2996 { 2997 /* Try to return a single REG if possible. This leads to better 2998 code generation; it isn't required for correctness. */ 2999 if (mode == pieces[0].mode) 3000 { 3001 gcc_assert (pieces.length () == 1); 3002 return pieces[0].get_rtx (first_zr, first_pr); 3003 } 3004 3005 /* Build up a PARALLEL that contains the individual pieces. */ 3006 rtvec rtxes = rtvec_alloc (pieces.length ()); 3007 for (unsigned int i = 0; i < pieces.length (); ++i) 3008 { 3009 rtx reg = pieces[i].get_rtx (first_zr, first_pr); 3010 rtx offset = gen_int_mode (pieces[i].offset, Pmode); 3011 RTVEC_ELT (rtxes, i) = gen_rtx_EXPR_LIST (VOIDmode, reg, offset); 3012 first_zr += pieces[i].num_zr; 3013 first_pr += pieces[i].num_pr; 3014 } 3015 return gen_rtx_PARALLEL (mode, rtxes); 3016 } 3017 3018 /* Analyze whether TYPE is a Pure Scalable Type according to the rules 3019 in the AAPCS64. */ 3020 3021 pure_scalable_type_info::analysis_result 3022 pure_scalable_type_info::analyze (const_tree type) 3023 { 3024 /* Prevent accidental reuse. */ 3025 gcc_assert (pieces.is_empty ()); 3026 3027 /* No code will be generated for erroneous types, so we won't establish 3028 an ABI mapping. */ 3029 if (type == error_mark_node) 3030 return NO_ABI_IDENTITY; 3031 3032 /* Zero-sized types disappear in the language->ABI mapping. */ 3033 if (TYPE_SIZE (type) && integer_zerop (TYPE_SIZE (type))) 3034 return NO_ABI_IDENTITY; 3035 3036 /* Check for SVTs, SPTs, and built-in tuple types that map to PSTs. */ 3037 piece p = {}; 3038 if (aarch64_sve::builtin_type_p (type, &p.num_zr, &p.num_pr)) 3039 { 3040 machine_mode mode = TYPE_MODE_RAW (type); 3041 gcc_assert (VECTOR_MODE_P (mode) 3042 && (!TARGET_SVE || aarch64_sve_mode_p (mode))); 3043 3044 p.mode = p.orig_mode = mode; 3045 add_piece (p); 3046 return IS_PST; 3047 } 3048 3049 /* Check for user-defined PSTs. */ 3050 if (TREE_CODE (type) == ARRAY_TYPE) 3051 return analyze_array (type); 3052 if (TREE_CODE (type) == RECORD_TYPE) 3053 return analyze_record (type); 3054 3055 return ISNT_PST; 3056 } 3057 3058 /* Analyze a type that is known not to be passed or returned in memory. 3059 Return true if it has an ABI identity and is a Pure Scalable Type. */ 3060 3061 bool 3062 pure_scalable_type_info::analyze_registers (const_tree type) 3063 { 3064 analysis_result result = analyze (type); 3065 gcc_assert (result != DOESNT_MATTER); 3066 return result == IS_PST; 3067 } 3068 3069 /* Subroutine of analyze for handling ARRAY_TYPEs. */ 3070 3071 pure_scalable_type_info::analysis_result 3072 pure_scalable_type_info::analyze_array (const_tree type) 3073 { 3074 /* Analyze the element type. */ 3075 pure_scalable_type_info element_info; 3076 analysis_result result = element_info.analyze (TREE_TYPE (type)); 3077 if (result != IS_PST) 3078 return result; 3079 3080 /* An array of unknown, flexible or variable length will be passed and 3081 returned by reference whatever we do. */ 3082 tree nelts_minus_one = array_type_nelts (type); 3083 if (!tree_fits_uhwi_p (nelts_minus_one)) 3084 return DOESNT_MATTER; 3085 3086 /* Likewise if the array is constant-sized but too big to be interesting. 3087 The double checks against MAX_PIECES are to protect against overflow. */ 3088 unsigned HOST_WIDE_INT count = tree_to_uhwi (nelts_minus_one); 3089 if (count > MAX_PIECES) 3090 return DOESNT_MATTER; 3091 count += 1; 3092 if (count * element_info.pieces.length () > MAX_PIECES) 3093 return DOESNT_MATTER; 3094 3095 /* The above checks should have weeded out elements of unknown size. */ 3096 poly_uint64 element_bytes; 3097 if (!poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (type)), &element_bytes)) 3098 gcc_unreachable (); 3099 3100 /* Build up the list of individual vectors and predicates. */ 3101 gcc_assert (!element_info.pieces.is_empty ()); 3102 for (unsigned int i = 0; i < count; ++i) 3103 for (unsigned int j = 0; j < element_info.pieces.length (); ++j) 3104 { 3105 piece p = element_info.pieces[j]; 3106 p.offset += i * element_bytes; 3107 add_piece (p); 3108 } 3109 return IS_PST; 3110 } 3111 3112 /* Subroutine of analyze for handling RECORD_TYPEs. */ 3113 3114 pure_scalable_type_info::analysis_result 3115 pure_scalable_type_info::analyze_record (const_tree type) 3116 { 3117 for (tree field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) 3118 { 3119 if (TREE_CODE (field) != FIELD_DECL) 3120 continue; 3121 3122 /* Zero-sized fields disappear in the language->ABI mapping. */ 3123 if (DECL_SIZE (field) && integer_zerop (DECL_SIZE (field))) 3124 continue; 3125 3126 /* All fields with an ABI identity must be PSTs for the record as 3127 a whole to be a PST. If any individual field is too big to be 3128 interesting then the record is too. */ 3129 pure_scalable_type_info field_info; 3130 analysis_result subresult = field_info.analyze (TREE_TYPE (field)); 3131 if (subresult == NO_ABI_IDENTITY) 3132 continue; 3133 if (subresult != IS_PST) 3134 return subresult; 3135 3136 /* Since all previous fields are PSTs, we ought to be able to track 3137 the field offset using poly_ints. */ 3138 tree bitpos = bit_position (field); 3139 gcc_assert (poly_int_tree_p (bitpos)); 3140 3141 /* For the same reason, it shouldn't be possible to create a PST field 3142 whose offset isn't byte-aligned. */ 3143 poly_widest_int wide_bytepos = exact_div (wi::to_poly_widest (bitpos), 3144 BITS_PER_UNIT); 3145 3146 /* Punt if the record is too big to be interesting. */ 3147 poly_uint64 bytepos; 3148 if (!wide_bytepos.to_uhwi (&bytepos) 3149 || pieces.length () + field_info.pieces.length () > MAX_PIECES) 3150 return DOESNT_MATTER; 3151 3152 /* Add the individual vectors and predicates in the field to the 3153 record's list. */ 3154 gcc_assert (!field_info.pieces.is_empty ()); 3155 for (unsigned int i = 0; i < field_info.pieces.length (); ++i) 3156 { 3157 piece p = field_info.pieces[i]; 3158 p.offset += bytepos; 3159 add_piece (p); 3160 } 3161 } 3162 /* Empty structures disappear in the language->ABI mapping. */ 3163 return pieces.is_empty () ? NO_ABI_IDENTITY : IS_PST; 3164 } 3165 3166 /* Add P to the list of pieces in the type. */ 3167 3168 void 3169 pure_scalable_type_info::add_piece (const piece &p) 3170 { 3171 /* Try to fold the new piece into the previous one to form a 3172 single-mode PST. For example, if we see three consecutive vectors 3173 of the same mode, we can represent them using the corresponding 3174 3-tuple mode. 3175 3176 This is purely an optimization. */ 3177 if (!pieces.is_empty ()) 3178 { 3179 piece &prev = pieces.last (); 3180 gcc_assert (VECTOR_MODE_P (p.mode) && VECTOR_MODE_P (prev.mode)); 3181 unsigned int nelems1, nelems2; 3182 if (prev.orig_mode == p.orig_mode 3183 && known_eq (prev.offset + GET_MODE_SIZE (prev.mode), p.offset) 3184 && constant_multiple_p (GET_MODE_NUNITS (prev.mode), 3185 GET_MODE_NUNITS (p.orig_mode), &nelems1) 3186 && constant_multiple_p (GET_MODE_NUNITS (p.mode), 3187 GET_MODE_NUNITS (p.orig_mode), &nelems2) 3188 && targetm.array_mode (p.orig_mode, 3189 nelems1 + nelems2).exists (&prev.mode)) 3190 { 3191 prev.num_zr += p.num_zr; 3192 prev.num_pr += p.num_pr; 3193 return; 3194 } 3195 } 3196 pieces.quick_push (p); 3197 } 3198 3199 /* Return true if at least one possible value of type TYPE includes at 3200 least one object of Pure Scalable Type, in the sense of the AAPCS64. 3201 3202 This is a relatively expensive test for some types, so it should 3203 generally be made as late as possible. */ 3204 3205 static bool 3206 aarch64_some_values_include_pst_objects_p (const_tree type) 3207 { 3208 if (TYPE_SIZE (type) && integer_zerop (TYPE_SIZE (type))) 3209 return false; 3210 3211 if (aarch64_sve::builtin_type_p (type)) 3212 return true; 3213 3214 if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == COMPLEX_TYPE) 3215 return aarch64_some_values_include_pst_objects_p (TREE_TYPE (type)); 3216 3217 if (RECORD_OR_UNION_TYPE_P (type)) 3218 for (tree field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) 3219 if (TREE_CODE (field) == FIELD_DECL 3220 && aarch64_some_values_include_pst_objects_p (TREE_TYPE (field))) 3221 return true; 3222 3223 return false; 3224 } 3225 3226 /* Return the descriptor of the SIMD ABI. */ 3227 3228 static const predefined_function_abi & 3229 aarch64_simd_abi (void) 3230 { 3231 predefined_function_abi &simd_abi = function_abis[ARM_PCS_SIMD]; 3232 if (!simd_abi.initialized_p ()) 3233 { 3234 HARD_REG_SET full_reg_clobbers 3235 = default_function_abi.full_reg_clobbers (); 3236 for (int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 3237 if (FP_SIMD_SAVED_REGNUM_P (regno)) 3238 CLEAR_HARD_REG_BIT (full_reg_clobbers, regno); 3239 simd_abi.initialize (ARM_PCS_SIMD, full_reg_clobbers); 3240 } 3241 return simd_abi; 3242 } 3243 3244 /* Return the descriptor of the SVE PCS. */ 3245 3246 static const predefined_function_abi & 3247 aarch64_sve_abi (void) 3248 { 3249 predefined_function_abi &sve_abi = function_abis[ARM_PCS_SVE]; 3250 if (!sve_abi.initialized_p ()) 3251 { 3252 HARD_REG_SET full_reg_clobbers 3253 = default_function_abi.full_reg_clobbers (); 3254 for (int regno = V8_REGNUM; regno <= V23_REGNUM; ++regno) 3255 CLEAR_HARD_REG_BIT (full_reg_clobbers, regno); 3256 for (int regno = P4_REGNUM; regno <= P15_REGNUM; ++regno) 3257 CLEAR_HARD_REG_BIT (full_reg_clobbers, regno); 3258 sve_abi.initialize (ARM_PCS_SVE, full_reg_clobbers); 3259 } 3260 return sve_abi; 3261 } 3262 3263 /* If X is an UNSPEC_SALT_ADDR expression, return the address that it 3264 wraps, otherwise return X itself. */ 3265 3266 static rtx 3267 strip_salt (rtx x) 3268 { 3269 rtx search = x; 3270 if (GET_CODE (search) == CONST) 3271 search = XEXP (search, 0); 3272 if (GET_CODE (search) == UNSPEC && XINT (search, 1) == UNSPEC_SALT_ADDR) 3273 x = XVECEXP (search, 0, 0); 3274 return x; 3275 } 3276 3277 /* Like strip_offset, but also strip any UNSPEC_SALT_ADDR from the 3278 expression. */ 3279 3280 static rtx 3281 strip_offset_and_salt (rtx addr, poly_int64 *offset) 3282 { 3283 return strip_salt (strip_offset (addr, offset)); 3284 } 3285 3286 /* Generate code to enable conditional branches in functions over 1 MiB. */ 3287 const char * 3288 aarch64_gen_far_branch (rtx * operands, int pos_label, const char * dest, 3289 const char * branch_format) 3290 { 3291 rtx_code_label * tmp_label = gen_label_rtx (); 3292 char label_buf[256]; 3293 char buffer[128]; 3294 ASM_GENERATE_INTERNAL_LABEL (label_buf, dest, 3295 CODE_LABEL_NUMBER (tmp_label)); 3296 const char *label_ptr = targetm.strip_name_encoding (label_buf); 3297 rtx dest_label = operands[pos_label]; 3298 operands[pos_label] = tmp_label; 3299 3300 snprintf (buffer, sizeof (buffer), "%s%s", branch_format, label_ptr); 3301 output_asm_insn (buffer, operands); 3302 3303 snprintf (buffer, sizeof (buffer), "b\t%%l%d\n%s:", pos_label, label_ptr); 3304 operands[pos_label] = dest_label; 3305 output_asm_insn (buffer, operands); 3306 return ""; 3307 } 3308 3309 void 3310 aarch64_err_no_fpadvsimd (machine_mode mode) 3311 { 3312 if (TARGET_GENERAL_REGS_ONLY) 3313 if (FLOAT_MODE_P (mode)) 3314 error ("%qs is incompatible with the use of floating-point types", 3315 "-mgeneral-regs-only"); 3316 else 3317 error ("%qs is incompatible with the use of vector types", 3318 "-mgeneral-regs-only"); 3319 else 3320 if (FLOAT_MODE_P (mode)) 3321 error ("%qs feature modifier is incompatible with the use of" 3322 " floating-point types", "+nofp"); 3323 else 3324 error ("%qs feature modifier is incompatible with the use of" 3325 " vector types", "+nofp"); 3326 } 3327 3328 /* Report when we try to do something that requires SVE when SVE is disabled. 3329 This is an error of last resort and isn't very high-quality. It usually 3330 involves attempts to measure the vector length in some way. */ 3331 static void 3332 aarch64_report_sve_required (void) 3333 { 3334 static bool reported_p = false; 3335 3336 /* Avoid reporting a slew of messages for a single oversight. */ 3337 if (reported_p) 3338 return; 3339 3340 error ("this operation requires the SVE ISA extension"); 3341 inform (input_location, "you can enable SVE using the command-line" 3342 " option %<-march%>, or by using the %<target%>" 3343 " attribute or pragma"); 3344 reported_p = true; 3345 } 3346 3347 /* Return true if REGNO is P0-P15 or one of the special FFR-related 3348 registers. */ 3349 inline bool 3350 pr_or_ffr_regnum_p (unsigned int regno) 3351 { 3352 return PR_REGNUM_P (regno) || regno == FFR_REGNUM || regno == FFRT_REGNUM; 3353 } 3354 3355 /* Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS. 3356 The register allocator chooses POINTER_AND_FP_REGS if FP_REGS and 3357 GENERAL_REGS have the same cost - even if POINTER_AND_FP_REGS has a much 3358 higher cost. POINTER_AND_FP_REGS is also used if the cost of both FP_REGS 3359 and GENERAL_REGS is lower than the memory cost (in this case the best class 3360 is the lowest cost one). Using POINTER_AND_FP_REGS irrespectively of its 3361 cost results in bad allocations with many redundant int<->FP moves which 3362 are expensive on various cores. 3363 To avoid this we don't allow POINTER_AND_FP_REGS as the allocno class, but 3364 force a decision between FP_REGS and GENERAL_REGS. We use the allocno class 3365 if it isn't POINTER_AND_FP_REGS. Similarly, use the best class if it isn't 3366 POINTER_AND_FP_REGS. Otherwise set the allocno class depending on the mode. 3367 The result of this is that it is no longer inefficient to have a higher 3368 memory move cost than the register move cost. 3369 */ 3370 3371 static reg_class_t 3372 aarch64_ira_change_pseudo_allocno_class (int regno, reg_class_t allocno_class, 3373 reg_class_t best_class) 3374 { 3375 machine_mode mode; 3376 3377 if (!reg_class_subset_p (GENERAL_REGS, allocno_class) 3378 || !reg_class_subset_p (FP_REGS, allocno_class)) 3379 return allocno_class; 3380 3381 if (!reg_class_subset_p (GENERAL_REGS, best_class) 3382 || !reg_class_subset_p (FP_REGS, best_class)) 3383 return best_class; 3384 3385 mode = PSEUDO_REGNO_MODE (regno); 3386 return FLOAT_MODE_P (mode) || VECTOR_MODE_P (mode) ? FP_REGS : GENERAL_REGS; 3387 } 3388 3389 static unsigned int 3390 aarch64_min_divisions_for_recip_mul (machine_mode mode) 3391 { 3392 if (GET_MODE_UNIT_SIZE (mode) == 4) 3393 return aarch64_tune_params.min_div_recip_mul_sf; 3394 return aarch64_tune_params.min_div_recip_mul_df; 3395 } 3396 3397 /* Return the reassociation width of treeop OPC with mode MODE. */ 3398 static int 3399 aarch64_reassociation_width (unsigned opc, machine_mode mode) 3400 { 3401 if (VECTOR_MODE_P (mode)) 3402 return aarch64_tune_params.vec_reassoc_width; 3403 if (INTEGRAL_MODE_P (mode)) 3404 return aarch64_tune_params.int_reassoc_width; 3405 /* Avoid reassociating floating point addition so we emit more FMAs. */ 3406 if (FLOAT_MODE_P (mode) && opc != PLUS_EXPR) 3407 return aarch64_tune_params.fp_reassoc_width; 3408 return 1; 3409 } 3410 3411 /* Provide a mapping from gcc register numbers to dwarf register numbers. */ 3412 unsigned 3413 aarch64_dbx_register_number (unsigned regno) 3414 { 3415 if (GP_REGNUM_P (regno)) 3416 return AARCH64_DWARF_R0 + regno - R0_REGNUM; 3417 else if (regno == SP_REGNUM) 3418 return AARCH64_DWARF_SP; 3419 else if (FP_REGNUM_P (regno)) 3420 return AARCH64_DWARF_V0 + regno - V0_REGNUM; 3421 else if (PR_REGNUM_P (regno)) 3422 return AARCH64_DWARF_P0 + regno - P0_REGNUM; 3423 else if (regno == VG_REGNUM) 3424 return AARCH64_DWARF_VG; 3425 3426 /* Return values >= DWARF_FRAME_REGISTERS indicate that there is no 3427 equivalent DWARF register. */ 3428 return DWARF_FRAME_REGISTERS; 3429 } 3430 3431 /* If X is a CONST_DOUBLE, return its bit representation as a constant 3432 integer, otherwise return X unmodified. */ 3433 static rtx 3434 aarch64_bit_representation (rtx x) 3435 { 3436 if (CONST_DOUBLE_P (x)) 3437 x = gen_lowpart (int_mode_for_mode (GET_MODE (x)).require (), x); 3438 return x; 3439 } 3440 3441 /* Return an estimate for the number of quadwords in an SVE vector. This is 3442 equivalent to the number of Advanced SIMD vectors in an SVE vector. */ 3443 static unsigned int 3444 aarch64_estimated_sve_vq () 3445 { 3446 return estimated_poly_value (BITS_PER_SVE_VECTOR) / 128; 3447 } 3448 3449 /* Return true if MODE is an SVE predicate mode. */ 3450 static bool 3451 aarch64_sve_pred_mode_p (machine_mode mode) 3452 { 3453 return (TARGET_SVE 3454 && (mode == VNx16BImode 3455 || mode == VNx8BImode 3456 || mode == VNx4BImode 3457 || mode == VNx2BImode)); 3458 } 3459 3460 /* Three mutually-exclusive flags describing a vector or predicate type. */ 3461 const unsigned int VEC_ADVSIMD = 1; 3462 const unsigned int VEC_SVE_DATA = 2; 3463 const unsigned int VEC_SVE_PRED = 4; 3464 /* Can be used in combination with VEC_ADVSIMD or VEC_SVE_DATA to indicate 3465 a structure of 2, 3 or 4 vectors. */ 3466 const unsigned int VEC_STRUCT = 8; 3467 /* Can be used in combination with VEC_SVE_DATA to indicate that the 3468 vector has fewer significant bytes than a full SVE vector. */ 3469 const unsigned int VEC_PARTIAL = 16; 3470 /* Useful combinations of the above. */ 3471 const unsigned int VEC_ANY_SVE = VEC_SVE_DATA | VEC_SVE_PRED; 3472 const unsigned int VEC_ANY_DATA = VEC_ADVSIMD | VEC_SVE_DATA; 3473 3474 /* Return a set of flags describing the vector properties of mode MODE. 3475 Ignore modes that are not supported by the current target. */ 3476 static unsigned int 3477 aarch64_classify_vector_mode (machine_mode mode) 3478 { 3479 if (aarch64_sve_pred_mode_p (mode)) 3480 return VEC_SVE_PRED; 3481 3482 /* Make the decision based on the mode's enum value rather than its 3483 properties, so that we keep the correct classification regardless 3484 of -msve-vector-bits. */ 3485 switch (mode) 3486 { 3487 /* Partial SVE QI vectors. */ 3488 case E_VNx2QImode: 3489 case E_VNx4QImode: 3490 case E_VNx8QImode: 3491 /* Partial SVE HI vectors. */ 3492 case E_VNx2HImode: 3493 case E_VNx4HImode: 3494 /* Partial SVE SI vector. */ 3495 case E_VNx2SImode: 3496 /* Partial SVE HF vectors. */ 3497 case E_VNx2HFmode: 3498 case E_VNx4HFmode: 3499 /* Partial SVE BF vectors. */ 3500 case E_VNx2BFmode: 3501 case E_VNx4BFmode: 3502 /* Partial SVE SF vector. */ 3503 case E_VNx2SFmode: 3504 return TARGET_SVE ? VEC_SVE_DATA | VEC_PARTIAL : 0; 3505 3506 case E_VNx16QImode: 3507 case E_VNx8HImode: 3508 case E_VNx4SImode: 3509 case E_VNx2DImode: 3510 case E_VNx8BFmode: 3511 case E_VNx8HFmode: 3512 case E_VNx4SFmode: 3513 case E_VNx2DFmode: 3514 return TARGET_SVE ? VEC_SVE_DATA : 0; 3515 3516 /* x2 SVE vectors. */ 3517 case E_VNx32QImode: 3518 case E_VNx16HImode: 3519 case E_VNx8SImode: 3520 case E_VNx4DImode: 3521 case E_VNx16BFmode: 3522 case E_VNx16HFmode: 3523 case E_VNx8SFmode: 3524 case E_VNx4DFmode: 3525 /* x3 SVE vectors. */ 3526 case E_VNx48QImode: 3527 case E_VNx24HImode: 3528 case E_VNx12SImode: 3529 case E_VNx6DImode: 3530 case E_VNx24BFmode: 3531 case E_VNx24HFmode: 3532 case E_VNx12SFmode: 3533 case E_VNx6DFmode: 3534 /* x4 SVE vectors. */ 3535 case E_VNx64QImode: 3536 case E_VNx32HImode: 3537 case E_VNx16SImode: 3538 case E_VNx8DImode: 3539 case E_VNx32BFmode: 3540 case E_VNx32HFmode: 3541 case E_VNx16SFmode: 3542 case E_VNx8DFmode: 3543 return TARGET_SVE ? VEC_SVE_DATA | VEC_STRUCT : 0; 3544 3545 case E_OImode: 3546 case E_CImode: 3547 case E_XImode: 3548 return TARGET_SIMD ? VEC_ADVSIMD | VEC_STRUCT : 0; 3549 3550 /* Structures of 64-bit Advanced SIMD vectors. */ 3551 case E_V2x8QImode: 3552 case E_V2x4HImode: 3553 case E_V2x2SImode: 3554 case E_V2x1DImode: 3555 case E_V2x4BFmode: 3556 case E_V2x4HFmode: 3557 case E_V2x2SFmode: 3558 case E_V2x1DFmode: 3559 case E_V3x8QImode: 3560 case E_V3x4HImode: 3561 case E_V3x2SImode: 3562 case E_V3x1DImode: 3563 case E_V3x4BFmode: 3564 case E_V3x4HFmode: 3565 case E_V3x2SFmode: 3566 case E_V3x1DFmode: 3567 case E_V4x8QImode: 3568 case E_V4x4HImode: 3569 case E_V4x2SImode: 3570 case E_V4x1DImode: 3571 case E_V4x4BFmode: 3572 case E_V4x4HFmode: 3573 case E_V4x2SFmode: 3574 case E_V4x1DFmode: 3575 return TARGET_SIMD ? VEC_ADVSIMD | VEC_STRUCT | VEC_PARTIAL : 0; 3576 3577 /* Structures of 128-bit Advanced SIMD vectors. */ 3578 case E_V2x16QImode: 3579 case E_V2x8HImode: 3580 case E_V2x4SImode: 3581 case E_V2x2DImode: 3582 case E_V2x8BFmode: 3583 case E_V2x8HFmode: 3584 case E_V2x4SFmode: 3585 case E_V2x2DFmode: 3586 case E_V3x16QImode: 3587 case E_V3x8HImode: 3588 case E_V3x4SImode: 3589 case E_V3x2DImode: 3590 case E_V3x8BFmode: 3591 case E_V3x8HFmode: 3592 case E_V3x4SFmode: 3593 case E_V3x2DFmode: 3594 case E_V4x16QImode: 3595 case E_V4x8HImode: 3596 case E_V4x4SImode: 3597 case E_V4x2DImode: 3598 case E_V4x8BFmode: 3599 case E_V4x8HFmode: 3600 case E_V4x4SFmode: 3601 case E_V4x2DFmode: 3602 return TARGET_SIMD ? VEC_ADVSIMD | VEC_STRUCT : 0; 3603 3604 /* 64-bit Advanced SIMD vectors. */ 3605 case E_V8QImode: 3606 case E_V4HImode: 3607 case E_V2SImode: 3608 /* ...E_V1DImode doesn't exist. */ 3609 case E_V4HFmode: 3610 case E_V4BFmode: 3611 case E_V2SFmode: 3612 case E_V1DFmode: 3613 /* 128-bit Advanced SIMD vectors. */ 3614 case E_V16QImode: 3615 case E_V8HImode: 3616 case E_V4SImode: 3617 case E_V2DImode: 3618 case E_V8HFmode: 3619 case E_V8BFmode: 3620 case E_V4SFmode: 3621 case E_V2DFmode: 3622 return TARGET_SIMD ? VEC_ADVSIMD : 0; 3623 3624 default: 3625 return 0; 3626 } 3627 } 3628 3629 /* Return true if MODE is any of the Advanced SIMD structure modes. */ 3630 bool 3631 aarch64_advsimd_struct_mode_p (machine_mode mode) 3632 { 3633 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 3634 return (vec_flags & VEC_ADVSIMD) && (vec_flags & VEC_STRUCT); 3635 } 3636 3637 /* Return true if MODE is an Advanced SIMD D-register structure mode. */ 3638 static bool 3639 aarch64_advsimd_partial_struct_mode_p (machine_mode mode) 3640 { 3641 return (aarch64_classify_vector_mode (mode) 3642 == (VEC_ADVSIMD | VEC_STRUCT | VEC_PARTIAL)); 3643 } 3644 3645 /* Return true if MODE is an Advanced SIMD Q-register structure mode. */ 3646 static bool 3647 aarch64_advsimd_full_struct_mode_p (machine_mode mode) 3648 { 3649 return (aarch64_classify_vector_mode (mode) == (VEC_ADVSIMD | VEC_STRUCT)); 3650 } 3651 3652 /* Return true if MODE is any of the data vector modes, including 3653 structure modes. */ 3654 static bool 3655 aarch64_vector_data_mode_p (machine_mode mode) 3656 { 3657 return aarch64_classify_vector_mode (mode) & VEC_ANY_DATA; 3658 } 3659 3660 /* Return true if MODE is any form of SVE mode, including predicates, 3661 vectors and structures. */ 3662 bool 3663 aarch64_sve_mode_p (machine_mode mode) 3664 { 3665 return aarch64_classify_vector_mode (mode) & VEC_ANY_SVE; 3666 } 3667 3668 /* Return true if MODE is an SVE data vector mode; either a single vector 3669 or a structure of vectors. */ 3670 static bool 3671 aarch64_sve_data_mode_p (machine_mode mode) 3672 { 3673 return aarch64_classify_vector_mode (mode) & VEC_SVE_DATA; 3674 } 3675 3676 /* Return the number of defined bytes in one constituent vector of 3677 SVE mode MODE, which has vector flags VEC_FLAGS. */ 3678 static poly_int64 3679 aarch64_vl_bytes (machine_mode mode, unsigned int vec_flags) 3680 { 3681 if (vec_flags & VEC_PARTIAL) 3682 /* A single partial vector. */ 3683 return GET_MODE_SIZE (mode); 3684 3685 if (vec_flags & VEC_SVE_DATA) 3686 /* A single vector or a tuple. */ 3687 return BYTES_PER_SVE_VECTOR; 3688 3689 /* A single predicate. */ 3690 gcc_assert (vec_flags & VEC_SVE_PRED); 3691 return BYTES_PER_SVE_PRED; 3692 } 3693 3694 /* If MODE holds an array of vectors, return the number of vectors 3695 in the array, otherwise return 1. */ 3696 3697 static unsigned int 3698 aarch64_ldn_stn_vectors (machine_mode mode) 3699 { 3700 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 3701 if (vec_flags == (VEC_ADVSIMD | VEC_PARTIAL | VEC_STRUCT)) 3702 return exact_div (GET_MODE_SIZE (mode), 8).to_constant (); 3703 if (vec_flags == (VEC_ADVSIMD | VEC_STRUCT)) 3704 return exact_div (GET_MODE_SIZE (mode), 16).to_constant (); 3705 if (vec_flags == (VEC_SVE_DATA | VEC_STRUCT)) 3706 return exact_div (GET_MODE_SIZE (mode), 3707 BYTES_PER_SVE_VECTOR).to_constant (); 3708 return 1; 3709 } 3710 3711 /* Given an Advanced SIMD vector mode MODE and a tuple size NELEMS, return the 3712 corresponding vector structure mode. */ 3713 static opt_machine_mode 3714 aarch64_advsimd_vector_array_mode (machine_mode mode, 3715 unsigned HOST_WIDE_INT nelems) 3716 { 3717 unsigned int flags = VEC_ADVSIMD | VEC_STRUCT; 3718 if (known_eq (GET_MODE_SIZE (mode), 8)) 3719 flags |= VEC_PARTIAL; 3720 3721 machine_mode struct_mode; 3722 FOR_EACH_MODE_IN_CLASS (struct_mode, GET_MODE_CLASS (mode)) 3723 if (aarch64_classify_vector_mode (struct_mode) == flags 3724 && GET_MODE_INNER (struct_mode) == GET_MODE_INNER (mode) 3725 && known_eq (GET_MODE_NUNITS (struct_mode), 3726 GET_MODE_NUNITS (mode) * nelems)) 3727 return struct_mode; 3728 return opt_machine_mode (); 3729 } 3730 3731 /* Return the SVE vector mode that has NUNITS elements of mode INNER_MODE. */ 3732 3733 opt_machine_mode 3734 aarch64_sve_data_mode (scalar_mode inner_mode, poly_uint64 nunits) 3735 { 3736 enum mode_class mclass = (is_a <scalar_float_mode> (inner_mode) 3737 ? MODE_VECTOR_FLOAT : MODE_VECTOR_INT); 3738 machine_mode mode; 3739 FOR_EACH_MODE_IN_CLASS (mode, mclass) 3740 if (inner_mode == GET_MODE_INNER (mode) 3741 && known_eq (nunits, GET_MODE_NUNITS (mode)) 3742 && aarch64_sve_data_mode_p (mode)) 3743 return mode; 3744 return opt_machine_mode (); 3745 } 3746 3747 /* Implement target hook TARGET_ARRAY_MODE. */ 3748 static opt_machine_mode 3749 aarch64_array_mode (machine_mode mode, unsigned HOST_WIDE_INT nelems) 3750 { 3751 if (aarch64_classify_vector_mode (mode) == VEC_SVE_DATA 3752 && IN_RANGE (nelems, 2, 4)) 3753 return aarch64_sve_data_mode (GET_MODE_INNER (mode), 3754 GET_MODE_NUNITS (mode) * nelems); 3755 if (aarch64_classify_vector_mode (mode) == VEC_ADVSIMD 3756 && IN_RANGE (nelems, 2, 4)) 3757 return aarch64_advsimd_vector_array_mode (mode, nelems); 3758 3759 return opt_machine_mode (); 3760 } 3761 3762 /* Implement target hook TARGET_ARRAY_MODE_SUPPORTED_P. */ 3763 static bool 3764 aarch64_array_mode_supported_p (machine_mode mode, 3765 unsigned HOST_WIDE_INT nelems) 3766 { 3767 if (TARGET_SIMD 3768 && (AARCH64_VALID_SIMD_QREG_MODE (mode) 3769 || AARCH64_VALID_SIMD_DREG_MODE (mode)) 3770 && (nelems >= 2 && nelems <= 4)) 3771 return true; 3772 3773 return false; 3774 } 3775 3776 /* MODE is some form of SVE vector mode. For data modes, return the number 3777 of vector register bits that each element of MODE occupies, such as 64 3778 for both VNx2DImode and VNx2SImode (where each 32-bit value is stored 3779 in a 64-bit container). For predicate modes, return the number of 3780 data bits controlled by each significant predicate bit. */ 3781 3782 static unsigned int 3783 aarch64_sve_container_bits (machine_mode mode) 3784 { 3785 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 3786 poly_uint64 vector_bits = (vec_flags & (VEC_PARTIAL | VEC_SVE_PRED) 3787 ? BITS_PER_SVE_VECTOR 3788 : GET_MODE_BITSIZE (mode)); 3789 return vector_element_size (vector_bits, GET_MODE_NUNITS (mode)); 3790 } 3791 3792 /* Return the SVE predicate mode to use for elements that have 3793 ELEM_NBYTES bytes, if such a mode exists. */ 3794 3795 opt_machine_mode 3796 aarch64_sve_pred_mode (unsigned int elem_nbytes) 3797 { 3798 if (TARGET_SVE) 3799 { 3800 if (elem_nbytes == 1) 3801 return VNx16BImode; 3802 if (elem_nbytes == 2) 3803 return VNx8BImode; 3804 if (elem_nbytes == 4) 3805 return VNx4BImode; 3806 if (elem_nbytes == 8) 3807 return VNx2BImode; 3808 } 3809 return opt_machine_mode (); 3810 } 3811 3812 /* Return the SVE predicate mode that should be used to control 3813 SVE mode MODE. */ 3814 3815 machine_mode 3816 aarch64_sve_pred_mode (machine_mode mode) 3817 { 3818 unsigned int bits = aarch64_sve_container_bits (mode); 3819 return aarch64_sve_pred_mode (bits / BITS_PER_UNIT).require (); 3820 } 3821 3822 /* Implement TARGET_VECTORIZE_GET_MASK_MODE. */ 3823 3824 static opt_machine_mode 3825 aarch64_get_mask_mode (machine_mode mode) 3826 { 3827 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 3828 if (vec_flags & VEC_SVE_DATA) 3829 return aarch64_sve_pred_mode (mode); 3830 3831 return default_get_mask_mode (mode); 3832 } 3833 3834 /* Return the integer element mode associated with SVE mode MODE. */ 3835 3836 static scalar_int_mode 3837 aarch64_sve_element_int_mode (machine_mode mode) 3838 { 3839 poly_uint64 vector_bits = (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL 3840 ? BITS_PER_SVE_VECTOR 3841 : GET_MODE_BITSIZE (mode)); 3842 unsigned int elt_bits = vector_element_size (vector_bits, 3843 GET_MODE_NUNITS (mode)); 3844 return int_mode_for_size (elt_bits, 0).require (); 3845 } 3846 3847 /* Return an integer element mode that contains exactly 3848 aarch64_sve_container_bits (MODE) bits. This is wider than 3849 aarch64_sve_element_int_mode if MODE is a partial vector, 3850 otherwise it's the same. */ 3851 3852 static scalar_int_mode 3853 aarch64_sve_container_int_mode (machine_mode mode) 3854 { 3855 return int_mode_for_size (aarch64_sve_container_bits (mode), 0).require (); 3856 } 3857 3858 /* Return the integer vector mode associated with SVE mode MODE. 3859 Unlike related_int_vector_mode, this can handle the case in which 3860 MODE is a predicate (and thus has a different total size). */ 3861 3862 machine_mode 3863 aarch64_sve_int_mode (machine_mode mode) 3864 { 3865 scalar_int_mode int_mode = aarch64_sve_element_int_mode (mode); 3866 return aarch64_sve_data_mode (int_mode, GET_MODE_NUNITS (mode)).require (); 3867 } 3868 3869 /* Implement TARGET_VECTORIZE_RELATED_MODE. */ 3870 3871 static opt_machine_mode 3872 aarch64_vectorize_related_mode (machine_mode vector_mode, 3873 scalar_mode element_mode, 3874 poly_uint64 nunits) 3875 { 3876 unsigned int vec_flags = aarch64_classify_vector_mode (vector_mode); 3877 3878 /* If we're operating on SVE vectors, try to return an SVE mode. */ 3879 poly_uint64 sve_nunits; 3880 if ((vec_flags & VEC_SVE_DATA) 3881 && multiple_p (BYTES_PER_SVE_VECTOR, 3882 GET_MODE_SIZE (element_mode), &sve_nunits)) 3883 { 3884 machine_mode sve_mode; 3885 if (maybe_ne (nunits, 0U)) 3886 { 3887 /* Try to find a full or partial SVE mode with exactly 3888 NUNITS units. */ 3889 if (multiple_p (sve_nunits, nunits) 3890 && aarch64_sve_data_mode (element_mode, 3891 nunits).exists (&sve_mode)) 3892 return sve_mode; 3893 } 3894 else 3895 { 3896 /* Take the preferred number of units from the number of bytes 3897 that fit in VECTOR_MODE. We always start by "autodetecting" 3898 a full vector mode with preferred_simd_mode, so vectors 3899 chosen here will also be full vector modes. Then 3900 autovectorize_vector_modes tries smaller starting modes 3901 and thus smaller preferred numbers of units. */ 3902 sve_nunits = ordered_min (sve_nunits, GET_MODE_SIZE (vector_mode)); 3903 if (aarch64_sve_data_mode (element_mode, 3904 sve_nunits).exists (&sve_mode)) 3905 return sve_mode; 3906 } 3907 } 3908 3909 /* Prefer to use 1 128-bit vector instead of 2 64-bit vectors. */ 3910 if ((vec_flags & VEC_ADVSIMD) 3911 && known_eq (nunits, 0U) 3912 && known_eq (GET_MODE_BITSIZE (vector_mode), 64U) 3913 && maybe_ge (GET_MODE_BITSIZE (element_mode) 3914 * GET_MODE_NUNITS (vector_mode), 128U)) 3915 { 3916 machine_mode res = aarch64_simd_container_mode (element_mode, 128); 3917 if (VECTOR_MODE_P (res)) 3918 return res; 3919 } 3920 3921 return default_vectorize_related_mode (vector_mode, element_mode, nunits); 3922 } 3923 3924 /* Implement TARGET_PREFERRED_ELSE_VALUE. For binary operations, 3925 prefer to use the first arithmetic operand as the else value if 3926 the else value doesn't matter, since that exactly matches the SVE 3927 destructive merging form. For ternary operations we could either 3928 pick the first operand and use FMAD-like instructions or the last 3929 operand and use FMLA-like instructions; the latter seems more 3930 natural. */ 3931 3932 static tree 3933 aarch64_preferred_else_value (unsigned, tree, unsigned int nops, tree *ops) 3934 { 3935 return nops == 3 ? ops[2] : ops[0]; 3936 } 3937 3938 /* Implement TARGET_HARD_REGNO_NREGS. */ 3939 3940 static unsigned int 3941 aarch64_hard_regno_nregs (unsigned regno, machine_mode mode) 3942 { 3943 /* ??? Logically we should only need to provide a value when 3944 HARD_REGNO_MODE_OK says that the combination is valid, 3945 but at the moment we need to handle all modes. Just ignore 3946 any runtime parts for registers that can't store them. */ 3947 HOST_WIDE_INT lowest_size = constant_lower_bound (GET_MODE_SIZE (mode)); 3948 switch (aarch64_regno_regclass (regno)) 3949 { 3950 case FP_REGS: 3951 case FP_LO_REGS: 3952 case FP_LO8_REGS: 3953 { 3954 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 3955 if (vec_flags & VEC_SVE_DATA) 3956 return exact_div (GET_MODE_SIZE (mode), 3957 aarch64_vl_bytes (mode, vec_flags)).to_constant (); 3958 if (vec_flags == (VEC_ADVSIMD | VEC_STRUCT | VEC_PARTIAL)) 3959 return GET_MODE_SIZE (mode).to_constant () / 8; 3960 return CEIL (lowest_size, UNITS_PER_VREG); 3961 } 3962 case PR_REGS: 3963 case PR_LO_REGS: 3964 case PR_HI_REGS: 3965 case FFR_REGS: 3966 case PR_AND_FFR_REGS: 3967 return 1; 3968 default: 3969 return CEIL (lowest_size, UNITS_PER_WORD); 3970 } 3971 gcc_unreachable (); 3972 } 3973 3974 /* Implement TARGET_HARD_REGNO_MODE_OK. */ 3975 3976 static bool 3977 aarch64_hard_regno_mode_ok (unsigned regno, machine_mode mode) 3978 { 3979 if (mode == V8DImode) 3980 return IN_RANGE (regno, R0_REGNUM, R23_REGNUM) 3981 && multiple_p (regno - R0_REGNUM, 2); 3982 3983 if (GET_MODE_CLASS (mode) == MODE_CC) 3984 return regno == CC_REGNUM; 3985 3986 if (regno == VG_REGNUM) 3987 /* This must have the same size as _Unwind_Word. */ 3988 return mode == DImode; 3989 3990 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 3991 if (vec_flags & VEC_SVE_PRED) 3992 return pr_or_ffr_regnum_p (regno); 3993 3994 if (pr_or_ffr_regnum_p (regno)) 3995 return false; 3996 3997 if (regno == SP_REGNUM) 3998 /* The purpose of comparing with ptr_mode is to support the 3999 global register variable associated with the stack pointer 4000 register via the syntax of asm ("wsp") in ILP32. */ 4001 return mode == Pmode || mode == ptr_mode; 4002 4003 if (regno == FRAME_POINTER_REGNUM || regno == ARG_POINTER_REGNUM) 4004 return mode == Pmode; 4005 4006 if (GP_REGNUM_P (regno)) 4007 { 4008 if (vec_flags & VEC_ANY_SVE) 4009 return false; 4010 if (known_le (GET_MODE_SIZE (mode), 8)) 4011 return true; 4012 if (known_le (GET_MODE_SIZE (mode), 16)) 4013 return (regno & 1) == 0; 4014 } 4015 else if (FP_REGNUM_P (regno)) 4016 { 4017 if (vec_flags & VEC_STRUCT) 4018 return end_hard_regno (mode, regno) - 1 <= V31_REGNUM; 4019 else 4020 return !VECTOR_MODE_P (mode) || vec_flags != 0; 4021 } 4022 4023 return false; 4024 } 4025 4026 /* Return true if a function with type FNTYPE returns its value in 4027 SVE vector or predicate registers. */ 4028 4029 static bool 4030 aarch64_returns_value_in_sve_regs_p (const_tree fntype) 4031 { 4032 tree return_type = TREE_TYPE (fntype); 4033 4034 pure_scalable_type_info pst_info; 4035 switch (pst_info.analyze (return_type)) 4036 { 4037 case pure_scalable_type_info::IS_PST: 4038 return (pst_info.num_zr () <= NUM_FP_ARG_REGS 4039 && pst_info.num_pr () <= NUM_PR_ARG_REGS); 4040 4041 case pure_scalable_type_info::DOESNT_MATTER: 4042 gcc_assert (aarch64_return_in_memory_1 (return_type)); 4043 return false; 4044 4045 case pure_scalable_type_info::NO_ABI_IDENTITY: 4046 case pure_scalable_type_info::ISNT_PST: 4047 return false; 4048 } 4049 gcc_unreachable (); 4050 } 4051 4052 /* Return true if a function with type FNTYPE takes arguments in 4053 SVE vector or predicate registers. */ 4054 4055 static bool 4056 aarch64_takes_arguments_in_sve_regs_p (const_tree fntype) 4057 { 4058 CUMULATIVE_ARGS args_so_far_v; 4059 aarch64_init_cumulative_args (&args_so_far_v, NULL_TREE, NULL_RTX, 4060 NULL_TREE, 0, true); 4061 cumulative_args_t args_so_far = pack_cumulative_args (&args_so_far_v); 4062 4063 for (tree chain = TYPE_ARG_TYPES (fntype); 4064 chain && chain != void_list_node; 4065 chain = TREE_CHAIN (chain)) 4066 { 4067 tree arg_type = TREE_VALUE (chain); 4068 if (arg_type == error_mark_node) 4069 return false; 4070 4071 function_arg_info arg (arg_type, /*named=*/true); 4072 apply_pass_by_reference_rules (&args_so_far_v, arg); 4073 pure_scalable_type_info pst_info; 4074 if (pst_info.analyze_registers (arg.type)) 4075 { 4076 unsigned int end_zr = args_so_far_v.aapcs_nvrn + pst_info.num_zr (); 4077 unsigned int end_pr = args_so_far_v.aapcs_nprn + pst_info.num_pr (); 4078 gcc_assert (end_zr <= NUM_FP_ARG_REGS && end_pr <= NUM_PR_ARG_REGS); 4079 return true; 4080 } 4081 4082 targetm.calls.function_arg_advance (args_so_far, arg); 4083 } 4084 return false; 4085 } 4086 4087 /* Implement TARGET_FNTYPE_ABI. */ 4088 4089 static const predefined_function_abi & 4090 aarch64_fntype_abi (const_tree fntype) 4091 { 4092 if (lookup_attribute ("aarch64_vector_pcs", TYPE_ATTRIBUTES (fntype))) 4093 return aarch64_simd_abi (); 4094 4095 if (aarch64_returns_value_in_sve_regs_p (fntype) 4096 || aarch64_takes_arguments_in_sve_regs_p (fntype)) 4097 return aarch64_sve_abi (); 4098 4099 return default_function_abi; 4100 } 4101 4102 /* Implement TARGET_COMPATIBLE_VECTOR_TYPES_P. */ 4103 4104 static bool 4105 aarch64_compatible_vector_types_p (const_tree type1, const_tree type2) 4106 { 4107 return (aarch64_sve::builtin_type_p (type1) 4108 == aarch64_sve::builtin_type_p (type2)); 4109 } 4110 4111 /* Return true if we should emit CFI for register REGNO. */ 4112 4113 static bool 4114 aarch64_emit_cfi_for_reg_p (unsigned int regno) 4115 { 4116 return (GP_REGNUM_P (regno) 4117 || !default_function_abi.clobbers_full_reg_p (regno)); 4118 } 4119 4120 /* Return the mode we should use to save and restore register REGNO. */ 4121 4122 static machine_mode 4123 aarch64_reg_save_mode (unsigned int regno) 4124 { 4125 if (GP_REGNUM_P (regno)) 4126 return DImode; 4127 4128 if (FP_REGNUM_P (regno)) 4129 switch (crtl->abi->id ()) 4130 { 4131 case ARM_PCS_AAPCS64: 4132 /* Only the low 64 bits are saved by the base PCS. */ 4133 return DFmode; 4134 4135 case ARM_PCS_SIMD: 4136 /* The vector PCS saves the low 128 bits (which is the full 4137 register on non-SVE targets). */ 4138 return V16QImode; 4139 4140 case ARM_PCS_SVE: 4141 /* Use vectors of DImode for registers that need frame 4142 information, so that the first 64 bytes of the save slot 4143 are always the equivalent of what storing D<n> would give. */ 4144 if (aarch64_emit_cfi_for_reg_p (regno)) 4145 return VNx2DImode; 4146 4147 /* Use vectors of bytes otherwise, so that the layout is 4148 endian-agnostic, and so that we can use LDR and STR for 4149 big-endian targets. */ 4150 return VNx16QImode; 4151 4152 case ARM_PCS_TLSDESC: 4153 case ARM_PCS_UNKNOWN: 4154 break; 4155 } 4156 4157 if (PR_REGNUM_P (regno)) 4158 /* Save the full predicate register. */ 4159 return VNx16BImode; 4160 4161 gcc_unreachable (); 4162 } 4163 4164 /* Implement TARGET_INSN_CALLEE_ABI. */ 4165 4166 const predefined_function_abi & 4167 aarch64_insn_callee_abi (const rtx_insn *insn) 4168 { 4169 rtx pat = PATTERN (insn); 4170 gcc_assert (GET_CODE (pat) == PARALLEL); 4171 rtx unspec = XVECEXP (pat, 0, 1); 4172 gcc_assert (GET_CODE (unspec) == UNSPEC 4173 && XINT (unspec, 1) == UNSPEC_CALLEE_ABI); 4174 return function_abis[INTVAL (XVECEXP (unspec, 0, 0))]; 4175 } 4176 4177 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. The callee only saves 4178 the lower 64 bits of a 128-bit register. Tell the compiler the callee 4179 clobbers the top 64 bits when restoring the bottom 64 bits. */ 4180 4181 static bool 4182 aarch64_hard_regno_call_part_clobbered (unsigned int abi_id, 4183 unsigned int regno, 4184 machine_mode mode) 4185 { 4186 if (FP_REGNUM_P (regno) && abi_id != ARM_PCS_SVE) 4187 { 4188 poly_int64 per_register_size = GET_MODE_SIZE (mode); 4189 unsigned int nregs = hard_regno_nregs (regno, mode); 4190 if (nregs > 1) 4191 per_register_size = exact_div (per_register_size, nregs); 4192 if (abi_id == ARM_PCS_SIMD || abi_id == ARM_PCS_TLSDESC) 4193 return maybe_gt (per_register_size, 16); 4194 return maybe_gt (per_register_size, 8); 4195 } 4196 return false; 4197 } 4198 4199 /* Implement REGMODE_NATURAL_SIZE. */ 4200 poly_uint64 4201 aarch64_regmode_natural_size (machine_mode mode) 4202 { 4203 /* The natural size for SVE data modes is one SVE data vector, 4204 and similarly for predicates. We can't independently modify 4205 anything smaller than that. */ 4206 /* ??? For now, only do this for variable-width SVE registers. 4207 Doing it for constant-sized registers breaks lower-subreg.cc. */ 4208 /* ??? And once that's fixed, we should probably have similar 4209 code for Advanced SIMD. */ 4210 if (!aarch64_sve_vg.is_constant ()) 4211 { 4212 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 4213 if (vec_flags & VEC_SVE_PRED) 4214 return BYTES_PER_SVE_PRED; 4215 if (vec_flags & VEC_SVE_DATA) 4216 return BYTES_PER_SVE_VECTOR; 4217 } 4218 return UNITS_PER_WORD; 4219 } 4220 4221 /* Implement HARD_REGNO_CALLER_SAVE_MODE. */ 4222 machine_mode 4223 aarch64_hard_regno_caller_save_mode (unsigned regno, unsigned, 4224 machine_mode mode) 4225 { 4226 /* The predicate mode determines which bits are significant and 4227 which are "don't care". Decreasing the number of lanes would 4228 lose data while increasing the number of lanes would make bits 4229 unnecessarily significant. */ 4230 if (PR_REGNUM_P (regno)) 4231 return mode; 4232 if (known_lt (GET_MODE_SIZE (mode), 4) 4233 && REG_CAN_CHANGE_MODE_P (regno, mode, SImode) 4234 && REG_CAN_CHANGE_MODE_P (regno, SImode, mode)) 4235 return SImode; 4236 return mode; 4237 } 4238 4239 /* Return true if I's bits are consecutive ones from the MSB. */ 4240 bool 4241 aarch64_high_bits_all_ones_p (HOST_WIDE_INT i) 4242 { 4243 return exact_log2 (-i) != HOST_WIDE_INT_M1; 4244 } 4245 4246 /* Implement TARGET_CONSTANT_ALIGNMENT. Make strings word-aligned so 4247 that strcpy from constants will be faster. */ 4248 4249 static HOST_WIDE_INT 4250 aarch64_constant_alignment (const_tree exp, HOST_WIDE_INT align) 4251 { 4252 if (TREE_CODE (exp) == STRING_CST && !optimize_size) 4253 return MAX (align, BITS_PER_WORD); 4254 return align; 4255 } 4256 4257 /* Return true if calls to DECL should be treated as 4258 long-calls (ie called via a register). */ 4259 static bool 4260 aarch64_decl_is_long_call_p (const_tree decl ATTRIBUTE_UNUSED) 4261 { 4262 return false; 4263 } 4264 4265 /* Return true if calls to symbol-ref SYM should be treated as 4266 long-calls (ie called via a register). */ 4267 bool 4268 aarch64_is_long_call_p (rtx sym) 4269 { 4270 return aarch64_decl_is_long_call_p (SYMBOL_REF_DECL (sym)); 4271 } 4272 4273 /* Return true if calls to symbol-ref SYM should not go through 4274 plt stubs. */ 4275 4276 bool 4277 aarch64_is_noplt_call_p (rtx sym) 4278 { 4279 const_tree decl = SYMBOL_REF_DECL (sym); 4280 4281 if (flag_pic 4282 && decl 4283 && (!flag_plt 4284 || lookup_attribute ("noplt", DECL_ATTRIBUTES (decl))) 4285 && !targetm.binds_local_p (decl)) 4286 return true; 4287 4288 return false; 4289 } 4290 4291 /* Emit an insn that's a simple single-set. Both the operands must be 4292 known to be valid. */ 4293 inline static rtx_insn * 4294 emit_set_insn (rtx x, rtx y) 4295 { 4296 return emit_insn (gen_rtx_SET (x, y)); 4297 } 4298 4299 /* X and Y are two things to compare using CODE. Emit the compare insn and 4300 return the rtx for register 0 in the proper mode. */ 4301 rtx 4302 aarch64_gen_compare_reg (RTX_CODE code, rtx x, rtx y) 4303 { 4304 machine_mode cmp_mode = GET_MODE (x); 4305 machine_mode cc_mode; 4306 rtx cc_reg; 4307 4308 if (cmp_mode == TImode) 4309 { 4310 gcc_assert (code == NE); 4311 4312 cc_mode = CCmode; 4313 cc_reg = gen_rtx_REG (cc_mode, CC_REGNUM); 4314 4315 rtx x_lo = operand_subword (x, 0, 0, TImode); 4316 rtx y_lo = operand_subword (y, 0, 0, TImode); 4317 emit_set_insn (cc_reg, gen_rtx_COMPARE (cc_mode, x_lo, y_lo)); 4318 4319 rtx x_hi = operand_subword (x, 1, 0, TImode); 4320 rtx y_hi = operand_subword (y, 1, 0, TImode); 4321 emit_insn (gen_ccmpccdi (cc_reg, cc_reg, x_hi, y_hi, 4322 gen_rtx_EQ (cc_mode, cc_reg, const0_rtx), 4323 GEN_INT (AARCH64_EQ))); 4324 } 4325 else 4326 { 4327 cc_mode = SELECT_CC_MODE (code, x, y); 4328 cc_reg = gen_rtx_REG (cc_mode, CC_REGNUM); 4329 emit_set_insn (cc_reg, gen_rtx_COMPARE (cc_mode, x, y)); 4330 } 4331 return cc_reg; 4332 } 4333 4334 /* Similarly, but maybe zero-extend Y if Y_MODE < SImode. */ 4335 4336 static rtx 4337 aarch64_gen_compare_reg_maybe_ze (RTX_CODE code, rtx x, rtx y, 4338 machine_mode y_mode) 4339 { 4340 if (y_mode == E_QImode || y_mode == E_HImode) 4341 { 4342 if (CONST_INT_P (y)) 4343 { 4344 y = GEN_INT (INTVAL (y) & GET_MODE_MASK (y_mode)); 4345 y_mode = SImode; 4346 } 4347 else 4348 { 4349 rtx t, cc_reg; 4350 machine_mode cc_mode; 4351 4352 t = gen_rtx_ZERO_EXTEND (SImode, y); 4353 t = gen_rtx_COMPARE (CC_SWPmode, t, x); 4354 cc_mode = CC_SWPmode; 4355 cc_reg = gen_rtx_REG (cc_mode, CC_REGNUM); 4356 emit_set_insn (cc_reg, t); 4357 return cc_reg; 4358 } 4359 } 4360 4361 if (!aarch64_plus_operand (y, y_mode)) 4362 y = force_reg (y_mode, y); 4363 4364 return aarch64_gen_compare_reg (code, x, y); 4365 } 4366 4367 /* Consider the operation: 4368 4369 OPERANDS[0] = CODE (OPERANDS[1], OPERANDS[2]) + OPERANDS[3] 4370 4371 where: 4372 4373 - CODE is [SU]MAX or [SU]MIN 4374 - OPERANDS[2] and OPERANDS[3] are constant integers 4375 - OPERANDS[3] is a positive or negative shifted 12-bit immediate 4376 - all operands have mode MODE 4377 4378 Decide whether it is possible to implement the operation using: 4379 4380 SUBS <tmp>, OPERANDS[1], -OPERANDS[3] 4381 or 4382 ADDS <tmp>, OPERANDS[1], OPERANDS[3] 4383 4384 followed by: 4385 4386 <insn> OPERANDS[0], <tmp>, [wx]zr, <cond> 4387 4388 where <insn> is one of CSEL, CSINV or CSINC. Return true if so. 4389 If GENERATE_P is true, also update OPERANDS as follows: 4390 4391 OPERANDS[4] = -OPERANDS[3] 4392 OPERANDS[5] = the rtl condition representing <cond> 4393 OPERANDS[6] = <tmp> 4394 OPERANDS[7] = 0 for CSEL, -1 for CSINV or 1 for CSINC. */ 4395 bool 4396 aarch64_maxmin_plus_const (rtx_code code, rtx *operands, bool generate_p) 4397 { 4398 signop sgn = (code == UMAX || code == UMIN ? UNSIGNED : SIGNED); 4399 rtx dst = operands[0]; 4400 rtx maxmin_op = operands[2]; 4401 rtx add_op = operands[3]; 4402 machine_mode mode = GET_MODE (dst); 4403 4404 /* max (x, y) - z == (x >= y + 1 ? x : y) - z 4405 == (x >= y ? x : y) - z 4406 == (x > y ? x : y) - z 4407 == (x > y - 1 ? x : y) - z 4408 4409 min (x, y) - z == (x <= y - 1 ? x : y) - z 4410 == (x <= y ? x : y) - z 4411 == (x < y ? x : y) - z 4412 == (x < y + 1 ? x : y) - z 4413 4414 Check whether z is in { y - 1, y, y + 1 } and pick the form(s) for 4415 which x is compared with z. Set DIFF to y - z. Thus the supported 4416 combinations are as follows, with DIFF being the value after the ":": 4417 4418 max (x, y) - z == x >= y + 1 ? x - (y + 1) : -1 [z == y + 1] 4419 == x >= y ? x - y : 0 [z == y] 4420 == x > y ? x - y : 0 [z == y] 4421 == x > y - 1 ? x - (y - 1) : 1 [z == y - 1] 4422 4423 min (x, y) - z == x <= y - 1 ? x - (y - 1) : 1 [z == y - 1] 4424 == x <= y ? x - y : 0 [z == y] 4425 == x < y ? x - y : 0 [z == y] 4426 == x < y + 1 ? x - (y + 1) : -1 [z == y + 1]. */ 4427 auto maxmin_val = rtx_mode_t (maxmin_op, mode); 4428 auto add_val = rtx_mode_t (add_op, mode); 4429 auto sub_val = wi::neg (add_val); 4430 auto diff = wi::sub (maxmin_val, sub_val); 4431 if (!(diff == 0 4432 || (diff == 1 && wi::gt_p (maxmin_val, sub_val, sgn)) 4433 || (diff == -1 && wi::lt_p (maxmin_val, sub_val, sgn)))) 4434 return false; 4435 4436 if (!generate_p) 4437 return true; 4438 4439 rtx_code cmp; 4440 switch (code) 4441 { 4442 case SMAX: 4443 cmp = diff == 1 ? GT : GE; 4444 break; 4445 case UMAX: 4446 cmp = diff == 1 ? GTU : GEU; 4447 break; 4448 case SMIN: 4449 cmp = diff == -1 ? LT : LE; 4450 break; 4451 case UMIN: 4452 cmp = diff == -1 ? LTU : LEU; 4453 break; 4454 default: 4455 gcc_unreachable (); 4456 } 4457 rtx cc = gen_rtx_REG (CCmode, CC_REGNUM); 4458 4459 operands[4] = immed_wide_int_const (sub_val, mode); 4460 operands[5] = gen_rtx_fmt_ee (cmp, VOIDmode, cc, const0_rtx); 4461 if (can_create_pseudo_p ()) 4462 operands[6] = gen_reg_rtx (mode); 4463 else 4464 operands[6] = dst; 4465 operands[7] = immed_wide_int_const (diff, mode); 4466 4467 return true; 4468 } 4469 4470 4471 /* Build the SYMBOL_REF for __tls_get_addr. */ 4472 4473 static GTY(()) rtx tls_get_addr_libfunc; 4474 4475 rtx 4476 aarch64_tls_get_addr (void) 4477 { 4478 if (!tls_get_addr_libfunc) 4479 tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr"); 4480 return tls_get_addr_libfunc; 4481 } 4482 4483 /* Return the TLS model to use for ADDR. */ 4484 4485 static enum tls_model 4486 tls_symbolic_operand_type (rtx addr) 4487 { 4488 enum tls_model tls_kind = TLS_MODEL_NONE; 4489 poly_int64 offset; 4490 addr = strip_offset_and_salt (addr, &offset); 4491 if (SYMBOL_REF_P (addr)) 4492 tls_kind = SYMBOL_REF_TLS_MODEL (addr); 4493 4494 return tls_kind; 4495 } 4496 4497 /* We'll allow lo_sum's in addresses in our legitimate addresses 4498 so that combine would take care of combining addresses where 4499 necessary, but for generation purposes, we'll generate the address 4500 as : 4501 RTL Absolute 4502 tmp = hi (symbol_ref); adrp x1, foo 4503 dest = lo_sum (tmp, symbol_ref); add dest, x1, :lo_12:foo 4504 nop 4505 4506 PIC TLS 4507 adrp x1, :got:foo adrp tmp, :tlsgd:foo 4508 ldr x1, [:got_lo12:foo] add dest, tmp, :tlsgd_lo12:foo 4509 bl __tls_get_addr 4510 nop 4511 4512 Load TLS symbol, depending on TLS mechanism and TLS access model. 4513 4514 Global Dynamic - Traditional TLS: 4515 adrp tmp, :tlsgd:imm 4516 add dest, tmp, #:tlsgd_lo12:imm 4517 bl __tls_get_addr 4518 4519 Global Dynamic - TLS Descriptors: 4520 adrp dest, :tlsdesc:imm 4521 ldr tmp, [dest, #:tlsdesc_lo12:imm] 4522 add dest, dest, #:tlsdesc_lo12:imm 4523 blr tmp 4524 mrs tp, tpidr_el0 4525 add dest, dest, tp 4526 4527 Initial Exec: 4528 mrs tp, tpidr_el0 4529 adrp tmp, :gottprel:imm 4530 ldr dest, [tmp, #:gottprel_lo12:imm] 4531 add dest, dest, tp 4532 4533 Local Exec: 4534 mrs tp, tpidr_el0 4535 add t0, tp, #:tprel_hi12:imm, lsl #12 4536 add t0, t0, #:tprel_lo12_nc:imm 4537 */ 4538 4539 static void 4540 aarch64_load_symref_appropriately (rtx dest, rtx imm, 4541 enum aarch64_symbol_type type) 4542 { 4543 switch (type) 4544 { 4545 case SYMBOL_SMALL_ABSOLUTE: 4546 { 4547 /* In ILP32, the mode of dest can be either SImode or DImode. */ 4548 rtx tmp_reg = dest; 4549 machine_mode mode = GET_MODE (dest); 4550 4551 gcc_assert (mode == Pmode || mode == ptr_mode); 4552 4553 if (can_create_pseudo_p ()) 4554 tmp_reg = gen_reg_rtx (mode); 4555 4556 emit_move_insn (tmp_reg, gen_rtx_HIGH (mode, copy_rtx (imm))); 4557 emit_insn (gen_add_losym (dest, tmp_reg, imm)); 4558 return; 4559 } 4560 4561 case SYMBOL_TINY_ABSOLUTE: 4562 emit_insn (gen_rtx_SET (dest, imm)); 4563 return; 4564 4565 case SYMBOL_SMALL_GOT_28K: 4566 { 4567 machine_mode mode = GET_MODE (dest); 4568 rtx gp_rtx = pic_offset_table_rtx; 4569 rtx insn; 4570 rtx mem; 4571 4572 /* NOTE: pic_offset_table_rtx can be NULL_RTX, because we can reach 4573 here before rtl expand. Tree IVOPT will generate rtl pattern to 4574 decide rtx costs, in which case pic_offset_table_rtx is not 4575 initialized. For that case no need to generate the first adrp 4576 instruction as the final cost for global variable access is 4577 one instruction. */ 4578 if (gp_rtx != NULL) 4579 { 4580 /* -fpic for -mcmodel=small allow 32K GOT table size (but we are 4581 using the page base as GOT base, the first page may be wasted, 4582 in the worst scenario, there is only 28K space for GOT). 4583 4584 The generate instruction sequence for accessing global variable 4585 is: 4586 4587 ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym] 4588 4589 Only one instruction needed. But we must initialize 4590 pic_offset_table_rtx properly. We generate initialize insn for 4591 every global access, and allow CSE to remove all redundant. 4592 4593 The final instruction sequences will look like the following 4594 for multiply global variables access. 4595 4596 adrp pic_offset_table_rtx, _GLOBAL_OFFSET_TABLE_ 4597 4598 ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym1] 4599 ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym2] 4600 ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym3] 4601 ... */ 4602 4603 rtx s = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); 4604 crtl->uses_pic_offset_table = 1; 4605 emit_move_insn (gp_rtx, gen_rtx_HIGH (Pmode, s)); 4606 4607 if (mode != GET_MODE (gp_rtx)) 4608 gp_rtx = gen_lowpart (mode, gp_rtx); 4609 4610 } 4611 4612 if (mode == ptr_mode) 4613 { 4614 if (mode == DImode) 4615 insn = gen_ldr_got_small_28k_di (dest, gp_rtx, imm); 4616 else 4617 insn = gen_ldr_got_small_28k_si (dest, gp_rtx, imm); 4618 4619 mem = XVECEXP (SET_SRC (insn), 0, 0); 4620 } 4621 else 4622 { 4623 gcc_assert (mode == Pmode); 4624 4625 insn = gen_ldr_got_small_28k_sidi (dest, gp_rtx, imm); 4626 mem = XVECEXP (XEXP (SET_SRC (insn), 0), 0, 0); 4627 } 4628 4629 /* The operand is expected to be MEM. Whenever the related insn 4630 pattern changed, above code which calculate mem should be 4631 updated. */ 4632 gcc_assert (MEM_P (mem)); 4633 MEM_READONLY_P (mem) = 1; 4634 MEM_NOTRAP_P (mem) = 1; 4635 emit_insn (insn); 4636 return; 4637 } 4638 4639 case SYMBOL_SMALL_GOT_4G: 4640 emit_insn (gen_rtx_SET (dest, imm)); 4641 return; 4642 4643 case SYMBOL_SMALL_TLSGD: 4644 { 4645 rtx_insn *insns; 4646 /* The return type of __tls_get_addr is the C pointer type 4647 so use ptr_mode. */ 4648 rtx result = gen_rtx_REG (ptr_mode, R0_REGNUM); 4649 rtx tmp_reg = dest; 4650 4651 if (GET_MODE (dest) != ptr_mode) 4652 tmp_reg = can_create_pseudo_p () ? gen_reg_rtx (ptr_mode) : result; 4653 4654 start_sequence (); 4655 if (ptr_mode == SImode) 4656 aarch64_emit_call_insn (gen_tlsgd_small_si (result, imm)); 4657 else 4658 aarch64_emit_call_insn (gen_tlsgd_small_di (result, imm)); 4659 insns = get_insns (); 4660 end_sequence (); 4661 4662 RTL_CONST_CALL_P (insns) = 1; 4663 emit_libcall_block (insns, tmp_reg, result, imm); 4664 /* Convert back to the mode of the dest adding a zero_extend 4665 from SImode (ptr_mode) to DImode (Pmode). */ 4666 if (dest != tmp_reg) 4667 convert_move (dest, tmp_reg, true); 4668 return; 4669 } 4670 4671 case SYMBOL_SMALL_TLSDESC: 4672 { 4673 machine_mode mode = GET_MODE (dest); 4674 rtx x0 = gen_rtx_REG (mode, R0_REGNUM); 4675 rtx tp; 4676 4677 gcc_assert (mode == Pmode || mode == ptr_mode); 4678 4679 /* In ILP32, the got entry is always of SImode size. Unlike 4680 small GOT, the dest is fixed at reg 0. */ 4681 if (TARGET_ILP32) 4682 emit_insn (gen_tlsdesc_small_si (imm)); 4683 else 4684 emit_insn (gen_tlsdesc_small_di (imm)); 4685 tp = aarch64_load_tp (NULL); 4686 4687 if (mode != Pmode) 4688 tp = gen_lowpart (mode, tp); 4689 4690 emit_insn (gen_rtx_SET (dest, gen_rtx_PLUS (mode, tp, x0))); 4691 if (REG_P (dest)) 4692 set_unique_reg_note (get_last_insn (), REG_EQUIV, imm); 4693 return; 4694 } 4695 4696 case SYMBOL_SMALL_TLSIE: 4697 { 4698 /* In ILP32, the mode of dest can be either SImode or DImode, 4699 while the got entry is always of SImode size. The mode of 4700 dest depends on how dest is used: if dest is assigned to a 4701 pointer (e.g. in the memory), it has SImode; it may have 4702 DImode if dest is dereferenced to access the memeory. 4703 This is why we have to handle three different tlsie_small 4704 patterns here (two patterns for ILP32). */ 4705 machine_mode mode = GET_MODE (dest); 4706 rtx tmp_reg = gen_reg_rtx (mode); 4707 rtx tp = aarch64_load_tp (NULL); 4708 4709 if (mode == ptr_mode) 4710 { 4711 if (mode == DImode) 4712 emit_insn (gen_tlsie_small_di (tmp_reg, imm)); 4713 else 4714 { 4715 emit_insn (gen_tlsie_small_si (tmp_reg, imm)); 4716 tp = gen_lowpart (mode, tp); 4717 } 4718 } 4719 else 4720 { 4721 gcc_assert (mode == Pmode); 4722 emit_insn (gen_tlsie_small_sidi (tmp_reg, imm)); 4723 } 4724 4725 emit_insn (gen_rtx_SET (dest, gen_rtx_PLUS (mode, tp, tmp_reg))); 4726 if (REG_P (dest)) 4727 set_unique_reg_note (get_last_insn (), REG_EQUIV, imm); 4728 return; 4729 } 4730 4731 case SYMBOL_TLSLE12: 4732 case SYMBOL_TLSLE24: 4733 case SYMBOL_TLSLE32: 4734 case SYMBOL_TLSLE48: 4735 { 4736 machine_mode mode = GET_MODE (dest); 4737 rtx tp = aarch64_load_tp (NULL); 4738 4739 if (mode != Pmode) 4740 tp = gen_lowpart (mode, tp); 4741 4742 switch (type) 4743 { 4744 case SYMBOL_TLSLE12: 4745 emit_insn ((mode == DImode ? gen_tlsle12_di : gen_tlsle12_si) 4746 (dest, tp, imm)); 4747 break; 4748 case SYMBOL_TLSLE24: 4749 emit_insn ((mode == DImode ? gen_tlsle24_di : gen_tlsle24_si) 4750 (dest, tp, imm)); 4751 break; 4752 case SYMBOL_TLSLE32: 4753 emit_insn ((mode == DImode ? gen_tlsle32_di : gen_tlsle32_si) 4754 (dest, imm)); 4755 emit_insn ((mode == DImode ? gen_adddi3 : gen_addsi3) 4756 (dest, dest, tp)); 4757 break; 4758 case SYMBOL_TLSLE48: 4759 emit_insn ((mode == DImode ? gen_tlsle48_di : gen_tlsle48_si) 4760 (dest, imm)); 4761 emit_insn ((mode == DImode ? gen_adddi3 : gen_addsi3) 4762 (dest, dest, tp)); 4763 break; 4764 default: 4765 gcc_unreachable (); 4766 } 4767 4768 if (REG_P (dest)) 4769 set_unique_reg_note (get_last_insn (), REG_EQUIV, imm); 4770 return; 4771 } 4772 4773 case SYMBOL_TINY_GOT: 4774 { 4775 rtx insn; 4776 machine_mode mode = GET_MODE (dest); 4777 4778 if (mode == ptr_mode) 4779 insn = gen_ldr_got_tiny (mode, dest, imm); 4780 else 4781 { 4782 gcc_assert (mode == Pmode); 4783 insn = gen_ldr_got_tiny_sidi (dest, imm); 4784 } 4785 4786 emit_insn (insn); 4787 return; 4788 } 4789 4790 case SYMBOL_TINY_TLSIE: 4791 { 4792 machine_mode mode = GET_MODE (dest); 4793 rtx tp = aarch64_load_tp (NULL); 4794 4795 if (mode == ptr_mode) 4796 { 4797 if (mode == DImode) 4798 emit_insn (gen_tlsie_tiny_di (dest, imm, tp)); 4799 else 4800 { 4801 tp = gen_lowpart (mode, tp); 4802 emit_insn (gen_tlsie_tiny_si (dest, imm, tp)); 4803 } 4804 } 4805 else 4806 { 4807 gcc_assert (mode == Pmode); 4808 emit_insn (gen_tlsie_tiny_sidi (dest, imm, tp)); 4809 } 4810 4811 if (REG_P (dest)) 4812 set_unique_reg_note (get_last_insn (), REG_EQUIV, imm); 4813 return; 4814 } 4815 4816 default: 4817 gcc_unreachable (); 4818 } 4819 } 4820 4821 /* Emit a move from SRC to DEST. Assume that the move expanders can 4822 handle all moves if !can_create_pseudo_p (). The distinction is 4823 important because, unlike emit_move_insn, the move expanders know 4824 how to force Pmode objects into the constant pool even when the 4825 constant pool address is not itself legitimate. */ 4826 static rtx 4827 aarch64_emit_move (rtx dest, rtx src) 4828 { 4829 return (can_create_pseudo_p () 4830 ? emit_move_insn (dest, src) 4831 : emit_move_insn_1 (dest, src)); 4832 } 4833 4834 /* Apply UNOPTAB to OP and store the result in DEST. */ 4835 4836 static void 4837 aarch64_emit_unop (rtx dest, optab unoptab, rtx op) 4838 { 4839 rtx tmp = expand_unop (GET_MODE (dest), unoptab, op, dest, 0); 4840 if (dest != tmp) 4841 emit_move_insn (dest, tmp); 4842 } 4843 4844 /* Apply BINOPTAB to OP0 and OP1 and store the result in DEST. */ 4845 4846 static void 4847 aarch64_emit_binop (rtx dest, optab binoptab, rtx op0, rtx op1) 4848 { 4849 rtx tmp = expand_binop (GET_MODE (dest), binoptab, op0, op1, dest, 0, 4850 OPTAB_DIRECT); 4851 if (dest != tmp) 4852 emit_move_insn (dest, tmp); 4853 } 4854 4855 /* Split a 128-bit move operation into two 64-bit move operations, 4856 taking care to handle partial overlap of register to register 4857 copies. Special cases are needed when moving between GP regs and 4858 FP regs. SRC can be a register, constant or memory; DST a register 4859 or memory. If either operand is memory it must not have any side 4860 effects. */ 4861 void 4862 aarch64_split_128bit_move (rtx dst, rtx src) 4863 { 4864 rtx dst_lo, dst_hi; 4865 rtx src_lo, src_hi; 4866 4867 machine_mode mode = GET_MODE (dst); 4868 4869 gcc_assert (mode == TImode || mode == TFmode); 4870 gcc_assert (!(side_effects_p (src) || side_effects_p (dst))); 4871 gcc_assert (mode == GET_MODE (src) || GET_MODE (src) == VOIDmode); 4872 4873 if (REG_P (dst) && REG_P (src)) 4874 { 4875 int src_regno = REGNO (src); 4876 int dst_regno = REGNO (dst); 4877 4878 /* Handle FP <-> GP regs. */ 4879 if (FP_REGNUM_P (dst_regno) && GP_REGNUM_P (src_regno)) 4880 { 4881 src_lo = gen_lowpart (word_mode, src); 4882 src_hi = gen_highpart (word_mode, src); 4883 4884 emit_insn (gen_aarch64_movlow_di (mode, dst, src_lo)); 4885 emit_insn (gen_aarch64_movhigh_di (mode, dst, src_hi)); 4886 return; 4887 } 4888 else if (GP_REGNUM_P (dst_regno) && FP_REGNUM_P (src_regno)) 4889 { 4890 dst_lo = gen_lowpart (word_mode, dst); 4891 dst_hi = gen_highpart (word_mode, dst); 4892 4893 emit_insn (gen_aarch64_movdi_low (mode, dst_lo, src)); 4894 emit_insn (gen_aarch64_movdi_high (mode, dst_hi, src)); 4895 return; 4896 } 4897 } 4898 4899 dst_lo = gen_lowpart (word_mode, dst); 4900 dst_hi = gen_highpart (word_mode, dst); 4901 src_lo = gen_lowpart (word_mode, src); 4902 src_hi = gen_highpart_mode (word_mode, mode, src); 4903 4904 /* At most one pairing may overlap. */ 4905 if (reg_overlap_mentioned_p (dst_lo, src_hi)) 4906 { 4907 aarch64_emit_move (dst_hi, src_hi); 4908 aarch64_emit_move (dst_lo, src_lo); 4909 } 4910 else 4911 { 4912 aarch64_emit_move (dst_lo, src_lo); 4913 aarch64_emit_move (dst_hi, src_hi); 4914 } 4915 } 4916 4917 /* Return true if we should split a move from 128-bit value SRC 4918 to 128-bit register DEST. */ 4919 4920 bool 4921 aarch64_split_128bit_move_p (rtx dst, rtx src) 4922 { 4923 if (FP_REGNUM_P (REGNO (dst))) 4924 return REG_P (src) && !FP_REGNUM_P (REGNO (src)); 4925 /* All moves to GPRs need to be split. */ 4926 return true; 4927 } 4928 4929 /* Split a complex SIMD move. */ 4930 4931 void 4932 aarch64_split_simd_move (rtx dst, rtx src) 4933 { 4934 machine_mode src_mode = GET_MODE (src); 4935 machine_mode dst_mode = GET_MODE (dst); 4936 4937 gcc_assert (VECTOR_MODE_P (dst_mode)); 4938 4939 if (REG_P (dst) && REG_P (src)) 4940 { 4941 gcc_assert (VECTOR_MODE_P (src_mode)); 4942 emit_insn (gen_aarch64_split_simd_mov (src_mode, dst, src)); 4943 } 4944 } 4945 4946 bool 4947 aarch64_zero_extend_const_eq (machine_mode xmode, rtx x, 4948 machine_mode ymode, rtx y) 4949 { 4950 rtx r = simplify_const_unary_operation (ZERO_EXTEND, xmode, y, ymode); 4951 gcc_assert (r != NULL); 4952 return rtx_equal_p (x, r); 4953 } 4954 4955 /* Return TARGET if it is nonnull and a register of mode MODE. 4956 Otherwise, return a fresh register of mode MODE if we can, 4957 or TARGET reinterpreted as MODE if we can't. */ 4958 4959 static rtx 4960 aarch64_target_reg (rtx target, machine_mode mode) 4961 { 4962 if (target && REG_P (target) && GET_MODE (target) == mode) 4963 return target; 4964 if (!can_create_pseudo_p ()) 4965 { 4966 gcc_assert (target); 4967 return gen_lowpart (mode, target); 4968 } 4969 return gen_reg_rtx (mode); 4970 } 4971 4972 /* Return a register that contains the constant in BUILDER, given that 4973 the constant is a legitimate move operand. Use TARGET as the register 4974 if it is nonnull and convenient. */ 4975 4976 static rtx 4977 aarch64_emit_set_immediate (rtx target, rtx_vector_builder &builder) 4978 { 4979 rtx src = builder.build (); 4980 target = aarch64_target_reg (target, GET_MODE (src)); 4981 emit_insn (gen_rtx_SET (target, src)); 4982 return target; 4983 } 4984 4985 static rtx 4986 aarch64_force_temporary (machine_mode mode, rtx x, rtx value) 4987 { 4988 if (can_create_pseudo_p ()) 4989 return force_reg (mode, value); 4990 else 4991 { 4992 gcc_assert (x); 4993 aarch64_emit_move (x, value); 4994 return x; 4995 } 4996 } 4997 4998 /* Return true if predicate value X is a constant in which every element 4999 is a CONST_INT. When returning true, describe X in BUILDER as a VNx16BI 5000 value, i.e. as a predicate in which all bits are significant. */ 5001 5002 static bool 5003 aarch64_get_sve_pred_bits (rtx_vector_builder &builder, rtx x) 5004 { 5005 if (!CONST_VECTOR_P (x)) 5006 return false; 5007 5008 unsigned int factor = vector_element_size (GET_MODE_NUNITS (VNx16BImode), 5009 GET_MODE_NUNITS (GET_MODE (x))); 5010 unsigned int npatterns = CONST_VECTOR_NPATTERNS (x) * factor; 5011 unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (x); 5012 builder.new_vector (VNx16BImode, npatterns, nelts_per_pattern); 5013 5014 unsigned int nelts = const_vector_encoded_nelts (x); 5015 for (unsigned int i = 0; i < nelts; ++i) 5016 { 5017 rtx elt = CONST_VECTOR_ENCODED_ELT (x, i); 5018 if (!CONST_INT_P (elt)) 5019 return false; 5020 5021 builder.quick_push (elt); 5022 for (unsigned int j = 1; j < factor; ++j) 5023 builder.quick_push (const0_rtx); 5024 } 5025 builder.finalize (); 5026 return true; 5027 } 5028 5029 /* BUILDER contains a predicate constant of mode VNx16BI. Return the 5030 widest predicate element size it can have (that is, the largest size 5031 for which each element would still be 0 or 1). */ 5032 5033 unsigned int 5034 aarch64_widest_sve_pred_elt_size (rtx_vector_builder &builder) 5035 { 5036 /* Start with the most optimistic assumption: that we only need 5037 one bit per pattern. This is what we will use if only the first 5038 bit in each pattern is ever set. */ 5039 unsigned int mask = GET_MODE_SIZE (DImode); 5040 mask |= builder.npatterns (); 5041 5042 /* Look for set bits. */ 5043 unsigned int nelts = builder.encoded_nelts (); 5044 for (unsigned int i = 1; i < nelts; ++i) 5045 if (INTVAL (builder.elt (i)) != 0) 5046 { 5047 if (i & 1) 5048 return 1; 5049 mask |= i; 5050 } 5051 return mask & -mask; 5052 } 5053 5054 /* If VNx16BImode rtx X is a canonical PTRUE for a predicate mode, 5055 return that predicate mode, otherwise return opt_machine_mode (). */ 5056 5057 opt_machine_mode 5058 aarch64_ptrue_all_mode (rtx x) 5059 { 5060 gcc_assert (GET_MODE (x) == VNx16BImode); 5061 if (!CONST_VECTOR_P (x) 5062 || !CONST_VECTOR_DUPLICATE_P (x) 5063 || !CONST_INT_P (CONST_VECTOR_ENCODED_ELT (x, 0)) 5064 || INTVAL (CONST_VECTOR_ENCODED_ELT (x, 0)) == 0) 5065 return opt_machine_mode (); 5066 5067 unsigned int nelts = const_vector_encoded_nelts (x); 5068 for (unsigned int i = 1; i < nelts; ++i) 5069 if (CONST_VECTOR_ENCODED_ELT (x, i) != const0_rtx) 5070 return opt_machine_mode (); 5071 5072 return aarch64_sve_pred_mode (nelts); 5073 } 5074 5075 /* BUILDER is a predicate constant of mode VNx16BI. Consider the value 5076 that the constant would have with predicate element size ELT_SIZE 5077 (ignoring the upper bits in each element) and return: 5078 5079 * -1 if all bits are set 5080 * N if the predicate has N leading set bits followed by all clear bits 5081 * 0 if the predicate does not have any of these forms. */ 5082 5083 int 5084 aarch64_partial_ptrue_length (rtx_vector_builder &builder, 5085 unsigned int elt_size) 5086 { 5087 /* If nelts_per_pattern is 3, we have set bits followed by clear bits 5088 followed by set bits. */ 5089 if (builder.nelts_per_pattern () == 3) 5090 return 0; 5091 5092 /* Skip over leading set bits. */ 5093 unsigned int nelts = builder.encoded_nelts (); 5094 unsigned int i = 0; 5095 for (; i < nelts; i += elt_size) 5096 if (INTVAL (builder.elt (i)) == 0) 5097 break; 5098 unsigned int vl = i / elt_size; 5099 5100 /* Check for the all-true case. */ 5101 if (i == nelts) 5102 return -1; 5103 5104 /* If nelts_per_pattern is 1, then either VL is zero, or we have a 5105 repeating pattern of set bits followed by clear bits. */ 5106 if (builder.nelts_per_pattern () != 2) 5107 return 0; 5108 5109 /* We have a "foreground" value and a duplicated "background" value. 5110 If the background might repeat and the last set bit belongs to it, 5111 we might have set bits followed by clear bits followed by set bits. */ 5112 if (i > builder.npatterns () && maybe_ne (nelts, builder.full_nelts ())) 5113 return 0; 5114 5115 /* Make sure that the rest are all clear. */ 5116 for (; i < nelts; i += elt_size) 5117 if (INTVAL (builder.elt (i)) != 0) 5118 return 0; 5119 5120 return vl; 5121 } 5122 5123 /* See if there is an svpattern that encodes an SVE predicate of mode 5124 PRED_MODE in which the first VL bits are set and the rest are clear. 5125 Return the pattern if so, otherwise return AARCH64_NUM_SVPATTERNS. 5126 A VL of -1 indicates an all-true vector. */ 5127 5128 aarch64_svpattern 5129 aarch64_svpattern_for_vl (machine_mode pred_mode, int vl) 5130 { 5131 if (vl < 0) 5132 return AARCH64_SV_ALL; 5133 5134 if (maybe_gt (vl, GET_MODE_NUNITS (pred_mode))) 5135 return AARCH64_NUM_SVPATTERNS; 5136 5137 if (vl >= 1 && vl <= 8) 5138 return aarch64_svpattern (AARCH64_SV_VL1 + (vl - 1)); 5139 5140 if (vl >= 16 && vl <= 256 && pow2p_hwi (vl)) 5141 return aarch64_svpattern (AARCH64_SV_VL16 + (exact_log2 (vl) - 4)); 5142 5143 int max_vl; 5144 if (GET_MODE_NUNITS (pred_mode).is_constant (&max_vl)) 5145 { 5146 if (vl == (max_vl / 3) * 3) 5147 return AARCH64_SV_MUL3; 5148 /* These would only trigger for non-power-of-2 lengths. */ 5149 if (vl == (max_vl & -4)) 5150 return AARCH64_SV_MUL4; 5151 if (vl == (1 << floor_log2 (max_vl))) 5152 return AARCH64_SV_POW2; 5153 if (vl == max_vl) 5154 return AARCH64_SV_ALL; 5155 } 5156 return AARCH64_NUM_SVPATTERNS; 5157 } 5158 5159 /* Return a VNx16BImode constant in which every sequence of ELT_SIZE 5160 bits has the lowest bit set and the upper bits clear. This is the 5161 VNx16BImode equivalent of a PTRUE for controlling elements of 5162 ELT_SIZE bytes. However, because the constant is VNx16BImode, 5163 all bits are significant, even the upper zeros. */ 5164 5165 rtx 5166 aarch64_ptrue_all (unsigned int elt_size) 5167 { 5168 rtx_vector_builder builder (VNx16BImode, elt_size, 1); 5169 builder.quick_push (const1_rtx); 5170 for (unsigned int i = 1; i < elt_size; ++i) 5171 builder.quick_push (const0_rtx); 5172 return builder.build (); 5173 } 5174 5175 /* Return an all-true predicate register of mode MODE. */ 5176 5177 rtx 5178 aarch64_ptrue_reg (machine_mode mode) 5179 { 5180 gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL); 5181 rtx reg = force_reg (VNx16BImode, CONSTM1_RTX (VNx16BImode)); 5182 return gen_lowpart (mode, reg); 5183 } 5184 5185 /* Return an all-false predicate register of mode MODE. */ 5186 5187 rtx 5188 aarch64_pfalse_reg (machine_mode mode) 5189 { 5190 gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL); 5191 rtx reg = force_reg (VNx16BImode, CONST0_RTX (VNx16BImode)); 5192 return gen_lowpart (mode, reg); 5193 } 5194 5195 /* PRED1[0] is a PTEST predicate and PRED1[1] is an aarch64_sve_ptrue_flag 5196 for it. PRED2[0] is the predicate for the instruction whose result 5197 is tested by the PTEST and PRED2[1] is again an aarch64_sve_ptrue_flag 5198 for it. Return true if we can prove that the two predicates are 5199 equivalent for PTEST purposes; that is, if we can replace PRED2[0] 5200 with PRED1[0] without changing behavior. */ 5201 5202 bool 5203 aarch64_sve_same_pred_for_ptest_p (rtx *pred1, rtx *pred2) 5204 { 5205 machine_mode mode = GET_MODE (pred1[0]); 5206 gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL 5207 && mode == GET_MODE (pred2[0]) 5208 && aarch64_sve_ptrue_flag (pred1[1], SImode) 5209 && aarch64_sve_ptrue_flag (pred2[1], SImode)); 5210 5211 bool ptrue1_p = (pred1[0] == CONSTM1_RTX (mode) 5212 || INTVAL (pred1[1]) == SVE_KNOWN_PTRUE); 5213 bool ptrue2_p = (pred2[0] == CONSTM1_RTX (mode) 5214 || INTVAL (pred2[1]) == SVE_KNOWN_PTRUE); 5215 return (ptrue1_p && ptrue2_p) || rtx_equal_p (pred1[0], pred2[0]); 5216 } 5217 5218 /* Emit a comparison CMP between OP0 and OP1, both of which have mode 5219 DATA_MODE, and return the result in a predicate of mode PRED_MODE. 5220 Use TARGET as the target register if nonnull and convenient. */ 5221 5222 static rtx 5223 aarch64_sve_emit_int_cmp (rtx target, machine_mode pred_mode, rtx_code cmp, 5224 machine_mode data_mode, rtx op1, rtx op2) 5225 { 5226 insn_code icode = code_for_aarch64_pred_cmp (cmp, data_mode); 5227 expand_operand ops[5]; 5228 create_output_operand (&ops[0], target, pred_mode); 5229 create_input_operand (&ops[1], CONSTM1_RTX (pred_mode), pred_mode); 5230 create_integer_operand (&ops[2], SVE_KNOWN_PTRUE); 5231 create_input_operand (&ops[3], op1, data_mode); 5232 create_input_operand (&ops[4], op2, data_mode); 5233 expand_insn (icode, 5, ops); 5234 return ops[0].value; 5235 } 5236 5237 /* Use a comparison to convert integer vector SRC into MODE, which is 5238 the corresponding SVE predicate mode. Use TARGET for the result 5239 if it's nonnull and convenient. */ 5240 5241 rtx 5242 aarch64_convert_sve_data_to_pred (rtx target, machine_mode mode, rtx src) 5243 { 5244 machine_mode src_mode = GET_MODE (src); 5245 return aarch64_sve_emit_int_cmp (target, mode, NE, src_mode, 5246 src, CONST0_RTX (src_mode)); 5247 } 5248 5249 /* Return the assembly token for svprfop value PRFOP. */ 5250 5251 static const char * 5252 svprfop_token (enum aarch64_svprfop prfop) 5253 { 5254 switch (prfop) 5255 { 5256 #define CASE(UPPER, LOWER, VALUE) case AARCH64_SV_##UPPER: return #LOWER; 5257 AARCH64_FOR_SVPRFOP (CASE) 5258 #undef CASE 5259 case AARCH64_NUM_SVPRFOPS: 5260 break; 5261 } 5262 gcc_unreachable (); 5263 } 5264 5265 /* Return the assembly string for an SVE prefetch operation with 5266 mnemonic MNEMONIC, given that PRFOP_RTX is the prefetch operation 5267 and that SUFFIX is the format for the remaining operands. */ 5268 5269 char * 5270 aarch64_output_sve_prefetch (const char *mnemonic, rtx prfop_rtx, 5271 const char *suffix) 5272 { 5273 static char buffer[128]; 5274 aarch64_svprfop prfop = (aarch64_svprfop) INTVAL (prfop_rtx); 5275 unsigned int written = snprintf (buffer, sizeof (buffer), "%s\t%s, %s", 5276 mnemonic, svprfop_token (prfop), suffix); 5277 gcc_assert (written < sizeof (buffer)); 5278 return buffer; 5279 } 5280 5281 /* Check whether we can calculate the number of elements in PATTERN 5282 at compile time, given that there are NELTS_PER_VQ elements per 5283 128-bit block. Return the value if so, otherwise return -1. */ 5284 5285 HOST_WIDE_INT 5286 aarch64_fold_sve_cnt_pat (aarch64_svpattern pattern, unsigned int nelts_per_vq) 5287 { 5288 unsigned int vl, const_vg; 5289 if (pattern >= AARCH64_SV_VL1 && pattern <= AARCH64_SV_VL8) 5290 vl = 1 + (pattern - AARCH64_SV_VL1); 5291 else if (pattern >= AARCH64_SV_VL16 && pattern <= AARCH64_SV_VL256) 5292 vl = 16 << (pattern - AARCH64_SV_VL16); 5293 else if (aarch64_sve_vg.is_constant (&const_vg)) 5294 { 5295 /* There are two vector granules per quadword. */ 5296 unsigned int nelts = (const_vg / 2) * nelts_per_vq; 5297 switch (pattern) 5298 { 5299 case AARCH64_SV_POW2: return 1 << floor_log2 (nelts); 5300 case AARCH64_SV_MUL4: return nelts & -4; 5301 case AARCH64_SV_MUL3: return (nelts / 3) * 3; 5302 case AARCH64_SV_ALL: return nelts; 5303 default: gcc_unreachable (); 5304 } 5305 } 5306 else 5307 return -1; 5308 5309 /* There are two vector granules per quadword. */ 5310 poly_uint64 nelts_all = exact_div (aarch64_sve_vg, 2) * nelts_per_vq; 5311 if (known_le (vl, nelts_all)) 5312 return vl; 5313 5314 /* Requesting more elements than are available results in a PFALSE. */ 5315 if (known_gt (vl, nelts_all)) 5316 return 0; 5317 5318 return -1; 5319 } 5320 5321 /* Return true if we can move VALUE into a register using a single 5322 CNT[BHWD] instruction. */ 5323 5324 static bool 5325 aarch64_sve_cnt_immediate_p (poly_int64 value) 5326 { 5327 HOST_WIDE_INT factor = value.coeffs[0]; 5328 /* The coefficient must be [1, 16] * {2, 4, 8, 16}. */ 5329 return (value.coeffs[1] == factor 5330 && IN_RANGE (factor, 2, 16 * 16) 5331 && (factor & 1) == 0 5332 && factor <= 16 * (factor & -factor)); 5333 } 5334 5335 /* Likewise for rtx X. */ 5336 5337 bool 5338 aarch64_sve_cnt_immediate_p (rtx x) 5339 { 5340 poly_int64 value; 5341 return poly_int_rtx_p (x, &value) && aarch64_sve_cnt_immediate_p (value); 5342 } 5343 5344 /* Return the asm string for an instruction with a CNT-like vector size 5345 operand (a vector pattern followed by a multiplier in the range [1, 16]). 5346 PREFIX is the mnemonic without the size suffix and OPERANDS is the 5347 first part of the operands template (the part that comes before the 5348 vector size itself). PATTERN is the pattern to use. FACTOR is the 5349 number of quadwords. NELTS_PER_VQ, if nonzero, is the number of elements 5350 in each quadword. If it is zero, we can use any element size. */ 5351 5352 static char * 5353 aarch64_output_sve_cnt_immediate (const char *prefix, const char *operands, 5354 aarch64_svpattern pattern, 5355 unsigned int factor, 5356 unsigned int nelts_per_vq) 5357 { 5358 static char buffer[sizeof ("sqincd\t%x0, %w0, vl256, mul #16")]; 5359 5360 if (nelts_per_vq == 0) 5361 /* There is some overlap in the ranges of the four CNT instructions. 5362 Here we always use the smallest possible element size, so that the 5363 multiplier is 1 whereever possible. */ 5364 nelts_per_vq = factor & -factor; 5365 int shift = std::min (exact_log2 (nelts_per_vq), 4); 5366 gcc_assert (IN_RANGE (shift, 1, 4)); 5367 char suffix = "dwhb"[shift - 1]; 5368 5369 factor >>= shift; 5370 unsigned int written; 5371 if (pattern == AARCH64_SV_ALL && factor == 1) 5372 written = snprintf (buffer, sizeof (buffer), "%s%c\t%s", 5373 prefix, suffix, operands); 5374 else if (factor == 1) 5375 written = snprintf (buffer, sizeof (buffer), "%s%c\t%s, %s", 5376 prefix, suffix, operands, svpattern_token (pattern)); 5377 else 5378 written = snprintf (buffer, sizeof (buffer), "%s%c\t%s, %s, mul #%d", 5379 prefix, suffix, operands, svpattern_token (pattern), 5380 factor); 5381 gcc_assert (written < sizeof (buffer)); 5382 return buffer; 5383 } 5384 5385 /* Return the asm string for an instruction with a CNT-like vector size 5386 operand (a vector pattern followed by a multiplier in the range [1, 16]). 5387 PREFIX is the mnemonic without the size suffix and OPERANDS is the 5388 first part of the operands template (the part that comes before the 5389 vector size itself). X is the value of the vector size operand, 5390 as a polynomial integer rtx; we need to convert this into an "all" 5391 pattern with a multiplier. */ 5392 5393 char * 5394 aarch64_output_sve_cnt_immediate (const char *prefix, const char *operands, 5395 rtx x) 5396 { 5397 poly_int64 value = rtx_to_poly_int64 (x); 5398 gcc_assert (aarch64_sve_cnt_immediate_p (value)); 5399 return aarch64_output_sve_cnt_immediate (prefix, operands, AARCH64_SV_ALL, 5400 value.coeffs[1], 0); 5401 } 5402 5403 /* Return the asm string for an instruction with a CNT-like vector size 5404 operand (a vector pattern followed by a multiplier in the range [1, 16]). 5405 PREFIX is the mnemonic without the size suffix and OPERANDS is the 5406 first part of the operands template (the part that comes before the 5407 vector size itself). CNT_PAT[0..2] are the operands of the 5408 UNSPEC_SVE_CNT_PAT; see aarch64_sve_cnt_pat for details. */ 5409 5410 char * 5411 aarch64_output_sve_cnt_pat_immediate (const char *prefix, 5412 const char *operands, rtx *cnt_pat) 5413 { 5414 aarch64_svpattern pattern = (aarch64_svpattern) INTVAL (cnt_pat[0]); 5415 unsigned int nelts_per_vq = INTVAL (cnt_pat[1]); 5416 unsigned int factor = INTVAL (cnt_pat[2]) * nelts_per_vq; 5417 return aarch64_output_sve_cnt_immediate (prefix, operands, pattern, 5418 factor, nelts_per_vq); 5419 } 5420 5421 /* Return true if we can add X using a single SVE INC or DEC instruction. */ 5422 5423 bool 5424 aarch64_sve_scalar_inc_dec_immediate_p (rtx x) 5425 { 5426 poly_int64 value; 5427 return (poly_int_rtx_p (x, &value) 5428 && (aarch64_sve_cnt_immediate_p (value) 5429 || aarch64_sve_cnt_immediate_p (-value))); 5430 } 5431 5432 /* Return the asm string for adding SVE INC/DEC immediate OFFSET to 5433 operand 0. */ 5434 5435 char * 5436 aarch64_output_sve_scalar_inc_dec (rtx offset) 5437 { 5438 poly_int64 offset_value = rtx_to_poly_int64 (offset); 5439 gcc_assert (offset_value.coeffs[0] == offset_value.coeffs[1]); 5440 if (offset_value.coeffs[1] > 0) 5441 return aarch64_output_sve_cnt_immediate ("inc", "%x0", AARCH64_SV_ALL, 5442 offset_value.coeffs[1], 0); 5443 else 5444 return aarch64_output_sve_cnt_immediate ("dec", "%x0", AARCH64_SV_ALL, 5445 -offset_value.coeffs[1], 0); 5446 } 5447 5448 /* Return true if we can add VALUE to a register using a single ADDVL 5449 or ADDPL instruction. */ 5450 5451 static bool 5452 aarch64_sve_addvl_addpl_immediate_p (poly_int64 value) 5453 { 5454 HOST_WIDE_INT factor = value.coeffs[0]; 5455 if (factor == 0 || value.coeffs[1] != factor) 5456 return false; 5457 /* FACTOR counts VG / 2, so a value of 2 is one predicate width 5458 and a value of 16 is one vector width. */ 5459 return (((factor & 15) == 0 && IN_RANGE (factor, -32 * 16, 31 * 16)) 5460 || ((factor & 1) == 0 && IN_RANGE (factor, -32 * 2, 31 * 2))); 5461 } 5462 5463 /* Likewise for rtx X. */ 5464 5465 bool 5466 aarch64_sve_addvl_addpl_immediate_p (rtx x) 5467 { 5468 poly_int64 value; 5469 return (poly_int_rtx_p (x, &value) 5470 && aarch64_sve_addvl_addpl_immediate_p (value)); 5471 } 5472 5473 /* Return the asm string for adding ADDVL or ADDPL immediate OFFSET 5474 to operand 1 and storing the result in operand 0. */ 5475 5476 char * 5477 aarch64_output_sve_addvl_addpl (rtx offset) 5478 { 5479 static char buffer[sizeof ("addpl\t%x0, %x1, #-") + 3 * sizeof (int)]; 5480 poly_int64 offset_value = rtx_to_poly_int64 (offset); 5481 gcc_assert (aarch64_sve_addvl_addpl_immediate_p (offset_value)); 5482 5483 int factor = offset_value.coeffs[1]; 5484 if ((factor & 15) == 0) 5485 snprintf (buffer, sizeof (buffer), "addvl\t%%x0, %%x1, #%d", factor / 16); 5486 else 5487 snprintf (buffer, sizeof (buffer), "addpl\t%%x0, %%x1, #%d", factor / 2); 5488 return buffer; 5489 } 5490 5491 /* Return true if X is a valid immediate for an SVE vector INC or DEC 5492 instruction. If it is, store the number of elements in each vector 5493 quadword in *NELTS_PER_VQ_OUT (if nonnull) and store the multiplication 5494 factor in *FACTOR_OUT (if nonnull). */ 5495 5496 bool 5497 aarch64_sve_vector_inc_dec_immediate_p (rtx x, int *factor_out, 5498 unsigned int *nelts_per_vq_out) 5499 { 5500 rtx elt; 5501 poly_int64 value; 5502 5503 if (!const_vec_duplicate_p (x, &elt) 5504 || !poly_int_rtx_p (elt, &value)) 5505 return false; 5506 5507 unsigned int nelts_per_vq = 128 / GET_MODE_UNIT_BITSIZE (GET_MODE (x)); 5508 if (nelts_per_vq != 8 && nelts_per_vq != 4 && nelts_per_vq != 2) 5509 /* There's no vector INCB. */ 5510 return false; 5511 5512 HOST_WIDE_INT factor = value.coeffs[0]; 5513 if (value.coeffs[1] != factor) 5514 return false; 5515 5516 /* The coefficient must be [1, 16] * NELTS_PER_VQ. */ 5517 if ((factor % nelts_per_vq) != 0 5518 || !IN_RANGE (abs (factor), nelts_per_vq, 16 * nelts_per_vq)) 5519 return false; 5520 5521 if (factor_out) 5522 *factor_out = factor; 5523 if (nelts_per_vq_out) 5524 *nelts_per_vq_out = nelts_per_vq; 5525 return true; 5526 } 5527 5528 /* Return true if X is a valid immediate for an SVE vector INC or DEC 5529 instruction. */ 5530 5531 bool 5532 aarch64_sve_vector_inc_dec_immediate_p (rtx x) 5533 { 5534 return aarch64_sve_vector_inc_dec_immediate_p (x, NULL, NULL); 5535 } 5536 5537 /* Return the asm template for an SVE vector INC or DEC instruction. 5538 OPERANDS gives the operands before the vector count and X is the 5539 value of the vector count operand itself. */ 5540 5541 char * 5542 aarch64_output_sve_vector_inc_dec (const char *operands, rtx x) 5543 { 5544 int factor; 5545 unsigned int nelts_per_vq; 5546 if (!aarch64_sve_vector_inc_dec_immediate_p (x, &factor, &nelts_per_vq)) 5547 gcc_unreachable (); 5548 if (factor < 0) 5549 return aarch64_output_sve_cnt_immediate ("dec", operands, AARCH64_SV_ALL, 5550 -factor, nelts_per_vq); 5551 else 5552 return aarch64_output_sve_cnt_immediate ("inc", operands, AARCH64_SV_ALL, 5553 factor, nelts_per_vq); 5554 } 5555 5556 static int 5557 aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate, 5558 scalar_int_mode mode) 5559 { 5560 int i; 5561 unsigned HOST_WIDE_INT val, val2, mask; 5562 int one_match, zero_match; 5563 int num_insns; 5564 5565 val = INTVAL (imm); 5566 5567 if (aarch64_move_imm (val, mode)) 5568 { 5569 if (generate) 5570 emit_insn (gen_rtx_SET (dest, imm)); 5571 return 1; 5572 } 5573 5574 /* Check to see if the low 32 bits are either 0xffffXXXX or 0xXXXXffff 5575 (with XXXX non-zero). In that case check to see if the move can be done in 5576 a smaller mode. */ 5577 val2 = val & 0xffffffff; 5578 if (mode == DImode 5579 && aarch64_move_imm (val2, SImode) 5580 && (((val >> 32) & 0xffff) == 0 || (val >> 48) == 0)) 5581 { 5582 if (generate) 5583 emit_insn (gen_rtx_SET (dest, GEN_INT (val2))); 5584 5585 /* Check if we have to emit a second instruction by checking to see 5586 if any of the upper 32 bits of the original DI mode value is set. */ 5587 if (val == val2) 5588 return 1; 5589 5590 i = (val >> 48) ? 48 : 32; 5591 5592 if (generate) 5593 emit_insn (gen_insv_immdi (dest, GEN_INT (i), 5594 GEN_INT ((val >> i) & 0xffff))); 5595 5596 return 2; 5597 } 5598 5599 if ((val >> 32) == 0 || mode == SImode) 5600 { 5601 if (generate) 5602 { 5603 emit_insn (gen_rtx_SET (dest, GEN_INT (val & 0xffff))); 5604 if (mode == SImode) 5605 emit_insn (gen_insv_immsi (dest, GEN_INT (16), 5606 GEN_INT ((val >> 16) & 0xffff))); 5607 else 5608 emit_insn (gen_insv_immdi (dest, GEN_INT (16), 5609 GEN_INT ((val >> 16) & 0xffff))); 5610 } 5611 return 2; 5612 } 5613 5614 /* Remaining cases are all for DImode. */ 5615 5616 mask = 0xffff; 5617 zero_match = ((val & mask) == 0) + ((val & (mask << 16)) == 0) + 5618 ((val & (mask << 32)) == 0) + ((val & (mask << 48)) == 0); 5619 one_match = ((~val & mask) == 0) + ((~val & (mask << 16)) == 0) + 5620 ((~val & (mask << 32)) == 0) + ((~val & (mask << 48)) == 0); 5621 5622 if (zero_match != 2 && one_match != 2) 5623 { 5624 /* Try emitting a bitmask immediate with a movk replacing 16 bits. 5625 For a 64-bit bitmask try whether changing 16 bits to all ones or 5626 zeroes creates a valid bitmask. To check any repeated bitmask, 5627 try using 16 bits from the other 32-bit half of val. */ 5628 5629 for (i = 0; i < 64; i += 16, mask <<= 16) 5630 { 5631 val2 = val & ~mask; 5632 if (val2 != val && aarch64_bitmask_imm (val2, mode)) 5633 break; 5634 val2 = val | mask; 5635 if (val2 != val && aarch64_bitmask_imm (val2, mode)) 5636 break; 5637 val2 = val2 & ~mask; 5638 val2 = val2 | (((val2 >> 32) | (val2 << 32)) & mask); 5639 if (val2 != val && aarch64_bitmask_imm (val2, mode)) 5640 break; 5641 } 5642 if (i != 64) 5643 { 5644 if (generate) 5645 { 5646 emit_insn (gen_rtx_SET (dest, GEN_INT (val2))); 5647 emit_insn (gen_insv_immdi (dest, GEN_INT (i), 5648 GEN_INT ((val >> i) & 0xffff))); 5649 } 5650 return 2; 5651 } 5652 } 5653 5654 /* Generate 2-4 instructions, skipping 16 bits of all zeroes or ones which 5655 are emitted by the initial mov. If one_match > zero_match, skip set bits, 5656 otherwise skip zero bits. */ 5657 5658 num_insns = 1; 5659 mask = 0xffff; 5660 val2 = one_match > zero_match ? ~val : val; 5661 i = (val2 & mask) != 0 ? 0 : (val2 & (mask << 16)) != 0 ? 16 : 32; 5662 5663 if (generate) 5664 emit_insn (gen_rtx_SET (dest, GEN_INT (one_match > zero_match 5665 ? (val | ~(mask << i)) 5666 : (val & (mask << i))))); 5667 for (i += 16; i < 64; i += 16) 5668 { 5669 if ((val2 & (mask << i)) == 0) 5670 continue; 5671 if (generate) 5672 emit_insn (gen_insv_immdi (dest, GEN_INT (i), 5673 GEN_INT ((val >> i) & 0xffff))); 5674 num_insns ++; 5675 } 5676 5677 return num_insns; 5678 } 5679 5680 /* Return whether imm is a 128-bit immediate which is simple enough to 5681 expand inline. */ 5682 bool 5683 aarch64_mov128_immediate (rtx imm) 5684 { 5685 if (CONST_INT_P (imm)) 5686 return true; 5687 5688 gcc_assert (CONST_WIDE_INT_NUNITS (imm) == 2); 5689 5690 rtx lo = GEN_INT (CONST_WIDE_INT_ELT (imm, 0)); 5691 rtx hi = GEN_INT (CONST_WIDE_INT_ELT (imm, 1)); 5692 5693 return aarch64_internal_mov_immediate (NULL_RTX, lo, false, DImode) 5694 + aarch64_internal_mov_immediate (NULL_RTX, hi, false, DImode) <= 4; 5695 } 5696 5697 5698 /* Return the number of temporary registers that aarch64_add_offset_1 5699 would need to add OFFSET to a register. */ 5700 5701 static unsigned int 5702 aarch64_add_offset_1_temporaries (HOST_WIDE_INT offset) 5703 { 5704 return absu_hwi (offset) < 0x1000000 ? 0 : 1; 5705 } 5706 5707 /* A subroutine of aarch64_add_offset. Set DEST to SRC + OFFSET for 5708 a non-polynomial OFFSET. MODE is the mode of the addition. 5709 FRAME_RELATED_P is true if the RTX_FRAME_RELATED flag should 5710 be set and CFA adjustments added to the generated instructions. 5711 5712 TEMP1, if nonnull, is a register of mode MODE that can be used as a 5713 temporary if register allocation is already complete. This temporary 5714 register may overlap DEST but must not overlap SRC. If TEMP1 is known 5715 to hold abs (OFFSET), EMIT_MOVE_IMM can be set to false to avoid emitting 5716 the immediate again. 5717 5718 Since this function may be used to adjust the stack pointer, we must 5719 ensure that it cannot cause transient stack deallocation (for example 5720 by first incrementing SP and then decrementing when adjusting by a 5721 large immediate). */ 5722 5723 static void 5724 aarch64_add_offset_1 (scalar_int_mode mode, rtx dest, 5725 rtx src, HOST_WIDE_INT offset, rtx temp1, 5726 bool frame_related_p, bool emit_move_imm) 5727 { 5728 gcc_assert (emit_move_imm || temp1 != NULL_RTX); 5729 gcc_assert (temp1 == NULL_RTX || !reg_overlap_mentioned_p (temp1, src)); 5730 5731 unsigned HOST_WIDE_INT moffset = absu_hwi (offset); 5732 rtx_insn *insn; 5733 5734 if (!moffset) 5735 { 5736 if (!rtx_equal_p (dest, src)) 5737 { 5738 insn = emit_insn (gen_rtx_SET (dest, src)); 5739 RTX_FRAME_RELATED_P (insn) = frame_related_p; 5740 } 5741 return; 5742 } 5743 5744 /* Single instruction adjustment. */ 5745 if (aarch64_uimm12_shift (moffset)) 5746 { 5747 insn = emit_insn (gen_add3_insn (dest, src, GEN_INT (offset))); 5748 RTX_FRAME_RELATED_P (insn) = frame_related_p; 5749 return; 5750 } 5751 5752 /* Emit 2 additions/subtractions if the adjustment is less than 24 bits 5753 and either: 5754 5755 a) the offset cannot be loaded by a 16-bit move or 5756 b) there is no spare register into which we can move it. */ 5757 if (moffset < 0x1000000 5758 && ((!temp1 && !can_create_pseudo_p ()) 5759 || !aarch64_move_imm (moffset, mode))) 5760 { 5761 HOST_WIDE_INT low_off = moffset & 0xfff; 5762 5763 low_off = offset < 0 ? -low_off : low_off; 5764 insn = emit_insn (gen_add3_insn (dest, src, GEN_INT (low_off))); 5765 RTX_FRAME_RELATED_P (insn) = frame_related_p; 5766 insn = emit_insn (gen_add2_insn (dest, GEN_INT (offset - low_off))); 5767 RTX_FRAME_RELATED_P (insn) = frame_related_p; 5768 return; 5769 } 5770 5771 /* Emit a move immediate if required and an addition/subtraction. */ 5772 if (emit_move_imm) 5773 { 5774 gcc_assert (temp1 != NULL_RTX || can_create_pseudo_p ()); 5775 temp1 = aarch64_force_temporary (mode, temp1, 5776 gen_int_mode (moffset, mode)); 5777 } 5778 insn = emit_insn (offset < 0 5779 ? gen_sub3_insn (dest, src, temp1) 5780 : gen_add3_insn (dest, src, temp1)); 5781 if (frame_related_p) 5782 { 5783 RTX_FRAME_RELATED_P (insn) = frame_related_p; 5784 rtx adj = plus_constant (mode, src, offset); 5785 add_reg_note (insn, REG_CFA_ADJUST_CFA, gen_rtx_SET (dest, adj)); 5786 } 5787 } 5788 5789 /* Return the number of temporary registers that aarch64_add_offset 5790 would need to move OFFSET into a register or add OFFSET to a register; 5791 ADD_P is true if we want the latter rather than the former. */ 5792 5793 static unsigned int 5794 aarch64_offset_temporaries (bool add_p, poly_int64 offset) 5795 { 5796 /* This follows the same structure as aarch64_add_offset. */ 5797 if (add_p && aarch64_sve_addvl_addpl_immediate_p (offset)) 5798 return 0; 5799 5800 unsigned int count = 0; 5801 HOST_WIDE_INT factor = offset.coeffs[1]; 5802 HOST_WIDE_INT constant = offset.coeffs[0] - factor; 5803 poly_int64 poly_offset (factor, factor); 5804 if (add_p && aarch64_sve_addvl_addpl_immediate_p (poly_offset)) 5805 /* Need one register for the ADDVL/ADDPL result. */ 5806 count += 1; 5807 else if (factor != 0) 5808 { 5809 factor = abs (factor); 5810 if (factor > 16 * (factor & -factor)) 5811 /* Need one register for the CNT result and one for the multiplication 5812 factor. If necessary, the second temporary can be reused for the 5813 constant part of the offset. */ 5814 return 2; 5815 /* Need one register for the CNT result (which might then 5816 be shifted). */ 5817 count += 1; 5818 } 5819 return count + aarch64_add_offset_1_temporaries (constant); 5820 } 5821 5822 /* If X can be represented as a poly_int64, return the number 5823 of temporaries that are required to add it to a register. 5824 Return -1 otherwise. */ 5825 5826 int 5827 aarch64_add_offset_temporaries (rtx x) 5828 { 5829 poly_int64 offset; 5830 if (!poly_int_rtx_p (x, &offset)) 5831 return -1; 5832 return aarch64_offset_temporaries (true, offset); 5833 } 5834 5835 /* Set DEST to SRC + OFFSET. MODE is the mode of the addition. 5836 FRAME_RELATED_P is true if the RTX_FRAME_RELATED flag should 5837 be set and CFA adjustments added to the generated instructions. 5838 5839 TEMP1, if nonnull, is a register of mode MODE that can be used as a 5840 temporary if register allocation is already complete. This temporary 5841 register may overlap DEST if !FRAME_RELATED_P but must not overlap SRC. 5842 If TEMP1 is known to hold abs (OFFSET), EMIT_MOVE_IMM can be set to 5843 false to avoid emitting the immediate again. 5844 5845 TEMP2, if nonnull, is a second temporary register that doesn't 5846 overlap either DEST or REG. 5847 5848 Since this function may be used to adjust the stack pointer, we must 5849 ensure that it cannot cause transient stack deallocation (for example 5850 by first incrementing SP and then decrementing when adjusting by a 5851 large immediate). */ 5852 5853 static void 5854 aarch64_add_offset (scalar_int_mode mode, rtx dest, rtx src, 5855 poly_int64 offset, rtx temp1, rtx temp2, 5856 bool frame_related_p, bool emit_move_imm = true) 5857 { 5858 gcc_assert (emit_move_imm || temp1 != NULL_RTX); 5859 gcc_assert (temp1 == NULL_RTX || !reg_overlap_mentioned_p (temp1, src)); 5860 gcc_assert (temp1 == NULL_RTX 5861 || !frame_related_p 5862 || !reg_overlap_mentioned_p (temp1, dest)); 5863 gcc_assert (temp2 == NULL_RTX || !reg_overlap_mentioned_p (dest, temp2)); 5864 5865 /* Try using ADDVL or ADDPL to add the whole value. */ 5866 if (src != const0_rtx && aarch64_sve_addvl_addpl_immediate_p (offset)) 5867 { 5868 rtx offset_rtx = gen_int_mode (offset, mode); 5869 rtx_insn *insn = emit_insn (gen_add3_insn (dest, src, offset_rtx)); 5870 RTX_FRAME_RELATED_P (insn) = frame_related_p; 5871 return; 5872 } 5873 5874 /* Coefficient 1 is multiplied by the number of 128-bit blocks in an 5875 SVE vector register, over and above the minimum size of 128 bits. 5876 This is equivalent to half the value returned by CNTD with a 5877 vector shape of ALL. */ 5878 HOST_WIDE_INT factor = offset.coeffs[1]; 5879 HOST_WIDE_INT constant = offset.coeffs[0] - factor; 5880 5881 /* Try using ADDVL or ADDPL to add the VG-based part. */ 5882 poly_int64 poly_offset (factor, factor); 5883 if (src != const0_rtx 5884 && aarch64_sve_addvl_addpl_immediate_p (poly_offset)) 5885 { 5886 rtx offset_rtx = gen_int_mode (poly_offset, mode); 5887 if (frame_related_p) 5888 { 5889 rtx_insn *insn = emit_insn (gen_add3_insn (dest, src, offset_rtx)); 5890 RTX_FRAME_RELATED_P (insn) = true; 5891 src = dest; 5892 } 5893 else 5894 { 5895 rtx addr = gen_rtx_PLUS (mode, src, offset_rtx); 5896 src = aarch64_force_temporary (mode, temp1, addr); 5897 temp1 = temp2; 5898 temp2 = NULL_RTX; 5899 } 5900 } 5901 /* Otherwise use a CNT-based sequence. */ 5902 else if (factor != 0) 5903 { 5904 /* Use a subtraction if we have a negative factor. */ 5905 rtx_code code = PLUS; 5906 if (factor < 0) 5907 { 5908 factor = -factor; 5909 code = MINUS; 5910 } 5911 5912 /* Calculate CNTD * FACTOR / 2. First try to fold the division 5913 into the multiplication. */ 5914 rtx val; 5915 int shift = 0; 5916 if (factor & 1) 5917 /* Use a right shift by 1. */ 5918 shift = -1; 5919 else 5920 factor /= 2; 5921 HOST_WIDE_INT low_bit = factor & -factor; 5922 if (factor <= 16 * low_bit) 5923 { 5924 if (factor > 16 * 8) 5925 { 5926 /* "CNTB Xn, ALL, MUL #FACTOR" is out of range, so calculate 5927 the value with the minimum multiplier and shift it into 5928 position. */ 5929 int extra_shift = exact_log2 (low_bit); 5930 shift += extra_shift; 5931 factor >>= extra_shift; 5932 } 5933 val = gen_int_mode (poly_int64 (factor * 2, factor * 2), mode); 5934 } 5935 else 5936 { 5937 /* Base the factor on LOW_BIT if we can calculate LOW_BIT 5938 directly, since that should increase the chances of being 5939 able to use a shift and add sequence. If LOW_BIT itself 5940 is out of range, just use CNTD. */ 5941 if (low_bit <= 16 * 8) 5942 factor /= low_bit; 5943 else 5944 low_bit = 1; 5945 5946 val = gen_int_mode (poly_int64 (low_bit * 2, low_bit * 2), mode); 5947 val = aarch64_force_temporary (mode, temp1, val); 5948 5949 if (can_create_pseudo_p ()) 5950 { 5951 rtx coeff1 = gen_int_mode (factor, mode); 5952 val = expand_mult (mode, val, coeff1, NULL_RTX, true, true); 5953 } 5954 else 5955 { 5956 /* Go back to using a negative multiplication factor if we have 5957 no register from which to subtract. */ 5958 if (code == MINUS && src == const0_rtx) 5959 { 5960 factor = -factor; 5961 code = PLUS; 5962 } 5963 rtx coeff1 = gen_int_mode (factor, mode); 5964 coeff1 = aarch64_force_temporary (mode, temp2, coeff1); 5965 val = gen_rtx_MULT (mode, val, coeff1); 5966 } 5967 } 5968 5969 if (shift > 0) 5970 { 5971 /* Multiply by 1 << SHIFT. */ 5972 val = aarch64_force_temporary (mode, temp1, val); 5973 val = gen_rtx_ASHIFT (mode, val, GEN_INT (shift)); 5974 } 5975 else if (shift == -1) 5976 { 5977 /* Divide by 2. */ 5978 val = aarch64_force_temporary (mode, temp1, val); 5979 val = gen_rtx_ASHIFTRT (mode, val, const1_rtx); 5980 } 5981 5982 /* Calculate SRC +/- CNTD * FACTOR / 2. */ 5983 if (src != const0_rtx) 5984 { 5985 val = aarch64_force_temporary (mode, temp1, val); 5986 val = gen_rtx_fmt_ee (code, mode, src, val); 5987 } 5988 else if (code == MINUS) 5989 { 5990 val = aarch64_force_temporary (mode, temp1, val); 5991 val = gen_rtx_NEG (mode, val); 5992 } 5993 5994 if (constant == 0 || frame_related_p) 5995 { 5996 rtx_insn *insn = emit_insn (gen_rtx_SET (dest, val)); 5997 if (frame_related_p) 5998 { 5999 RTX_FRAME_RELATED_P (insn) = true; 6000 add_reg_note (insn, REG_CFA_ADJUST_CFA, 6001 gen_rtx_SET (dest, plus_constant (Pmode, src, 6002 poly_offset))); 6003 } 6004 src = dest; 6005 if (constant == 0) 6006 return; 6007 } 6008 else 6009 { 6010 src = aarch64_force_temporary (mode, temp1, val); 6011 temp1 = temp2; 6012 temp2 = NULL_RTX; 6013 } 6014 6015 emit_move_imm = true; 6016 } 6017 6018 aarch64_add_offset_1 (mode, dest, src, constant, temp1, 6019 frame_related_p, emit_move_imm); 6020 } 6021 6022 /* Like aarch64_add_offset, but the offset is given as an rtx rather 6023 than a poly_int64. */ 6024 6025 void 6026 aarch64_split_add_offset (scalar_int_mode mode, rtx dest, rtx src, 6027 rtx offset_rtx, rtx temp1, rtx temp2) 6028 { 6029 aarch64_add_offset (mode, dest, src, rtx_to_poly_int64 (offset_rtx), 6030 temp1, temp2, false); 6031 } 6032 6033 /* Add DELTA to the stack pointer, marking the instructions frame-related. 6034 TEMP1 is available as a temporary if nonnull. EMIT_MOVE_IMM is false 6035 if TEMP1 already contains abs (DELTA). */ 6036 6037 static inline void 6038 aarch64_add_sp (rtx temp1, rtx temp2, poly_int64 delta, bool emit_move_imm) 6039 { 6040 aarch64_add_offset (Pmode, stack_pointer_rtx, stack_pointer_rtx, delta, 6041 temp1, temp2, true, emit_move_imm); 6042 } 6043 6044 /* Subtract DELTA from the stack pointer, marking the instructions 6045 frame-related if FRAME_RELATED_P. TEMP1 is available as a temporary 6046 if nonnull. */ 6047 6048 static inline void 6049 aarch64_sub_sp (rtx temp1, rtx temp2, poly_int64 delta, bool frame_related_p, 6050 bool emit_move_imm = true) 6051 { 6052 aarch64_add_offset (Pmode, stack_pointer_rtx, stack_pointer_rtx, -delta, 6053 temp1, temp2, frame_related_p, emit_move_imm); 6054 } 6055 6056 /* Set DEST to (vec_series BASE STEP). */ 6057 6058 static void 6059 aarch64_expand_vec_series (rtx dest, rtx base, rtx step) 6060 { 6061 machine_mode mode = GET_MODE (dest); 6062 scalar_mode inner = GET_MODE_INNER (mode); 6063 6064 /* Each operand can be a register or an immediate in the range [-16, 15]. */ 6065 if (!aarch64_sve_index_immediate_p (base)) 6066 base = force_reg (inner, base); 6067 if (!aarch64_sve_index_immediate_p (step)) 6068 step = force_reg (inner, step); 6069 6070 emit_set_insn (dest, gen_rtx_VEC_SERIES (mode, base, step)); 6071 } 6072 6073 /* Duplicate 128-bit Advanced SIMD vector SRC so that it fills an SVE 6074 register of mode MODE. Use TARGET for the result if it's nonnull 6075 and convenient. 6076 6077 The two vector modes must have the same element mode. The behavior 6078 is to duplicate architectural lane N of SRC into architectural lanes 6079 N + I * STEP of the result. On big-endian targets, architectural 6080 lane 0 of an Advanced SIMD vector is the last element of the vector 6081 in memory layout, so for big-endian targets this operation has the 6082 effect of reversing SRC before duplicating it. Callers need to 6083 account for this. */ 6084 6085 rtx 6086 aarch64_expand_sve_dupq (rtx target, machine_mode mode, rtx src) 6087 { 6088 machine_mode src_mode = GET_MODE (src); 6089 gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER (src_mode)); 6090 insn_code icode = (BYTES_BIG_ENDIAN 6091 ? code_for_aarch64_vec_duplicate_vq_be (mode) 6092 : code_for_aarch64_vec_duplicate_vq_le (mode)); 6093 6094 unsigned int i = 0; 6095 expand_operand ops[3]; 6096 create_output_operand (&ops[i++], target, mode); 6097 create_output_operand (&ops[i++], src, src_mode); 6098 if (BYTES_BIG_ENDIAN) 6099 { 6100 /* Create a PARALLEL describing the reversal of SRC. */ 6101 unsigned int nelts_per_vq = 128 / GET_MODE_UNIT_BITSIZE (mode); 6102 rtx sel = aarch64_gen_stepped_int_parallel (nelts_per_vq, 6103 nelts_per_vq - 1, -1); 6104 create_fixed_operand (&ops[i++], sel); 6105 } 6106 expand_insn (icode, i, ops); 6107 return ops[0].value; 6108 } 6109 6110 /* Try to force 128-bit vector value SRC into memory and use LD1RQ to fetch 6111 the memory image into DEST. Return true on success. */ 6112 6113 static bool 6114 aarch64_expand_sve_ld1rq (rtx dest, rtx src) 6115 { 6116 src = force_const_mem (GET_MODE (src), src); 6117 if (!src) 6118 return false; 6119 6120 /* Make sure that the address is legitimate. */ 6121 if (!aarch64_sve_ld1rq_operand_p (src)) 6122 { 6123 rtx addr = force_reg (Pmode, XEXP (src, 0)); 6124 src = replace_equiv_address (src, addr); 6125 } 6126 6127 machine_mode mode = GET_MODE (dest); 6128 machine_mode pred_mode = aarch64_sve_pred_mode (mode); 6129 rtx ptrue = aarch64_ptrue_reg (pred_mode); 6130 emit_insn (gen_aarch64_sve_ld1rq (mode, dest, src, ptrue)); 6131 return true; 6132 } 6133 6134 /* SRC is an SVE CONST_VECTOR that contains N "foreground" values followed 6135 by N "background" values. Try to move it into TARGET using: 6136 6137 PTRUE PRED.<T>, VL<N> 6138 MOV TRUE.<T>, #<foreground> 6139 MOV FALSE.<T>, #<background> 6140 SEL TARGET.<T>, PRED.<T>, TRUE.<T>, FALSE.<T> 6141 6142 The PTRUE is always a single instruction but the MOVs might need a 6143 longer sequence. If the background value is zero (as it often is), 6144 the sequence can sometimes collapse to a PTRUE followed by a 6145 zero-predicated move. 6146 6147 Return the target on success, otherwise return null. */ 6148 6149 static rtx 6150 aarch64_expand_sve_const_vector_sel (rtx target, rtx src) 6151 { 6152 gcc_assert (CONST_VECTOR_NELTS_PER_PATTERN (src) == 2); 6153 6154 /* Make sure that the PTRUE is valid. */ 6155 machine_mode mode = GET_MODE (src); 6156 machine_mode pred_mode = aarch64_sve_pred_mode (mode); 6157 unsigned int npatterns = CONST_VECTOR_NPATTERNS (src); 6158 if (aarch64_svpattern_for_vl (pred_mode, npatterns) 6159 == AARCH64_NUM_SVPATTERNS) 6160 return NULL_RTX; 6161 6162 rtx_vector_builder pred_builder (pred_mode, npatterns, 2); 6163 rtx_vector_builder true_builder (mode, npatterns, 1); 6164 rtx_vector_builder false_builder (mode, npatterns, 1); 6165 for (unsigned int i = 0; i < npatterns; ++i) 6166 { 6167 true_builder.quick_push (CONST_VECTOR_ENCODED_ELT (src, i)); 6168 pred_builder.quick_push (CONST1_RTX (BImode)); 6169 } 6170 for (unsigned int i = 0; i < npatterns; ++i) 6171 { 6172 false_builder.quick_push (CONST_VECTOR_ENCODED_ELT (src, i + npatterns)); 6173 pred_builder.quick_push (CONST0_RTX (BImode)); 6174 } 6175 expand_operand ops[4]; 6176 create_output_operand (&ops[0], target, mode); 6177 create_input_operand (&ops[1], true_builder.build (), mode); 6178 create_input_operand (&ops[2], false_builder.build (), mode); 6179 create_input_operand (&ops[3], pred_builder.build (), pred_mode); 6180 expand_insn (code_for_vcond_mask (mode, mode), 4, ops); 6181 return target; 6182 } 6183 6184 /* Return a register containing CONST_VECTOR SRC, given that SRC has an 6185 SVE data mode and isn't a legitimate constant. Use TARGET for the 6186 result if convenient. 6187 6188 The returned register can have whatever mode seems most natural 6189 given the contents of SRC. */ 6190 6191 static rtx 6192 aarch64_expand_sve_const_vector (rtx target, rtx src) 6193 { 6194 machine_mode mode = GET_MODE (src); 6195 unsigned int npatterns = CONST_VECTOR_NPATTERNS (src); 6196 unsigned int nelts_per_pattern = CONST_VECTOR_NELTS_PER_PATTERN (src); 6197 scalar_mode elt_mode = GET_MODE_INNER (mode); 6198 unsigned int elt_bits = GET_MODE_BITSIZE (elt_mode); 6199 unsigned int container_bits = aarch64_sve_container_bits (mode); 6200 unsigned int encoded_bits = npatterns * nelts_per_pattern * container_bits; 6201 6202 if (nelts_per_pattern == 1 6203 && encoded_bits <= 128 6204 && container_bits != elt_bits) 6205 { 6206 /* We have a partial vector mode and a constant whose full-vector 6207 equivalent would occupy a repeating 128-bit sequence. Build that 6208 full-vector equivalent instead, so that we have the option of 6209 using LD1RQ and Advanced SIMD operations. */ 6210 unsigned int repeat = container_bits / elt_bits; 6211 machine_mode full_mode = aarch64_full_sve_mode (elt_mode).require (); 6212 rtx_vector_builder builder (full_mode, npatterns * repeat, 1); 6213 for (unsigned int i = 0; i < npatterns; ++i) 6214 for (unsigned int j = 0; j < repeat; ++j) 6215 builder.quick_push (CONST_VECTOR_ENCODED_ELT (src, i)); 6216 target = aarch64_target_reg (target, full_mode); 6217 return aarch64_expand_sve_const_vector (target, builder.build ()); 6218 } 6219 6220 if (nelts_per_pattern == 1 && encoded_bits == 128) 6221 { 6222 /* The constant is a duplicated quadword but can't be narrowed 6223 beyond a quadword. Get the memory image of the first quadword 6224 as a 128-bit vector and try using LD1RQ to load it from memory. 6225 6226 The effect for both endiannesses is to load memory lane N into 6227 architectural lanes N + I * STEP of the result. On big-endian 6228 targets, the layout of the 128-bit vector in an Advanced SIMD 6229 register would be different from its layout in an SVE register, 6230 but this 128-bit vector is a memory value only. */ 6231 machine_mode vq_mode = aarch64_vq_mode (elt_mode).require (); 6232 rtx vq_value = simplify_gen_subreg (vq_mode, src, mode, 0); 6233 if (vq_value && aarch64_expand_sve_ld1rq (target, vq_value)) 6234 return target; 6235 } 6236 6237 if (nelts_per_pattern == 1 && encoded_bits < 128) 6238 { 6239 /* The vector is a repeating sequence of 64 bits or fewer. 6240 See if we can load them using an Advanced SIMD move and then 6241 duplicate it to fill a vector. This is better than using a GPR 6242 move because it keeps everything in the same register file. */ 6243 machine_mode vq_mode = aarch64_vq_mode (elt_mode).require (); 6244 rtx_vector_builder builder (vq_mode, npatterns, 1); 6245 for (unsigned int i = 0; i < npatterns; ++i) 6246 { 6247 /* We want memory lane N to go into architectural lane N, 6248 so reverse for big-endian targets. The DUP .Q pattern 6249 has a compensating reverse built-in. */ 6250 unsigned int srci = BYTES_BIG_ENDIAN ? npatterns - i - 1 : i; 6251 builder.quick_push (CONST_VECTOR_ENCODED_ELT (src, srci)); 6252 } 6253 rtx vq_src = builder.build (); 6254 if (aarch64_simd_valid_immediate (vq_src, NULL)) 6255 { 6256 vq_src = force_reg (vq_mode, vq_src); 6257 return aarch64_expand_sve_dupq (target, mode, vq_src); 6258 } 6259 6260 /* Get an integer representation of the repeating part of Advanced 6261 SIMD vector VQ_SRC. This preserves the endianness of VQ_SRC, 6262 which for big-endian targets is lane-swapped wrt a normal 6263 Advanced SIMD vector. This means that for both endiannesses, 6264 memory lane N of SVE vector SRC corresponds to architectural 6265 lane N of a register holding VQ_SRC. This in turn means that 6266 memory lane 0 of SVE vector SRC is in the lsb of VQ_SRC (viewed 6267 as a single 128-bit value) and thus that memory lane 0 of SRC is 6268 in the lsb of the integer. Duplicating the integer therefore 6269 ensures that memory lane N of SRC goes into architectural lane 6270 N + I * INDEX of the SVE register. */ 6271 scalar_mode int_mode = int_mode_for_size (encoded_bits, 0).require (); 6272 rtx elt_value = simplify_gen_subreg (int_mode, vq_src, vq_mode, 0); 6273 if (elt_value) 6274 { 6275 /* Pretend that we had a vector of INT_MODE to start with. */ 6276 elt_mode = int_mode; 6277 mode = aarch64_full_sve_mode (int_mode).require (); 6278 6279 /* If the integer can be moved into a general register by a 6280 single instruction, do that and duplicate the result. */ 6281 if (CONST_INT_P (elt_value) 6282 && aarch64_move_imm (INTVAL (elt_value), elt_mode)) 6283 { 6284 elt_value = force_reg (elt_mode, elt_value); 6285 return expand_vector_broadcast (mode, elt_value); 6286 } 6287 } 6288 else if (npatterns == 1) 6289 /* We're duplicating a single value, but can't do better than 6290 force it to memory and load from there. This handles things 6291 like symbolic constants. */ 6292 elt_value = CONST_VECTOR_ENCODED_ELT (src, 0); 6293 6294 if (elt_value) 6295 { 6296 /* Load the element from memory if we can, otherwise move it into 6297 a register and use a DUP. */ 6298 rtx op = force_const_mem (elt_mode, elt_value); 6299 if (!op) 6300 op = force_reg (elt_mode, elt_value); 6301 return expand_vector_broadcast (mode, op); 6302 } 6303 } 6304 6305 /* Try using INDEX. */ 6306 rtx base, step; 6307 if (const_vec_series_p (src, &base, &step)) 6308 { 6309 aarch64_expand_vec_series (target, base, step); 6310 return target; 6311 } 6312 6313 /* From here on, it's better to force the whole constant to memory 6314 if we can. */ 6315 if (GET_MODE_NUNITS (mode).is_constant ()) 6316 return NULL_RTX; 6317 6318 if (nelts_per_pattern == 2) 6319 if (rtx res = aarch64_expand_sve_const_vector_sel (target, src)) 6320 return res; 6321 6322 /* Expand each pattern individually. */ 6323 gcc_assert (npatterns > 1); 6324 rtx_vector_builder builder; 6325 auto_vec<rtx, 16> vectors (npatterns); 6326 for (unsigned int i = 0; i < npatterns; ++i) 6327 { 6328 builder.new_vector (mode, 1, nelts_per_pattern); 6329 for (unsigned int j = 0; j < nelts_per_pattern; ++j) 6330 builder.quick_push (CONST_VECTOR_ELT (src, i + j * npatterns)); 6331 vectors.quick_push (force_reg (mode, builder.build ())); 6332 } 6333 6334 /* Use permutes to interleave the separate vectors. */ 6335 while (npatterns > 1) 6336 { 6337 npatterns /= 2; 6338 for (unsigned int i = 0; i < npatterns; ++i) 6339 { 6340 rtx tmp = (npatterns == 1 ? target : gen_reg_rtx (mode)); 6341 rtvec v = gen_rtvec (2, vectors[i], vectors[i + npatterns]); 6342 emit_set_insn (tmp, gen_rtx_UNSPEC (mode, v, UNSPEC_ZIP1)); 6343 vectors[i] = tmp; 6344 } 6345 } 6346 gcc_assert (vectors[0] == target); 6347 return target; 6348 } 6349 6350 /* Use WHILE to set a predicate register of mode MODE in which the first 6351 VL bits are set and the rest are clear. Use TARGET for the register 6352 if it's nonnull and convenient. */ 6353 6354 static rtx 6355 aarch64_sve_move_pred_via_while (rtx target, machine_mode mode, 6356 unsigned int vl) 6357 { 6358 rtx limit = force_reg (DImode, gen_int_mode (vl, DImode)); 6359 target = aarch64_target_reg (target, mode); 6360 emit_insn (gen_while (UNSPEC_WHILELO, DImode, mode, 6361 target, const0_rtx, limit)); 6362 return target; 6363 } 6364 6365 static rtx 6366 aarch64_expand_sve_const_pred_1 (rtx, rtx_vector_builder &, bool); 6367 6368 /* BUILDER is a constant predicate in which the index of every set bit 6369 is a multiple of ELT_SIZE (which is <= 8). Try to load the constant 6370 by inverting every element at a multiple of ELT_SIZE and EORing the 6371 result with an ELT_SIZE PTRUE. 6372 6373 Return a register that contains the constant on success, otherwise 6374 return null. Use TARGET as the register if it is nonnull and 6375 convenient. */ 6376 6377 static rtx 6378 aarch64_expand_sve_const_pred_eor (rtx target, rtx_vector_builder &builder, 6379 unsigned int elt_size) 6380 { 6381 /* Invert every element at a multiple of ELT_SIZE, keeping the 6382 other bits zero. */ 6383 rtx_vector_builder inv_builder (VNx16BImode, builder.npatterns (), 6384 builder.nelts_per_pattern ()); 6385 for (unsigned int i = 0; i < builder.encoded_nelts (); ++i) 6386 if ((i & (elt_size - 1)) == 0 && INTVAL (builder.elt (i)) == 0) 6387 inv_builder.quick_push (const1_rtx); 6388 else 6389 inv_builder.quick_push (const0_rtx); 6390 inv_builder.finalize (); 6391 6392 /* See if we can load the constant cheaply. */ 6393 rtx inv = aarch64_expand_sve_const_pred_1 (NULL_RTX, inv_builder, false); 6394 if (!inv) 6395 return NULL_RTX; 6396 6397 /* EOR the result with an ELT_SIZE PTRUE. */ 6398 rtx mask = aarch64_ptrue_all (elt_size); 6399 mask = force_reg (VNx16BImode, mask); 6400 inv = gen_lowpart (VNx16BImode, inv); 6401 target = aarch64_target_reg (target, VNx16BImode); 6402 emit_insn (gen_aarch64_pred_z (XOR, VNx16BImode, target, mask, inv, mask)); 6403 return target; 6404 } 6405 6406 /* BUILDER is a constant predicate in which the index of every set bit 6407 is a multiple of ELT_SIZE (which is <= 8). Try to load the constant 6408 using a TRN1 of size PERMUTE_SIZE, which is >= ELT_SIZE. Return the 6409 register on success, otherwise return null. Use TARGET as the register 6410 if nonnull and convenient. */ 6411 6412 static rtx 6413 aarch64_expand_sve_const_pred_trn (rtx target, rtx_vector_builder &builder, 6414 unsigned int elt_size, 6415 unsigned int permute_size) 6416 { 6417 /* We're going to split the constant into two new constants A and B, 6418 with element I of BUILDER going into A if (I & PERMUTE_SIZE) == 0 6419 and into B otherwise. E.g. for PERMUTE_SIZE == 4 && ELT_SIZE == 1: 6420 6421 A: { 0, 1, 2, 3, _, _, _, _, 8, 9, 10, 11, _, _, _, _ } 6422 B: { 4, 5, 6, 7, _, _, _, _, 12, 13, 14, 15, _, _, _, _ } 6423 6424 where _ indicates elements that will be discarded by the permute. 6425 6426 First calculate the ELT_SIZEs for A and B. */ 6427 unsigned int a_elt_size = GET_MODE_SIZE (DImode); 6428 unsigned int b_elt_size = GET_MODE_SIZE (DImode); 6429 for (unsigned int i = 0; i < builder.encoded_nelts (); i += elt_size) 6430 if (INTVAL (builder.elt (i)) != 0) 6431 { 6432 if (i & permute_size) 6433 b_elt_size |= i - permute_size; 6434 else 6435 a_elt_size |= i; 6436 } 6437 a_elt_size &= -a_elt_size; 6438 b_elt_size &= -b_elt_size; 6439 6440 /* Now construct the vectors themselves. */ 6441 rtx_vector_builder a_builder (VNx16BImode, builder.npatterns (), 6442 builder.nelts_per_pattern ()); 6443 rtx_vector_builder b_builder (VNx16BImode, builder.npatterns (), 6444 builder.nelts_per_pattern ()); 6445 unsigned int nelts = builder.encoded_nelts (); 6446 for (unsigned int i = 0; i < nelts; ++i) 6447 if (i & (elt_size - 1)) 6448 { 6449 a_builder.quick_push (const0_rtx); 6450 b_builder.quick_push (const0_rtx); 6451 } 6452 else if ((i & permute_size) == 0) 6453 { 6454 /* The A and B elements are significant. */ 6455 a_builder.quick_push (builder.elt (i)); 6456 b_builder.quick_push (builder.elt (i + permute_size)); 6457 } 6458 else 6459 { 6460 /* The A and B elements are going to be discarded, so pick whatever 6461 is likely to give a nice constant. We are targeting element 6462 sizes A_ELT_SIZE and B_ELT_SIZE for A and B respectively, 6463 with the aim of each being a sequence of ones followed by 6464 a sequence of zeros. So: 6465 6466 * if X_ELT_SIZE <= PERMUTE_SIZE, the best approach is to 6467 duplicate the last X_ELT_SIZE element, to extend the 6468 current sequence of ones or zeros. 6469 6470 * if X_ELT_SIZE > PERMUTE_SIZE, the best approach is to add a 6471 zero, so that the constant really does have X_ELT_SIZE and 6472 not a smaller size. */ 6473 if (a_elt_size > permute_size) 6474 a_builder.quick_push (const0_rtx); 6475 else 6476 a_builder.quick_push (a_builder.elt (i - a_elt_size)); 6477 if (b_elt_size > permute_size) 6478 b_builder.quick_push (const0_rtx); 6479 else 6480 b_builder.quick_push (b_builder.elt (i - b_elt_size)); 6481 } 6482 a_builder.finalize (); 6483 b_builder.finalize (); 6484 6485 /* Try loading A into a register. */ 6486 rtx_insn *last = get_last_insn (); 6487 rtx a = aarch64_expand_sve_const_pred_1 (NULL_RTX, a_builder, false); 6488 if (!a) 6489 return NULL_RTX; 6490 6491 /* Try loading B into a register. */ 6492 rtx b = a; 6493 if (a_builder != b_builder) 6494 { 6495 b = aarch64_expand_sve_const_pred_1 (NULL_RTX, b_builder, false); 6496 if (!b) 6497 { 6498 delete_insns_since (last); 6499 return NULL_RTX; 6500 } 6501 } 6502 6503 /* Emit the TRN1 itself. We emit a TRN that operates on VNx16BI 6504 operands but permutes them as though they had mode MODE. */ 6505 machine_mode mode = aarch64_sve_pred_mode (permute_size).require (); 6506 target = aarch64_target_reg (target, GET_MODE (a)); 6507 rtx type_reg = CONST0_RTX (mode); 6508 emit_insn (gen_aarch64_sve_trn1_conv (mode, target, a, b, type_reg)); 6509 return target; 6510 } 6511 6512 /* Subroutine of aarch64_expand_sve_const_pred. Try to load the VNx16BI 6513 constant in BUILDER into an SVE predicate register. Return the register 6514 on success, otherwise return null. Use TARGET for the register if 6515 nonnull and convenient. 6516 6517 ALLOW_RECURSE_P is true if we can use methods that would call this 6518 function recursively. */ 6519 6520 static rtx 6521 aarch64_expand_sve_const_pred_1 (rtx target, rtx_vector_builder &builder, 6522 bool allow_recurse_p) 6523 { 6524 if (builder.encoded_nelts () == 1) 6525 /* A PFALSE or a PTRUE .B ALL. */ 6526 return aarch64_emit_set_immediate (target, builder); 6527 6528 unsigned int elt_size = aarch64_widest_sve_pred_elt_size (builder); 6529 if (int vl = aarch64_partial_ptrue_length (builder, elt_size)) 6530 { 6531 /* If we can load the constant using PTRUE, use it as-is. */ 6532 machine_mode mode = aarch64_sve_pred_mode (elt_size).require (); 6533 if (aarch64_svpattern_for_vl (mode, vl) != AARCH64_NUM_SVPATTERNS) 6534 return aarch64_emit_set_immediate (target, builder); 6535 6536 /* Otherwise use WHILE to set the first VL bits. */ 6537 return aarch64_sve_move_pred_via_while (target, mode, vl); 6538 } 6539 6540 if (!allow_recurse_p) 6541 return NULL_RTX; 6542 6543 /* Try inverting the vector in element size ELT_SIZE and then EORing 6544 the result with an ELT_SIZE PTRUE. */ 6545 if (INTVAL (builder.elt (0)) == 0) 6546 if (rtx res = aarch64_expand_sve_const_pred_eor (target, builder, 6547 elt_size)) 6548 return res; 6549 6550 /* Try using TRN1 to permute two simpler constants. */ 6551 for (unsigned int i = elt_size; i <= 8; i *= 2) 6552 if (rtx res = aarch64_expand_sve_const_pred_trn (target, builder, 6553 elt_size, i)) 6554 return res; 6555 6556 return NULL_RTX; 6557 } 6558 6559 /* Return an SVE predicate register that contains the VNx16BImode 6560 constant in BUILDER, without going through the move expanders. 6561 6562 The returned register can have whatever mode seems most natural 6563 given the contents of BUILDER. Use TARGET for the result if 6564 convenient. */ 6565 6566 static rtx 6567 aarch64_expand_sve_const_pred (rtx target, rtx_vector_builder &builder) 6568 { 6569 /* Try loading the constant using pure predicate operations. */ 6570 if (rtx res = aarch64_expand_sve_const_pred_1 (target, builder, true)) 6571 return res; 6572 6573 /* Try forcing the constant to memory. */ 6574 if (builder.full_nelts ().is_constant ()) 6575 if (rtx mem = force_const_mem (VNx16BImode, builder.build ())) 6576 { 6577 target = aarch64_target_reg (target, VNx16BImode); 6578 emit_move_insn (target, mem); 6579 return target; 6580 } 6581 6582 /* The last resort is to load the constant as an integer and then 6583 compare it against zero. Use -1 for set bits in order to increase 6584 the changes of using SVE DUPM or an Advanced SIMD byte mask. */ 6585 rtx_vector_builder int_builder (VNx16QImode, builder.npatterns (), 6586 builder.nelts_per_pattern ()); 6587 for (unsigned int i = 0; i < builder.encoded_nelts (); ++i) 6588 int_builder.quick_push (INTVAL (builder.elt (i)) 6589 ? constm1_rtx : const0_rtx); 6590 return aarch64_convert_sve_data_to_pred (target, VNx16BImode, 6591 int_builder.build ()); 6592 } 6593 6594 /* Set DEST to immediate IMM. */ 6595 6596 void 6597 aarch64_expand_mov_immediate (rtx dest, rtx imm) 6598 { 6599 machine_mode mode = GET_MODE (dest); 6600 6601 /* Check on what type of symbol it is. */ 6602 scalar_int_mode int_mode; 6603 if ((SYMBOL_REF_P (imm) 6604 || LABEL_REF_P (imm) 6605 || GET_CODE (imm) == CONST 6606 || GET_CODE (imm) == CONST_POLY_INT) 6607 && is_a <scalar_int_mode> (mode, &int_mode)) 6608 { 6609 rtx mem; 6610 poly_int64 offset; 6611 HOST_WIDE_INT const_offset; 6612 enum aarch64_symbol_type sty; 6613 6614 /* If we have (const (plus symbol offset)), separate out the offset 6615 before we start classifying the symbol. */ 6616 rtx base = strip_offset (imm, &offset); 6617 6618 /* We must always add an offset involving VL separately, rather than 6619 folding it into the relocation. */ 6620 if (!offset.is_constant (&const_offset)) 6621 { 6622 if (!TARGET_SVE) 6623 { 6624 aarch64_report_sve_required (); 6625 return; 6626 } 6627 if (base == const0_rtx && aarch64_sve_cnt_immediate_p (offset)) 6628 emit_insn (gen_rtx_SET (dest, imm)); 6629 else 6630 { 6631 /* Do arithmetic on 32-bit values if the result is smaller 6632 than that. */ 6633 if (partial_subreg_p (int_mode, SImode)) 6634 { 6635 /* It is invalid to do symbol calculations in modes 6636 narrower than SImode. */ 6637 gcc_assert (base == const0_rtx); 6638 dest = gen_lowpart (SImode, dest); 6639 int_mode = SImode; 6640 } 6641 if (base != const0_rtx) 6642 { 6643 base = aarch64_force_temporary (int_mode, dest, base); 6644 aarch64_add_offset (int_mode, dest, base, offset, 6645 NULL_RTX, NULL_RTX, false); 6646 } 6647 else 6648 aarch64_add_offset (int_mode, dest, base, offset, 6649 dest, NULL_RTX, false); 6650 } 6651 return; 6652 } 6653 6654 sty = aarch64_classify_symbol (base, const_offset); 6655 switch (sty) 6656 { 6657 case SYMBOL_FORCE_TO_MEM: 6658 if (int_mode != ptr_mode) 6659 imm = convert_memory_address (ptr_mode, imm); 6660 6661 if (const_offset != 0 6662 && targetm.cannot_force_const_mem (ptr_mode, imm)) 6663 { 6664 gcc_assert (can_create_pseudo_p ()); 6665 base = aarch64_force_temporary (int_mode, dest, base); 6666 aarch64_add_offset (int_mode, dest, base, const_offset, 6667 NULL_RTX, NULL_RTX, false); 6668 return; 6669 } 6670 6671 mem = force_const_mem (ptr_mode, imm); 6672 gcc_assert (mem); 6673 6674 /* If we aren't generating PC relative literals, then 6675 we need to expand the literal pool access carefully. 6676 This is something that needs to be done in a number 6677 of places, so could well live as a separate function. */ 6678 if (!aarch64_pcrelative_literal_loads) 6679 { 6680 gcc_assert (can_create_pseudo_p ()); 6681 base = gen_reg_rtx (ptr_mode); 6682 aarch64_expand_mov_immediate (base, XEXP (mem, 0)); 6683 if (ptr_mode != Pmode) 6684 base = convert_memory_address (Pmode, base); 6685 mem = gen_rtx_MEM (ptr_mode, base); 6686 } 6687 6688 if (int_mode != ptr_mode) 6689 mem = gen_rtx_ZERO_EXTEND (int_mode, mem); 6690 6691 emit_insn (gen_rtx_SET (dest, mem)); 6692 6693 return; 6694 6695 case SYMBOL_SMALL_TLSGD: 6696 case SYMBOL_SMALL_TLSDESC: 6697 case SYMBOL_SMALL_TLSIE: 6698 case SYMBOL_SMALL_GOT_28K: 6699 case SYMBOL_SMALL_GOT_4G: 6700 case SYMBOL_TINY_GOT: 6701 case SYMBOL_TINY_TLSIE: 6702 if (const_offset != 0) 6703 { 6704 gcc_assert(can_create_pseudo_p ()); 6705 base = aarch64_force_temporary (int_mode, dest, base); 6706 aarch64_add_offset (int_mode, dest, base, const_offset, 6707 NULL_RTX, NULL_RTX, false); 6708 return; 6709 } 6710 /* FALLTHRU */ 6711 6712 case SYMBOL_SMALL_ABSOLUTE: 6713 case SYMBOL_TINY_ABSOLUTE: 6714 case SYMBOL_TLSLE12: 6715 case SYMBOL_TLSLE24: 6716 case SYMBOL_TLSLE32: 6717 case SYMBOL_TLSLE48: 6718 aarch64_load_symref_appropriately (dest, imm, sty); 6719 return; 6720 6721 default: 6722 gcc_unreachable (); 6723 } 6724 } 6725 6726 if (!CONST_INT_P (imm)) 6727 { 6728 if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL) 6729 { 6730 /* Only the low bit of each .H, .S and .D element is defined, 6731 so we can set the upper bits to whatever we like. If the 6732 predicate is all-true in MODE, prefer to set all the undefined 6733 bits as well, so that we can share a single .B predicate for 6734 all modes. */ 6735 if (imm == CONSTM1_RTX (mode)) 6736 imm = CONSTM1_RTX (VNx16BImode); 6737 6738 /* All methods for constructing predicate modes wider than VNx16BI 6739 will set the upper bits of each element to zero. Expose this 6740 by moving such constants as a VNx16BI, so that all bits are 6741 significant and so that constants for different modes can be 6742 shared. The wider constant will still be available as a 6743 REG_EQUAL note. */ 6744 rtx_vector_builder builder; 6745 if (aarch64_get_sve_pred_bits (builder, imm)) 6746 { 6747 rtx res = aarch64_expand_sve_const_pred (dest, builder); 6748 if (dest != res) 6749 emit_move_insn (dest, gen_lowpart (mode, res)); 6750 return; 6751 } 6752 } 6753 6754 if (GET_CODE (imm) == HIGH 6755 || aarch64_simd_valid_immediate (imm, NULL)) 6756 { 6757 emit_insn (gen_rtx_SET (dest, imm)); 6758 return; 6759 } 6760 6761 if (CONST_VECTOR_P (imm) && aarch64_sve_data_mode_p (mode)) 6762 if (rtx res = aarch64_expand_sve_const_vector (dest, imm)) 6763 { 6764 if (dest != res) 6765 emit_insn (gen_aarch64_sve_reinterpret (mode, dest, res)); 6766 return; 6767 } 6768 6769 rtx mem = force_const_mem (mode, imm); 6770 gcc_assert (mem); 6771 emit_move_insn (dest, mem); 6772 return; 6773 } 6774 6775 aarch64_internal_mov_immediate (dest, imm, true, 6776 as_a <scalar_int_mode> (mode)); 6777 } 6778 6779 /* Return the MEM rtx that provides the canary value that should be used 6780 for stack-smashing protection. MODE is the mode of the memory. 6781 For SSP_GLOBAL, DECL_RTL is the MEM rtx for the canary variable 6782 (__stack_chk_guard), otherwise it has no useful value. SALT_TYPE 6783 indicates whether the caller is performing a SET or a TEST operation. */ 6784 6785 rtx 6786 aarch64_stack_protect_canary_mem (machine_mode mode, rtx decl_rtl, 6787 aarch64_salt_type salt_type) 6788 { 6789 rtx addr; 6790 if (aarch64_stack_protector_guard == SSP_GLOBAL) 6791 { 6792 gcc_assert (MEM_P (decl_rtl)); 6793 addr = XEXP (decl_rtl, 0); 6794 poly_int64 offset; 6795 rtx base = strip_offset_and_salt (addr, &offset); 6796 if (!SYMBOL_REF_P (base)) 6797 return decl_rtl; 6798 6799 rtvec v = gen_rtvec (2, base, GEN_INT (salt_type)); 6800 addr = gen_rtx_UNSPEC (Pmode, v, UNSPEC_SALT_ADDR); 6801 addr = gen_rtx_CONST (Pmode, addr); 6802 addr = plus_constant (Pmode, addr, offset); 6803 } 6804 else 6805 { 6806 /* Calculate the address from the system register. */ 6807 rtx salt = GEN_INT (salt_type); 6808 addr = gen_reg_rtx (mode); 6809 if (mode == DImode) 6810 emit_insn (gen_reg_stack_protect_address_di (addr, salt)); 6811 else 6812 { 6813 emit_insn (gen_reg_stack_protect_address_si (addr, salt)); 6814 addr = convert_memory_address (Pmode, addr); 6815 } 6816 addr = plus_constant (Pmode, addr, aarch64_stack_protector_guard_offset); 6817 } 6818 return gen_rtx_MEM (mode, force_reg (Pmode, addr)); 6819 } 6820 6821 /* Emit an SVE predicated move from SRC to DEST. PRED is a predicate 6822 that is known to contain PTRUE. */ 6823 6824 void 6825 aarch64_emit_sve_pred_move (rtx dest, rtx pred, rtx src) 6826 { 6827 expand_operand ops[3]; 6828 machine_mode mode = GET_MODE (dest); 6829 create_output_operand (&ops[0], dest, mode); 6830 create_input_operand (&ops[1], pred, GET_MODE(pred)); 6831 create_input_operand (&ops[2], src, mode); 6832 temporary_volatile_ok v (true); 6833 expand_insn (code_for_aarch64_pred_mov (mode), 3, ops); 6834 } 6835 6836 /* Expand a pre-RA SVE data move from SRC to DEST in which at least one 6837 operand is in memory. In this case we need to use the predicated LD1 6838 and ST1 instead of LDR and STR, both for correctness on big-endian 6839 targets and because LD1 and ST1 support a wider range of addressing modes. 6840 PRED_MODE is the mode of the predicate. 6841 6842 See the comment at the head of aarch64-sve.md for details about the 6843 big-endian handling. */ 6844 6845 void 6846 aarch64_expand_sve_mem_move (rtx dest, rtx src, machine_mode pred_mode) 6847 { 6848 machine_mode mode = GET_MODE (dest); 6849 rtx ptrue = aarch64_ptrue_reg (pred_mode); 6850 if (!register_operand (src, mode) 6851 && !register_operand (dest, mode)) 6852 { 6853 rtx tmp = gen_reg_rtx (mode); 6854 if (MEM_P (src)) 6855 aarch64_emit_sve_pred_move (tmp, ptrue, src); 6856 else 6857 emit_move_insn (tmp, src); 6858 src = tmp; 6859 } 6860 aarch64_emit_sve_pred_move (dest, ptrue, src); 6861 } 6862 6863 /* Called only on big-endian targets. See whether an SVE vector move 6864 from SRC to DEST is effectively a REV[BHW] instruction, because at 6865 least one operand is a subreg of an SVE vector that has wider or 6866 narrower elements. Return true and emit the instruction if so. 6867 6868 For example: 6869 6870 (set (reg:VNx8HI R1) (subreg:VNx8HI (reg:VNx16QI R2) 0)) 6871 6872 represents a VIEW_CONVERT between the following vectors, viewed 6873 in memory order: 6874 6875 R2: { [0].high, [0].low, [1].high, [1].low, ... } 6876 R1: { [0], [1], [2], [3], ... } 6877 6878 The high part of lane X in R2 should therefore correspond to lane X*2 6879 of R1, but the register representations are: 6880 6881 msb lsb 6882 R2: ...... [1].high [1].low [0].high [0].low 6883 R1: ...... [3] [2] [1] [0] 6884 6885 where the low part of lane X in R2 corresponds to lane X*2 in R1. 6886 We therefore need a reverse operation to swap the high and low values 6887 around. 6888 6889 This is purely an optimization. Without it we would spill the 6890 subreg operand to the stack in one mode and reload it in the 6891 other mode, which has the same effect as the REV. */ 6892 6893 bool 6894 aarch64_maybe_expand_sve_subreg_move (rtx dest, rtx src) 6895 { 6896 gcc_assert (BYTES_BIG_ENDIAN); 6897 6898 /* Do not try to optimize subregs that LRA has created for matched 6899 reloads. These subregs only exist as a temporary measure to make 6900 the RTL well-formed, but they are exempt from the usual 6901 TARGET_CAN_CHANGE_MODE_CLASS rules. 6902 6903 For example, if we have: 6904 6905 (set (reg:VNx8HI R1) (foo:VNx8HI (reg:VNx4SI R2))) 6906 6907 and the constraints require R1 and R2 to be in the same register, 6908 LRA may need to create RTL such as: 6909 6910 (set (subreg:VNx4SI (reg:VNx8HI TMP) 0) (reg:VNx4SI R2)) 6911 (set (reg:VNx8HI TMP) (foo:VNx8HI (subreg:VNx4SI (reg:VNx8HI TMP) 0))) 6912 (set (reg:VNx8HI R1) (reg:VNx8HI TMP)) 6913 6914 which forces both the input and output of the original instruction 6915 to use the same hard register. But for this to work, the normal 6916 rules have to be suppressed on the subreg input, otherwise LRA 6917 would need to reload that input too, meaning that the process 6918 would never terminate. To compensate for this, the normal rules 6919 are also suppressed for the subreg output of the first move. 6920 Ignoring the special case and handling the first move normally 6921 would therefore generate wrong code: we would reverse the elements 6922 for the first subreg but not reverse them back for the second subreg. */ 6923 if (SUBREG_P (dest) && !LRA_SUBREG_P (dest)) 6924 dest = SUBREG_REG (dest); 6925 if (SUBREG_P (src) && !LRA_SUBREG_P (src)) 6926 src = SUBREG_REG (src); 6927 6928 /* The optimization handles two single SVE REGs with different element 6929 sizes. */ 6930 if (!REG_P (dest) 6931 || !REG_P (src) 6932 || aarch64_classify_vector_mode (GET_MODE (dest)) != VEC_SVE_DATA 6933 || aarch64_classify_vector_mode (GET_MODE (src)) != VEC_SVE_DATA 6934 || (GET_MODE_UNIT_SIZE (GET_MODE (dest)) 6935 == GET_MODE_UNIT_SIZE (GET_MODE (src)))) 6936 return false; 6937 6938 /* Generate *aarch64_sve_mov<mode>_subreg_be. */ 6939 rtx ptrue = aarch64_ptrue_reg (VNx16BImode); 6940 rtx unspec = gen_rtx_UNSPEC (GET_MODE (dest), gen_rtvec (2, ptrue, src), 6941 UNSPEC_REV_SUBREG); 6942 emit_insn (gen_rtx_SET (dest, unspec)); 6943 return true; 6944 } 6945 6946 /* Return a copy of X with mode MODE, without changing its other 6947 attributes. Unlike gen_lowpart, this doesn't care whether the 6948 mode change is valid. */ 6949 6950 rtx 6951 aarch64_replace_reg_mode (rtx x, machine_mode mode) 6952 { 6953 if (GET_MODE (x) == mode) 6954 return x; 6955 6956 x = shallow_copy_rtx (x); 6957 set_mode_and_regno (x, mode, REGNO (x)); 6958 return x; 6959 } 6960 6961 /* Return the SVE REV[BHW] unspec for reversing quantites of mode MODE 6962 stored in wider integer containers. */ 6963 6964 static unsigned int 6965 aarch64_sve_rev_unspec (machine_mode mode) 6966 { 6967 switch (GET_MODE_UNIT_SIZE (mode)) 6968 { 6969 case 1: return UNSPEC_REVB; 6970 case 2: return UNSPEC_REVH; 6971 case 4: return UNSPEC_REVW; 6972 } 6973 gcc_unreachable (); 6974 } 6975 6976 /* Split a *aarch64_sve_mov<mode>_subreg_be pattern with the given 6977 operands. */ 6978 6979 void 6980 aarch64_split_sve_subreg_move (rtx dest, rtx ptrue, rtx src) 6981 { 6982 /* Decide which REV operation we need. The mode with wider elements 6983 determines the mode of the operands and the mode with the narrower 6984 elements determines the reverse width. */ 6985 machine_mode mode_with_wider_elts = aarch64_sve_int_mode (GET_MODE (dest)); 6986 machine_mode mode_with_narrower_elts = aarch64_sve_int_mode (GET_MODE (src)); 6987 if (GET_MODE_UNIT_SIZE (mode_with_wider_elts) 6988 < GET_MODE_UNIT_SIZE (mode_with_narrower_elts)) 6989 std::swap (mode_with_wider_elts, mode_with_narrower_elts); 6990 6991 unsigned int unspec = aarch64_sve_rev_unspec (mode_with_narrower_elts); 6992 machine_mode pred_mode = aarch64_sve_pred_mode (mode_with_wider_elts); 6993 6994 /* Get the operands in the appropriate modes and emit the instruction. */ 6995 ptrue = gen_lowpart (pred_mode, ptrue); 6996 dest = aarch64_replace_reg_mode (dest, mode_with_wider_elts); 6997 src = aarch64_replace_reg_mode (src, mode_with_wider_elts); 6998 emit_insn (gen_aarch64_pred (unspec, mode_with_wider_elts, 6999 dest, ptrue, src)); 7000 } 7001 7002 static bool 7003 aarch64_function_ok_for_sibcall (tree, tree exp) 7004 { 7005 if (crtl->abi->id () != expr_callee_abi (exp).id ()) 7006 return false; 7007 7008 return true; 7009 } 7010 7011 /* Subroutine of aarch64_pass_by_reference for arguments that are not 7012 passed in SVE registers. */ 7013 7014 static bool 7015 aarch64_pass_by_reference_1 (CUMULATIVE_ARGS *pcum, 7016 const function_arg_info &arg) 7017 { 7018 HOST_WIDE_INT size; 7019 machine_mode dummymode; 7020 int nregs; 7021 7022 /* GET_MODE_SIZE (BLKmode) is useless since it is 0. */ 7023 if (arg.mode == BLKmode && arg.type) 7024 size = int_size_in_bytes (arg.type); 7025 else 7026 /* No frontends can create types with variable-sized modes, so we 7027 shouldn't be asked to pass or return them. */ 7028 size = GET_MODE_SIZE (arg.mode).to_constant (); 7029 7030 /* Aggregates are passed by reference based on their size. */ 7031 if (arg.aggregate_type_p ()) 7032 size = int_size_in_bytes (arg.type); 7033 7034 /* Variable sized arguments are always returned by reference. */ 7035 if (size < 0) 7036 return true; 7037 7038 /* Can this be a candidate to be passed in fp/simd register(s)? */ 7039 if (aarch64_vfp_is_call_or_return_candidate (arg.mode, arg.type, 7040 &dummymode, &nregs, NULL, 7041 !pcum || pcum->silent_p)) 7042 return false; 7043 7044 /* Arguments which are variable sized or larger than 2 registers are 7045 passed by reference unless they are a homogenous floating point 7046 aggregate. */ 7047 return size > 2 * UNITS_PER_WORD; 7048 } 7049 7050 /* Implement TARGET_PASS_BY_REFERENCE. */ 7051 7052 static bool 7053 aarch64_pass_by_reference (cumulative_args_t pcum_v, 7054 const function_arg_info &arg) 7055 { 7056 CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); 7057 7058 if (!arg.type) 7059 return aarch64_pass_by_reference_1 (pcum, arg); 7060 7061 pure_scalable_type_info pst_info; 7062 switch (pst_info.analyze (arg.type)) 7063 { 7064 case pure_scalable_type_info::IS_PST: 7065 if (pcum && !pcum->silent_p && !TARGET_SVE) 7066 /* We can't gracefully recover at this point, so make this a 7067 fatal error. */ 7068 fatal_error (input_location, "arguments of type %qT require" 7069 " the SVE ISA extension", arg.type); 7070 7071 /* Variadic SVE types are passed by reference. Normal non-variadic 7072 arguments are too if we've run out of registers. */ 7073 return (!arg.named 7074 || pcum->aapcs_nvrn + pst_info.num_zr () > NUM_FP_ARG_REGS 7075 || pcum->aapcs_nprn + pst_info.num_pr () > NUM_PR_ARG_REGS); 7076 7077 case pure_scalable_type_info::DOESNT_MATTER: 7078 gcc_assert (aarch64_pass_by_reference_1 (pcum, arg)); 7079 return true; 7080 7081 case pure_scalable_type_info::NO_ABI_IDENTITY: 7082 case pure_scalable_type_info::ISNT_PST: 7083 return aarch64_pass_by_reference_1 (pcum, arg); 7084 } 7085 gcc_unreachable (); 7086 } 7087 7088 /* Return TRUE if VALTYPE is padded to its least significant bits. */ 7089 static bool 7090 aarch64_return_in_msb (const_tree valtype) 7091 { 7092 machine_mode dummy_mode; 7093 int dummy_int; 7094 7095 /* Never happens in little-endian mode. */ 7096 if (!BYTES_BIG_ENDIAN) 7097 return false; 7098 7099 /* Only composite types smaller than or equal to 16 bytes can 7100 be potentially returned in registers. */ 7101 if (!aarch64_composite_type_p (valtype, TYPE_MODE (valtype)) 7102 || int_size_in_bytes (valtype) <= 0 7103 || int_size_in_bytes (valtype) > 16) 7104 return false; 7105 7106 /* But not a composite that is an HFA (Homogeneous Floating-point Aggregate) 7107 or an HVA (Homogeneous Short-Vector Aggregate); such a special composite 7108 is always passed/returned in the least significant bits of fp/simd 7109 register(s). */ 7110 if (aarch64_vfp_is_call_or_return_candidate (TYPE_MODE (valtype), valtype, 7111 &dummy_mode, &dummy_int, NULL, 7112 false)) 7113 return false; 7114 7115 /* Likewise pure scalable types for SVE vector and predicate registers. */ 7116 pure_scalable_type_info pst_info; 7117 if (pst_info.analyze_registers (valtype)) 7118 return false; 7119 7120 return true; 7121 } 7122 7123 /* Implement TARGET_FUNCTION_VALUE. 7124 Define how to find the value returned by a function. */ 7125 7126 static rtx 7127 aarch64_function_value (const_tree type, const_tree func, 7128 bool outgoing ATTRIBUTE_UNUSED) 7129 { 7130 machine_mode mode; 7131 int unsignedp; 7132 7133 mode = TYPE_MODE (type); 7134 if (INTEGRAL_TYPE_P (type)) 7135 mode = promote_function_mode (type, mode, &unsignedp, func, 1); 7136 7137 pure_scalable_type_info pst_info; 7138 if (type && pst_info.analyze_registers (type)) 7139 return pst_info.get_rtx (mode, V0_REGNUM, P0_REGNUM); 7140 7141 /* Generic vectors that map to full SVE modes with -msve-vector-bits=N 7142 are returned in memory, not by value. */ 7143 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 7144 bool sve_p = (vec_flags & VEC_ANY_SVE); 7145 7146 if (aarch64_return_in_msb (type)) 7147 { 7148 HOST_WIDE_INT size = int_size_in_bytes (type); 7149 7150 if (size % UNITS_PER_WORD != 0) 7151 { 7152 size += UNITS_PER_WORD - size % UNITS_PER_WORD; 7153 mode = int_mode_for_size (size * BITS_PER_UNIT, 0).require (); 7154 } 7155 } 7156 7157 int count; 7158 machine_mode ag_mode; 7159 if (aarch64_vfp_is_call_or_return_candidate (mode, type, &ag_mode, &count, 7160 NULL, false)) 7161 { 7162 gcc_assert (!sve_p); 7163 if (!aarch64_composite_type_p (type, mode)) 7164 { 7165 gcc_assert (count == 1 && mode == ag_mode); 7166 return gen_rtx_REG (mode, V0_REGNUM); 7167 } 7168 else if (aarch64_advsimd_full_struct_mode_p (mode) 7169 && known_eq (GET_MODE_SIZE (ag_mode), 16)) 7170 return gen_rtx_REG (mode, V0_REGNUM); 7171 else if (aarch64_advsimd_partial_struct_mode_p (mode) 7172 && known_eq (GET_MODE_SIZE (ag_mode), 8)) 7173 return gen_rtx_REG (mode, V0_REGNUM); 7174 else 7175 { 7176 int i; 7177 rtx par; 7178 7179 par = gen_rtx_PARALLEL (mode, rtvec_alloc (count)); 7180 for (i = 0; i < count; i++) 7181 { 7182 rtx tmp = gen_rtx_REG (ag_mode, V0_REGNUM + i); 7183 rtx offset = gen_int_mode (i * GET_MODE_SIZE (ag_mode), Pmode); 7184 tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, offset); 7185 XVECEXP (par, 0, i) = tmp; 7186 } 7187 return par; 7188 } 7189 } 7190 else 7191 { 7192 if (sve_p) 7193 { 7194 /* Vector types can acquire a partial SVE mode using things like 7195 __attribute__((vector_size(N))), and this is potentially useful. 7196 However, the choice of mode doesn't affect the type's ABI 7197 identity, so we should treat the types as though they had 7198 the associated integer mode, just like they did before SVE 7199 was introduced. 7200 7201 We know that the vector must be 128 bits or smaller, 7202 otherwise we'd have returned it in memory instead. */ 7203 gcc_assert (type 7204 && (aarch64_some_values_include_pst_objects_p (type) 7205 || (vec_flags & VEC_PARTIAL))); 7206 7207 scalar_int_mode int_mode = int_mode_for_mode (mode).require (); 7208 rtx reg = gen_rtx_REG (int_mode, R0_REGNUM); 7209 rtx pair = gen_rtx_EXPR_LIST (VOIDmode, reg, const0_rtx); 7210 return gen_rtx_PARALLEL (mode, gen_rtvec (1, pair)); 7211 } 7212 return gen_rtx_REG (mode, R0_REGNUM); 7213 } 7214 } 7215 7216 /* Implements TARGET_FUNCTION_VALUE_REGNO_P. 7217 Return true if REGNO is the number of a hard register in which the values 7218 of called function may come back. */ 7219 7220 static bool 7221 aarch64_function_value_regno_p (const unsigned int regno) 7222 { 7223 /* Maximum of 16 bytes can be returned in the general registers. Examples 7224 of 16-byte return values are: 128-bit integers and 16-byte small 7225 structures (excluding homogeneous floating-point aggregates). */ 7226 if (regno == R0_REGNUM || regno == R1_REGNUM) 7227 return true; 7228 7229 /* Up to four fp/simd registers can return a function value, e.g. a 7230 homogeneous floating-point aggregate having four members. */ 7231 if (regno >= V0_REGNUM && regno < V0_REGNUM + HA_MAX_NUM_FLDS) 7232 return TARGET_FLOAT; 7233 7234 return false; 7235 } 7236 7237 /* Subroutine for aarch64_return_in_memory for types that are not returned 7238 in SVE registers. */ 7239 7240 static bool 7241 aarch64_return_in_memory_1 (const_tree type) 7242 { 7243 HOST_WIDE_INT size; 7244 machine_mode ag_mode; 7245 int count; 7246 7247 if (!AGGREGATE_TYPE_P (type) 7248 && TREE_CODE (type) != COMPLEX_TYPE 7249 && TREE_CODE (type) != VECTOR_TYPE) 7250 /* Simple scalar types always returned in registers. */ 7251 return false; 7252 7253 if (aarch64_vfp_is_call_or_return_candidate (TYPE_MODE (type), type, 7254 &ag_mode, &count, NULL, false)) 7255 return false; 7256 7257 /* Types larger than 2 registers returned in memory. */ 7258 size = int_size_in_bytes (type); 7259 return (size < 0 || size > 2 * UNITS_PER_WORD); 7260 } 7261 7262 /* Implement TARGET_RETURN_IN_MEMORY. 7263 7264 If the type T of the result of a function is such that 7265 void func (T arg) 7266 would require that arg be passed as a value in a register (or set of 7267 registers) according to the parameter passing rules, then the result 7268 is returned in the same registers as would be used for such an 7269 argument. */ 7270 7271 static bool 7272 aarch64_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) 7273 { 7274 pure_scalable_type_info pst_info; 7275 switch (pst_info.analyze (type)) 7276 { 7277 case pure_scalable_type_info::IS_PST: 7278 return (pst_info.num_zr () > NUM_FP_ARG_REGS 7279 || pst_info.num_pr () > NUM_PR_ARG_REGS); 7280 7281 case pure_scalable_type_info::DOESNT_MATTER: 7282 gcc_assert (aarch64_return_in_memory_1 (type)); 7283 return true; 7284 7285 case pure_scalable_type_info::NO_ABI_IDENTITY: 7286 case pure_scalable_type_info::ISNT_PST: 7287 return aarch64_return_in_memory_1 (type); 7288 } 7289 gcc_unreachable (); 7290 } 7291 7292 static bool 7293 aarch64_vfp_is_call_candidate (cumulative_args_t pcum_v, machine_mode mode, 7294 const_tree type, int *nregs) 7295 { 7296 CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); 7297 return aarch64_vfp_is_call_or_return_candidate (mode, type, 7298 &pcum->aapcs_vfp_rmode, 7299 nregs, NULL, pcum->silent_p); 7300 } 7301 7302 /* Given MODE and TYPE of a function argument, return the alignment in 7303 bits. The idea is to suppress any stronger alignment requested by 7304 the user and opt for the natural alignment (specified in AAPCS64 \S 7305 4.1). ABI_BREAK is set to the old alignment if the alignment was 7306 incorrectly calculated in versions of GCC prior to GCC-9. This is 7307 a helper function for local use only. */ 7308 7309 static unsigned int 7310 aarch64_function_arg_alignment (machine_mode mode, const_tree type, 7311 unsigned int *abi_break) 7312 { 7313 *abi_break = 0; 7314 if (!type) 7315 return GET_MODE_ALIGNMENT (mode); 7316 7317 if (integer_zerop (TYPE_SIZE (type))) 7318 return 0; 7319 7320 gcc_assert (TYPE_MODE (type) == mode); 7321 7322 if (!AGGREGATE_TYPE_P (type)) 7323 { 7324 /* The ABI alignment is the natural alignment of the type, without 7325 any attributes applied. Normally this is the alignment of the 7326 TYPE_MAIN_VARIANT, but not always; see PR108910 for a counterexample. 7327 For now we just handle the known exceptions explicitly. */ 7328 type = TYPE_MAIN_VARIANT (type); 7329 if (POINTER_TYPE_P (type)) 7330 { 7331 gcc_assert (known_eq (POINTER_SIZE, GET_MODE_BITSIZE (mode))); 7332 return POINTER_SIZE; 7333 } 7334 return TYPE_ALIGN (type); 7335 } 7336 7337 if (TREE_CODE (type) == ARRAY_TYPE) 7338 return TYPE_ALIGN (TREE_TYPE (type)); 7339 7340 unsigned int alignment = 0; 7341 unsigned int bitfield_alignment = 0; 7342 for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) 7343 if (TREE_CODE (field) == FIELD_DECL) 7344 { 7345 /* Note that we explicitly consider zero-sized fields here, 7346 even though they don't map to AAPCS64 machine types. 7347 For example, in: 7348 7349 struct __attribute__((aligned(8))) empty {}; 7350 7351 struct s { 7352 [[no_unique_address]] empty e; 7353 int x; 7354 }; 7355 7356 "s" contains only one Fundamental Data Type (the int field) 7357 but gains 8-byte alignment and size thanks to "e". */ 7358 alignment = std::max (alignment, DECL_ALIGN (field)); 7359 if (DECL_BIT_FIELD_TYPE (field)) 7360 bitfield_alignment 7361 = std::max (bitfield_alignment, 7362 TYPE_ALIGN (DECL_BIT_FIELD_TYPE (field))); 7363 } 7364 7365 if (bitfield_alignment > alignment) 7366 { 7367 *abi_break = alignment; 7368 return bitfield_alignment; 7369 } 7370 7371 return alignment; 7372 } 7373 7374 /* Layout a function argument according to the AAPCS64 rules. The rule 7375 numbers refer to the rule numbers in the AAPCS64. ORIG_MODE is the 7376 mode that was originally given to us by the target hook, whereas the 7377 mode in ARG might be the result of replacing partial SVE modes with 7378 the equivalent integer mode. */ 7379 7380 static void 7381 aarch64_layout_arg (cumulative_args_t pcum_v, const function_arg_info &arg) 7382 { 7383 CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); 7384 tree type = arg.type; 7385 machine_mode mode = arg.mode; 7386 int ncrn, nvrn, nregs; 7387 bool allocate_ncrn, allocate_nvrn; 7388 HOST_WIDE_INT size; 7389 unsigned int abi_break; 7390 7391 /* We need to do this once per argument. */ 7392 if (pcum->aapcs_arg_processed) 7393 return; 7394 7395 bool warn_pcs_change 7396 = (warn_psabi 7397 && !pcum->silent_p 7398 && (currently_expanding_function_start 7399 || currently_expanding_gimple_stmt)); 7400 7401 unsigned int alignment 7402 = aarch64_function_arg_alignment (mode, type, &abi_break); 7403 gcc_assert (!alignment || abi_break < alignment); 7404 7405 pcum->aapcs_arg_processed = true; 7406 7407 pure_scalable_type_info pst_info; 7408 if (type && pst_info.analyze_registers (type)) 7409 { 7410 /* aarch64_function_arg_alignment has never had an effect on 7411 this case. */ 7412 7413 /* The PCS says that it is invalid to pass an SVE value to an 7414 unprototyped function. There is no ABI-defined location we 7415 can return in this case, so we have no real choice but to raise 7416 an error immediately, even though this is only a query function. */ 7417 if (arg.named && pcum->pcs_variant != ARM_PCS_SVE) 7418 { 7419 gcc_assert (!pcum->silent_p); 7420 error ("SVE type %qT cannot be passed to an unprototyped function", 7421 arg.type); 7422 /* Avoid repeating the message, and avoid tripping the assert 7423 below. */ 7424 pcum->pcs_variant = ARM_PCS_SVE; 7425 } 7426 7427 /* We would have converted the argument into pass-by-reference 7428 form if it didn't fit in registers. */ 7429 pcum->aapcs_nextnvrn = pcum->aapcs_nvrn + pst_info.num_zr (); 7430 pcum->aapcs_nextnprn = pcum->aapcs_nprn + pst_info.num_pr (); 7431 gcc_assert (arg.named 7432 && pcum->pcs_variant == ARM_PCS_SVE 7433 && pcum->aapcs_nextnvrn <= NUM_FP_ARG_REGS 7434 && pcum->aapcs_nextnprn <= NUM_PR_ARG_REGS); 7435 pcum->aapcs_reg = pst_info.get_rtx (mode, V0_REGNUM + pcum->aapcs_nvrn, 7436 P0_REGNUM + pcum->aapcs_nprn); 7437 return; 7438 } 7439 7440 /* Generic vectors that map to full SVE modes with -msve-vector-bits=N 7441 are passed by reference, not by value. */ 7442 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 7443 bool sve_p = (vec_flags & VEC_ANY_SVE); 7444 if (sve_p) 7445 /* Vector types can acquire a partial SVE mode using things like 7446 __attribute__((vector_size(N))), and this is potentially useful. 7447 However, the choice of mode doesn't affect the type's ABI 7448 identity, so we should treat the types as though they had 7449 the associated integer mode, just like they did before SVE 7450 was introduced. 7451 7452 We know that the vector must be 128 bits or smaller, 7453 otherwise we'd have passed it in memory instead. */ 7454 gcc_assert (type 7455 && (aarch64_some_values_include_pst_objects_p (type) 7456 || (vec_flags & VEC_PARTIAL))); 7457 7458 /* Size in bytes, rounded to the nearest multiple of 8 bytes. */ 7459 if (type) 7460 size = int_size_in_bytes (type); 7461 else 7462 /* No frontends can create types with variable-sized modes, so we 7463 shouldn't be asked to pass or return them. */ 7464 size = GET_MODE_SIZE (mode).to_constant (); 7465 size = ROUND_UP (size, UNITS_PER_WORD); 7466 7467 allocate_ncrn = (type) ? !(FLOAT_TYPE_P (type)) : !FLOAT_MODE_P (mode); 7468 allocate_nvrn = aarch64_vfp_is_call_candidate (pcum_v, 7469 mode, 7470 type, 7471 &nregs); 7472 gcc_assert (!sve_p || !allocate_nvrn); 7473 7474 /* allocate_ncrn may be false-positive, but allocate_nvrn is quite reliable. 7475 The following code thus handles passing by SIMD/FP registers first. */ 7476 7477 nvrn = pcum->aapcs_nvrn; 7478 7479 /* C1 - C5 for floating point, homogenous floating point aggregates (HFA) 7480 and homogenous short-vector aggregates (HVA). */ 7481 if (allocate_nvrn) 7482 { 7483 /* aarch64_function_arg_alignment has never had an effect on 7484 this case. */ 7485 if (!pcum->silent_p && !TARGET_FLOAT) 7486 aarch64_err_no_fpadvsimd (mode); 7487 7488 if (nvrn + nregs <= NUM_FP_ARG_REGS) 7489 { 7490 pcum->aapcs_nextnvrn = nvrn + nregs; 7491 if (!aarch64_composite_type_p (type, mode)) 7492 { 7493 gcc_assert (nregs == 1); 7494 pcum->aapcs_reg = gen_rtx_REG (mode, V0_REGNUM + nvrn); 7495 } 7496 else if (aarch64_advsimd_full_struct_mode_p (mode) 7497 && known_eq (GET_MODE_SIZE (pcum->aapcs_vfp_rmode), 16)) 7498 pcum->aapcs_reg = gen_rtx_REG (mode, V0_REGNUM + nvrn); 7499 else if (aarch64_advsimd_partial_struct_mode_p (mode) 7500 && known_eq (GET_MODE_SIZE (pcum->aapcs_vfp_rmode), 8)) 7501 pcum->aapcs_reg = gen_rtx_REG (mode, V0_REGNUM + nvrn); 7502 else 7503 { 7504 rtx par; 7505 int i; 7506 par = gen_rtx_PARALLEL (mode, rtvec_alloc (nregs)); 7507 for (i = 0; i < nregs; i++) 7508 { 7509 rtx tmp = gen_rtx_REG (pcum->aapcs_vfp_rmode, 7510 V0_REGNUM + nvrn + i); 7511 rtx offset = gen_int_mode 7512 (i * GET_MODE_SIZE (pcum->aapcs_vfp_rmode), Pmode); 7513 tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, offset); 7514 XVECEXP (par, 0, i) = tmp; 7515 } 7516 pcum->aapcs_reg = par; 7517 } 7518 return; 7519 } 7520 else 7521 { 7522 /* C.3 NSRN is set to 8. */ 7523 pcum->aapcs_nextnvrn = NUM_FP_ARG_REGS; 7524 goto on_stack; 7525 } 7526 } 7527 7528 ncrn = pcum->aapcs_ncrn; 7529 nregs = size / UNITS_PER_WORD; 7530 7531 /* C6 - C9. though the sign and zero extension semantics are 7532 handled elsewhere. This is the case where the argument fits 7533 entirely general registers. */ 7534 if (allocate_ncrn && (ncrn + nregs <= NUM_ARG_REGS)) 7535 { 7536 gcc_assert (nregs == 0 || nregs == 1 || nregs == 2); 7537 7538 /* C.8 if the argument has an alignment of 16 then the NGRN is 7539 rounded up to the next even number. */ 7540 if (nregs == 2 7541 && ncrn % 2 7542 /* The == 16 * BITS_PER_UNIT instead of >= 16 * BITS_PER_UNIT 7543 comparison is there because for > 16 * BITS_PER_UNIT 7544 alignment nregs should be > 2 and therefore it should be 7545 passed by reference rather than value. */ 7546 && (aarch64_function_arg_alignment (mode, type, &abi_break) 7547 == 16 * BITS_PER_UNIT)) 7548 { 7549 if (warn_pcs_change && abi_break) 7550 inform (input_location, "parameter passing for argument of type " 7551 "%qT changed in GCC 9.1", type); 7552 ++ncrn; 7553 gcc_assert (ncrn + nregs <= NUM_ARG_REGS); 7554 } 7555 7556 /* If an argument with an SVE mode needs to be shifted up to the 7557 high part of the register, treat it as though it had an integer mode. 7558 Using the normal (parallel [...]) would suppress the shifting. */ 7559 if (sve_p 7560 && BYTES_BIG_ENDIAN 7561 && maybe_ne (GET_MODE_SIZE (mode), nregs * UNITS_PER_WORD) 7562 && aarch64_pad_reg_upward (mode, type, false)) 7563 { 7564 mode = int_mode_for_mode (mode).require (); 7565 sve_p = false; 7566 } 7567 7568 /* NREGS can be 0 when e.g. an empty structure is to be passed. 7569 A reg is still generated for it, but the caller should be smart 7570 enough not to use it. */ 7571 if (nregs == 0 7572 || (nregs == 1 && !sve_p) 7573 || GET_MODE_CLASS (mode) == MODE_INT) 7574 pcum->aapcs_reg = gen_rtx_REG (mode, R0_REGNUM + ncrn); 7575 else 7576 { 7577 rtx par; 7578 int i; 7579 7580 par = gen_rtx_PARALLEL (mode, rtvec_alloc (nregs)); 7581 for (i = 0; i < nregs; i++) 7582 { 7583 scalar_int_mode reg_mode = word_mode; 7584 if (nregs == 1) 7585 reg_mode = int_mode_for_mode (mode).require (); 7586 rtx tmp = gen_rtx_REG (reg_mode, R0_REGNUM + ncrn + i); 7587 tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, 7588 GEN_INT (i * UNITS_PER_WORD)); 7589 XVECEXP (par, 0, i) = tmp; 7590 } 7591 pcum->aapcs_reg = par; 7592 } 7593 7594 pcum->aapcs_nextncrn = ncrn + nregs; 7595 return; 7596 } 7597 7598 /* C.11 */ 7599 pcum->aapcs_nextncrn = NUM_ARG_REGS; 7600 7601 /* The argument is passed on stack; record the needed number of words for 7602 this argument and align the total size if necessary. */ 7603 on_stack: 7604 pcum->aapcs_stack_words = size / UNITS_PER_WORD; 7605 7606 if (aarch64_function_arg_alignment (mode, type, &abi_break) 7607 == 16 * BITS_PER_UNIT) 7608 { 7609 int new_size = ROUND_UP (pcum->aapcs_stack_size, 16 / UNITS_PER_WORD); 7610 if (pcum->aapcs_stack_size != new_size) 7611 { 7612 if (warn_pcs_change && abi_break) 7613 inform (input_location, "parameter passing for argument of type " 7614 "%qT changed in GCC 9.1", type); 7615 pcum->aapcs_stack_size = new_size; 7616 } 7617 } 7618 return; 7619 } 7620 7621 /* Implement TARGET_FUNCTION_ARG. */ 7622 7623 static rtx 7624 aarch64_function_arg (cumulative_args_t pcum_v, const function_arg_info &arg) 7625 { 7626 CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); 7627 gcc_assert (pcum->pcs_variant == ARM_PCS_AAPCS64 7628 || pcum->pcs_variant == ARM_PCS_SIMD 7629 || pcum->pcs_variant == ARM_PCS_SVE); 7630 7631 if (arg.end_marker_p ()) 7632 return gen_int_mode (pcum->pcs_variant, DImode); 7633 7634 aarch64_layout_arg (pcum_v, arg); 7635 return pcum->aapcs_reg; 7636 } 7637 7638 void 7639 aarch64_init_cumulative_args (CUMULATIVE_ARGS *pcum, 7640 const_tree fntype, 7641 rtx libname ATTRIBUTE_UNUSED, 7642 const_tree fndecl ATTRIBUTE_UNUSED, 7643 unsigned n_named ATTRIBUTE_UNUSED, 7644 bool silent_p) 7645 { 7646 pcum->aapcs_ncrn = 0; 7647 pcum->aapcs_nvrn = 0; 7648 pcum->aapcs_nprn = 0; 7649 pcum->aapcs_nextncrn = 0; 7650 pcum->aapcs_nextnvrn = 0; 7651 pcum->aapcs_nextnprn = 0; 7652 if (fntype) 7653 pcum->pcs_variant = (arm_pcs) fntype_abi (fntype).id (); 7654 else 7655 pcum->pcs_variant = ARM_PCS_AAPCS64; 7656 pcum->aapcs_reg = NULL_RTX; 7657 pcum->aapcs_arg_processed = false; 7658 pcum->aapcs_stack_words = 0; 7659 pcum->aapcs_stack_size = 0; 7660 pcum->silent_p = silent_p; 7661 7662 if (!silent_p 7663 && !TARGET_FLOAT 7664 && fntype && fntype != error_mark_node) 7665 { 7666 const_tree type = TREE_TYPE (fntype); 7667 machine_mode mode ATTRIBUTE_UNUSED; /* To pass pointer as argument. */ 7668 int nregs ATTRIBUTE_UNUSED; /* Likewise. */ 7669 if (aarch64_vfp_is_call_or_return_candidate (TYPE_MODE (type), type, 7670 &mode, &nregs, NULL, false)) 7671 aarch64_err_no_fpadvsimd (TYPE_MODE (type)); 7672 } 7673 7674 if (!silent_p 7675 && !TARGET_SVE 7676 && pcum->pcs_variant == ARM_PCS_SVE) 7677 { 7678 /* We can't gracefully recover at this point, so make this a 7679 fatal error. */ 7680 if (fndecl) 7681 fatal_error (input_location, "%qE requires the SVE ISA extension", 7682 fndecl); 7683 else 7684 fatal_error (input_location, "calls to functions of type %qT require" 7685 " the SVE ISA extension", fntype); 7686 } 7687 } 7688 7689 static void 7690 aarch64_function_arg_advance (cumulative_args_t pcum_v, 7691 const function_arg_info &arg) 7692 { 7693 CUMULATIVE_ARGS *pcum = get_cumulative_args (pcum_v); 7694 if (pcum->pcs_variant == ARM_PCS_AAPCS64 7695 || pcum->pcs_variant == ARM_PCS_SIMD 7696 || pcum->pcs_variant == ARM_PCS_SVE) 7697 { 7698 aarch64_layout_arg (pcum_v, arg); 7699 gcc_assert ((pcum->aapcs_reg != NULL_RTX) 7700 != (pcum->aapcs_stack_words != 0)); 7701 pcum->aapcs_arg_processed = false; 7702 pcum->aapcs_ncrn = pcum->aapcs_nextncrn; 7703 pcum->aapcs_nvrn = pcum->aapcs_nextnvrn; 7704 pcum->aapcs_nprn = pcum->aapcs_nextnprn; 7705 pcum->aapcs_stack_size += pcum->aapcs_stack_words; 7706 pcum->aapcs_stack_words = 0; 7707 pcum->aapcs_reg = NULL_RTX; 7708 } 7709 } 7710 7711 bool 7712 aarch64_function_arg_regno_p (unsigned regno) 7713 { 7714 return ((GP_REGNUM_P (regno) && regno < R0_REGNUM + NUM_ARG_REGS) 7715 || (FP_REGNUM_P (regno) && regno < V0_REGNUM + NUM_FP_ARG_REGS)); 7716 } 7717 7718 /* Implement FUNCTION_ARG_BOUNDARY. Every parameter gets at least 7719 PARM_BOUNDARY bits of alignment, but will be given anything up 7720 to STACK_BOUNDARY bits if the type requires it. This makes sure 7721 that both before and after the layout of each argument, the Next 7722 Stacked Argument Address (NSAA) will have a minimum alignment of 7723 8 bytes. */ 7724 7725 static unsigned int 7726 aarch64_function_arg_boundary (machine_mode mode, const_tree type) 7727 { 7728 unsigned int abi_break; 7729 unsigned int alignment = aarch64_function_arg_alignment (mode, type, 7730 &abi_break); 7731 alignment = MIN (MAX (alignment, PARM_BOUNDARY), STACK_BOUNDARY); 7732 if (abi_break && warn_psabi) 7733 { 7734 abi_break = MIN (MAX (abi_break, PARM_BOUNDARY), STACK_BOUNDARY); 7735 if (alignment != abi_break) 7736 inform (input_location, "parameter passing for argument of type " 7737 "%qT changed in GCC 9.1", type); 7738 } 7739 return alignment; 7740 } 7741 7742 /* Implement TARGET_GET_RAW_RESULT_MODE and TARGET_GET_RAW_ARG_MODE. */ 7743 7744 static fixed_size_mode 7745 aarch64_get_reg_raw_mode (int regno) 7746 { 7747 if (TARGET_SVE && FP_REGNUM_P (regno)) 7748 /* Don't use the SVE part of the register for __builtin_apply and 7749 __builtin_return. The SVE registers aren't used by the normal PCS, 7750 so using them there would be a waste of time. The PCS extensions 7751 for SVE types are fundamentally incompatible with the 7752 __builtin_return/__builtin_apply interface. */ 7753 return as_a <fixed_size_mode> (V16QImode); 7754 return default_get_reg_raw_mode (regno); 7755 } 7756 7757 /* Implement TARGET_FUNCTION_ARG_PADDING. 7758 7759 Small aggregate types are placed in the lowest memory address. 7760 7761 The related parameter passing rules are B.4, C.3, C.5 and C.14. */ 7762 7763 static pad_direction 7764 aarch64_function_arg_padding (machine_mode mode, const_tree type) 7765 { 7766 /* On little-endian targets, the least significant byte of every stack 7767 argument is passed at the lowest byte address of the stack slot. */ 7768 if (!BYTES_BIG_ENDIAN) 7769 return PAD_UPWARD; 7770 7771 /* Otherwise, integral, floating-point and pointer types are padded downward: 7772 the least significant byte of a stack argument is passed at the highest 7773 byte address of the stack slot. */ 7774 if (type 7775 ? (INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type) 7776 || POINTER_TYPE_P (type)) 7777 : (SCALAR_INT_MODE_P (mode) || SCALAR_FLOAT_MODE_P (mode))) 7778 return PAD_DOWNWARD; 7779 7780 /* Everything else padded upward, i.e. data in first byte of stack slot. */ 7781 return PAD_UPWARD; 7782 } 7783 7784 /* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST). 7785 7786 It specifies padding for the last (may also be the only) 7787 element of a block move between registers and memory. If 7788 assuming the block is in the memory, padding upward means that 7789 the last element is padded after its highest significant byte, 7790 while in downward padding, the last element is padded at the 7791 its least significant byte side. 7792 7793 Small aggregates and small complex types are always padded 7794 upwards. 7795 7796 We don't need to worry about homogeneous floating-point or 7797 short-vector aggregates; their move is not affected by the 7798 padding direction determined here. Regardless of endianness, 7799 each element of such an aggregate is put in the least 7800 significant bits of a fp/simd register. 7801 7802 Return !BYTES_BIG_ENDIAN if the least significant byte of the 7803 register has useful data, and return the opposite if the most 7804 significant byte does. */ 7805 7806 bool 7807 aarch64_pad_reg_upward (machine_mode mode, const_tree type, 7808 bool first ATTRIBUTE_UNUSED) 7809 { 7810 7811 /* Aside from pure scalable types, small composite types are always 7812 padded upward. */ 7813 if (BYTES_BIG_ENDIAN && aarch64_composite_type_p (type, mode)) 7814 { 7815 HOST_WIDE_INT size; 7816 if (type) 7817 size = int_size_in_bytes (type); 7818 else 7819 /* No frontends can create types with variable-sized modes, so we 7820 shouldn't be asked to pass or return them. */ 7821 size = GET_MODE_SIZE (mode).to_constant (); 7822 if (size < 2 * UNITS_PER_WORD) 7823 { 7824 pure_scalable_type_info pst_info; 7825 if (pst_info.analyze_registers (type)) 7826 return false; 7827 return true; 7828 } 7829 } 7830 7831 /* Otherwise, use the default padding. */ 7832 return !BYTES_BIG_ENDIAN; 7833 } 7834 7835 static scalar_int_mode 7836 aarch64_libgcc_cmp_return_mode (void) 7837 { 7838 return SImode; 7839 } 7840 7841 #define PROBE_INTERVAL (1 << STACK_CHECK_PROBE_INTERVAL_EXP) 7842 7843 /* We use the 12-bit shifted immediate arithmetic instructions so values 7844 must be multiple of (1 << 12), i.e. 4096. */ 7845 #define ARITH_FACTOR 4096 7846 7847 #if (PROBE_INTERVAL % ARITH_FACTOR) != 0 7848 #error Cannot use simple address calculation for stack probing 7849 #endif 7850 7851 /* Emit code to probe a range of stack addresses from FIRST to FIRST+POLY_SIZE, 7852 inclusive. These are offsets from the current stack pointer. */ 7853 7854 static void 7855 aarch64_emit_probe_stack_range (HOST_WIDE_INT first, poly_int64 poly_size) 7856 { 7857 HOST_WIDE_INT size; 7858 if (!poly_size.is_constant (&size)) 7859 { 7860 sorry ("stack probes for SVE frames"); 7861 return; 7862 } 7863 7864 rtx reg1 = gen_rtx_REG (Pmode, PROBE_STACK_FIRST_REGNUM); 7865 7866 /* See the same assertion on PROBE_INTERVAL above. */ 7867 gcc_assert ((first % ARITH_FACTOR) == 0); 7868 7869 /* See if we have a constant small number of probes to generate. If so, 7870 that's the easy case. */ 7871 if (size <= PROBE_INTERVAL) 7872 { 7873 const HOST_WIDE_INT base = ROUND_UP (size, ARITH_FACTOR); 7874 7875 emit_set_insn (reg1, 7876 plus_constant (Pmode, 7877 stack_pointer_rtx, -(first + base))); 7878 emit_stack_probe (plus_constant (Pmode, reg1, base - size)); 7879 } 7880 7881 /* The run-time loop is made up of 8 insns in the generic case while the 7882 compile-time loop is made up of 4+2*(n-2) insns for n # of intervals. */ 7883 else if (size <= 4 * PROBE_INTERVAL) 7884 { 7885 HOST_WIDE_INT i, rem; 7886 7887 emit_set_insn (reg1, 7888 plus_constant (Pmode, 7889 stack_pointer_rtx, 7890 -(first + PROBE_INTERVAL))); 7891 emit_stack_probe (reg1); 7892 7893 /* Probe at FIRST + N * PROBE_INTERVAL for values of N from 2 until 7894 it exceeds SIZE. If only two probes are needed, this will not 7895 generate any code. Then probe at FIRST + SIZE. */ 7896 for (i = 2 * PROBE_INTERVAL; i < size; i += PROBE_INTERVAL) 7897 { 7898 emit_set_insn (reg1, 7899 plus_constant (Pmode, reg1, -PROBE_INTERVAL)); 7900 emit_stack_probe (reg1); 7901 } 7902 7903 rem = size - (i - PROBE_INTERVAL); 7904 if (rem > 256) 7905 { 7906 const HOST_WIDE_INT base = ROUND_UP (rem, ARITH_FACTOR); 7907 7908 emit_set_insn (reg1, plus_constant (Pmode, reg1, -base)); 7909 emit_stack_probe (plus_constant (Pmode, reg1, base - rem)); 7910 } 7911 else 7912 emit_stack_probe (plus_constant (Pmode, reg1, -rem)); 7913 } 7914 7915 /* Otherwise, do the same as above, but in a loop. Note that we must be 7916 extra careful with variables wrapping around because we might be at 7917 the very top (or the very bottom) of the address space and we have 7918 to be able to handle this case properly; in particular, we use an 7919 equality test for the loop condition. */ 7920 else 7921 { 7922 rtx reg2 = gen_rtx_REG (Pmode, PROBE_STACK_SECOND_REGNUM); 7923 7924 /* Step 1: round SIZE to the previous multiple of the interval. */ 7925 7926 HOST_WIDE_INT rounded_size = size & -PROBE_INTERVAL; 7927 7928 7929 /* Step 2: compute initial and final value of the loop counter. */ 7930 7931 /* TEST_ADDR = SP + FIRST. */ 7932 emit_set_insn (reg1, 7933 plus_constant (Pmode, stack_pointer_rtx, -first)); 7934 7935 /* LAST_ADDR = SP + FIRST + ROUNDED_SIZE. */ 7936 HOST_WIDE_INT adjustment = - (first + rounded_size); 7937 if (! aarch64_uimm12_shift (adjustment)) 7938 { 7939 aarch64_internal_mov_immediate (reg2, GEN_INT (adjustment), 7940 true, Pmode); 7941 emit_set_insn (reg2, gen_rtx_PLUS (Pmode, stack_pointer_rtx, reg2)); 7942 } 7943 else 7944 emit_set_insn (reg2, 7945 plus_constant (Pmode, stack_pointer_rtx, adjustment)); 7946 7947 /* Step 3: the loop 7948 7949 do 7950 { 7951 TEST_ADDR = TEST_ADDR + PROBE_INTERVAL 7952 probe at TEST_ADDR 7953 } 7954 while (TEST_ADDR != LAST_ADDR) 7955 7956 probes at FIRST + N * PROBE_INTERVAL for values of N from 1 7957 until it is equal to ROUNDED_SIZE. */ 7958 7959 emit_insn (gen_probe_stack_range (reg1, reg1, reg2)); 7960 7961 7962 /* Step 4: probe at FIRST + SIZE if we cannot assert at compile-time 7963 that SIZE is equal to ROUNDED_SIZE. */ 7964 7965 if (size != rounded_size) 7966 { 7967 HOST_WIDE_INT rem = size - rounded_size; 7968 7969 if (rem > 256) 7970 { 7971 const HOST_WIDE_INT base = ROUND_UP (rem, ARITH_FACTOR); 7972 7973 emit_set_insn (reg2, plus_constant (Pmode, reg2, -base)); 7974 emit_stack_probe (plus_constant (Pmode, reg2, base - rem)); 7975 } 7976 else 7977 emit_stack_probe (plus_constant (Pmode, reg2, -rem)); 7978 } 7979 } 7980 7981 /* Make sure nothing is scheduled before we are done. */ 7982 emit_insn (gen_blockage ()); 7983 } 7984 7985 /* Probe a range of stack addresses from REG1 to REG2 inclusive. These are 7986 absolute addresses. */ 7987 7988 const char * 7989 aarch64_output_probe_stack_range (rtx reg1, rtx reg2) 7990 { 7991 static int labelno = 0; 7992 char loop_lab[32]; 7993 rtx xops[2]; 7994 7995 ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++); 7996 7997 /* Loop. */ 7998 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab); 7999 8000 HOST_WIDE_INT stack_clash_probe_interval 8001 = 1 << param_stack_clash_protection_guard_size; 8002 8003 /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL. */ 8004 xops[0] = reg1; 8005 HOST_WIDE_INT interval; 8006 if (flag_stack_clash_protection) 8007 interval = stack_clash_probe_interval; 8008 else 8009 interval = PROBE_INTERVAL; 8010 8011 gcc_assert (aarch64_uimm12_shift (interval)); 8012 xops[1] = GEN_INT (interval); 8013 8014 output_asm_insn ("sub\t%0, %0, %1", xops); 8015 8016 /* If doing stack clash protection then we probe up by the ABI specified 8017 amount. We do this because we're dropping full pages at a time in the 8018 loop. But if we're doing non-stack clash probing, probe at SP 0. */ 8019 if (flag_stack_clash_protection) 8020 xops[1] = GEN_INT (STACK_CLASH_CALLER_GUARD); 8021 else 8022 xops[1] = CONST0_RTX (GET_MODE (xops[1])); 8023 8024 /* Probe at TEST_ADDR. If we're inside the loop it is always safe to probe 8025 by this amount for each iteration. */ 8026 output_asm_insn ("str\txzr, [%0, %1]", xops); 8027 8028 /* Test if TEST_ADDR == LAST_ADDR. */ 8029 xops[1] = reg2; 8030 output_asm_insn ("cmp\t%0, %1", xops); 8031 8032 /* Branch. */ 8033 fputs ("\tb.ne\t", asm_out_file); 8034 assemble_name_raw (asm_out_file, loop_lab); 8035 fputc ('\n', asm_out_file); 8036 8037 return ""; 8038 } 8039 8040 /* Emit the probe loop for doing stack clash probes and stack adjustments for 8041 SVE. This emits probes from BASE to BASE - ADJUSTMENT based on a guard size 8042 of GUARD_SIZE. When a probe is emitted it is done at most 8043 MIN_PROBE_THRESHOLD bytes from the current BASE at an interval of 8044 at most MIN_PROBE_THRESHOLD. By the end of this function 8045 BASE = BASE - ADJUSTMENT. */ 8046 8047 const char * 8048 aarch64_output_probe_sve_stack_clash (rtx base, rtx adjustment, 8049 rtx min_probe_threshold, rtx guard_size) 8050 { 8051 /* This function is not allowed to use any instruction generation function 8052 like gen_ and friends. If you do you'll likely ICE during CFG validation, 8053 so instead emit the code you want using output_asm_insn. */ 8054 gcc_assert (flag_stack_clash_protection); 8055 gcc_assert (CONST_INT_P (min_probe_threshold) && CONST_INT_P (guard_size)); 8056 gcc_assert (INTVAL (guard_size) > INTVAL (min_probe_threshold)); 8057 8058 /* The minimum required allocation before the residual requires probing. */ 8059 HOST_WIDE_INT residual_probe_guard = INTVAL (min_probe_threshold); 8060 8061 /* Clamp the value down to the nearest value that can be used with a cmp. */ 8062 residual_probe_guard = aarch64_clamp_to_uimm12_shift (residual_probe_guard); 8063 rtx probe_offset_value_rtx = gen_int_mode (residual_probe_guard, Pmode); 8064 8065 gcc_assert (INTVAL (min_probe_threshold) >= residual_probe_guard); 8066 gcc_assert (aarch64_uimm12_shift (residual_probe_guard)); 8067 8068 static int labelno = 0; 8069 char loop_start_lab[32]; 8070 char loop_end_lab[32]; 8071 rtx xops[2]; 8072 8073 ASM_GENERATE_INTERNAL_LABEL (loop_start_lab, "SVLPSPL", labelno); 8074 ASM_GENERATE_INTERNAL_LABEL (loop_end_lab, "SVLPEND", labelno++); 8075 8076 /* Emit loop start label. */ 8077 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_start_lab); 8078 8079 /* ADJUSTMENT < RESIDUAL_PROBE_GUARD. */ 8080 xops[0] = adjustment; 8081 xops[1] = probe_offset_value_rtx; 8082 output_asm_insn ("cmp\t%0, %1", xops); 8083 8084 /* Branch to end if not enough adjustment to probe. */ 8085 fputs ("\tb.lt\t", asm_out_file); 8086 assemble_name_raw (asm_out_file, loop_end_lab); 8087 fputc ('\n', asm_out_file); 8088 8089 /* BASE = BASE - RESIDUAL_PROBE_GUARD. */ 8090 xops[0] = base; 8091 xops[1] = probe_offset_value_rtx; 8092 output_asm_insn ("sub\t%0, %0, %1", xops); 8093 8094 /* Probe at BASE. */ 8095 xops[1] = const0_rtx; 8096 output_asm_insn ("str\txzr, [%0, %1]", xops); 8097 8098 /* ADJUSTMENT = ADJUSTMENT - RESIDUAL_PROBE_GUARD. */ 8099 xops[0] = adjustment; 8100 xops[1] = probe_offset_value_rtx; 8101 output_asm_insn ("sub\t%0, %0, %1", xops); 8102 8103 /* Branch to start if still more bytes to allocate. */ 8104 fputs ("\tb\t", asm_out_file); 8105 assemble_name_raw (asm_out_file, loop_start_lab); 8106 fputc ('\n', asm_out_file); 8107 8108 /* No probe leave. */ 8109 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_end_lab); 8110 8111 /* BASE = BASE - ADJUSTMENT. */ 8112 xops[0] = base; 8113 xops[1] = adjustment; 8114 output_asm_insn ("sub\t%0, %0, %1", xops); 8115 return ""; 8116 } 8117 8118 /* Determine whether a frame chain needs to be generated. */ 8119 static bool 8120 aarch64_needs_frame_chain (void) 8121 { 8122 /* Force a frame chain for EH returns so the return address is at FP+8. */ 8123 if (frame_pointer_needed || crtl->calls_eh_return) 8124 return true; 8125 8126 /* A leaf function cannot have calls or write LR. */ 8127 bool is_leaf = crtl->is_leaf && !df_regs_ever_live_p (LR_REGNUM); 8128 8129 /* Don't use a frame chain in leaf functions if leaf frame pointers 8130 are disabled. */ 8131 if (flag_omit_leaf_frame_pointer && is_leaf) 8132 return false; 8133 8134 return aarch64_use_frame_pointer; 8135 } 8136 8137 /* Return true if the current function should save registers above 8138 the locals area, rather than below it. */ 8139 8140 static bool 8141 aarch64_save_regs_above_locals_p () 8142 { 8143 /* When using stack smash protection, make sure that the canary slot 8144 comes between the locals and the saved registers. Otherwise, 8145 it would be possible for a carefully sized smash attack to change 8146 the saved registers (particularly LR and FP) without reaching the 8147 canary. */ 8148 return crtl->stack_protect_guard; 8149 } 8150 8151 /* Mark the registers that need to be saved by the callee and calculate 8152 the size of the callee-saved registers area and frame record (both FP 8153 and LR may be omitted). */ 8154 static void 8155 aarch64_layout_frame (void) 8156 { 8157 int regno, last_fp_reg = INVALID_REGNUM; 8158 machine_mode vector_save_mode = aarch64_reg_save_mode (V8_REGNUM); 8159 poly_int64 vector_save_size = GET_MODE_SIZE (vector_save_mode); 8160 bool frame_related_fp_reg_p = false; 8161 aarch64_frame &frame = cfun->machine->frame; 8162 poly_int64 top_of_locals = -1; 8163 8164 frame.emit_frame_chain = aarch64_needs_frame_chain (); 8165 8166 /* Adjust the outgoing arguments size if required. Keep it in sync with what 8167 the mid-end is doing. */ 8168 crtl->outgoing_args_size = STACK_DYNAMIC_OFFSET (cfun); 8169 8170 #define SLOT_NOT_REQUIRED (-2) 8171 #define SLOT_REQUIRED (-1) 8172 8173 frame.wb_push_candidate1 = INVALID_REGNUM; 8174 frame.wb_push_candidate2 = INVALID_REGNUM; 8175 frame.spare_pred_reg = INVALID_REGNUM; 8176 8177 /* First mark all the registers that really need to be saved... */ 8178 for (regno = 0; regno <= LAST_SAVED_REGNUM; regno++) 8179 frame.reg_offset[regno] = SLOT_NOT_REQUIRED; 8180 8181 /* ... that includes the eh data registers (if needed)... */ 8182 if (crtl->calls_eh_return) 8183 for (regno = 0; EH_RETURN_DATA_REGNO (regno) != INVALID_REGNUM; regno++) 8184 frame.reg_offset[EH_RETURN_DATA_REGNO (regno)] = SLOT_REQUIRED; 8185 8186 /* ... and any callee saved register that dataflow says is live. */ 8187 for (regno = R0_REGNUM; regno <= R30_REGNUM; regno++) 8188 if (df_regs_ever_live_p (regno) 8189 && !fixed_regs[regno] 8190 && (regno == R30_REGNUM 8191 || !crtl->abi->clobbers_full_reg_p (regno))) 8192 frame.reg_offset[regno] = SLOT_REQUIRED; 8193 8194 for (regno = V0_REGNUM; regno <= V31_REGNUM; regno++) 8195 if (df_regs_ever_live_p (regno) 8196 && !fixed_regs[regno] 8197 && !crtl->abi->clobbers_full_reg_p (regno)) 8198 { 8199 frame.reg_offset[regno] = SLOT_REQUIRED; 8200 last_fp_reg = regno; 8201 if (aarch64_emit_cfi_for_reg_p (regno)) 8202 frame_related_fp_reg_p = true; 8203 } 8204 8205 /* Big-endian SVE frames need a spare predicate register in order 8206 to save Z8-Z15. Decide which register they should use. Prefer 8207 an unused argument register if possible, so that we don't force P4 8208 to be saved unnecessarily. */ 8209 if (frame_related_fp_reg_p 8210 && crtl->abi->id () == ARM_PCS_SVE 8211 && BYTES_BIG_ENDIAN) 8212 { 8213 bitmap live1 = df_get_live_out (ENTRY_BLOCK_PTR_FOR_FN (cfun)); 8214 bitmap live2 = df_get_live_in (EXIT_BLOCK_PTR_FOR_FN (cfun)); 8215 for (regno = P0_REGNUM; regno <= P7_REGNUM; regno++) 8216 if (!bitmap_bit_p (live1, regno) && !bitmap_bit_p (live2, regno)) 8217 break; 8218 gcc_assert (regno <= P7_REGNUM); 8219 frame.spare_pred_reg = regno; 8220 df_set_regs_ever_live (regno, true); 8221 } 8222 8223 for (regno = P0_REGNUM; regno <= P15_REGNUM; regno++) 8224 if (df_regs_ever_live_p (regno) 8225 && !fixed_regs[regno] 8226 && !crtl->abi->clobbers_full_reg_p (regno)) 8227 frame.reg_offset[regno] = SLOT_REQUIRED; 8228 8229 bool regs_at_top_p = aarch64_save_regs_above_locals_p (); 8230 8231 poly_int64 offset = crtl->outgoing_args_size; 8232 gcc_assert (multiple_p (offset, STACK_BOUNDARY / BITS_PER_UNIT)); 8233 if (regs_at_top_p) 8234 { 8235 offset += get_frame_size (); 8236 offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT); 8237 top_of_locals = offset; 8238 } 8239 frame.bytes_below_saved_regs = offset; 8240 frame.sve_save_and_probe = INVALID_REGNUM; 8241 8242 /* Now assign stack slots for the registers. Start with the predicate 8243 registers, since predicate LDR and STR have a relatively small 8244 offset range. These saves happen below the hard frame pointer. */ 8245 for (regno = P0_REGNUM; regno <= P15_REGNUM; regno++) 8246 if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED)) 8247 { 8248 if (frame.sve_save_and_probe == INVALID_REGNUM) 8249 frame.sve_save_and_probe = regno; 8250 frame.reg_offset[regno] = offset; 8251 offset += BYTES_PER_SVE_PRED; 8252 } 8253 8254 poly_int64 saved_prs_size = offset - frame.bytes_below_saved_regs; 8255 if (maybe_ne (saved_prs_size, 0)) 8256 { 8257 /* If we have any vector registers to save above the predicate registers, 8258 the offset of the vector register save slots need to be a multiple 8259 of the vector size. This lets us use the immediate forms of LDR/STR 8260 (or LD1/ST1 for big-endian). 8261 8262 A vector register is 8 times the size of a predicate register, 8263 and we need to save a maximum of 12 predicate registers, so the 8264 first vector register will be at either #1, MUL VL or #2, MUL VL. 8265 8266 If we don't have any vector registers to save, and we know how 8267 big the predicate save area is, we can just round it up to the 8268 next 16-byte boundary. */ 8269 if (last_fp_reg == (int) INVALID_REGNUM && offset.is_constant ()) 8270 offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT); 8271 else 8272 { 8273 if (known_le (saved_prs_size, vector_save_size)) 8274 offset = frame.bytes_below_saved_regs + vector_save_size; 8275 else if (known_le (saved_prs_size, vector_save_size * 2)) 8276 offset = frame.bytes_below_saved_regs + vector_save_size * 2; 8277 else 8278 gcc_unreachable (); 8279 } 8280 } 8281 8282 /* If we need to save any SVE vector registers, add them next. */ 8283 if (last_fp_reg != (int) INVALID_REGNUM && crtl->abi->id () == ARM_PCS_SVE) 8284 for (regno = V0_REGNUM; regno <= V31_REGNUM; regno++) 8285 if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED)) 8286 { 8287 if (frame.sve_save_and_probe == INVALID_REGNUM) 8288 frame.sve_save_and_probe = regno; 8289 frame.reg_offset[regno] = offset; 8290 offset += vector_save_size; 8291 } 8292 8293 /* OFFSET is now the offset of the hard frame pointer from the bottom 8294 of the callee save area. */ 8295 auto below_hard_fp_saved_regs_size = offset - frame.bytes_below_saved_regs; 8296 bool saves_below_hard_fp_p = maybe_ne (below_hard_fp_saved_regs_size, 0); 8297 gcc_assert (!saves_below_hard_fp_p 8298 || (frame.sve_save_and_probe != INVALID_REGNUM 8299 && known_eq (frame.reg_offset[frame.sve_save_and_probe], 8300 frame.bytes_below_saved_regs))); 8301 8302 frame.bytes_below_hard_fp = offset; 8303 frame.hard_fp_save_and_probe = INVALID_REGNUM; 8304 8305 auto allocate_gpr_slot = [&](unsigned int regno) 8306 { 8307 if (frame.hard_fp_save_and_probe == INVALID_REGNUM) 8308 frame.hard_fp_save_and_probe = regno; 8309 frame.reg_offset[regno] = offset; 8310 if (frame.wb_push_candidate1 == INVALID_REGNUM) 8311 frame.wb_push_candidate1 = regno; 8312 else if (frame.wb_push_candidate2 == INVALID_REGNUM) 8313 frame.wb_push_candidate2 = regno; 8314 offset += UNITS_PER_WORD; 8315 }; 8316 8317 if (frame.emit_frame_chain) 8318 { 8319 /* FP and LR are placed in the linkage record. */ 8320 allocate_gpr_slot (R29_REGNUM); 8321 allocate_gpr_slot (R30_REGNUM); 8322 } 8323 else if (flag_stack_clash_protection 8324 && known_eq (frame.reg_offset[R30_REGNUM], SLOT_REQUIRED)) 8325 /* Put the LR save slot first, since it makes a good choice of probe 8326 for stack clash purposes. The idea is that the link register usually 8327 has to be saved before a call anyway, and so we lose little by 8328 stopping it from being individually shrink-wrapped. */ 8329 allocate_gpr_slot (R30_REGNUM); 8330 8331 for (regno = R0_REGNUM; regno <= R30_REGNUM; regno++) 8332 if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED)) 8333 allocate_gpr_slot (regno); 8334 8335 poly_int64 max_int_offset = offset; 8336 offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT); 8337 bool has_align_gap = maybe_ne (offset, max_int_offset); 8338 8339 for (regno = V0_REGNUM; regno <= V31_REGNUM; regno++) 8340 if (known_eq (frame.reg_offset[regno], SLOT_REQUIRED)) 8341 { 8342 if (frame.hard_fp_save_and_probe == INVALID_REGNUM) 8343 frame.hard_fp_save_and_probe = regno; 8344 /* If there is an alignment gap between integer and fp callee-saves, 8345 allocate the last fp register to it if possible. */ 8346 if (regno == last_fp_reg 8347 && has_align_gap 8348 && known_eq (vector_save_size, 8) 8349 && multiple_p (offset, 16)) 8350 { 8351 frame.reg_offset[regno] = max_int_offset; 8352 break; 8353 } 8354 8355 frame.reg_offset[regno] = offset; 8356 if (frame.wb_push_candidate1 == INVALID_REGNUM) 8357 frame.wb_push_candidate1 = regno; 8358 else if (frame.wb_push_candidate2 == INVALID_REGNUM 8359 && frame.wb_push_candidate1 >= V0_REGNUM) 8360 frame.wb_push_candidate2 = regno; 8361 offset += vector_save_size; 8362 } 8363 8364 offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT); 8365 8366 auto saved_regs_size = offset - frame.bytes_below_saved_regs; 8367 gcc_assert (known_eq (saved_regs_size, below_hard_fp_saved_regs_size) 8368 || (frame.hard_fp_save_and_probe != INVALID_REGNUM 8369 && known_eq (frame.reg_offset[frame.hard_fp_save_and_probe], 8370 frame.bytes_below_hard_fp))); 8371 8372 /* With stack-clash, a register must be saved in non-leaf functions. 8373 The saving of the bottommost register counts as an implicit probe, 8374 which allows us to maintain the invariant described in the comment 8375 at expand_prologue. */ 8376 gcc_assert (crtl->is_leaf || maybe_ne (saved_regs_size, 0)); 8377 8378 if (!regs_at_top_p) 8379 { 8380 offset += get_frame_size (); 8381 offset = aligned_upper_bound (offset, STACK_BOUNDARY / BITS_PER_UNIT); 8382 top_of_locals = offset; 8383 } 8384 offset += frame.saved_varargs_size; 8385 gcc_assert (multiple_p (offset, STACK_BOUNDARY / BITS_PER_UNIT)); 8386 frame.frame_size = offset; 8387 8388 frame.bytes_above_hard_fp = frame.frame_size - frame.bytes_below_hard_fp; 8389 gcc_assert (known_ge (top_of_locals, 0)); 8390 frame.bytes_above_locals = frame.frame_size - top_of_locals; 8391 8392 frame.initial_adjust = 0; 8393 frame.final_adjust = 0; 8394 frame.callee_adjust = 0; 8395 frame.sve_callee_adjust = 0; 8396 8397 frame.wb_pop_candidate1 = frame.wb_push_candidate1; 8398 frame.wb_pop_candidate2 = frame.wb_push_candidate2; 8399 8400 /* Shadow call stack only deals with functions where the LR is pushed 8401 onto the stack and without specifying the "no_sanitize" attribute 8402 with the argument "shadow-call-stack". */ 8403 frame.is_scs_enabled 8404 = (!crtl->calls_eh_return 8405 && sanitize_flags_p (SANITIZE_SHADOW_CALL_STACK) 8406 && known_ge (frame.reg_offset[LR_REGNUM], 0)); 8407 8408 /* When shadow call stack is enabled, the scs_pop in the epilogue will 8409 restore x30, and we don't need to pop x30 again in the traditional 8410 way. Pop candidates record the registers that need to be popped 8411 eventually. */ 8412 if (frame.is_scs_enabled) 8413 { 8414 if (frame.wb_pop_candidate2 == R30_REGNUM) 8415 frame.wb_pop_candidate2 = INVALID_REGNUM; 8416 else if (frame.wb_pop_candidate1 == R30_REGNUM) 8417 frame.wb_pop_candidate1 = INVALID_REGNUM; 8418 } 8419 8420 /* If candidate2 is INVALID_REGNUM, we need to adjust max_push_offset to 8421 256 to ensure that the offset meets the requirements of emit_move_insn. 8422 Similarly, if candidate1 is INVALID_REGNUM, we need to set 8423 max_push_offset to 0, because no registers are popped at this time, 8424 so callee_adjust cannot be adjusted. */ 8425 HOST_WIDE_INT max_push_offset = 0; 8426 if (frame.wb_pop_candidate1 != INVALID_REGNUM) 8427 { 8428 if (frame.wb_pop_candidate2 != INVALID_REGNUM) 8429 max_push_offset = 512; 8430 else 8431 max_push_offset = 256; 8432 } 8433 8434 HOST_WIDE_INT const_size, const_below_saved_regs, const_above_fp; 8435 HOST_WIDE_INT const_saved_regs_size; 8436 if (known_eq (saved_regs_size, 0)) 8437 frame.initial_adjust = frame.frame_size; 8438 else if (frame.frame_size.is_constant (&const_size) 8439 && const_size < max_push_offset 8440 && known_eq (frame.bytes_above_hard_fp, const_size)) 8441 { 8442 /* Simple, small frame with no data below the saved registers. 8443 8444 stp reg1, reg2, [sp, -frame_size]! 8445 stp reg3, reg4, [sp, 16] */ 8446 frame.callee_adjust = const_size; 8447 } 8448 else if (frame.bytes_below_saved_regs.is_constant (&const_below_saved_regs) 8449 && saved_regs_size.is_constant (&const_saved_regs_size) 8450 && const_below_saved_regs + const_saved_regs_size < 512 8451 /* We could handle this case even with data below the saved 8452 registers, provided that that data left us with valid offsets 8453 for all predicate and vector save slots. It's such a rare 8454 case that it hardly seems worth the effort though. */ 8455 && (!saves_below_hard_fp_p || const_below_saved_regs == 0) 8456 && !(cfun->calls_alloca 8457 && frame.bytes_above_hard_fp.is_constant (&const_above_fp) 8458 && const_above_fp < max_push_offset)) 8459 { 8460 /* Frame with small area below the saved registers: 8461 8462 sub sp, sp, frame_size 8463 stp reg1, reg2, [sp, bytes_below_saved_regs] 8464 stp reg3, reg4, [sp, bytes_below_saved_regs + 16] */ 8465 frame.initial_adjust = frame.frame_size; 8466 } 8467 else if (saves_below_hard_fp_p 8468 && known_eq (saved_regs_size, below_hard_fp_saved_regs_size)) 8469 { 8470 /* Frame in which all saves are SVE saves: 8471 8472 sub sp, sp, frame_size - bytes_below_saved_regs 8473 save SVE registers relative to SP 8474 sub sp, sp, bytes_below_saved_regs */ 8475 frame.initial_adjust = frame.frame_size - frame.bytes_below_saved_regs; 8476 frame.final_adjust = frame.bytes_below_saved_regs; 8477 } 8478 else if (frame.bytes_above_hard_fp.is_constant (&const_above_fp) 8479 && const_above_fp < max_push_offset) 8480 { 8481 /* Frame with large area below the saved registers, or with SVE saves, 8482 but with a small area above: 8483 8484 stp reg1, reg2, [sp, -hard_fp_offset]! 8485 stp reg3, reg4, [sp, 16] 8486 [sub sp, sp, below_hard_fp_saved_regs_size] 8487 [save SVE registers relative to SP] 8488 sub sp, sp, bytes_below_saved_regs */ 8489 frame.callee_adjust = const_above_fp; 8490 frame.sve_callee_adjust = below_hard_fp_saved_regs_size; 8491 frame.final_adjust = frame.bytes_below_saved_regs; 8492 } 8493 else 8494 { 8495 /* General case: 8496 8497 sub sp, sp, hard_fp_offset 8498 stp x29, x30, [sp, 0] 8499 add x29, sp, 0 8500 stp reg3, reg4, [sp, 16] 8501 [sub sp, sp, below_hard_fp_saved_regs_size] 8502 [save SVE registers relative to SP] 8503 sub sp, sp, bytes_below_saved_regs */ 8504 frame.initial_adjust = frame.bytes_above_hard_fp; 8505 frame.sve_callee_adjust = below_hard_fp_saved_regs_size; 8506 frame.final_adjust = frame.bytes_below_saved_regs; 8507 } 8508 8509 /* The frame is allocated in pieces, with each non-final piece 8510 including a register save at offset 0 that acts as a probe for 8511 the following piece. In addition, the save of the bottommost register 8512 acts as a probe for callees and allocas. Roll back any probes that 8513 aren't needed. 8514 8515 A probe isn't needed if it is associated with the final allocation 8516 (including callees and allocas) that happens before the epilogue is 8517 executed. */ 8518 if (crtl->is_leaf 8519 && !cfun->calls_alloca 8520 && known_eq (frame.final_adjust, 0)) 8521 { 8522 if (maybe_ne (frame.sve_callee_adjust, 0)) 8523 frame.sve_save_and_probe = INVALID_REGNUM; 8524 else 8525 frame.hard_fp_save_and_probe = INVALID_REGNUM; 8526 } 8527 8528 /* Make sure the individual adjustments add up to the full frame size. */ 8529 gcc_assert (known_eq (frame.initial_adjust 8530 + frame.callee_adjust 8531 + frame.sve_callee_adjust 8532 + frame.final_adjust, frame.frame_size)); 8533 8534 if (!frame.emit_frame_chain && frame.callee_adjust == 0) 8535 { 8536 /* We've decided not to associate any register saves with the initial 8537 stack allocation. */ 8538 frame.wb_pop_candidate1 = frame.wb_push_candidate1 = INVALID_REGNUM; 8539 frame.wb_pop_candidate2 = frame.wb_push_candidate2 = INVALID_REGNUM; 8540 } 8541 8542 frame.laid_out = true; 8543 } 8544 8545 /* Return true if the register REGNO is saved on entry to 8546 the current function. */ 8547 8548 static bool 8549 aarch64_register_saved_on_entry (int regno) 8550 { 8551 return known_ge (cfun->machine->frame.reg_offset[regno], 0); 8552 } 8553 8554 /* Return the next register up from REGNO up to LIMIT for the callee 8555 to save. */ 8556 8557 static unsigned 8558 aarch64_next_callee_save (unsigned regno, unsigned limit) 8559 { 8560 while (regno <= limit && !aarch64_register_saved_on_entry (regno)) 8561 regno ++; 8562 return regno; 8563 } 8564 8565 /* Push the register number REGNO of mode MODE to the stack with write-back 8566 adjusting the stack by ADJUSTMENT. */ 8567 8568 static void 8569 aarch64_pushwb_single_reg (machine_mode mode, unsigned regno, 8570 HOST_WIDE_INT adjustment) 8571 { 8572 rtx base_rtx = stack_pointer_rtx; 8573 rtx insn, reg, mem; 8574 8575 reg = gen_rtx_REG (mode, regno); 8576 mem = gen_rtx_PRE_MODIFY (Pmode, base_rtx, 8577 plus_constant (Pmode, base_rtx, -adjustment)); 8578 mem = gen_frame_mem (mode, mem); 8579 8580 insn = emit_move_insn (mem, reg); 8581 RTX_FRAME_RELATED_P (insn) = 1; 8582 } 8583 8584 /* Generate and return an instruction to store the pair of registers 8585 REG and REG2 of mode MODE to location BASE with write-back adjusting 8586 the stack location BASE by ADJUSTMENT. */ 8587 8588 static rtx 8589 aarch64_gen_storewb_pair (machine_mode mode, rtx base, rtx reg, rtx reg2, 8590 HOST_WIDE_INT adjustment) 8591 { 8592 switch (mode) 8593 { 8594 case E_DImode: 8595 return gen_storewb_pairdi_di (base, base, reg, reg2, 8596 GEN_INT (-adjustment), 8597 GEN_INT (UNITS_PER_WORD - adjustment)); 8598 case E_DFmode: 8599 return gen_storewb_pairdf_di (base, base, reg, reg2, 8600 GEN_INT (-adjustment), 8601 GEN_INT (UNITS_PER_WORD - adjustment)); 8602 case E_TFmode: 8603 return gen_storewb_pairtf_di (base, base, reg, reg2, 8604 GEN_INT (-adjustment), 8605 GEN_INT (UNITS_PER_VREG - adjustment)); 8606 case E_V16QImode: 8607 return gen_storewb_pairv16qi_di (base, base, reg, reg2, 8608 GEN_INT (-adjustment), 8609 GEN_INT (UNITS_PER_VREG - adjustment)); 8610 default: 8611 gcc_unreachable (); 8612 } 8613 } 8614 8615 /* Push registers numbered REGNO1 and REGNO2 to the stack, adjusting the 8616 stack pointer by ADJUSTMENT. */ 8617 8618 static void 8619 aarch64_push_regs (unsigned regno1, unsigned regno2, HOST_WIDE_INT adjustment) 8620 { 8621 rtx_insn *insn; 8622 machine_mode mode = aarch64_reg_save_mode (regno1); 8623 8624 if (regno2 == INVALID_REGNUM) 8625 return aarch64_pushwb_single_reg (mode, regno1, adjustment); 8626 8627 rtx reg1 = gen_rtx_REG (mode, regno1); 8628 rtx reg2 = gen_rtx_REG (mode, regno2); 8629 8630 insn = emit_insn (aarch64_gen_storewb_pair (mode, stack_pointer_rtx, reg1, 8631 reg2, adjustment)); 8632 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 2)) = 1; 8633 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 1)) = 1; 8634 RTX_FRAME_RELATED_P (insn) = 1; 8635 } 8636 8637 /* Load the pair of register REG, REG2 of mode MODE from stack location BASE, 8638 adjusting it by ADJUSTMENT afterwards. */ 8639 8640 static rtx 8641 aarch64_gen_loadwb_pair (machine_mode mode, rtx base, rtx reg, rtx reg2, 8642 HOST_WIDE_INT adjustment) 8643 { 8644 switch (mode) 8645 { 8646 case E_DImode: 8647 return gen_loadwb_pairdi_di (base, base, reg, reg2, GEN_INT (adjustment), 8648 GEN_INT (UNITS_PER_WORD)); 8649 case E_DFmode: 8650 return gen_loadwb_pairdf_di (base, base, reg, reg2, GEN_INT (adjustment), 8651 GEN_INT (UNITS_PER_WORD)); 8652 case E_TFmode: 8653 return gen_loadwb_pairtf_di (base, base, reg, reg2, GEN_INT (adjustment), 8654 GEN_INT (UNITS_PER_VREG)); 8655 case E_V16QImode: 8656 return gen_loadwb_pairv16qi_di (base, base, reg, reg2, 8657 GEN_INT (adjustment), 8658 GEN_INT (UNITS_PER_VREG)); 8659 default: 8660 gcc_unreachable (); 8661 } 8662 } 8663 8664 /* Pop the two registers numbered REGNO1, REGNO2 from the stack, adjusting it 8665 afterwards by ADJUSTMENT and writing the appropriate REG_CFA_RESTORE notes 8666 into CFI_OPS. */ 8667 8668 static void 8669 aarch64_pop_regs (unsigned regno1, unsigned regno2, HOST_WIDE_INT adjustment, 8670 rtx *cfi_ops) 8671 { 8672 machine_mode mode = aarch64_reg_save_mode (regno1); 8673 rtx reg1 = gen_rtx_REG (mode, regno1); 8674 8675 *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg1, *cfi_ops); 8676 8677 if (regno2 == INVALID_REGNUM) 8678 { 8679 rtx mem = plus_constant (Pmode, stack_pointer_rtx, adjustment); 8680 mem = gen_rtx_POST_MODIFY (Pmode, stack_pointer_rtx, mem); 8681 emit_move_insn (reg1, gen_frame_mem (mode, mem)); 8682 } 8683 else 8684 { 8685 rtx reg2 = gen_rtx_REG (mode, regno2); 8686 *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg2, *cfi_ops); 8687 emit_insn (aarch64_gen_loadwb_pair (mode, stack_pointer_rtx, reg1, 8688 reg2, adjustment)); 8689 } 8690 } 8691 8692 /* Generate and return a store pair instruction of mode MODE to store 8693 register REG1 to MEM1 and register REG2 to MEM2. */ 8694 8695 static rtx 8696 aarch64_gen_store_pair (machine_mode mode, rtx mem1, rtx reg1, rtx mem2, 8697 rtx reg2) 8698 { 8699 switch (mode) 8700 { 8701 case E_DImode: 8702 return gen_store_pair_dw_didi (mem1, reg1, mem2, reg2); 8703 8704 case E_DFmode: 8705 return gen_store_pair_dw_dfdf (mem1, reg1, mem2, reg2); 8706 8707 case E_TFmode: 8708 return gen_store_pair_dw_tftf (mem1, reg1, mem2, reg2); 8709 8710 case E_V4SImode: 8711 return gen_vec_store_pairv4siv4si (mem1, reg1, mem2, reg2); 8712 8713 case E_V16QImode: 8714 return gen_vec_store_pairv16qiv16qi (mem1, reg1, mem2, reg2); 8715 8716 default: 8717 gcc_unreachable (); 8718 } 8719 } 8720 8721 /* Generate and regurn a load pair isntruction of mode MODE to load register 8722 REG1 from MEM1 and register REG2 from MEM2. */ 8723 8724 static rtx 8725 aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2, 8726 rtx mem2) 8727 { 8728 switch (mode) 8729 { 8730 case E_DImode: 8731 return gen_load_pair_dw_didi (reg1, mem1, reg2, mem2); 8732 8733 case E_DFmode: 8734 return gen_load_pair_dw_dfdf (reg1, mem1, reg2, mem2); 8735 8736 case E_TFmode: 8737 return gen_load_pair_dw_tftf (reg1, mem1, reg2, mem2); 8738 8739 case E_V4SImode: 8740 return gen_load_pairv4siv4si (reg1, mem1, reg2, mem2); 8741 8742 case E_V16QImode: 8743 return gen_load_pairv16qiv16qi (reg1, mem1, reg2, mem2); 8744 8745 default: 8746 gcc_unreachable (); 8747 } 8748 } 8749 8750 /* Return TRUE if return address signing should be enabled for the current 8751 function, otherwise return FALSE. */ 8752 8753 bool 8754 aarch64_return_address_signing_enabled (void) 8755 { 8756 /* This function should only be called after frame laid out. */ 8757 gcc_assert (cfun->machine->frame.laid_out); 8758 8759 /* Turn return address signing off in any function that uses 8760 __builtin_eh_return. The address passed to __builtin_eh_return 8761 is not signed so either it has to be signed (with original sp) 8762 or the code path that uses it has to avoid authenticating it. 8763 Currently eh return introduces a return to anywhere gadget, no 8764 matter what we do here since it uses ret with user provided 8765 address. An ideal fix for that is to use indirect branch which 8766 can be protected with BTI j (to some extent). */ 8767 if (crtl->calls_eh_return) 8768 return false; 8769 8770 /* If signing scope is AARCH64_FUNCTION_NON_LEAF, we only sign a leaf function 8771 if its LR is pushed onto stack. */ 8772 return (aarch64_ra_sign_scope == AARCH64_FUNCTION_ALL 8773 || (aarch64_ra_sign_scope == AARCH64_FUNCTION_NON_LEAF 8774 && known_ge (cfun->machine->frame.reg_offset[LR_REGNUM], 0))); 8775 } 8776 8777 /* Return TRUE if Branch Target Identification Mechanism is enabled. */ 8778 bool 8779 aarch64_bti_enabled (void) 8780 { 8781 return (aarch64_enable_bti == 1); 8782 } 8783 8784 /* The caller is going to use ST1D or LD1D to save or restore an SVE 8785 register in mode MODE at BASE_RTX + OFFSET, where OFFSET is in 8786 the range [1, 16] * GET_MODE_SIZE (MODE). Prepare for this by: 8787 8788 (1) updating BASE_RTX + OFFSET so that it is a legitimate ST1D 8789 or LD1D address 8790 8791 (2) setting PRED to a valid predicate register for the ST1D or LD1D, 8792 if the variable isn't already nonnull 8793 8794 (1) is needed when OFFSET is in the range [8, 16] * GET_MODE_SIZE (MODE). 8795 Handle this case using a temporary base register that is suitable for 8796 all offsets in that range. Use ANCHOR_REG as this base register if it 8797 is nonnull, otherwise create a new register and store it in ANCHOR_REG. */ 8798 8799 static inline void 8800 aarch64_adjust_sve_callee_save_base (machine_mode mode, rtx &base_rtx, 8801 rtx &anchor_reg, poly_int64 &offset, 8802 rtx &ptrue) 8803 { 8804 if (maybe_ge (offset, 8 * GET_MODE_SIZE (mode))) 8805 { 8806 /* This is the maximum valid offset of the anchor from the base. 8807 Lower values would be valid too. */ 8808 poly_int64 anchor_offset = 16 * GET_MODE_SIZE (mode); 8809 if (!anchor_reg) 8810 { 8811 anchor_reg = gen_rtx_REG (Pmode, STACK_CLASH_SVE_CFA_REGNUM); 8812 emit_insn (gen_add3_insn (anchor_reg, base_rtx, 8813 gen_int_mode (anchor_offset, Pmode))); 8814 } 8815 base_rtx = anchor_reg; 8816 offset -= anchor_offset; 8817 } 8818 if (!ptrue) 8819 { 8820 int pred_reg = cfun->machine->frame.spare_pred_reg; 8821 emit_move_insn (gen_rtx_REG (VNx16BImode, pred_reg), 8822 CONSTM1_RTX (VNx16BImode)); 8823 ptrue = gen_rtx_REG (VNx2BImode, pred_reg); 8824 } 8825 } 8826 8827 /* Add a REG_CFA_EXPRESSION note to INSN to say that register REG 8828 is saved at BASE + OFFSET. */ 8829 8830 static void 8831 aarch64_add_cfa_expression (rtx_insn *insn, rtx reg, 8832 rtx base, poly_int64 offset) 8833 { 8834 rtx mem = gen_frame_mem (GET_MODE (reg), 8835 plus_constant (Pmode, base, offset)); 8836 add_reg_note (insn, REG_CFA_EXPRESSION, gen_rtx_SET (mem, reg)); 8837 } 8838 8839 /* Emit code to save the callee-saved registers from register number START 8840 to LIMIT to the stack. The stack pointer is currently BYTES_BELOW_SP 8841 bytes above the bottom of the static frame. Skip any write-back 8842 candidates if SKIP_WB is true. HARD_FP_VALID_P is true if the hard 8843 frame pointer has been set up. */ 8844 8845 static void 8846 aarch64_save_callee_saves (poly_int64 bytes_below_sp, 8847 unsigned start, unsigned limit, bool skip_wb, 8848 bool hard_fp_valid_p) 8849 { 8850 aarch64_frame &frame = cfun->machine->frame; 8851 rtx_insn *insn; 8852 unsigned regno; 8853 unsigned regno2; 8854 rtx anchor_reg = NULL_RTX, ptrue = NULL_RTX; 8855 8856 for (regno = aarch64_next_callee_save (start, limit); 8857 regno <= limit; 8858 regno = aarch64_next_callee_save (regno + 1, limit)) 8859 { 8860 rtx reg, mem; 8861 poly_int64 offset; 8862 bool frame_related_p = aarch64_emit_cfi_for_reg_p (regno); 8863 8864 if (skip_wb 8865 && (regno == frame.wb_push_candidate1 8866 || regno == frame.wb_push_candidate2)) 8867 continue; 8868 8869 if (cfun->machine->reg_is_wrapped_separately[regno]) 8870 continue; 8871 8872 machine_mode mode = aarch64_reg_save_mode (regno); 8873 reg = gen_rtx_REG (mode, regno); 8874 offset = frame.reg_offset[regno] - bytes_below_sp; 8875 rtx base_rtx = stack_pointer_rtx; 8876 poly_int64 sp_offset = offset; 8877 8878 HOST_WIDE_INT const_offset; 8879 if (mode == VNx2DImode && BYTES_BIG_ENDIAN) 8880 aarch64_adjust_sve_callee_save_base (mode, base_rtx, anchor_reg, 8881 offset, ptrue); 8882 else if (GP_REGNUM_P (regno) 8883 && (!offset.is_constant (&const_offset) || const_offset >= 512)) 8884 { 8885 poly_int64 fp_offset = frame.bytes_below_hard_fp - bytes_below_sp; 8886 if (hard_fp_valid_p) 8887 base_rtx = hard_frame_pointer_rtx; 8888 else 8889 { 8890 if (!anchor_reg) 8891 { 8892 anchor_reg = gen_rtx_REG (Pmode, STACK_CLASH_SVE_CFA_REGNUM); 8893 emit_insn (gen_add3_insn (anchor_reg, base_rtx, 8894 gen_int_mode (fp_offset, Pmode))); 8895 } 8896 base_rtx = anchor_reg; 8897 } 8898 offset -= fp_offset; 8899 } 8900 mem = gen_frame_mem (mode, plus_constant (Pmode, base_rtx, offset)); 8901 bool need_cfa_note_p = (base_rtx != stack_pointer_rtx); 8902 8903 if (!aarch64_sve_mode_p (mode) 8904 && (regno2 = aarch64_next_callee_save (regno + 1, limit)) <= limit 8905 && !cfun->machine->reg_is_wrapped_separately[regno2] 8906 && known_eq (GET_MODE_SIZE (mode), 8907 frame.reg_offset[regno2] - frame.reg_offset[regno])) 8908 { 8909 rtx reg2 = gen_rtx_REG (mode, regno2); 8910 rtx mem2; 8911 8912 offset += GET_MODE_SIZE (mode); 8913 mem2 = gen_frame_mem (mode, plus_constant (Pmode, base_rtx, offset)); 8914 insn = emit_insn (aarch64_gen_store_pair (mode, mem, reg, mem2, 8915 reg2)); 8916 8917 /* The first part of a frame-related parallel insn is 8918 always assumed to be relevant to the frame 8919 calculations; subsequent parts, are only 8920 frame-related if explicitly marked. */ 8921 if (aarch64_emit_cfi_for_reg_p (regno2)) 8922 { 8923 if (need_cfa_note_p) 8924 aarch64_add_cfa_expression (insn, reg2, stack_pointer_rtx, 8925 sp_offset + GET_MODE_SIZE (mode)); 8926 else 8927 RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, 1)) = 1; 8928 } 8929 8930 regno = regno2; 8931 } 8932 else if (mode == VNx2DImode && BYTES_BIG_ENDIAN) 8933 { 8934 insn = emit_insn (gen_aarch64_pred_mov (mode, mem, ptrue, reg)); 8935 need_cfa_note_p = true; 8936 } 8937 else if (aarch64_sve_mode_p (mode)) 8938 insn = emit_insn (gen_rtx_SET (mem, reg)); 8939 else 8940 insn = emit_move_insn (mem, reg); 8941 8942 RTX_FRAME_RELATED_P (insn) = frame_related_p; 8943 if (frame_related_p && need_cfa_note_p) 8944 aarch64_add_cfa_expression (insn, reg, stack_pointer_rtx, sp_offset); 8945 } 8946 } 8947 8948 /* Emit code to restore the callee registers from register number START 8949 up to and including LIMIT. The stack pointer is currently BYTES_BELOW_SP 8950 bytes above the bottom of the static frame. Skip any write-back 8951 candidates if SKIP_WB is true. Write the appropriate REG_CFA_RESTORE 8952 notes into CFI_OPS. */ 8953 8954 static void 8955 aarch64_restore_callee_saves (poly_int64 bytes_below_sp, unsigned start, 8956 unsigned limit, bool skip_wb, rtx *cfi_ops) 8957 { 8958 aarch64_frame &frame = cfun->machine->frame; 8959 unsigned regno; 8960 unsigned regno2; 8961 poly_int64 offset; 8962 rtx anchor_reg = NULL_RTX, ptrue = NULL_RTX; 8963 8964 for (regno = aarch64_next_callee_save (start, limit); 8965 regno <= limit; 8966 regno = aarch64_next_callee_save (regno + 1, limit)) 8967 { 8968 bool frame_related_p = aarch64_emit_cfi_for_reg_p (regno); 8969 if (cfun->machine->reg_is_wrapped_separately[regno]) 8970 continue; 8971 8972 rtx reg, mem; 8973 8974 if (skip_wb 8975 && (regno == frame.wb_pop_candidate1 8976 || regno == frame.wb_pop_candidate2)) 8977 continue; 8978 8979 machine_mode mode = aarch64_reg_save_mode (regno); 8980 reg = gen_rtx_REG (mode, regno); 8981 offset = frame.reg_offset[regno] - bytes_below_sp; 8982 rtx base_rtx = stack_pointer_rtx; 8983 if (mode == VNx2DImode && BYTES_BIG_ENDIAN) 8984 aarch64_adjust_sve_callee_save_base (mode, base_rtx, anchor_reg, 8985 offset, ptrue); 8986 mem = gen_frame_mem (mode, plus_constant (Pmode, base_rtx, offset)); 8987 8988 if (!aarch64_sve_mode_p (mode) 8989 && (regno2 = aarch64_next_callee_save (regno + 1, limit)) <= limit 8990 && !cfun->machine->reg_is_wrapped_separately[regno2] 8991 && known_eq (GET_MODE_SIZE (mode), 8992 frame.reg_offset[regno2] - frame.reg_offset[regno])) 8993 { 8994 rtx reg2 = gen_rtx_REG (mode, regno2); 8995 rtx mem2; 8996 8997 offset += GET_MODE_SIZE (mode); 8998 mem2 = gen_frame_mem (mode, plus_constant (Pmode, base_rtx, offset)); 8999 emit_insn (aarch64_gen_load_pair (mode, reg, mem, reg2, mem2)); 9000 9001 *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg2, *cfi_ops); 9002 regno = regno2; 9003 } 9004 else if (mode == VNx2DImode && BYTES_BIG_ENDIAN) 9005 emit_insn (gen_aarch64_pred_mov (mode, reg, ptrue, mem)); 9006 else if (aarch64_sve_mode_p (mode)) 9007 emit_insn (gen_rtx_SET (reg, mem)); 9008 else 9009 emit_move_insn (reg, mem); 9010 if (frame_related_p) 9011 *cfi_ops = alloc_reg_note (REG_CFA_RESTORE, reg, *cfi_ops); 9012 } 9013 } 9014 9015 /* Return true if OFFSET is a signed 4-bit value multiplied by the size 9016 of MODE. */ 9017 9018 static inline bool 9019 offset_4bit_signed_scaled_p (machine_mode mode, poly_int64 offset) 9020 { 9021 HOST_WIDE_INT multiple; 9022 return (constant_multiple_p (offset, GET_MODE_SIZE (mode), &multiple) 9023 && IN_RANGE (multiple, -8, 7)); 9024 } 9025 9026 /* Return true if OFFSET is a signed 6-bit value multiplied by the size 9027 of MODE. */ 9028 9029 static inline bool 9030 offset_6bit_signed_scaled_p (machine_mode mode, poly_int64 offset) 9031 { 9032 HOST_WIDE_INT multiple; 9033 return (constant_multiple_p (offset, GET_MODE_SIZE (mode), &multiple) 9034 && IN_RANGE (multiple, -32, 31)); 9035 } 9036 9037 /* Return true if OFFSET is an unsigned 6-bit value multiplied by the size 9038 of MODE. */ 9039 9040 static inline bool 9041 offset_6bit_unsigned_scaled_p (machine_mode mode, poly_int64 offset) 9042 { 9043 HOST_WIDE_INT multiple; 9044 return (constant_multiple_p (offset, GET_MODE_SIZE (mode), &multiple) 9045 && IN_RANGE (multiple, 0, 63)); 9046 } 9047 9048 /* Return true if OFFSET is a signed 7-bit value multiplied by the size 9049 of MODE. */ 9050 9051 bool 9052 aarch64_offset_7bit_signed_scaled_p (machine_mode mode, poly_int64 offset) 9053 { 9054 HOST_WIDE_INT multiple; 9055 return (constant_multiple_p (offset, GET_MODE_SIZE (mode), &multiple) 9056 && IN_RANGE (multiple, -64, 63)); 9057 } 9058 9059 /* Return true if OFFSET is a signed 9-bit value. */ 9060 9061 bool 9062 aarch64_offset_9bit_signed_unscaled_p (machine_mode mode ATTRIBUTE_UNUSED, 9063 poly_int64 offset) 9064 { 9065 HOST_WIDE_INT const_offset; 9066 return (offset.is_constant (&const_offset) 9067 && IN_RANGE (const_offset, -256, 255)); 9068 } 9069 9070 /* Return true if OFFSET is a signed 9-bit value multiplied by the size 9071 of MODE. */ 9072 9073 static inline bool 9074 offset_9bit_signed_scaled_p (machine_mode mode, poly_int64 offset) 9075 { 9076 HOST_WIDE_INT multiple; 9077 return (constant_multiple_p (offset, GET_MODE_SIZE (mode), &multiple) 9078 && IN_RANGE (multiple, -256, 255)); 9079 } 9080 9081 /* Return true if OFFSET is an unsigned 12-bit value multiplied by the size 9082 of MODE. */ 9083 9084 static inline bool 9085 offset_12bit_unsigned_scaled_p (machine_mode mode, poly_int64 offset) 9086 { 9087 HOST_WIDE_INT multiple; 9088 return (constant_multiple_p (offset, GET_MODE_SIZE (mode), &multiple) 9089 && IN_RANGE (multiple, 0, 4095)); 9090 } 9091 9092 /* Implement TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS. */ 9093 9094 static sbitmap 9095 aarch64_get_separate_components (void) 9096 { 9097 aarch64_frame &frame = cfun->machine->frame; 9098 sbitmap components = sbitmap_alloc (LAST_SAVED_REGNUM + 1); 9099 bitmap_clear (components); 9100 9101 /* The registers we need saved to the frame. */ 9102 for (unsigned regno = 0; regno <= LAST_SAVED_REGNUM; regno++) 9103 if (aarch64_register_saved_on_entry (regno)) 9104 { 9105 /* Punt on saves and restores that use ST1D and LD1D. We could 9106 try to be smarter, but it would involve making sure that the 9107 spare predicate register itself is safe to use at the save 9108 and restore points. Also, when a frame pointer is being used, 9109 the slots are often out of reach of ST1D and LD1D anyway. */ 9110 machine_mode mode = aarch64_reg_save_mode (regno); 9111 if (mode == VNx2DImode && BYTES_BIG_ENDIAN) 9112 continue; 9113 9114 poly_int64 offset = frame.reg_offset[regno]; 9115 9116 /* Get the offset relative to the register we'll use. */ 9117 if (frame_pointer_needed) 9118 offset -= frame.bytes_below_hard_fp; 9119 9120 /* Check that we can access the stack slot of the register with one 9121 direct load with no adjustments needed. */ 9122 if (aarch64_sve_mode_p (mode) 9123 ? offset_9bit_signed_scaled_p (mode, offset) 9124 : offset_12bit_unsigned_scaled_p (mode, offset)) 9125 bitmap_set_bit (components, regno); 9126 } 9127 9128 /* Don't mess with the hard frame pointer. */ 9129 if (frame_pointer_needed) 9130 bitmap_clear_bit (components, HARD_FRAME_POINTER_REGNUM); 9131 9132 /* If the spare predicate register used by big-endian SVE code 9133 is call-preserved, it must be saved in the main prologue 9134 before any saves that use it. */ 9135 if (frame.spare_pred_reg != INVALID_REGNUM) 9136 bitmap_clear_bit (components, frame.spare_pred_reg); 9137 9138 unsigned reg1 = frame.wb_push_candidate1; 9139 unsigned reg2 = frame.wb_push_candidate2; 9140 /* If registers have been chosen to be stored/restored with 9141 writeback don't interfere with them to avoid having to output explicit 9142 stack adjustment instructions. */ 9143 if (reg2 != INVALID_REGNUM) 9144 bitmap_clear_bit (components, reg2); 9145 if (reg1 != INVALID_REGNUM) 9146 bitmap_clear_bit (components, reg1); 9147 9148 bitmap_clear_bit (components, LR_REGNUM); 9149 bitmap_clear_bit (components, SP_REGNUM); 9150 if (flag_stack_clash_protection) 9151 { 9152 if (frame.sve_save_and_probe != INVALID_REGNUM) 9153 bitmap_clear_bit (components, frame.sve_save_and_probe); 9154 if (frame.hard_fp_save_and_probe != INVALID_REGNUM) 9155 bitmap_clear_bit (components, frame.hard_fp_save_and_probe); 9156 } 9157 9158 return components; 9159 } 9160 9161 /* Implement TARGET_SHRINK_WRAP_COMPONENTS_FOR_BB. */ 9162 9163 static sbitmap 9164 aarch64_components_for_bb (basic_block bb) 9165 { 9166 bitmap in = DF_LIVE_IN (bb); 9167 bitmap gen = &DF_LIVE_BB_INFO (bb)->gen; 9168 bitmap kill = &DF_LIVE_BB_INFO (bb)->kill; 9169 9170 sbitmap components = sbitmap_alloc (LAST_SAVED_REGNUM + 1); 9171 bitmap_clear (components); 9172 9173 /* Clobbered registers don't generate values in any meaningful sense, 9174 since nothing after the clobber can rely on their value. And we can't 9175 say that partially-clobbered registers are unconditionally killed, 9176 because whether they're killed or not depends on the mode of the 9177 value they're holding. Thus partially call-clobbered registers 9178 appear in neither the kill set nor the gen set. 9179 9180 Check manually for any calls that clobber more of a register than the 9181 current function can. */ 9182 function_abi_aggregator callee_abis; 9183 rtx_insn *insn; 9184 FOR_BB_INSNS (bb, insn) 9185 if (CALL_P (insn)) 9186 callee_abis.note_callee_abi (insn_callee_abi (insn)); 9187 HARD_REG_SET extra_caller_saves = callee_abis.caller_save_regs (*crtl->abi); 9188 9189 /* GPRs are used in a bb if they are in the IN, GEN, or KILL sets. */ 9190 for (unsigned regno = 0; regno <= LAST_SAVED_REGNUM; regno++) 9191 if (!fixed_regs[regno] 9192 && !crtl->abi->clobbers_full_reg_p (regno) 9193 && (TEST_HARD_REG_BIT (extra_caller_saves, regno) 9194 || bitmap_bit_p (in, regno) 9195 || bitmap_bit_p (gen, regno) 9196 || bitmap_bit_p (kill, regno))) 9197 { 9198 bitmap_set_bit (components, regno); 9199 9200 /* If there is a callee-save at an adjacent offset, add it too 9201 to increase the use of LDP/STP. */ 9202 poly_int64 offset = cfun->machine->frame.reg_offset[regno]; 9203 unsigned regno2 = multiple_p (offset, 16) ? regno + 1 : regno - 1; 9204 9205 if (regno2 <= LAST_SAVED_REGNUM) 9206 { 9207 poly_int64 offset2 = cfun->machine->frame.reg_offset[regno2]; 9208 if (regno < regno2 9209 ? known_eq (offset + 8, offset2) 9210 : multiple_p (offset2, 16) && known_eq (offset2 + 8, offset)) 9211 bitmap_set_bit (components, regno2); 9212 } 9213 } 9214 9215 return components; 9216 } 9217 9218 /* Implement TARGET_SHRINK_WRAP_DISQUALIFY_COMPONENTS. 9219 Nothing to do for aarch64. */ 9220 9221 static void 9222 aarch64_disqualify_components (sbitmap, edge, sbitmap, bool) 9223 { 9224 } 9225 9226 /* Return the next set bit in BMP from START onwards. Return the total number 9227 of bits in BMP if no set bit is found at or after START. */ 9228 9229 static unsigned int 9230 aarch64_get_next_set_bit (sbitmap bmp, unsigned int start) 9231 { 9232 unsigned int nbits = SBITMAP_SIZE (bmp); 9233 if (start == nbits) 9234 return start; 9235 9236 gcc_assert (start < nbits); 9237 for (unsigned int i = start; i < nbits; i++) 9238 if (bitmap_bit_p (bmp, i)) 9239 return i; 9240 9241 return nbits; 9242 } 9243 9244 /* Do the work for aarch64_emit_prologue_components and 9245 aarch64_emit_epilogue_components. COMPONENTS is the bitmap of registers 9246 to save/restore, PROLOGUE_P indicates whether to emit the prologue sequence 9247 for these components or the epilogue sequence. That is, it determines 9248 whether we should emit stores or loads and what kind of CFA notes to attach 9249 to the insns. Otherwise the logic for the two sequences is very 9250 similar. */ 9251 9252 static void 9253 aarch64_process_components (sbitmap components, bool prologue_p) 9254 { 9255 aarch64_frame &frame = cfun->machine->frame; 9256 rtx ptr_reg = gen_rtx_REG (Pmode, frame_pointer_needed 9257 ? HARD_FRAME_POINTER_REGNUM 9258 : STACK_POINTER_REGNUM); 9259 9260 unsigned last_regno = SBITMAP_SIZE (components); 9261 unsigned regno = aarch64_get_next_set_bit (components, R0_REGNUM); 9262 rtx_insn *insn = NULL; 9263 9264 while (regno != last_regno) 9265 { 9266 bool frame_related_p = aarch64_emit_cfi_for_reg_p (regno); 9267 machine_mode mode = aarch64_reg_save_mode (regno); 9268 9269 rtx reg = gen_rtx_REG (mode, regno); 9270 poly_int64 offset = frame.reg_offset[regno]; 9271 if (frame_pointer_needed) 9272 offset -= frame.bytes_below_hard_fp; 9273 9274 rtx addr = plus_constant (Pmode, ptr_reg, offset); 9275 rtx mem = gen_frame_mem (mode, addr); 9276 9277 rtx set = prologue_p ? gen_rtx_SET (mem, reg) : gen_rtx_SET (reg, mem); 9278 unsigned regno2 = aarch64_get_next_set_bit (components, regno + 1); 9279 /* No more registers to handle after REGNO. 9280 Emit a single save/restore and exit. */ 9281 if (regno2 == last_regno) 9282 { 9283 insn = emit_insn (set); 9284 if (frame_related_p) 9285 { 9286 RTX_FRAME_RELATED_P (insn) = 1; 9287 if (prologue_p) 9288 add_reg_note (insn, REG_CFA_OFFSET, copy_rtx (set)); 9289 else 9290 add_reg_note (insn, REG_CFA_RESTORE, reg); 9291 } 9292 break; 9293 } 9294 9295 poly_int64 offset2 = frame.reg_offset[regno2]; 9296 /* The next register is not of the same class or its offset is not 9297 mergeable with the current one into a pair. */ 9298 if (aarch64_sve_mode_p (mode) 9299 || !satisfies_constraint_Ump (mem) 9300 || GP_REGNUM_P (regno) != GP_REGNUM_P (regno2) 9301 || (crtl->abi->id () == ARM_PCS_SIMD && FP_REGNUM_P (regno)) 9302 || maybe_ne ((offset2 - frame.reg_offset[regno]), 9303 GET_MODE_SIZE (mode))) 9304 { 9305 insn = emit_insn (set); 9306 if (frame_related_p) 9307 { 9308 RTX_FRAME_RELATED_P (insn) = 1; 9309 if (prologue_p) 9310 add_reg_note (insn, REG_CFA_OFFSET, copy_rtx (set)); 9311 else 9312 add_reg_note (insn, REG_CFA_RESTORE, reg); 9313 } 9314 9315 regno = regno2; 9316 continue; 9317 } 9318 9319 bool frame_related2_p = aarch64_emit_cfi_for_reg_p (regno2); 9320 9321 /* REGNO2 can be saved/restored in a pair with REGNO. */ 9322 rtx reg2 = gen_rtx_REG (mode, regno2); 9323 if (frame_pointer_needed) 9324 offset2 -= frame.bytes_below_hard_fp; 9325 rtx addr2 = plus_constant (Pmode, ptr_reg, offset2); 9326 rtx mem2 = gen_frame_mem (mode, addr2); 9327 rtx set2 = prologue_p ? gen_rtx_SET (mem2, reg2) 9328 : gen_rtx_SET (reg2, mem2); 9329 9330 if (prologue_p) 9331 insn = emit_insn (aarch64_gen_store_pair (mode, mem, reg, mem2, reg2)); 9332 else 9333 insn = emit_insn (aarch64_gen_load_pair (mode, reg, mem, reg2, mem2)); 9334 9335 if (frame_related_p || frame_related2_p) 9336 { 9337 RTX_FRAME_RELATED_P (insn) = 1; 9338 if (prologue_p) 9339 { 9340 if (frame_related_p) 9341 add_reg_note (insn, REG_CFA_OFFSET, set); 9342 if (frame_related2_p) 9343 add_reg_note (insn, REG_CFA_OFFSET, set2); 9344 } 9345 else 9346 { 9347 if (frame_related_p) 9348 add_reg_note (insn, REG_CFA_RESTORE, reg); 9349 if (frame_related2_p) 9350 add_reg_note (insn, REG_CFA_RESTORE, reg2); 9351 } 9352 } 9353 9354 regno = aarch64_get_next_set_bit (components, regno2 + 1); 9355 } 9356 } 9357 9358 /* Implement TARGET_SHRINK_WRAP_EMIT_PROLOGUE_COMPONENTS. */ 9359 9360 static void 9361 aarch64_emit_prologue_components (sbitmap components) 9362 { 9363 aarch64_process_components (components, true); 9364 } 9365 9366 /* Implement TARGET_SHRINK_WRAP_EMIT_EPILOGUE_COMPONENTS. */ 9367 9368 static void 9369 aarch64_emit_epilogue_components (sbitmap components) 9370 { 9371 aarch64_process_components (components, false); 9372 } 9373 9374 /* Implement TARGET_SHRINK_WRAP_SET_HANDLED_COMPONENTS. */ 9375 9376 static void 9377 aarch64_set_handled_components (sbitmap components) 9378 { 9379 for (unsigned regno = 0; regno <= LAST_SAVED_REGNUM; regno++) 9380 if (bitmap_bit_p (components, regno)) 9381 cfun->machine->reg_is_wrapped_separately[regno] = true; 9382 } 9383 9384 /* On AArch64 we have an ABI defined safe buffer. This constant is used to 9385 determining the probe offset for alloca. */ 9386 9387 static HOST_WIDE_INT 9388 aarch64_stack_clash_protection_alloca_probe_range (void) 9389 { 9390 return STACK_CLASH_CALLER_GUARD; 9391 } 9392 9393 9394 /* Allocate POLY_SIZE bytes of stack space using TEMP1 and TEMP2 as scratch 9395 registers, given that the stack pointer is currently BYTES_BELOW_SP bytes 9396 above the bottom of the static frame. 9397 9398 If POLY_SIZE is not large enough to require a probe this function will only 9399 adjust the stack. When allocating the stack space FRAME_RELATED_P is then 9400 used to indicate if the allocation is frame related. FINAL_ADJUSTMENT_P 9401 indicates whether we are allocating the area below the saved registers. 9402 If we are then we ensure that any allocation larger than the ABI defined 9403 buffer needs a probe so that the invariant of having a 1KB buffer is 9404 maintained. 9405 9406 We emit barriers after each stack adjustment to prevent optimizations from 9407 breaking the invariant that we never drop the stack more than a page. This 9408 invariant is needed to make it easier to correctly handle asynchronous 9409 events, e.g. if we were to allow the stack to be dropped by more than a page 9410 and then have multiple probes up and we take a signal somewhere in between 9411 then the signal handler doesn't know the state of the stack and can make no 9412 assumptions about which pages have been probed. */ 9413 9414 static void 9415 aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2, 9416 poly_int64 poly_size, 9417 poly_int64 bytes_below_sp, 9418 bool frame_related_p, 9419 bool final_adjustment_p) 9420 { 9421 aarch64_frame &frame = cfun->machine->frame; 9422 HOST_WIDE_INT guard_size 9423 = 1 << param_stack_clash_protection_guard_size; 9424 HOST_WIDE_INT guard_used_by_caller = STACK_CLASH_CALLER_GUARD; 9425 HOST_WIDE_INT byte_sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT; 9426 gcc_assert (multiple_p (poly_size, byte_sp_alignment)); 9427 HOST_WIDE_INT min_probe_threshold 9428 = (final_adjustment_p 9429 ? guard_used_by_caller + byte_sp_alignment 9430 : guard_size - guard_used_by_caller); 9431 poly_int64 frame_size = frame.frame_size; 9432 9433 /* We should always have a positive probe threshold. */ 9434 gcc_assert (min_probe_threshold > 0); 9435 9436 if (flag_stack_clash_protection && !final_adjustment_p) 9437 { 9438 poly_int64 initial_adjust = frame.initial_adjust; 9439 poly_int64 sve_callee_adjust = frame.sve_callee_adjust; 9440 poly_int64 final_adjust = frame.final_adjust; 9441 9442 if (known_eq (frame_size, 0)) 9443 { 9444 dump_stack_clash_frame_info (NO_PROBE_NO_FRAME, false); 9445 } 9446 else if (known_lt (initial_adjust + sve_callee_adjust, 9447 guard_size - guard_used_by_caller) 9448 && known_lt (final_adjust, guard_used_by_caller)) 9449 { 9450 dump_stack_clash_frame_info (NO_PROBE_SMALL_FRAME, true); 9451 } 9452 } 9453 9454 /* If SIZE is not large enough to require probing, just adjust the stack and 9455 exit. */ 9456 if (known_lt (poly_size, min_probe_threshold) 9457 || !flag_stack_clash_protection) 9458 { 9459 aarch64_sub_sp (temp1, temp2, poly_size, frame_related_p); 9460 return; 9461 } 9462 9463 HOST_WIDE_INT size; 9464 /* Handle the SVE non-constant case first. */ 9465 if (!poly_size.is_constant (&size)) 9466 { 9467 if (dump_file) 9468 { 9469 fprintf (dump_file, "Stack clash SVE prologue: "); 9470 print_dec (poly_size, dump_file); 9471 fprintf (dump_file, " bytes, dynamic probing will be required.\n"); 9472 } 9473 9474 /* First calculate the amount of bytes we're actually spilling. */ 9475 aarch64_add_offset (Pmode, temp1, CONST0_RTX (Pmode), 9476 poly_size, temp1, temp2, false, true); 9477 9478 auto initial_cfa_offset = frame.frame_size - bytes_below_sp; 9479 auto final_cfa_offset = initial_cfa_offset + poly_size; 9480 if (frame_related_p) 9481 { 9482 /* This is done to provide unwinding information for the stack 9483 adjustments we're about to do, however to prevent the optimizers 9484 from removing the R11 move and leaving the CFA note (which would be 9485 very wrong) we tie the old and new stack pointer together. 9486 The tie will expand to nothing but the optimizers will not touch 9487 the instruction. */ 9488 rtx stack_ptr_copy = gen_rtx_REG (Pmode, STACK_CLASH_SVE_CFA_REGNUM); 9489 auto *insn = emit_move_insn (stack_ptr_copy, stack_pointer_rtx); 9490 emit_insn (gen_stack_tie (stack_ptr_copy, stack_pointer_rtx)); 9491 9492 /* We want the CFA independent of the stack pointer for the 9493 duration of the loop. */ 9494 add_reg_note (insn, REG_CFA_DEF_CFA, 9495 plus_constant (Pmode, stack_ptr_copy, 9496 initial_cfa_offset)); 9497 RTX_FRAME_RELATED_P (insn) = 1; 9498 } 9499 9500 rtx probe_const = gen_int_mode (min_probe_threshold, Pmode); 9501 rtx guard_const = gen_int_mode (guard_size, Pmode); 9502 9503 auto *insn 9504 = emit_insn (gen_probe_sve_stack_clash (Pmode, stack_pointer_rtx, 9505 stack_pointer_rtx, temp1, 9506 probe_const, guard_const)); 9507 9508 /* Now reset the CFA register if needed. */ 9509 if (frame_related_p) 9510 { 9511 add_reg_note (insn, REG_CFA_DEF_CFA, 9512 plus_constant (Pmode, stack_pointer_rtx, 9513 final_cfa_offset)); 9514 RTX_FRAME_RELATED_P (insn) = 1; 9515 } 9516 9517 return; 9518 } 9519 9520 if (dump_file) 9521 fprintf (dump_file, 9522 "Stack clash AArch64 prologue: " HOST_WIDE_INT_PRINT_DEC 9523 " bytes, probing will be required.\n", size); 9524 9525 /* Round size to the nearest multiple of guard_size, and calculate the 9526 residual as the difference between the original size and the rounded 9527 size. */ 9528 HOST_WIDE_INT rounded_size = ROUND_DOWN (size, guard_size); 9529 HOST_WIDE_INT residual = size - rounded_size; 9530 9531 /* We can handle a small number of allocations/probes inline. Otherwise 9532 punt to a loop. */ 9533 if (rounded_size <= STACK_CLASH_MAX_UNROLL_PAGES * guard_size) 9534 { 9535 for (HOST_WIDE_INT i = 0; i < rounded_size; i += guard_size) 9536 { 9537 aarch64_sub_sp (NULL, temp2, guard_size, true); 9538 emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx, 9539 guard_used_by_caller)); 9540 emit_insn (gen_blockage ()); 9541 } 9542 dump_stack_clash_frame_info (PROBE_INLINE, size != rounded_size); 9543 } 9544 else 9545 { 9546 /* Compute the ending address. */ 9547 aarch64_add_offset (Pmode, temp1, stack_pointer_rtx, -rounded_size, 9548 temp1, NULL, false, true); 9549 rtx_insn *insn = get_last_insn (); 9550 9551 /* For the initial allocation, we don't have a frame pointer 9552 set up, so we always need CFI notes. If we're doing the 9553 final allocation, then we may have a frame pointer, in which 9554 case it is the CFA, otherwise we need CFI notes. 9555 9556 We can determine which allocation we are doing by looking at 9557 the value of FRAME_RELATED_P since the final allocations are not 9558 frame related. */ 9559 auto cfa_offset = frame.frame_size - (bytes_below_sp - rounded_size); 9560 if (frame_related_p) 9561 { 9562 /* We want the CFA independent of the stack pointer for the 9563 duration of the loop. */ 9564 add_reg_note (insn, REG_CFA_DEF_CFA, 9565 plus_constant (Pmode, temp1, cfa_offset)); 9566 RTX_FRAME_RELATED_P (insn) = 1; 9567 } 9568 9569 /* This allocates and probes the stack. Note that this re-uses some of 9570 the existing Ada stack protection code. However we are guaranteed not 9571 to enter the non loop or residual branches of that code. 9572 9573 The non-loop part won't be entered because if our allocation amount 9574 doesn't require a loop, the case above would handle it. 9575 9576 The residual amount won't be entered because TEMP1 is a mutliple of 9577 the allocation size. The residual will always be 0. As such, the only 9578 part we are actually using from that code is the loop setup. The 9579 actual probing is done in aarch64_output_probe_stack_range. */ 9580 insn = emit_insn (gen_probe_stack_range (stack_pointer_rtx, 9581 stack_pointer_rtx, temp1)); 9582 9583 /* Now reset the CFA register if needed. */ 9584 if (frame_related_p) 9585 { 9586 add_reg_note (insn, REG_CFA_DEF_CFA, 9587 plus_constant (Pmode, stack_pointer_rtx, cfa_offset)); 9588 RTX_FRAME_RELATED_P (insn) = 1; 9589 } 9590 9591 emit_insn (gen_blockage ()); 9592 dump_stack_clash_frame_info (PROBE_LOOP, size != rounded_size); 9593 } 9594 9595 /* Handle any residuals. Residuals of at least MIN_PROBE_THRESHOLD have to 9596 be probed. This maintains the requirement that each page is probed at 9597 least once. For initial probing we probe only if the allocation is 9598 more than GUARD_SIZE - buffer, and below the saved registers we probe 9599 if the amount is larger than buffer. GUARD_SIZE - buffer + buffer == 9600 GUARD_SIZE. This works that for any allocation that is large enough to 9601 trigger a probe here, we'll have at least one, and if they're not large 9602 enough for this code to emit anything for them, The page would have been 9603 probed by the saving of FP/LR either by this function or any callees. If 9604 we don't have any callees then we won't have more stack adjustments and so 9605 are still safe. */ 9606 if (residual) 9607 { 9608 gcc_assert (guard_used_by_caller + byte_sp_alignment <= size); 9609 9610 /* If we're doing final adjustments, and we've done any full page 9611 allocations then any residual needs to be probed. */ 9612 if (final_adjustment_p && rounded_size != 0) 9613 min_probe_threshold = 0; 9614 9615 aarch64_sub_sp (temp1, temp2, residual, frame_related_p); 9616 if (residual >= min_probe_threshold) 9617 { 9618 if (dump_file) 9619 fprintf (dump_file, 9620 "Stack clash AArch64 prologue residuals: " 9621 HOST_WIDE_INT_PRINT_DEC " bytes, probing will be required." 9622 "\n", residual); 9623 9624 emit_stack_probe (plus_constant (Pmode, stack_pointer_rtx, 9625 guard_used_by_caller)); 9626 emit_insn (gen_blockage ()); 9627 } 9628 } 9629 } 9630 9631 /* Return 1 if the register is used by the epilogue. We need to say the 9632 return register is used, but only after epilogue generation is complete. 9633 Note that in the case of sibcalls, the values "used by the epilogue" are 9634 considered live at the start of the called function. 9635 9636 For SIMD functions we need to return 1 for FP registers that are saved and 9637 restored by a function but are not zero in call_used_regs. If we do not do 9638 this optimizations may remove the restore of the register. */ 9639 9640 int 9641 aarch64_epilogue_uses (int regno) 9642 { 9643 if (epilogue_completed) 9644 { 9645 if (regno == LR_REGNUM) 9646 return 1; 9647 } 9648 return 0; 9649 } 9650 9651 /* AArch64 stack frames generated by this compiler look like: 9652 9653 +-------------------------------+ 9654 | | 9655 | incoming stack arguments | 9656 | | 9657 +-------------------------------+ 9658 | | <-- incoming stack pointer (aligned) 9659 | callee-allocated save area | 9660 | for register varargs | 9661 | | 9662 +-------------------------------+ 9663 | local variables (1) | <-- frame_pointer_rtx 9664 | | 9665 +-------------------------------+ 9666 | padding (1) | 9667 +-------------------------------+ 9668 | callee-saved registers | 9669 +-------------------------------+ 9670 | LR' | 9671 +-------------------------------+ 9672 | FP' | 9673 +-------------------------------+ <-- hard_frame_pointer_rtx (aligned) 9674 | SVE vector registers | 9675 +-------------------------------+ 9676 | SVE predicate registers | 9677 +-------------------------------+ 9678 | local variables (2) | 9679 +-------------------------------+ 9680 | padding (2) | 9681 +-------------------------------+ 9682 | dynamic allocation | 9683 +-------------------------------+ 9684 | padding | 9685 +-------------------------------+ 9686 | outgoing stack arguments | <-- arg_pointer 9687 | | 9688 +-------------------------------+ 9689 | | <-- stack_pointer_rtx (aligned) 9690 9691 The regions marked (1) and (2) are mutually exclusive. (2) is used 9692 when aarch64_save_regs_above_locals_p is true. 9693 9694 Dynamic stack allocations via alloca() decrease stack_pointer_rtx 9695 but leave frame_pointer_rtx and hard_frame_pointer_rtx 9696 unchanged. 9697 9698 By default for stack-clash we assume the guard is at least 64KB, but this 9699 value is configurable to either 4KB or 64KB. We also force the guard size to 9700 be the same as the probing interval and both values are kept in sync. 9701 9702 With those assumptions the callee can allocate up to 63KB (or 3KB depending 9703 on the guard size) of stack space without probing. 9704 9705 When probing is needed, we emit a probe at the start of the prologue 9706 and every PARAM_STACK_CLASH_PROTECTION_GUARD_SIZE bytes thereafter. 9707 9708 We can also use register saves as probes. These are stored in 9709 sve_save_and_probe and hard_fp_save_and_probe. 9710 9711 For outgoing arguments we probe if the size is larger than 1KB, such that 9712 the ABI specified buffer is maintained for the next callee. 9713 9714 The following registers are reserved during frame layout and should not be 9715 used for any other purpose: 9716 9717 - r11: Used by stack clash protection when SVE is enabled, and also 9718 as an anchor register when saving and restoring registers 9719 - r12(EP0) and r13(EP1): Used as temporaries for stack adjustment. 9720 - r14 and r15: Used for speculation tracking. 9721 - r16(IP0), r17(IP1): Used by indirect tailcalls. 9722 - r30(LR), r29(FP): Used by standard frame layout. 9723 9724 These registers must be avoided in frame layout related code unless the 9725 explicit intention is to interact with one of the features listed above. */ 9726 9727 /* Generate the prologue instructions for entry into a function. 9728 Establish the stack frame by decreasing the stack pointer with a 9729 properly calculated size and, if necessary, create a frame record 9730 filled with the values of LR and previous frame pointer. The 9731 current FP is also set up if it is in use. */ 9732 9733 void 9734 aarch64_expand_prologue (void) 9735 { 9736 aarch64_frame &frame = cfun->machine->frame; 9737 poly_int64 frame_size = frame.frame_size; 9738 poly_int64 initial_adjust = frame.initial_adjust; 9739 HOST_WIDE_INT callee_adjust = frame.callee_adjust; 9740 poly_int64 final_adjust = frame.final_adjust; 9741 poly_int64 sve_callee_adjust = frame.sve_callee_adjust; 9742 unsigned reg1 = frame.wb_push_candidate1; 9743 unsigned reg2 = frame.wb_push_candidate2; 9744 bool emit_frame_chain = frame.emit_frame_chain; 9745 rtx_insn *insn; 9746 9747 if (flag_stack_clash_protection && known_eq (callee_adjust, 0)) 9748 { 9749 /* Fold the SVE allocation into the initial allocation. 9750 We don't do this in aarch64_layout_arg to avoid pessimizing 9751 the epilogue code. */ 9752 initial_adjust += sve_callee_adjust; 9753 sve_callee_adjust = 0; 9754 } 9755 9756 /* Sign return address for functions. */ 9757 if (aarch64_return_address_signing_enabled ()) 9758 { 9759 switch (aarch64_ra_sign_key) 9760 { 9761 case AARCH64_KEY_A: 9762 insn = emit_insn (gen_paciasp ()); 9763 break; 9764 case AARCH64_KEY_B: 9765 insn = emit_insn (gen_pacibsp ()); 9766 break; 9767 default: 9768 gcc_unreachable (); 9769 } 9770 add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx); 9771 RTX_FRAME_RELATED_P (insn) = 1; 9772 } 9773 9774 /* Push return address to shadow call stack. */ 9775 if (frame.is_scs_enabled) 9776 emit_insn (gen_scs_push ()); 9777 9778 if (flag_stack_usage_info) 9779 current_function_static_stack_size = constant_lower_bound (frame_size); 9780 9781 if (flag_stack_check == STATIC_BUILTIN_STACK_CHECK) 9782 { 9783 if (crtl->is_leaf && !cfun->calls_alloca) 9784 { 9785 if (maybe_gt (frame_size, PROBE_INTERVAL) 9786 && maybe_gt (frame_size, get_stack_check_protect ())) 9787 aarch64_emit_probe_stack_range (get_stack_check_protect (), 9788 (frame_size 9789 - get_stack_check_protect ())); 9790 } 9791 else if (maybe_gt (frame_size, 0)) 9792 aarch64_emit_probe_stack_range (get_stack_check_protect (), frame_size); 9793 } 9794 9795 rtx tmp0_rtx = gen_rtx_REG (Pmode, EP0_REGNUM); 9796 rtx tmp1_rtx = gen_rtx_REG (Pmode, EP1_REGNUM); 9797 9798 /* In theory we should never have both an initial adjustment 9799 and a callee save adjustment. Verify that is the case since the 9800 code below does not handle it for -fstack-clash-protection. */ 9801 gcc_assert (known_eq (initial_adjust, 0) || callee_adjust == 0); 9802 9803 /* The offset of the current SP from the bottom of the static frame. */ 9804 poly_int64 bytes_below_sp = frame_size; 9805 9806 /* Will only probe if the initial adjustment is larger than the guard 9807 less the amount of the guard reserved for use by the caller's 9808 outgoing args. */ 9809 aarch64_allocate_and_probe_stack_space (tmp0_rtx, tmp1_rtx, initial_adjust, 9810 bytes_below_sp, true, false); 9811 bytes_below_sp -= initial_adjust; 9812 9813 if (callee_adjust != 0) 9814 { 9815 aarch64_push_regs (reg1, reg2, callee_adjust); 9816 bytes_below_sp -= callee_adjust; 9817 } 9818 9819 if (emit_frame_chain) 9820 { 9821 /* The offset of the frame chain record (if any) from the current SP. */ 9822 poly_int64 chain_offset = (initial_adjust + callee_adjust 9823 - frame.bytes_above_hard_fp); 9824 gcc_assert (known_ge (chain_offset, 0)); 9825 9826 if (callee_adjust == 0) 9827 { 9828 reg1 = R29_REGNUM; 9829 reg2 = R30_REGNUM; 9830 aarch64_save_callee_saves (bytes_below_sp, reg1, reg2, 9831 false, false); 9832 } 9833 else 9834 gcc_assert (known_eq (chain_offset, 0)); 9835 aarch64_add_offset (Pmode, hard_frame_pointer_rtx, 9836 stack_pointer_rtx, chain_offset, 9837 tmp1_rtx, tmp0_rtx, frame_pointer_needed); 9838 if (frame_pointer_needed && !frame_size.is_constant ()) 9839 { 9840 /* Variable-sized frames need to describe the save slot 9841 address using DW_CFA_expression rather than DW_CFA_offset. 9842 This means that, without taking further action, the 9843 locations of the registers that we've already saved would 9844 remain based on the stack pointer even after we redefine 9845 the CFA based on the frame pointer. We therefore need new 9846 DW_CFA_expressions to re-express the save slots with addresses 9847 based on the frame pointer. */ 9848 rtx_insn *insn = get_last_insn (); 9849 gcc_assert (RTX_FRAME_RELATED_P (insn)); 9850 9851 /* Add an explicit CFA definition if this was previously 9852 implicit. */ 9853 if (!find_reg_note (insn, REG_CFA_ADJUST_CFA, NULL_RTX)) 9854 { 9855 rtx src = plus_constant (Pmode, stack_pointer_rtx, chain_offset); 9856 add_reg_note (insn, REG_CFA_ADJUST_CFA, 9857 gen_rtx_SET (hard_frame_pointer_rtx, src)); 9858 } 9859 9860 /* Change the save slot expressions for the registers that 9861 we've already saved. */ 9862 aarch64_add_cfa_expression (insn, regno_reg_rtx[reg2], 9863 hard_frame_pointer_rtx, UNITS_PER_WORD); 9864 aarch64_add_cfa_expression (insn, regno_reg_rtx[reg1], 9865 hard_frame_pointer_rtx, 0); 9866 } 9867 emit_insn (gen_stack_tie (stack_pointer_rtx, hard_frame_pointer_rtx)); 9868 } 9869 9870 aarch64_save_callee_saves (bytes_below_sp, R0_REGNUM, R30_REGNUM, 9871 callee_adjust != 0 || emit_frame_chain, 9872 emit_frame_chain); 9873 if (maybe_ne (sve_callee_adjust, 0)) 9874 { 9875 gcc_assert (!flag_stack_clash_protection 9876 || known_eq (initial_adjust, 0)); 9877 aarch64_allocate_and_probe_stack_space (tmp1_rtx, tmp0_rtx, 9878 sve_callee_adjust, 9879 bytes_below_sp, 9880 !frame_pointer_needed, false); 9881 bytes_below_sp -= sve_callee_adjust; 9882 } 9883 aarch64_save_callee_saves (bytes_below_sp, P0_REGNUM, P15_REGNUM, 9884 false, emit_frame_chain); 9885 aarch64_save_callee_saves (bytes_below_sp, V0_REGNUM, V31_REGNUM, 9886 callee_adjust != 0 || emit_frame_chain, 9887 emit_frame_chain); 9888 9889 /* We may need to probe the final adjustment if it is larger than the guard 9890 that is assumed by the called. */ 9891 aarch64_allocate_and_probe_stack_space (tmp1_rtx, tmp0_rtx, final_adjust, 9892 bytes_below_sp, 9893 !frame_pointer_needed, true); 9894 bytes_below_sp -= final_adjust; 9895 gcc_assert (known_eq (bytes_below_sp, 0)); 9896 if (emit_frame_chain && maybe_ne (final_adjust, 0)) 9897 emit_insn (gen_stack_tie (stack_pointer_rtx, hard_frame_pointer_rtx)); 9898 } 9899 9900 /* Return TRUE if we can use a simple_return insn. 9901 9902 This function checks whether the callee saved stack is empty, which 9903 means no restore actions are need. The pro_and_epilogue will use 9904 this to check whether shrink-wrapping opt is feasible. */ 9905 9906 bool 9907 aarch64_use_return_insn_p (void) 9908 { 9909 if (!reload_completed) 9910 return false; 9911 9912 if (crtl->profile) 9913 return false; 9914 9915 return known_eq (cfun->machine->frame.frame_size, 0); 9916 } 9917 9918 /* Generate the epilogue instructions for returning from a function. 9919 This is almost exactly the reverse of the prolog sequence, except 9920 that we need to insert barriers to avoid scheduling loads that read 9921 from a deallocated stack, and we optimize the unwind records by 9922 emitting them all together if possible. */ 9923 void 9924 aarch64_expand_epilogue (bool for_sibcall) 9925 { 9926 aarch64_frame &frame = cfun->machine->frame; 9927 poly_int64 initial_adjust = frame.initial_adjust; 9928 HOST_WIDE_INT callee_adjust = frame.callee_adjust; 9929 poly_int64 final_adjust = frame.final_adjust; 9930 poly_int64 sve_callee_adjust = frame.sve_callee_adjust; 9931 poly_int64 bytes_below_hard_fp = frame.bytes_below_hard_fp; 9932 unsigned reg1 = frame.wb_pop_candidate1; 9933 unsigned reg2 = frame.wb_pop_candidate2; 9934 unsigned int last_gpr = (frame.is_scs_enabled 9935 ? R29_REGNUM : R30_REGNUM); 9936 rtx cfi_ops = NULL; 9937 rtx_insn *insn; 9938 /* A stack clash protection prologue may not have left EP0_REGNUM or 9939 EP1_REGNUM in a usable state. The same is true for allocations 9940 with an SVE component, since we then need both temporary registers 9941 for each allocation. For stack clash we are in a usable state if 9942 the adjustment is less than GUARD_SIZE - GUARD_USED_BY_CALLER. */ 9943 HOST_WIDE_INT guard_size 9944 = 1 << param_stack_clash_protection_guard_size; 9945 HOST_WIDE_INT guard_used_by_caller = STACK_CLASH_CALLER_GUARD; 9946 9947 /* We can re-use the registers when: 9948 9949 (a) the deallocation amount is the same as the corresponding 9950 allocation amount (which is false if we combine the initial 9951 and SVE callee save allocations in the prologue); and 9952 9953 (b) the allocation amount doesn't need a probe (which is false 9954 if the amount is guard_size - guard_used_by_caller or greater). 9955 9956 In such situations the register should remain live with the correct 9957 value. */ 9958 bool can_inherit_p = (initial_adjust.is_constant () 9959 && final_adjust.is_constant () 9960 && (!flag_stack_clash_protection 9961 || (known_lt (initial_adjust, 9962 guard_size - guard_used_by_caller) 9963 && known_eq (sve_callee_adjust, 0)))); 9964 9965 /* We need to add memory barrier to prevent read from deallocated stack. */ 9966 bool need_barrier_p 9967 = maybe_ne (get_frame_size () 9968 + frame.saved_varargs_size, 0); 9969 9970 /* Emit a barrier to prevent loads from a deallocated stack. */ 9971 if (maybe_gt (final_adjust, crtl->outgoing_args_size) 9972 || cfun->calls_alloca 9973 || crtl->calls_eh_return) 9974 { 9975 emit_insn (gen_stack_tie (stack_pointer_rtx, stack_pointer_rtx)); 9976 need_barrier_p = false; 9977 } 9978 9979 /* Restore the stack pointer from the frame pointer if it may not 9980 be the same as the stack pointer. */ 9981 rtx tmp0_rtx = gen_rtx_REG (Pmode, EP0_REGNUM); 9982 rtx tmp1_rtx = gen_rtx_REG (Pmode, EP1_REGNUM); 9983 if (frame_pointer_needed 9984 && (maybe_ne (final_adjust, 0) || cfun->calls_alloca)) 9985 /* If writeback is used when restoring callee-saves, the CFA 9986 is restored on the instruction doing the writeback. */ 9987 aarch64_add_offset (Pmode, stack_pointer_rtx, 9988 hard_frame_pointer_rtx, 9989 -bytes_below_hard_fp + final_adjust, 9990 tmp1_rtx, tmp0_rtx, callee_adjust == 0); 9991 else 9992 /* The case where we need to re-use the register here is very rare, so 9993 avoid the complicated condition and just always emit a move if the 9994 immediate doesn't fit. */ 9995 aarch64_add_sp (tmp1_rtx, tmp0_rtx, final_adjust, true); 9996 9997 /* Restore the vector registers before the predicate registers, 9998 so that we can use P4 as a temporary for big-endian SVE frames. */ 9999 aarch64_restore_callee_saves (final_adjust, V0_REGNUM, V31_REGNUM, 10000 callee_adjust != 0, &cfi_ops); 10001 aarch64_restore_callee_saves (final_adjust, P0_REGNUM, P15_REGNUM, 10002 false, &cfi_ops); 10003 if (maybe_ne (sve_callee_adjust, 0)) 10004 aarch64_add_sp (NULL_RTX, NULL_RTX, sve_callee_adjust, true); 10005 10006 /* When shadow call stack is enabled, the scs_pop in the epilogue will 10007 restore x30, we don't need to restore x30 again in the traditional 10008 way. */ 10009 aarch64_restore_callee_saves (final_adjust + sve_callee_adjust, 10010 R0_REGNUM, last_gpr, 10011 callee_adjust != 0, &cfi_ops); 10012 10013 if (need_barrier_p) 10014 emit_insn (gen_stack_tie (stack_pointer_rtx, stack_pointer_rtx)); 10015 10016 if (callee_adjust != 0) 10017 aarch64_pop_regs (reg1, reg2, callee_adjust, &cfi_ops); 10018 10019 /* If we have no register restore information, the CFA must have been 10020 defined in terms of the stack pointer since the end of the prologue. */ 10021 gcc_assert (cfi_ops || !frame_pointer_needed); 10022 10023 if (cfi_ops && (callee_adjust != 0 || maybe_gt (initial_adjust, 65536))) 10024 { 10025 /* Emit delayed restores and set the CFA to be SP + initial_adjust. */ 10026 insn = get_last_insn (); 10027 rtx new_cfa = plus_constant (Pmode, stack_pointer_rtx, initial_adjust); 10028 REG_NOTES (insn) = alloc_reg_note (REG_CFA_DEF_CFA, new_cfa, cfi_ops); 10029 RTX_FRAME_RELATED_P (insn) = 1; 10030 cfi_ops = NULL; 10031 } 10032 10033 /* Liveness of EP0_REGNUM can not be trusted across function calls either, so 10034 add restriction on emit_move optimization to leaf functions. */ 10035 aarch64_add_sp (tmp0_rtx, tmp1_rtx, initial_adjust, 10036 (!can_inherit_p || !crtl->is_leaf 10037 || df_regs_ever_live_p (EP0_REGNUM))); 10038 10039 if (cfi_ops) 10040 { 10041 /* Emit delayed restores and reset the CFA to be SP. */ 10042 insn = get_last_insn (); 10043 cfi_ops = alloc_reg_note (REG_CFA_DEF_CFA, stack_pointer_rtx, cfi_ops); 10044 REG_NOTES (insn) = cfi_ops; 10045 RTX_FRAME_RELATED_P (insn) = 1; 10046 } 10047 10048 /* Pop return address from shadow call stack. */ 10049 if (frame.is_scs_enabled) 10050 { 10051 machine_mode mode = aarch64_reg_save_mode (R30_REGNUM); 10052 rtx reg = gen_rtx_REG (mode, R30_REGNUM); 10053 10054 insn = emit_insn (gen_scs_pop ()); 10055 add_reg_note (insn, REG_CFA_RESTORE, reg); 10056 RTX_FRAME_RELATED_P (insn) = 1; 10057 } 10058 10059 /* We prefer to emit the combined return/authenticate instruction RETAA, 10060 however there are three cases in which we must instead emit an explicit 10061 authentication instruction. 10062 10063 1) Sibcalls don't return in a normal way, so if we're about to call one 10064 we must authenticate. 10065 10066 2) The RETAA instruction is not available without FEAT_PAuth, so if we 10067 are generating code for !TARGET_PAUTH we can't use it and must 10068 explicitly authenticate. 10069 */ 10070 if (aarch64_return_address_signing_enabled () 10071 && (for_sibcall || !TARGET_PAUTH)) 10072 { 10073 switch (aarch64_ra_sign_key) 10074 { 10075 case AARCH64_KEY_A: 10076 insn = emit_insn (gen_autiasp ()); 10077 break; 10078 case AARCH64_KEY_B: 10079 insn = emit_insn (gen_autibsp ()); 10080 break; 10081 default: 10082 gcc_unreachable (); 10083 } 10084 add_reg_note (insn, REG_CFA_TOGGLE_RA_MANGLE, const0_rtx); 10085 RTX_FRAME_RELATED_P (insn) = 1; 10086 } 10087 10088 /* Stack adjustment for exception handler. */ 10089 if (crtl->calls_eh_return && !for_sibcall) 10090 { 10091 /* We need to unwind the stack by the offset computed by 10092 EH_RETURN_STACKADJ_RTX. We have already reset the CFA 10093 to be SP; letting the CFA move during this adjustment 10094 is just as correct as retaining the CFA from the body 10095 of the function. Therefore, do nothing special. */ 10096 emit_insn (gen_add2_insn (stack_pointer_rtx, EH_RETURN_STACKADJ_RTX)); 10097 } 10098 10099 emit_use (gen_rtx_REG (DImode, LR_REGNUM)); 10100 if (!for_sibcall) 10101 emit_jump_insn (ret_rtx); 10102 } 10103 10104 /* Implement EH_RETURN_HANDLER_RTX. EH returns need to either return 10105 normally or return to a previous frame after unwinding. 10106 10107 An EH return uses a single shared return sequence. The epilogue is 10108 exactly like a normal epilogue except that it has an extra input 10109 register (EH_RETURN_STACKADJ_RTX) which contains the stack adjustment 10110 that must be applied after the frame has been destroyed. An extra label 10111 is inserted before the epilogue which initializes this register to zero, 10112 and this is the entry point for a normal return. 10113 10114 An actual EH return updates the return address, initializes the stack 10115 adjustment and jumps directly into the epilogue (bypassing the zeroing 10116 of the adjustment). Since the return address is typically saved on the 10117 stack when a function makes a call, the saved LR must be updated outside 10118 the epilogue. 10119 10120 This poses problems as the store is generated well before the epilogue, 10121 so the offset of LR is not known yet. Also optimizations will remove the 10122 store as it appears dead, even after the epilogue is generated (as the 10123 base or offset for loading LR is different in many cases). 10124 10125 To avoid these problems this implementation forces the frame pointer 10126 in eh_return functions so that the location of LR is fixed and known early. 10127 It also marks the store volatile, so no optimization is permitted to 10128 remove the store. */ 10129 rtx 10130 aarch64_eh_return_handler_rtx (void) 10131 { 10132 rtx tmp = gen_frame_mem (Pmode, 10133 plus_constant (Pmode, hard_frame_pointer_rtx, UNITS_PER_WORD)); 10134 10135 /* Mark the store volatile, so no optimization is permitted to remove it. */ 10136 MEM_VOLATILE_P (tmp) = true; 10137 return tmp; 10138 } 10139 10140 /* Output code to add DELTA to the first argument, and then jump 10141 to FUNCTION. Used for C++ multiple inheritance. */ 10142 static void 10143 aarch64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, 10144 HOST_WIDE_INT delta, 10145 HOST_WIDE_INT vcall_offset, 10146 tree function) 10147 { 10148 /* The this pointer is always in x0. Note that this differs from 10149 Arm where the this pointer maybe bumped to r1 if r0 is required 10150 to return a pointer to an aggregate. On AArch64 a result value 10151 pointer will be in x8. */ 10152 int this_regno = R0_REGNUM; 10153 rtx this_rtx, temp0, temp1, addr, funexp; 10154 rtx_insn *insn; 10155 const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk)); 10156 10157 if (aarch64_bti_enabled ()) 10158 emit_insn (gen_bti_c()); 10159 10160 reload_completed = 1; 10161 emit_note (NOTE_INSN_PROLOGUE_END); 10162 10163 this_rtx = gen_rtx_REG (Pmode, this_regno); 10164 temp0 = gen_rtx_REG (Pmode, EP0_REGNUM); 10165 temp1 = gen_rtx_REG (Pmode, EP1_REGNUM); 10166 10167 if (vcall_offset == 0) 10168 aarch64_add_offset (Pmode, this_rtx, this_rtx, delta, temp1, temp0, false); 10169 else 10170 { 10171 gcc_assert ((vcall_offset & (POINTER_BYTES - 1)) == 0); 10172 10173 addr = this_rtx; 10174 if (delta != 0) 10175 { 10176 if (delta >= -256 && delta < 256) 10177 addr = gen_rtx_PRE_MODIFY (Pmode, this_rtx, 10178 plus_constant (Pmode, this_rtx, delta)); 10179 else 10180 aarch64_add_offset (Pmode, this_rtx, this_rtx, delta, 10181 temp1, temp0, false); 10182 } 10183 10184 if (Pmode == ptr_mode) 10185 aarch64_emit_move (temp0, gen_rtx_MEM (ptr_mode, addr)); 10186 else 10187 aarch64_emit_move (temp0, 10188 gen_rtx_ZERO_EXTEND (Pmode, 10189 gen_rtx_MEM (ptr_mode, addr))); 10190 10191 if (vcall_offset >= -256 && vcall_offset < 4096 * POINTER_BYTES) 10192 addr = plus_constant (Pmode, temp0, vcall_offset); 10193 else 10194 { 10195 aarch64_internal_mov_immediate (temp1, GEN_INT (vcall_offset), true, 10196 Pmode); 10197 addr = gen_rtx_PLUS (Pmode, temp0, temp1); 10198 } 10199 10200 if (Pmode == ptr_mode) 10201 aarch64_emit_move (temp1, gen_rtx_MEM (ptr_mode,addr)); 10202 else 10203 aarch64_emit_move (temp1, 10204 gen_rtx_SIGN_EXTEND (Pmode, 10205 gen_rtx_MEM (ptr_mode, addr))); 10206 10207 emit_insn (gen_add2_insn (this_rtx, temp1)); 10208 } 10209 10210 /* Generate a tail call to the target function. */ 10211 if (!TREE_USED (function)) 10212 { 10213 assemble_external (function); 10214 TREE_USED (function) = 1; 10215 } 10216 funexp = XEXP (DECL_RTL (function), 0); 10217 funexp = gen_rtx_MEM (FUNCTION_MODE, funexp); 10218 rtx callee_abi = gen_int_mode (fndecl_abi (function).id (), DImode); 10219 insn = emit_call_insn (gen_sibcall (funexp, const0_rtx, callee_abi)); 10220 SIBLING_CALL_P (insn) = 1; 10221 10222 insn = get_insns (); 10223 shorten_branches (insn); 10224 10225 assemble_start_function (thunk, fnname); 10226 final_start_function (insn, file, 1); 10227 final (insn, file, 1); 10228 final_end_function (); 10229 assemble_end_function (thunk, fnname); 10230 10231 /* Stop pretending to be a post-reload pass. */ 10232 reload_completed = 0; 10233 } 10234 10235 static bool 10236 aarch64_tls_referenced_p (rtx x) 10237 { 10238 if (!TARGET_HAVE_TLS) 10239 return false; 10240 subrtx_iterator::array_type array; 10241 FOR_EACH_SUBRTX (iter, array, x, ALL) 10242 { 10243 const_rtx x = *iter; 10244 if (SYMBOL_REF_P (x) && SYMBOL_REF_TLS_MODEL (x) != 0) 10245 return true; 10246 /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are 10247 TLS offsets, not real symbol references. */ 10248 if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS) 10249 iter.skip_subrtxes (); 10250 } 10251 return false; 10252 } 10253 10254 10255 /* Return true if val can be encoded as a 12-bit unsigned immediate with 10256 a left shift of 0 or 12 bits. */ 10257 bool 10258 aarch64_uimm12_shift (HOST_WIDE_INT val) 10259 { 10260 return ((val & (((HOST_WIDE_INT) 0xfff) << 0)) == val 10261 || (val & (((HOST_WIDE_INT) 0xfff) << 12)) == val 10262 ); 10263 } 10264 10265 /* Returns the nearest value to VAL that will fit as a 12-bit unsigned immediate 10266 that can be created with a left shift of 0 or 12. */ 10267 static HOST_WIDE_INT 10268 aarch64_clamp_to_uimm12_shift (HOST_WIDE_INT val) 10269 { 10270 /* Check to see if the value fits in 24 bits, as that is the maximum we can 10271 handle correctly. */ 10272 gcc_assert ((val & 0xffffff) == val); 10273 10274 if (((val & 0xfff) << 0) == val) 10275 return val; 10276 10277 return val & (0xfff << 12); 10278 } 10279 10280 /* Return true if val is an immediate that can be loaded into a 10281 register by a MOVZ instruction. */ 10282 static bool 10283 aarch64_movw_imm (HOST_WIDE_INT val, scalar_int_mode mode) 10284 { 10285 if (GET_MODE_SIZE (mode) > 4) 10286 { 10287 if ((val & (((HOST_WIDE_INT) 0xffff) << 32)) == val 10288 || (val & (((HOST_WIDE_INT) 0xffff) << 48)) == val) 10289 return 1; 10290 } 10291 else 10292 { 10293 /* Ignore sign extension. */ 10294 val &= (HOST_WIDE_INT) 0xffffffff; 10295 } 10296 return ((val & (((HOST_WIDE_INT) 0xffff) << 0)) == val 10297 || (val & (((HOST_WIDE_INT) 0xffff) << 16)) == val); 10298 } 10299 10300 /* Test whether: 10301 10302 X = (X & AND_VAL) | IOR_VAL; 10303 10304 can be implemented using: 10305 10306 MOVK X, #(IOR_VAL >> shift), LSL #shift 10307 10308 Return the shift if so, otherwise return -1. */ 10309 int 10310 aarch64_movk_shift (const wide_int_ref &and_val, 10311 const wide_int_ref &ior_val) 10312 { 10313 unsigned int precision = and_val.get_precision (); 10314 unsigned HOST_WIDE_INT mask = 0xffff; 10315 for (unsigned int shift = 0; shift < precision; shift += 16) 10316 { 10317 if (and_val == ~mask && (ior_val & mask) == ior_val) 10318 return shift; 10319 mask <<= 16; 10320 } 10321 return -1; 10322 } 10323 10324 /* VAL is a value with the inner mode of MODE. Replicate it to fill a 10325 64-bit (DImode) integer. */ 10326 10327 static unsigned HOST_WIDE_INT 10328 aarch64_replicate_bitmask_imm (unsigned HOST_WIDE_INT val, machine_mode mode) 10329 { 10330 unsigned int size = GET_MODE_UNIT_PRECISION (mode); 10331 while (size < 64) 10332 { 10333 val &= (HOST_WIDE_INT_1U << size) - 1; 10334 val |= val << size; 10335 size *= 2; 10336 } 10337 return val; 10338 } 10339 10340 /* Multipliers for repeating bitmasks of width 32, 16, 8, 4, and 2. */ 10341 10342 static const unsigned HOST_WIDE_INT bitmask_imm_mul[] = 10343 { 10344 0x0000000100000001ull, 10345 0x0001000100010001ull, 10346 0x0101010101010101ull, 10347 0x1111111111111111ull, 10348 0x5555555555555555ull, 10349 }; 10350 10351 10352 /* Return true if val is a valid bitmask immediate. */ 10353 10354 bool 10355 aarch64_bitmask_imm (HOST_WIDE_INT val_in, machine_mode mode) 10356 { 10357 unsigned HOST_WIDE_INT val, tmp, mask, first_one, next_one; 10358 int bits; 10359 10360 /* Check for a single sequence of one bits and return quickly if so. 10361 The special cases of all ones and all zeroes returns false. */ 10362 val = aarch64_replicate_bitmask_imm (val_in, mode); 10363 tmp = val + (val & -val); 10364 10365 if (tmp == (tmp & -tmp)) 10366 return (val + 1) > 1; 10367 10368 /* Replicate 32-bit immediates so we can treat them as 64-bit. */ 10369 if (mode == SImode) 10370 val = (val << 32) | (val & 0xffffffff); 10371 10372 /* Invert if the immediate doesn't start with a zero bit - this means we 10373 only need to search for sequences of one bits. */ 10374 if (val & 1) 10375 val = ~val; 10376 10377 /* Find the first set bit and set tmp to val with the first sequence of one 10378 bits removed. Return success if there is a single sequence of ones. */ 10379 first_one = val & -val; 10380 tmp = val & (val + first_one); 10381 10382 if (tmp == 0) 10383 return true; 10384 10385 /* Find the next set bit and compute the difference in bit position. */ 10386 next_one = tmp & -tmp; 10387 bits = clz_hwi (first_one) - clz_hwi (next_one); 10388 mask = val ^ tmp; 10389 10390 /* Check the bit position difference is a power of 2, and that the first 10391 sequence of one bits fits within 'bits' bits. */ 10392 if ((mask >> bits) != 0 || bits != (bits & -bits)) 10393 return false; 10394 10395 /* Check the sequence of one bits is repeated 64/bits times. */ 10396 return val == mask * bitmask_imm_mul[__builtin_clz (bits) - 26]; 10397 } 10398 10399 /* Create mask of ones, covering the lowest to highest bits set in VAL_IN. 10400 Assumed precondition: VAL_IN Is not zero. */ 10401 10402 unsigned HOST_WIDE_INT 10403 aarch64_and_split_imm1 (HOST_WIDE_INT val_in) 10404 { 10405 int lowest_bit_set = ctz_hwi (val_in); 10406 int highest_bit_set = floor_log2 (val_in); 10407 gcc_assert (val_in != 0); 10408 10409 return ((HOST_WIDE_INT_UC (2) << highest_bit_set) - 10410 (HOST_WIDE_INT_1U << lowest_bit_set)); 10411 } 10412 10413 /* Create constant where bits outside of lowest bit set to highest bit set 10414 are set to 1. */ 10415 10416 unsigned HOST_WIDE_INT 10417 aarch64_and_split_imm2 (HOST_WIDE_INT val_in) 10418 { 10419 return val_in | ~aarch64_and_split_imm1 (val_in); 10420 } 10421 10422 /* Return true if VAL_IN is a valid 'and' bitmask immediate. */ 10423 10424 bool 10425 aarch64_and_bitmask_imm (unsigned HOST_WIDE_INT val_in, machine_mode mode) 10426 { 10427 scalar_int_mode int_mode; 10428 if (!is_a <scalar_int_mode> (mode, &int_mode)) 10429 return false; 10430 10431 if (aarch64_bitmask_imm (val_in, int_mode)) 10432 return false; 10433 10434 if (aarch64_move_imm (val_in, int_mode)) 10435 return false; 10436 10437 unsigned HOST_WIDE_INT imm2 = aarch64_and_split_imm2 (val_in); 10438 10439 return aarch64_bitmask_imm (imm2, int_mode); 10440 } 10441 10442 /* Return true if val is an immediate that can be loaded into a 10443 register in a single instruction. */ 10444 bool 10445 aarch64_move_imm (HOST_WIDE_INT val, machine_mode mode) 10446 { 10447 scalar_int_mode int_mode; 10448 if (!is_a <scalar_int_mode> (mode, &int_mode)) 10449 return false; 10450 10451 if (aarch64_movw_imm (val, int_mode) || aarch64_movw_imm (~val, int_mode)) 10452 return 1; 10453 return aarch64_bitmask_imm (val, int_mode); 10454 } 10455 10456 static bool 10457 aarch64_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED, rtx x) 10458 { 10459 if (GET_CODE (x) == HIGH) 10460 return true; 10461 10462 /* There's no way to calculate VL-based values using relocations. */ 10463 subrtx_iterator::array_type array; 10464 FOR_EACH_SUBRTX (iter, array, x, ALL) 10465 if (GET_CODE (*iter) == CONST_POLY_INT) 10466 return true; 10467 10468 poly_int64 offset; 10469 rtx base = strip_offset_and_salt (x, &offset); 10470 if (SYMBOL_REF_P (base) || LABEL_REF_P (base)) 10471 { 10472 /* We checked for POLY_INT_CST offsets above. */ 10473 if (aarch64_classify_symbol (base, offset.to_constant ()) 10474 != SYMBOL_FORCE_TO_MEM) 10475 return true; 10476 else 10477 /* Avoid generating a 64-bit relocation in ILP32; leave 10478 to aarch64_expand_mov_immediate to handle it properly. */ 10479 return mode != ptr_mode; 10480 } 10481 10482 return aarch64_tls_referenced_p (x); 10483 } 10484 10485 /* Implement TARGET_CASE_VALUES_THRESHOLD. 10486 The expansion for a table switch is quite expensive due to the number 10487 of instructions, the table lookup and hard to predict indirect jump. 10488 When optimizing for speed, and -O3 enabled, use the per-core tuning if 10489 set, otherwise use tables for >= 11 cases as a tradeoff between size and 10490 performance. When optimizing for size, use 8 for smallest codesize. */ 10491 10492 static unsigned int 10493 aarch64_case_values_threshold (void) 10494 { 10495 /* Use the specified limit for the number of cases before using jump 10496 tables at higher optimization levels. */ 10497 if (optimize > 2 10498 && selected_cpu->tune->max_case_values != 0) 10499 return selected_cpu->tune->max_case_values; 10500 else 10501 return optimize_size ? 8 : 11; 10502 } 10503 10504 /* Return true if register REGNO is a valid index register. 10505 STRICT_P is true if REG_OK_STRICT is in effect. */ 10506 10507 bool 10508 aarch64_regno_ok_for_index_p (int regno, bool strict_p) 10509 { 10510 if (!HARD_REGISTER_NUM_P (regno)) 10511 { 10512 if (!strict_p) 10513 return true; 10514 10515 if (!reg_renumber) 10516 return false; 10517 10518 regno = reg_renumber[regno]; 10519 } 10520 return GP_REGNUM_P (regno); 10521 } 10522 10523 /* Return true if register REGNO is a valid base register for mode MODE. 10524 STRICT_P is true if REG_OK_STRICT is in effect. */ 10525 10526 bool 10527 aarch64_regno_ok_for_base_p (int regno, bool strict_p) 10528 { 10529 if (!HARD_REGISTER_NUM_P (regno)) 10530 { 10531 if (!strict_p) 10532 return true; 10533 10534 if (!reg_renumber) 10535 return false; 10536 10537 regno = reg_renumber[regno]; 10538 } 10539 10540 /* The fake registers will be eliminated to either the stack or 10541 hard frame pointer, both of which are usually valid base registers. 10542 Reload deals with the cases where the eliminated form isn't valid. */ 10543 return (GP_REGNUM_P (regno) 10544 || regno == SP_REGNUM 10545 || regno == FRAME_POINTER_REGNUM 10546 || regno == ARG_POINTER_REGNUM); 10547 } 10548 10549 /* Return true if X is a valid base register for mode MODE. 10550 STRICT_P is true if REG_OK_STRICT is in effect. */ 10551 10552 static bool 10553 aarch64_base_register_rtx_p (rtx x, bool strict_p) 10554 { 10555 if (!strict_p 10556 && SUBREG_P (x) 10557 && contains_reg_of_mode[GENERAL_REGS][GET_MODE (SUBREG_REG (x))]) 10558 x = SUBREG_REG (x); 10559 10560 return (REG_P (x) && aarch64_regno_ok_for_base_p (REGNO (x), strict_p)); 10561 } 10562 10563 /* Return true if address offset is a valid index. If it is, fill in INFO 10564 appropriately. STRICT_P is true if REG_OK_STRICT is in effect. */ 10565 10566 static bool 10567 aarch64_classify_index (struct aarch64_address_info *info, rtx x, 10568 machine_mode mode, bool strict_p) 10569 { 10570 enum aarch64_address_type type; 10571 rtx index; 10572 int shift; 10573 10574 /* (reg:P) */ 10575 if ((REG_P (x) || SUBREG_P (x)) 10576 && GET_MODE (x) == Pmode) 10577 { 10578 type = ADDRESS_REG_REG; 10579 index = x; 10580 shift = 0; 10581 } 10582 /* (sign_extend:DI (reg:SI)) */ 10583 else if ((GET_CODE (x) == SIGN_EXTEND 10584 || GET_CODE (x) == ZERO_EXTEND) 10585 && GET_MODE (x) == DImode 10586 && GET_MODE (XEXP (x, 0)) == SImode) 10587 { 10588 type = (GET_CODE (x) == SIGN_EXTEND) 10589 ? ADDRESS_REG_SXTW : ADDRESS_REG_UXTW; 10590 index = XEXP (x, 0); 10591 shift = 0; 10592 } 10593 /* (mult:DI (sign_extend:DI (reg:SI)) (const_int scale)) */ 10594 else if (GET_CODE (x) == MULT 10595 && (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND 10596 || GET_CODE (XEXP (x, 0)) == ZERO_EXTEND) 10597 && GET_MODE (XEXP (x, 0)) == DImode 10598 && GET_MODE (XEXP (XEXP (x, 0), 0)) == SImode 10599 && CONST_INT_P (XEXP (x, 1))) 10600 { 10601 type = (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND) 10602 ? ADDRESS_REG_SXTW : ADDRESS_REG_UXTW; 10603 index = XEXP (XEXP (x, 0), 0); 10604 shift = exact_log2 (INTVAL (XEXP (x, 1))); 10605 } 10606 /* (ashift:DI (sign_extend:DI (reg:SI)) (const_int shift)) */ 10607 else if (GET_CODE (x) == ASHIFT 10608 && (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND 10609 || GET_CODE (XEXP (x, 0)) == ZERO_EXTEND) 10610 && GET_MODE (XEXP (x, 0)) == DImode 10611 && GET_MODE (XEXP (XEXP (x, 0), 0)) == SImode 10612 && CONST_INT_P (XEXP (x, 1))) 10613 { 10614 type = (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND) 10615 ? ADDRESS_REG_SXTW : ADDRESS_REG_UXTW; 10616 index = XEXP (XEXP (x, 0), 0); 10617 shift = INTVAL (XEXP (x, 1)); 10618 } 10619 /* (and:DI (mult:DI (reg:DI) (const_int scale)) 10620 (const_int 0xffffffff<<shift)) */ 10621 else if (GET_CODE (x) == AND 10622 && GET_MODE (x) == DImode 10623 && GET_CODE (XEXP (x, 0)) == MULT 10624 && GET_MODE (XEXP (XEXP (x, 0), 0)) == DImode 10625 && CONST_INT_P (XEXP (XEXP (x, 0), 1)) 10626 && CONST_INT_P (XEXP (x, 1))) 10627 { 10628 type = ADDRESS_REG_UXTW; 10629 index = XEXP (XEXP (x, 0), 0); 10630 shift = exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1))); 10631 if (INTVAL (XEXP (x, 1)) != (HOST_WIDE_INT)0xffffffff << shift) 10632 shift = -1; 10633 } 10634 /* (and:DI (ashift:DI (reg:DI) (const_int shift)) 10635 (const_int 0xffffffff<<shift)) */ 10636 else if (GET_CODE (x) == AND 10637 && GET_MODE (x) == DImode 10638 && GET_CODE (XEXP (x, 0)) == ASHIFT 10639 && GET_MODE (XEXP (XEXP (x, 0), 0)) == DImode 10640 && CONST_INT_P (XEXP (XEXP (x, 0), 1)) 10641 && CONST_INT_P (XEXP (x, 1))) 10642 { 10643 type = ADDRESS_REG_UXTW; 10644 index = XEXP (XEXP (x, 0), 0); 10645 shift = INTVAL (XEXP (XEXP (x, 0), 1)); 10646 if (INTVAL (XEXP (x, 1)) != (HOST_WIDE_INT)0xffffffff << shift) 10647 shift = -1; 10648 } 10649 /* (mult:P (reg:P) (const_int scale)) */ 10650 else if (GET_CODE (x) == MULT 10651 && GET_MODE (x) == Pmode 10652 && GET_MODE (XEXP (x, 0)) == Pmode 10653 && CONST_INT_P (XEXP (x, 1))) 10654 { 10655 type = ADDRESS_REG_REG; 10656 index = XEXP (x, 0); 10657 shift = exact_log2 (INTVAL (XEXP (x, 1))); 10658 } 10659 /* (ashift:P (reg:P) (const_int shift)) */ 10660 else if (GET_CODE (x) == ASHIFT 10661 && GET_MODE (x) == Pmode 10662 && GET_MODE (XEXP (x, 0)) == Pmode 10663 && CONST_INT_P (XEXP (x, 1))) 10664 { 10665 type = ADDRESS_REG_REG; 10666 index = XEXP (x, 0); 10667 shift = INTVAL (XEXP (x, 1)); 10668 } 10669 else 10670 return false; 10671 10672 if (!strict_p 10673 && SUBREG_P (index) 10674 && contains_reg_of_mode[GENERAL_REGS][GET_MODE (SUBREG_REG (index))]) 10675 index = SUBREG_REG (index); 10676 10677 if (aarch64_sve_data_mode_p (mode)) 10678 { 10679 if (type != ADDRESS_REG_REG 10680 || (1 << shift) != GET_MODE_UNIT_SIZE (mode)) 10681 return false; 10682 } 10683 else 10684 { 10685 if (shift != 0 10686 && !(IN_RANGE (shift, 1, 3) 10687 && known_eq (1 << shift, GET_MODE_SIZE (mode)))) 10688 return false; 10689 } 10690 10691 if (REG_P (index) 10692 && aarch64_regno_ok_for_index_p (REGNO (index), strict_p)) 10693 { 10694 info->type = type; 10695 info->offset = index; 10696 info->shift = shift; 10697 return true; 10698 } 10699 10700 return false; 10701 } 10702 10703 /* Return true if MODE is one of the modes for which we 10704 support LDP/STP operations. */ 10705 10706 static bool 10707 aarch64_mode_valid_for_sched_fusion_p (machine_mode mode) 10708 { 10709 return mode == SImode || mode == DImode 10710 || mode == SFmode || mode == DFmode 10711 || (aarch64_vector_mode_supported_p (mode) 10712 && (known_eq (GET_MODE_SIZE (mode), 8) 10713 || (known_eq (GET_MODE_SIZE (mode), 16) 10714 && (aarch64_tune_params.extra_tuning_flags 10715 & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS) == 0))); 10716 } 10717 10718 /* Return true if REGNO is a virtual pointer register, or an eliminable 10719 "soft" frame register. Like REGNO_PTR_FRAME_P except that we don't 10720 include stack_pointer or hard_frame_pointer. */ 10721 static bool 10722 virt_or_elim_regno_p (unsigned regno) 10723 { 10724 return ((regno >= FIRST_VIRTUAL_REGISTER 10725 && regno <= LAST_VIRTUAL_POINTER_REGISTER) 10726 || regno == FRAME_POINTER_REGNUM 10727 || regno == ARG_POINTER_REGNUM); 10728 } 10729 10730 /* Return true if X is a valid address of type TYPE for machine mode MODE. 10731 If it is, fill in INFO appropriately. STRICT_P is true if 10732 REG_OK_STRICT is in effect. */ 10733 10734 bool 10735 aarch64_classify_address (struct aarch64_address_info *info, 10736 rtx x, machine_mode mode, bool strict_p, 10737 aarch64_addr_query_type type) 10738 { 10739 enum rtx_code code = GET_CODE (x); 10740 rtx op0, op1; 10741 poly_int64 offset; 10742 10743 HOST_WIDE_INT const_size; 10744 10745 /* Whether a vector mode is partial doesn't affect address legitimacy. 10746 Partial vectors like VNx8QImode allow the same indexed addressing 10747 mode and MUL VL addressing mode as full vectors like VNx16QImode; 10748 in both cases, MUL VL counts multiples of GET_MODE_SIZE. */ 10749 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 10750 vec_flags &= ~VEC_PARTIAL; 10751 10752 /* On BE, we use load/store pair for all large int mode load/stores. 10753 TI/TFmode may also use a load/store pair. */ 10754 bool advsimd_struct_p = (vec_flags == (VEC_ADVSIMD | VEC_STRUCT)); 10755 bool load_store_pair_p = (type == ADDR_QUERY_LDP_STP 10756 || type == ADDR_QUERY_LDP_STP_N 10757 || mode == TImode 10758 || mode == TFmode 10759 || (BYTES_BIG_ENDIAN && advsimd_struct_p)); 10760 /* If we are dealing with ADDR_QUERY_LDP_STP_N that means the incoming mode 10761 corresponds to the actual size of the memory being loaded/stored and the 10762 mode of the corresponding addressing mode is half of that. */ 10763 if (type == ADDR_QUERY_LDP_STP_N) 10764 { 10765 if (known_eq (GET_MODE_SIZE (mode), 16)) 10766 mode = DFmode; 10767 else if (known_eq (GET_MODE_SIZE (mode), 8)) 10768 mode = SFmode; 10769 else 10770 return false; 10771 } 10772 10773 bool allow_reg_index_p = (!load_store_pair_p 10774 && ((vec_flags == 0 10775 && known_lt (GET_MODE_SIZE (mode), 16)) 10776 || vec_flags == VEC_ADVSIMD 10777 || vec_flags & VEC_SVE_DATA)); 10778 10779 /* For SVE, only accept [Rn], [Rn, #offset, MUL VL] and [Rn, Rm, LSL #shift]. 10780 The latter is not valid for SVE predicates, and that's rejected through 10781 allow_reg_index_p above. */ 10782 if ((vec_flags & (VEC_SVE_DATA | VEC_SVE_PRED)) != 0 10783 && (code != REG && code != PLUS)) 10784 return false; 10785 10786 /* On LE, for AdvSIMD, don't support anything other than POST_INC or 10787 REG addressing. */ 10788 if (advsimd_struct_p 10789 && !BYTES_BIG_ENDIAN 10790 && (code != POST_INC && code != REG)) 10791 return false; 10792 10793 gcc_checking_assert (GET_MODE (x) == VOIDmode 10794 || SCALAR_INT_MODE_P (GET_MODE (x))); 10795 10796 switch (code) 10797 { 10798 case REG: 10799 case SUBREG: 10800 info->type = ADDRESS_REG_IMM; 10801 info->base = x; 10802 info->offset = const0_rtx; 10803 info->const_offset = 0; 10804 return aarch64_base_register_rtx_p (x, strict_p); 10805 10806 case PLUS: 10807 op0 = XEXP (x, 0); 10808 op1 = XEXP (x, 1); 10809 10810 if (! strict_p 10811 && REG_P (op0) 10812 && virt_or_elim_regno_p (REGNO (op0)) 10813 && poly_int_rtx_p (op1, &offset)) 10814 { 10815 info->type = ADDRESS_REG_IMM; 10816 info->base = op0; 10817 info->offset = op1; 10818 info->const_offset = offset; 10819 10820 return true; 10821 } 10822 10823 if (maybe_ne (GET_MODE_SIZE (mode), 0) 10824 && aarch64_base_register_rtx_p (op0, strict_p) 10825 && poly_int_rtx_p (op1, &offset)) 10826 { 10827 info->type = ADDRESS_REG_IMM; 10828 info->base = op0; 10829 info->offset = op1; 10830 info->const_offset = offset; 10831 10832 /* TImode and TFmode values are allowed in both pairs of X 10833 registers and individual Q registers. The available 10834 address modes are: 10835 X,X: 7-bit signed scaled offset 10836 Q: 9-bit signed offset 10837 We conservatively require an offset representable in either mode. 10838 When performing the check for pairs of X registers i.e. LDP/STP 10839 pass down DImode since that is the natural size of the LDP/STP 10840 instruction memory accesses. */ 10841 if (mode == TImode || mode == TFmode) 10842 return (aarch64_offset_7bit_signed_scaled_p (DImode, offset) 10843 && (aarch64_offset_9bit_signed_unscaled_p (mode, offset) 10844 || offset_12bit_unsigned_scaled_p (mode, offset))); 10845 10846 if (mode == V8DImode) 10847 return (aarch64_offset_7bit_signed_scaled_p (DImode, offset) 10848 && aarch64_offset_7bit_signed_scaled_p (DImode, offset + 48)); 10849 10850 /* A 7bit offset check because OImode will emit a ldp/stp 10851 instruction (only big endian will get here). 10852 For ldp/stp instructions, the offset is scaled for the size of a 10853 single element of the pair. */ 10854 if (aarch64_advsimd_partial_struct_mode_p (mode) 10855 && known_eq (GET_MODE_SIZE (mode), 16)) 10856 return aarch64_offset_7bit_signed_scaled_p (DImode, offset); 10857 if (aarch64_advsimd_full_struct_mode_p (mode) 10858 && known_eq (GET_MODE_SIZE (mode), 32)) 10859 return aarch64_offset_7bit_signed_scaled_p (TImode, offset); 10860 10861 /* Three 9/12 bit offsets checks because CImode will emit three 10862 ldr/str instructions (only big endian will get here). */ 10863 if (aarch64_advsimd_partial_struct_mode_p (mode) 10864 && known_eq (GET_MODE_SIZE (mode), 24)) 10865 return (aarch64_offset_7bit_signed_scaled_p (DImode, offset) 10866 && (aarch64_offset_9bit_signed_unscaled_p (DImode, 10867 offset + 16) 10868 || offset_12bit_unsigned_scaled_p (DImode, 10869 offset + 16))); 10870 if (aarch64_advsimd_full_struct_mode_p (mode) 10871 && known_eq (GET_MODE_SIZE (mode), 48)) 10872 return (aarch64_offset_7bit_signed_scaled_p (TImode, offset) 10873 && (aarch64_offset_9bit_signed_unscaled_p (TImode, 10874 offset + 32) 10875 || offset_12bit_unsigned_scaled_p (TImode, 10876 offset + 32))); 10877 10878 /* Two 7bit offsets checks because XImode will emit two ldp/stp 10879 instructions (only big endian will get here). */ 10880 if (aarch64_advsimd_partial_struct_mode_p (mode) 10881 && known_eq (GET_MODE_SIZE (mode), 32)) 10882 return (aarch64_offset_7bit_signed_scaled_p (DImode, offset) 10883 && aarch64_offset_7bit_signed_scaled_p (DImode, 10884 offset + 16)); 10885 if (aarch64_advsimd_full_struct_mode_p (mode) 10886 && known_eq (GET_MODE_SIZE (mode), 64)) 10887 return (aarch64_offset_7bit_signed_scaled_p (TImode, offset) 10888 && aarch64_offset_7bit_signed_scaled_p (TImode, 10889 offset + 32)); 10890 10891 /* Make "m" use the LD1 offset range for SVE data modes, so 10892 that pre-RTL optimizers like ivopts will work to that 10893 instead of the wider LDR/STR range. */ 10894 if (vec_flags == VEC_SVE_DATA) 10895 return (type == ADDR_QUERY_M 10896 ? offset_4bit_signed_scaled_p (mode, offset) 10897 : offset_9bit_signed_scaled_p (mode, offset)); 10898 10899 if (vec_flags == (VEC_SVE_DATA | VEC_STRUCT)) 10900 { 10901 poly_int64 end_offset = (offset 10902 + GET_MODE_SIZE (mode) 10903 - BYTES_PER_SVE_VECTOR); 10904 return (type == ADDR_QUERY_M 10905 ? offset_4bit_signed_scaled_p (mode, offset) 10906 : (offset_9bit_signed_scaled_p (SVE_BYTE_MODE, offset) 10907 && offset_9bit_signed_scaled_p (SVE_BYTE_MODE, 10908 end_offset))); 10909 } 10910 10911 if (vec_flags == VEC_SVE_PRED) 10912 return offset_9bit_signed_scaled_p (mode, offset); 10913 10914 if (load_store_pair_p) 10915 return ((known_eq (GET_MODE_SIZE (mode), 4) 10916 || known_eq (GET_MODE_SIZE (mode), 8) 10917 || known_eq (GET_MODE_SIZE (mode), 16)) 10918 && aarch64_offset_7bit_signed_scaled_p (mode, offset)); 10919 else 10920 return (aarch64_offset_9bit_signed_unscaled_p (mode, offset) 10921 || offset_12bit_unsigned_scaled_p (mode, offset)); 10922 } 10923 10924 if (allow_reg_index_p) 10925 { 10926 /* Look for base + (scaled/extended) index register. */ 10927 if (aarch64_base_register_rtx_p (op0, strict_p) 10928 && aarch64_classify_index (info, op1, mode, strict_p)) 10929 { 10930 info->base = op0; 10931 return true; 10932 } 10933 if (aarch64_base_register_rtx_p (op1, strict_p) 10934 && aarch64_classify_index (info, op0, mode, strict_p)) 10935 { 10936 info->base = op1; 10937 return true; 10938 } 10939 } 10940 10941 return false; 10942 10943 case POST_INC: 10944 case POST_DEC: 10945 case PRE_INC: 10946 case PRE_DEC: 10947 info->type = ADDRESS_REG_WB; 10948 info->base = XEXP (x, 0); 10949 info->offset = NULL_RTX; 10950 return aarch64_base_register_rtx_p (info->base, strict_p); 10951 10952 case POST_MODIFY: 10953 case PRE_MODIFY: 10954 info->type = ADDRESS_REG_WB; 10955 info->base = XEXP (x, 0); 10956 if (GET_CODE (XEXP (x, 1)) == PLUS 10957 && poly_int_rtx_p (XEXP (XEXP (x, 1), 1), &offset) 10958 && rtx_equal_p (XEXP (XEXP (x, 1), 0), info->base) 10959 && aarch64_base_register_rtx_p (info->base, strict_p)) 10960 { 10961 info->offset = XEXP (XEXP (x, 1), 1); 10962 info->const_offset = offset; 10963 10964 /* TImode and TFmode values are allowed in both pairs of X 10965 registers and individual Q registers. The available 10966 address modes are: 10967 X,X: 7-bit signed scaled offset 10968 Q: 9-bit signed offset 10969 We conservatively require an offset representable in either mode. 10970 */ 10971 if (mode == TImode || mode == TFmode) 10972 return (aarch64_offset_7bit_signed_scaled_p (mode, offset) 10973 && aarch64_offset_9bit_signed_unscaled_p (mode, offset)); 10974 10975 if (load_store_pair_p) 10976 return ((known_eq (GET_MODE_SIZE (mode), 4) 10977 || known_eq (GET_MODE_SIZE (mode), 8) 10978 || known_eq (GET_MODE_SIZE (mode), 16)) 10979 && aarch64_offset_7bit_signed_scaled_p (mode, offset)); 10980 else 10981 return aarch64_offset_9bit_signed_unscaled_p (mode, offset); 10982 } 10983 return false; 10984 10985 case CONST: 10986 case SYMBOL_REF: 10987 case LABEL_REF: 10988 /* load literal: pc-relative constant pool entry. Only supported 10989 for SI mode or larger. */ 10990 info->type = ADDRESS_SYMBOLIC; 10991 10992 if (!load_store_pair_p 10993 && GET_MODE_SIZE (mode).is_constant (&const_size) 10994 && const_size >= 4) 10995 { 10996 poly_int64 offset; 10997 rtx sym = strip_offset_and_salt (x, &offset); 10998 return ((LABEL_REF_P (sym) 10999 || (SYMBOL_REF_P (sym) 11000 && CONSTANT_POOL_ADDRESS_P (sym) 11001 && aarch64_pcrelative_literal_loads))); 11002 } 11003 return false; 11004 11005 case LO_SUM: 11006 info->type = ADDRESS_LO_SUM; 11007 info->base = XEXP (x, 0); 11008 info->offset = XEXP (x, 1); 11009 if (allow_reg_index_p 11010 && aarch64_base_register_rtx_p (info->base, strict_p)) 11011 { 11012 poly_int64 offset; 11013 HOST_WIDE_INT const_offset; 11014 rtx sym = strip_offset_and_salt (info->offset, &offset); 11015 if (SYMBOL_REF_P (sym) 11016 && offset.is_constant (&const_offset) 11017 && (aarch64_classify_symbol (sym, const_offset) 11018 == SYMBOL_SMALL_ABSOLUTE)) 11019 { 11020 /* The symbol and offset must be aligned to the access size. */ 11021 unsigned int align; 11022 11023 if (CONSTANT_POOL_ADDRESS_P (sym)) 11024 align = GET_MODE_ALIGNMENT (get_pool_mode (sym)); 11025 else if (TREE_CONSTANT_POOL_ADDRESS_P (sym)) 11026 { 11027 tree exp = SYMBOL_REF_DECL (sym); 11028 align = TYPE_ALIGN (TREE_TYPE (exp)); 11029 align = aarch64_constant_alignment (exp, align); 11030 } 11031 else if (SYMBOL_REF_DECL (sym)) 11032 align = DECL_ALIGN (SYMBOL_REF_DECL (sym)); 11033 else if (SYMBOL_REF_HAS_BLOCK_INFO_P (sym) 11034 && SYMBOL_REF_BLOCK (sym) != NULL) 11035 align = SYMBOL_REF_BLOCK (sym)->alignment; 11036 else 11037 align = BITS_PER_UNIT; 11038 11039 poly_int64 ref_size = GET_MODE_SIZE (mode); 11040 if (known_eq (ref_size, 0)) 11041 ref_size = GET_MODE_SIZE (DImode); 11042 11043 return (multiple_p (const_offset, ref_size) 11044 && multiple_p (align / BITS_PER_UNIT, ref_size)); 11045 } 11046 } 11047 return false; 11048 11049 default: 11050 return false; 11051 } 11052 } 11053 11054 /* Return true if the address X is valid for a PRFM instruction. 11055 STRICT_P is true if we should do strict checking with 11056 aarch64_classify_address. */ 11057 11058 bool 11059 aarch64_address_valid_for_prefetch_p (rtx x, bool strict_p) 11060 { 11061 struct aarch64_address_info addr; 11062 11063 /* PRFM accepts the same addresses as DImode... */ 11064 bool res = aarch64_classify_address (&addr, x, DImode, strict_p); 11065 if (!res) 11066 return false; 11067 11068 /* ... except writeback forms. */ 11069 return addr.type != ADDRESS_REG_WB; 11070 } 11071 11072 bool 11073 aarch64_symbolic_address_p (rtx x) 11074 { 11075 poly_int64 offset; 11076 x = strip_offset_and_salt (x, &offset); 11077 return SYMBOL_REF_P (x) || LABEL_REF_P (x); 11078 } 11079 11080 /* Classify the base of symbolic expression X. */ 11081 11082 enum aarch64_symbol_type 11083 aarch64_classify_symbolic_expression (rtx x) 11084 { 11085 rtx offset; 11086 11087 split_const (x, &x, &offset); 11088 return aarch64_classify_symbol (x, INTVAL (offset)); 11089 } 11090 11091 11092 /* Return TRUE if X is a legitimate address for accessing memory in 11093 mode MODE. */ 11094 static bool 11095 aarch64_legitimate_address_hook_p (machine_mode mode, rtx x, bool strict_p) 11096 { 11097 struct aarch64_address_info addr; 11098 11099 return aarch64_classify_address (&addr, x, mode, strict_p); 11100 } 11101 11102 /* Return TRUE if X is a legitimate address of type TYPE for accessing 11103 memory in mode MODE. STRICT_P is true if REG_OK_STRICT is in effect. */ 11104 bool 11105 aarch64_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, 11106 aarch64_addr_query_type type) 11107 { 11108 struct aarch64_address_info addr; 11109 11110 return aarch64_classify_address (&addr, x, mode, strict_p, type); 11111 } 11112 11113 /* Implement TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT. */ 11114 11115 static bool 11116 aarch64_legitimize_address_displacement (rtx *offset1, rtx *offset2, 11117 poly_int64 orig_offset, 11118 machine_mode mode) 11119 { 11120 HOST_WIDE_INT size; 11121 if (GET_MODE_SIZE (mode).is_constant (&size)) 11122 { 11123 HOST_WIDE_INT const_offset, second_offset; 11124 11125 /* A general SVE offset is A * VQ + B. Remove the A component from 11126 coefficient 0 in order to get the constant B. */ 11127 const_offset = orig_offset.coeffs[0] - orig_offset.coeffs[1]; 11128 11129 /* Split an out-of-range address displacement into a base and 11130 offset. Use 4KB range for 1- and 2-byte accesses and a 16KB 11131 range otherwise to increase opportunities for sharing the base 11132 address of different sizes. Unaligned accesses use the signed 11133 9-bit range, TImode/TFmode use the intersection of signed 11134 scaled 7-bit and signed 9-bit offset. */ 11135 if (mode == TImode || mode == TFmode) 11136 second_offset = ((const_offset + 0x100) & 0x1f8) - 0x100; 11137 else if ((const_offset & (size - 1)) != 0) 11138 second_offset = ((const_offset + 0x100) & 0x1ff) - 0x100; 11139 else 11140 second_offset = const_offset & (size < 4 ? 0xfff : 0x3ffc); 11141 11142 if (second_offset == 0 || known_eq (orig_offset, second_offset)) 11143 return false; 11144 11145 /* Split the offset into second_offset and the rest. */ 11146 *offset1 = gen_int_mode (orig_offset - second_offset, Pmode); 11147 *offset2 = gen_int_mode (second_offset, Pmode); 11148 return true; 11149 } 11150 else 11151 { 11152 /* Get the mode we should use as the basis of the range. For structure 11153 modes this is the mode of one vector. */ 11154 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 11155 machine_mode step_mode 11156 = (vec_flags & VEC_STRUCT) != 0 ? SVE_BYTE_MODE : mode; 11157 11158 /* Get the "mul vl" multiplier we'd like to use. */ 11159 HOST_WIDE_INT factor = GET_MODE_SIZE (step_mode).coeffs[1]; 11160 HOST_WIDE_INT vnum = orig_offset.coeffs[1] / factor; 11161 if (vec_flags & VEC_SVE_DATA) 11162 /* LDR supports a 9-bit range, but the move patterns for 11163 structure modes require all vectors to be in range of the 11164 same base. The simplest way of accomodating that while still 11165 promoting reuse of anchor points between different modes is 11166 to use an 8-bit range unconditionally. */ 11167 vnum = ((vnum + 128) & 255) - 128; 11168 else 11169 /* Predicates are only handled singly, so we might as well use 11170 the full range. */ 11171 vnum = ((vnum + 256) & 511) - 256; 11172 if (vnum == 0) 11173 return false; 11174 11175 /* Convert the "mul vl" multiplier into a byte offset. */ 11176 poly_int64 second_offset = GET_MODE_SIZE (step_mode) * vnum; 11177 if (known_eq (second_offset, orig_offset)) 11178 return false; 11179 11180 /* Split the offset into second_offset and the rest. */ 11181 *offset1 = gen_int_mode (orig_offset - second_offset, Pmode); 11182 *offset2 = gen_int_mode (second_offset, Pmode); 11183 return true; 11184 } 11185 } 11186 11187 /* Return the binary representation of floating point constant VALUE in INTVAL. 11188 If the value cannot be converted, return false without setting INTVAL. 11189 The conversion is done in the given MODE. */ 11190 bool 11191 aarch64_reinterpret_float_as_int (rtx value, unsigned HOST_WIDE_INT *intval) 11192 { 11193 11194 /* We make a general exception for 0. */ 11195 if (aarch64_float_const_zero_rtx_p (value)) 11196 { 11197 *intval = 0; 11198 return true; 11199 } 11200 11201 scalar_float_mode mode; 11202 if (!CONST_DOUBLE_P (value) 11203 || !is_a <scalar_float_mode> (GET_MODE (value), &mode) 11204 || GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT 11205 /* Only support up to DF mode. */ 11206 || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (DFmode)) 11207 return false; 11208 11209 unsigned HOST_WIDE_INT ival = 0; 11210 11211 long res[2]; 11212 real_to_target (res, 11213 CONST_DOUBLE_REAL_VALUE (value), 11214 REAL_MODE_FORMAT (mode)); 11215 11216 if (mode == DFmode) 11217 { 11218 int order = BYTES_BIG_ENDIAN ? 1 : 0; 11219 ival = zext_hwi (res[order], 32); 11220 ival |= (zext_hwi (res[1 - order], 32) << 32); 11221 } 11222 else 11223 ival = zext_hwi (res[0], 32); 11224 11225 *intval = ival; 11226 return true; 11227 } 11228 11229 /* Return TRUE if rtx X is an immediate constant that can be moved using a 11230 single MOV(+MOVK) followed by an FMOV. */ 11231 bool 11232 aarch64_float_const_rtx_p (rtx x) 11233 { 11234 machine_mode mode = GET_MODE (x); 11235 if (mode == VOIDmode) 11236 return false; 11237 11238 /* Determine whether it's cheaper to write float constants as 11239 mov/movk pairs over ldr/adrp pairs. */ 11240 unsigned HOST_WIDE_INT ival; 11241 11242 if (CONST_DOUBLE_P (x) 11243 && SCALAR_FLOAT_MODE_P (mode) 11244 && aarch64_reinterpret_float_as_int (x, &ival)) 11245 { 11246 scalar_int_mode imode = (mode == HFmode 11247 ? SImode 11248 : int_mode_for_mode (mode).require ()); 11249 int num_instr = aarch64_internal_mov_immediate 11250 (NULL_RTX, gen_int_mode (ival, imode), false, imode); 11251 return num_instr < 3; 11252 } 11253 11254 return false; 11255 } 11256 11257 /* Return TRUE if rtx X is immediate constant 0.0 */ 11258 bool 11259 aarch64_float_const_zero_rtx_p (rtx x) 11260 { 11261 if (GET_MODE (x) == VOIDmode) 11262 return false; 11263 11264 if (REAL_VALUE_MINUS_ZERO (*CONST_DOUBLE_REAL_VALUE (x))) 11265 return !HONOR_SIGNED_ZEROS (GET_MODE (x)); 11266 return real_equal (CONST_DOUBLE_REAL_VALUE (x), &dconst0); 11267 } 11268 11269 /* Return TRUE if rtx X is immediate constant that fits in a single 11270 MOVI immediate operation. */ 11271 bool 11272 aarch64_can_const_movi_rtx_p (rtx x, machine_mode mode) 11273 { 11274 if (!TARGET_SIMD) 11275 return false; 11276 11277 machine_mode vmode; 11278 scalar_int_mode imode; 11279 unsigned HOST_WIDE_INT ival; 11280 11281 if (CONST_DOUBLE_P (x) 11282 && SCALAR_FLOAT_MODE_P (mode)) 11283 { 11284 if (!aarch64_reinterpret_float_as_int (x, &ival)) 11285 return false; 11286 11287 /* We make a general exception for 0. */ 11288 if (aarch64_float_const_zero_rtx_p (x)) 11289 return true; 11290 11291 imode = int_mode_for_mode (mode).require (); 11292 } 11293 else if (CONST_INT_P (x) 11294 && is_a <scalar_int_mode> (mode, &imode)) 11295 ival = INTVAL (x); 11296 else 11297 return false; 11298 11299 /* use a 64 bit mode for everything except for DI/DF mode, where we use 11300 a 128 bit vector mode. */ 11301 int width = GET_MODE_BITSIZE (imode) == 64 ? 128 : 64; 11302 11303 vmode = aarch64_simd_container_mode (imode, width); 11304 rtx v_op = aarch64_simd_gen_const_vector_dup (vmode, ival); 11305 11306 return aarch64_simd_valid_immediate (v_op, NULL); 11307 } 11308 11309 11310 /* Return the fixed registers used for condition codes. */ 11311 11312 static bool 11313 aarch64_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2) 11314 { 11315 *p1 = CC_REGNUM; 11316 *p2 = INVALID_REGNUM; 11317 return true; 11318 } 11319 11320 /* This function is used by the call expanders of the machine description. 11321 RESULT is the register in which the result is returned. It's NULL for 11322 "call" and "sibcall". 11323 MEM is the location of the function call. 11324 CALLEE_ABI is a const_int that gives the arm_pcs of the callee. 11325 SIBCALL indicates whether this function call is normal call or sibling call. 11326 It will generate different pattern accordingly. */ 11327 11328 void 11329 aarch64_expand_call (rtx result, rtx mem, rtx callee_abi, bool sibcall) 11330 { 11331 rtx call, callee, tmp; 11332 rtvec vec; 11333 machine_mode mode; 11334 11335 gcc_assert (MEM_P (mem)); 11336 callee = XEXP (mem, 0); 11337 mode = GET_MODE (callee); 11338 gcc_assert (mode == Pmode); 11339 11340 /* Decide if we should generate indirect calls by loading the 11341 address of the callee into a register before performing 11342 the branch-and-link. */ 11343 if (SYMBOL_REF_P (callee) 11344 ? (aarch64_is_long_call_p (callee) 11345 || aarch64_is_noplt_call_p (callee)) 11346 : !REG_P (callee)) 11347 XEXP (mem, 0) = force_reg (mode, callee); 11348 11349 call = gen_rtx_CALL (VOIDmode, mem, const0_rtx); 11350 11351 if (result != NULL_RTX) 11352 call = gen_rtx_SET (result, call); 11353 11354 if (sibcall) 11355 tmp = ret_rtx; 11356 else 11357 tmp = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, LR_REGNUM)); 11358 11359 gcc_assert (CONST_INT_P (callee_abi)); 11360 callee_abi = gen_rtx_UNSPEC (DImode, gen_rtvec (1, callee_abi), 11361 UNSPEC_CALLEE_ABI); 11362 11363 vec = gen_rtvec (3, call, callee_abi, tmp); 11364 call = gen_rtx_PARALLEL (VOIDmode, vec); 11365 11366 aarch64_emit_call_insn (call); 11367 } 11368 11369 /* Emit call insn with PAT and do aarch64-specific handling. */ 11370 11371 void 11372 aarch64_emit_call_insn (rtx pat) 11373 { 11374 rtx insn = emit_call_insn (pat); 11375 11376 rtx *fusage = &CALL_INSN_FUNCTION_USAGE (insn); 11377 clobber_reg (fusage, gen_rtx_REG (word_mode, IP0_REGNUM)); 11378 clobber_reg (fusage, gen_rtx_REG (word_mode, IP1_REGNUM)); 11379 } 11380 11381 machine_mode 11382 aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y) 11383 { 11384 machine_mode mode_x = GET_MODE (x); 11385 rtx_code code_x = GET_CODE (x); 11386 11387 /* All floating point compares return CCFP if it is an equality 11388 comparison, and CCFPE otherwise. */ 11389 if (GET_MODE_CLASS (mode_x) == MODE_FLOAT) 11390 { 11391 switch (code) 11392 { 11393 case EQ: 11394 case NE: 11395 case UNORDERED: 11396 case ORDERED: 11397 case UNLT: 11398 case UNLE: 11399 case UNGT: 11400 case UNGE: 11401 case UNEQ: 11402 return CCFPmode; 11403 11404 case LT: 11405 case LE: 11406 case GT: 11407 case GE: 11408 case LTGT: 11409 return CCFPEmode; 11410 11411 default: 11412 gcc_unreachable (); 11413 } 11414 } 11415 11416 /* Equality comparisons of short modes against zero can be performed 11417 using the TST instruction with the appropriate bitmask. */ 11418 if (y == const0_rtx && (REG_P (x) || SUBREG_P (x)) 11419 && (code == EQ || code == NE) 11420 && (mode_x == HImode || mode_x == QImode)) 11421 return CC_NZmode; 11422 11423 /* Similarly, comparisons of zero_extends from shorter modes can 11424 be performed using an ANDS with an immediate mask. */ 11425 if (y == const0_rtx && code_x == ZERO_EXTEND 11426 && (mode_x == SImode || mode_x == DImode) 11427 && (GET_MODE (XEXP (x, 0)) == HImode || GET_MODE (XEXP (x, 0)) == QImode) 11428 && (code == EQ || code == NE)) 11429 return CC_NZmode; 11430 11431 if ((mode_x == SImode || mode_x == DImode) 11432 && y == const0_rtx 11433 && (code == EQ || code == NE || code == LT || code == GE) 11434 && (code_x == PLUS || code_x == MINUS || code_x == AND 11435 || code_x == NEG 11436 || (code_x == ZERO_EXTRACT && CONST_INT_P (XEXP (x, 1)) 11437 && CONST_INT_P (XEXP (x, 2))))) 11438 return CC_NZmode; 11439 11440 /* A compare with a shifted operand. Because of canonicalization, 11441 the comparison will have to be swapped when we emit the assembly 11442 code. */ 11443 if ((mode_x == SImode || mode_x == DImode) 11444 && (REG_P (y) || SUBREG_P (y) || y == const0_rtx) 11445 && (code_x == ASHIFT || code_x == ASHIFTRT 11446 || code_x == LSHIFTRT 11447 || code_x == ZERO_EXTEND || code_x == SIGN_EXTEND)) 11448 return CC_SWPmode; 11449 11450 /* Similarly for a negated operand, but we can only do this for 11451 equalities. */ 11452 if ((mode_x == SImode || mode_x == DImode) 11453 && (REG_P (y) || SUBREG_P (y)) 11454 && (code == EQ || code == NE) 11455 && code_x == NEG) 11456 return CC_Zmode; 11457 11458 /* A test for unsigned overflow from an addition. */ 11459 if ((mode_x == DImode || mode_x == TImode) 11460 && (code == LTU || code == GEU) 11461 && code_x == PLUS 11462 && rtx_equal_p (XEXP (x, 0), y)) 11463 return CC_Cmode; 11464 11465 /* A test for unsigned overflow from an add with carry. */ 11466 if ((mode_x == DImode || mode_x == TImode) 11467 && (code == LTU || code == GEU) 11468 && code_x == PLUS 11469 && CONST_SCALAR_INT_P (y) 11470 && (rtx_mode_t (y, mode_x) 11471 == (wi::shwi (1, mode_x) 11472 << (GET_MODE_BITSIZE (mode_x).to_constant () / 2)))) 11473 return CC_ADCmode; 11474 11475 /* A test for signed overflow. */ 11476 if ((mode_x == DImode || mode_x == TImode) 11477 && code == NE 11478 && code_x == PLUS 11479 && GET_CODE (y) == SIGN_EXTEND) 11480 return CC_Vmode; 11481 11482 /* For everything else, return CCmode. */ 11483 return CCmode; 11484 } 11485 11486 static int 11487 aarch64_get_condition_code_1 (machine_mode, enum rtx_code); 11488 11489 int 11490 aarch64_get_condition_code (rtx x) 11491 { 11492 machine_mode mode = GET_MODE (XEXP (x, 0)); 11493 enum rtx_code comp_code = GET_CODE (x); 11494 11495 if (GET_MODE_CLASS (mode) != MODE_CC) 11496 mode = SELECT_CC_MODE (comp_code, XEXP (x, 0), XEXP (x, 1)); 11497 return aarch64_get_condition_code_1 (mode, comp_code); 11498 } 11499 11500 static int 11501 aarch64_get_condition_code_1 (machine_mode mode, enum rtx_code comp_code) 11502 { 11503 switch (mode) 11504 { 11505 case E_CCFPmode: 11506 case E_CCFPEmode: 11507 switch (comp_code) 11508 { 11509 case GE: return AARCH64_GE; 11510 case GT: return AARCH64_GT; 11511 case LE: return AARCH64_LS; 11512 case LT: return AARCH64_MI; 11513 case NE: return AARCH64_NE; 11514 case EQ: return AARCH64_EQ; 11515 case ORDERED: return AARCH64_VC; 11516 case UNORDERED: return AARCH64_VS; 11517 case UNLT: return AARCH64_LT; 11518 case UNLE: return AARCH64_LE; 11519 case UNGT: return AARCH64_HI; 11520 case UNGE: return AARCH64_PL; 11521 default: return -1; 11522 } 11523 break; 11524 11525 case E_CCmode: 11526 switch (comp_code) 11527 { 11528 case NE: return AARCH64_NE; 11529 case EQ: return AARCH64_EQ; 11530 case GE: return AARCH64_GE; 11531 case GT: return AARCH64_GT; 11532 case LE: return AARCH64_LE; 11533 case LT: return AARCH64_LT; 11534 case GEU: return AARCH64_CS; 11535 case GTU: return AARCH64_HI; 11536 case LEU: return AARCH64_LS; 11537 case LTU: return AARCH64_CC; 11538 default: return -1; 11539 } 11540 break; 11541 11542 case E_CC_SWPmode: 11543 switch (comp_code) 11544 { 11545 case NE: return AARCH64_NE; 11546 case EQ: return AARCH64_EQ; 11547 case GE: return AARCH64_LE; 11548 case GT: return AARCH64_LT; 11549 case LE: return AARCH64_GE; 11550 case LT: return AARCH64_GT; 11551 case GEU: return AARCH64_LS; 11552 case GTU: return AARCH64_CC; 11553 case LEU: return AARCH64_CS; 11554 case LTU: return AARCH64_HI; 11555 default: return -1; 11556 } 11557 break; 11558 11559 case E_CC_NZCmode: 11560 switch (comp_code) 11561 { 11562 case NE: return AARCH64_NE; /* = any */ 11563 case EQ: return AARCH64_EQ; /* = none */ 11564 case GE: return AARCH64_PL; /* = nfrst */ 11565 case LT: return AARCH64_MI; /* = first */ 11566 case GEU: return AARCH64_CS; /* = nlast */ 11567 case GTU: return AARCH64_HI; /* = pmore */ 11568 case LEU: return AARCH64_LS; /* = plast */ 11569 case LTU: return AARCH64_CC; /* = last */ 11570 default: return -1; 11571 } 11572 break; 11573 11574 case E_CC_NZmode: 11575 switch (comp_code) 11576 { 11577 case NE: return AARCH64_NE; 11578 case EQ: return AARCH64_EQ; 11579 case GE: return AARCH64_PL; 11580 case LT: return AARCH64_MI; 11581 default: return -1; 11582 } 11583 break; 11584 11585 case E_CC_Zmode: 11586 switch (comp_code) 11587 { 11588 case NE: return AARCH64_NE; 11589 case EQ: return AARCH64_EQ; 11590 default: return -1; 11591 } 11592 break; 11593 11594 case E_CC_Cmode: 11595 switch (comp_code) 11596 { 11597 case LTU: return AARCH64_CS; 11598 case GEU: return AARCH64_CC; 11599 default: return -1; 11600 } 11601 break; 11602 11603 case E_CC_ADCmode: 11604 switch (comp_code) 11605 { 11606 case GEU: return AARCH64_CS; 11607 case LTU: return AARCH64_CC; 11608 default: return -1; 11609 } 11610 break; 11611 11612 case E_CC_Vmode: 11613 switch (comp_code) 11614 { 11615 case NE: return AARCH64_VS; 11616 case EQ: return AARCH64_VC; 11617 default: return -1; 11618 } 11619 break; 11620 11621 default: 11622 return -1; 11623 } 11624 11625 return -1; 11626 } 11627 11628 bool 11629 aarch64_const_vec_all_same_in_range_p (rtx x, 11630 HOST_WIDE_INT minval, 11631 HOST_WIDE_INT maxval) 11632 { 11633 rtx elt; 11634 return (const_vec_duplicate_p (x, &elt) 11635 && CONST_INT_P (elt) 11636 && IN_RANGE (INTVAL (elt), minval, maxval)); 11637 } 11638 11639 bool 11640 aarch64_const_vec_all_same_int_p (rtx x, HOST_WIDE_INT val) 11641 { 11642 return aarch64_const_vec_all_same_in_range_p (x, val, val); 11643 } 11644 11645 /* Return true if VEC is a constant in which every element is in the range 11646 [MINVAL, MAXVAL]. The elements do not need to have the same value. */ 11647 11648 static bool 11649 aarch64_const_vec_all_in_range_p (rtx vec, 11650 HOST_WIDE_INT minval, 11651 HOST_WIDE_INT maxval) 11652 { 11653 if (!CONST_VECTOR_P (vec) 11654 || GET_MODE_CLASS (GET_MODE (vec)) != MODE_VECTOR_INT) 11655 return false; 11656 11657 int nunits; 11658 if (!CONST_VECTOR_STEPPED_P (vec)) 11659 nunits = const_vector_encoded_nelts (vec); 11660 else if (!CONST_VECTOR_NUNITS (vec).is_constant (&nunits)) 11661 return false; 11662 11663 for (int i = 0; i < nunits; i++) 11664 { 11665 rtx vec_elem = CONST_VECTOR_ELT (vec, i); 11666 if (!CONST_INT_P (vec_elem) 11667 || !IN_RANGE (INTVAL (vec_elem), minval, maxval)) 11668 return false; 11669 } 11670 return true; 11671 } 11672 11673 /* N Z C V. */ 11674 #define AARCH64_CC_V 1 11675 #define AARCH64_CC_C (1 << 1) 11676 #define AARCH64_CC_Z (1 << 2) 11677 #define AARCH64_CC_N (1 << 3) 11678 11679 /* N Z C V flags for ccmp. Indexed by AARCH64_COND_CODE. */ 11680 static const int aarch64_nzcv_codes[] = 11681 { 11682 0, /* EQ, Z == 1. */ 11683 AARCH64_CC_Z, /* NE, Z == 0. */ 11684 0, /* CS, C == 1. */ 11685 AARCH64_CC_C, /* CC, C == 0. */ 11686 0, /* MI, N == 1. */ 11687 AARCH64_CC_N, /* PL, N == 0. */ 11688 0, /* VS, V == 1. */ 11689 AARCH64_CC_V, /* VC, V == 0. */ 11690 0, /* HI, C ==1 && Z == 0. */ 11691 AARCH64_CC_C, /* LS, !(C == 1 && Z == 0). */ 11692 AARCH64_CC_V, /* GE, N == V. */ 11693 0, /* LT, N != V. */ 11694 AARCH64_CC_Z, /* GT, Z == 0 && N == V. */ 11695 0, /* LE, !(Z == 0 && N == V). */ 11696 0, /* AL, Any. */ 11697 0 /* NV, Any. */ 11698 }; 11699 11700 /* Print floating-point vector immediate operand X to F, negating it 11701 first if NEGATE is true. Return true on success, false if it isn't 11702 a constant we can handle. */ 11703 11704 static bool 11705 aarch64_print_vector_float_operand (FILE *f, rtx x, bool negate) 11706 { 11707 rtx elt; 11708 11709 if (!const_vec_duplicate_p (x, &elt)) 11710 return false; 11711 11712 REAL_VALUE_TYPE r = *CONST_DOUBLE_REAL_VALUE (elt); 11713 if (negate) 11714 r = real_value_negate (&r); 11715 11716 /* Handle the SVE single-bit immediates specially, since they have a 11717 fixed form in the assembly syntax. */ 11718 if (real_equal (&r, &dconst0)) 11719 asm_fprintf (f, "0.0"); 11720 else if (real_equal (&r, &dconst2)) 11721 asm_fprintf (f, "2.0"); 11722 else if (real_equal (&r, &dconst1)) 11723 asm_fprintf (f, "1.0"); 11724 else if (real_equal (&r, &dconsthalf)) 11725 asm_fprintf (f, "0.5"); 11726 else 11727 { 11728 const int buf_size = 20; 11729 char float_buf[buf_size] = {'\0'}; 11730 real_to_decimal_for_mode (float_buf, &r, buf_size, buf_size, 11731 1, GET_MODE (elt)); 11732 asm_fprintf (f, "%s", float_buf); 11733 } 11734 11735 return true; 11736 } 11737 11738 /* Return the equivalent letter for size. */ 11739 static char 11740 sizetochar (int size) 11741 { 11742 switch (size) 11743 { 11744 case 64: return 'd'; 11745 case 32: return 's'; 11746 case 16: return 'h'; 11747 case 8 : return 'b'; 11748 default: gcc_unreachable (); 11749 } 11750 } 11751 11752 /* Print operand X to file F in a target specific manner according to CODE. 11753 The acceptable formatting commands given by CODE are: 11754 'c': An integer or symbol address without a preceding # 11755 sign. 11756 'C': Take the duplicated element in a vector constant 11757 and print it in hex. 11758 'D': Take the duplicated element in a vector constant 11759 and print it as an unsigned integer, in decimal. 11760 'e': Print the sign/zero-extend size as a character 8->b, 11761 16->h, 32->w. Can also be used for masks: 11762 0xff->b, 0xffff->h, 0xffffffff->w. 11763 'I': If the operand is a duplicated vector constant, 11764 replace it with the duplicated scalar. If the 11765 operand is then a floating-point constant, replace 11766 it with the integer bit representation. Print the 11767 transformed constant as a signed decimal number. 11768 'p': Prints N such that 2^N == X (X must be power of 2 and 11769 const int). 11770 'P': Print the number of non-zero bits in X (a const_int). 11771 'H': Print the higher numbered register of a pair (TImode) 11772 of regs. 11773 'm': Print a condition (eq, ne, etc). 11774 'M': Same as 'm', but invert condition. 11775 'N': Take the duplicated element in a vector constant 11776 and print the negative of it in decimal. 11777 'b/h/s/d/q': Print a scalar FP/SIMD register name. 11778 'S/T/U/V': Print a FP/SIMD register name for a register list. 11779 The register printed is the FP/SIMD register name 11780 of X + 0/1/2/3 for S/T/U/V. 11781 'R': Print a scalar Integer/FP/SIMD register name + 1. 11782 'X': Print bottom 16 bits of integer constant in hex. 11783 'w/x': Print a general register name or the zero register 11784 (32-bit or 64-bit). 11785 '0': Print a normal operand, if it's a general register, 11786 then we assume DImode. 11787 'k': Print NZCV for conditional compare instructions. 11788 'A': Output address constant representing the first 11789 argument of X, specifying a relocation offset 11790 if appropriate. 11791 'L': Output constant address specified by X 11792 with a relocation offset if appropriate. 11793 'G': Prints address of X, specifying a PC relative 11794 relocation mode if appropriate. 11795 'y': Output address of LDP or STP - this is used for 11796 some LDP/STPs which don't use a PARALLEL in their 11797 pattern (so the mode needs to be adjusted). 11798 'z': Output address of a typical LDP or STP. */ 11799 11800 static void 11801 aarch64_print_operand (FILE *f, rtx x, int code) 11802 { 11803 rtx elt; 11804 switch (code) 11805 { 11806 case 'c': 11807 if (CONST_INT_P (x)) 11808 fprintf (f, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); 11809 else 11810 { 11811 poly_int64 offset; 11812 rtx base = strip_offset_and_salt (x, &offset); 11813 if (SYMBOL_REF_P (base)) 11814 output_addr_const (f, x); 11815 else 11816 output_operand_lossage ("unsupported operand for code '%c'", code); 11817 } 11818 break; 11819 11820 case 'e': 11821 { 11822 x = unwrap_const_vec_duplicate (x); 11823 if (!CONST_INT_P (x)) 11824 { 11825 output_operand_lossage ("invalid operand for '%%%c'", code); 11826 return; 11827 } 11828 11829 HOST_WIDE_INT val = INTVAL (x); 11830 if ((val & ~7) == 8 || val == 0xff) 11831 fputc ('b', f); 11832 else if ((val & ~7) == 16 || val == 0xffff) 11833 fputc ('h', f); 11834 else if ((val & ~7) == 32 || val == 0xffffffff) 11835 fputc ('w', f); 11836 else 11837 { 11838 output_operand_lossage ("invalid operand for '%%%c'", code); 11839 return; 11840 } 11841 } 11842 break; 11843 11844 case 'p': 11845 { 11846 int n; 11847 11848 if (!CONST_INT_P (x) || (n = exact_log2 (INTVAL (x))) < 0) 11849 { 11850 output_operand_lossage ("invalid operand for '%%%c'", code); 11851 return; 11852 } 11853 11854 asm_fprintf (f, "%d", n); 11855 } 11856 break; 11857 11858 case 'P': 11859 if (!CONST_INT_P (x)) 11860 { 11861 output_operand_lossage ("invalid operand for '%%%c'", code); 11862 return; 11863 } 11864 11865 asm_fprintf (f, "%u", popcount_hwi (INTVAL (x))); 11866 break; 11867 11868 case 'H': 11869 if (x == const0_rtx) 11870 { 11871 asm_fprintf (f, "xzr"); 11872 break; 11873 } 11874 11875 if (!REG_P (x) || !GP_REGNUM_P (REGNO (x) + 1)) 11876 { 11877 output_operand_lossage ("invalid operand for '%%%c'", code); 11878 return; 11879 } 11880 11881 asm_fprintf (f, "%s", reg_names [REGNO (x) + 1]); 11882 break; 11883 11884 case 'I': 11885 { 11886 x = aarch64_bit_representation (unwrap_const_vec_duplicate (x)); 11887 if (CONST_INT_P (x)) 11888 asm_fprintf (f, "%wd", INTVAL (x)); 11889 else 11890 { 11891 output_operand_lossage ("invalid operand for '%%%c'", code); 11892 return; 11893 } 11894 break; 11895 } 11896 11897 case 'M': 11898 case 'm': 11899 { 11900 int cond_code; 11901 /* CONST_TRUE_RTX means al/nv (al is the default, don't print it). */ 11902 if (x == const_true_rtx) 11903 { 11904 if (code == 'M') 11905 fputs ("nv", f); 11906 return; 11907 } 11908 11909 if (!COMPARISON_P (x)) 11910 { 11911 output_operand_lossage ("invalid operand for '%%%c'", code); 11912 return; 11913 } 11914 11915 cond_code = aarch64_get_condition_code (x); 11916 gcc_assert (cond_code >= 0); 11917 if (code == 'M') 11918 cond_code = AARCH64_INVERSE_CONDITION_CODE (cond_code); 11919 if (GET_MODE (XEXP (x, 0)) == CC_NZCmode) 11920 fputs (aarch64_sve_condition_codes[cond_code], f); 11921 else 11922 fputs (aarch64_condition_codes[cond_code], f); 11923 } 11924 break; 11925 11926 case 'N': 11927 if (!const_vec_duplicate_p (x, &elt)) 11928 { 11929 output_operand_lossage ("invalid vector constant"); 11930 return; 11931 } 11932 11933 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_INT) 11934 asm_fprintf (f, "%wd", (HOST_WIDE_INT) -UINTVAL (elt)); 11935 else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_FLOAT 11936 && aarch64_print_vector_float_operand (f, x, true)) 11937 ; 11938 else 11939 { 11940 output_operand_lossage ("invalid vector constant"); 11941 return; 11942 } 11943 break; 11944 11945 case 'b': 11946 case 'h': 11947 case 's': 11948 case 'd': 11949 case 'q': 11950 if (!REG_P (x) || !FP_REGNUM_P (REGNO (x))) 11951 { 11952 output_operand_lossage ("incompatible floating point / vector register operand for '%%%c'", code); 11953 return; 11954 } 11955 asm_fprintf (f, "%c%d", code, REGNO (x) - V0_REGNUM); 11956 break; 11957 11958 case 'S': 11959 case 'T': 11960 case 'U': 11961 case 'V': 11962 if (!REG_P (x) || !FP_REGNUM_P (REGNO (x))) 11963 { 11964 output_operand_lossage ("incompatible floating point / vector register operand for '%%%c'", code); 11965 return; 11966 } 11967 asm_fprintf (f, "%c%d", 11968 aarch64_sve_data_mode_p (GET_MODE (x)) ? 'z' : 'v', 11969 REGNO (x) - V0_REGNUM + (code - 'S')); 11970 break; 11971 11972 case 'R': 11973 if (REG_P (x) && FP_REGNUM_P (REGNO (x)) 11974 && (aarch64_advsimd_partial_struct_mode_p (GET_MODE (x)))) 11975 asm_fprintf (f, "d%d", REGNO (x) - V0_REGNUM + 1); 11976 else if (REG_P (x) && FP_REGNUM_P (REGNO (x))) 11977 asm_fprintf (f, "q%d", REGNO (x) - V0_REGNUM + 1); 11978 else if (REG_P (x) && GP_REGNUM_P (REGNO (x))) 11979 asm_fprintf (f, "x%d", REGNO (x) - R0_REGNUM + 1); 11980 else 11981 output_operand_lossage ("incompatible register operand for '%%%c'", 11982 code); 11983 break; 11984 11985 case 'X': 11986 if (!CONST_INT_P (x)) 11987 { 11988 output_operand_lossage ("invalid operand for '%%%c'", code); 11989 return; 11990 } 11991 asm_fprintf (f, "0x%wx", UINTVAL (x) & 0xffff); 11992 break; 11993 11994 case 'C': 11995 { 11996 /* Print a replicated constant in hex. */ 11997 if (!const_vec_duplicate_p (x, &elt) || !CONST_INT_P (elt)) 11998 { 11999 output_operand_lossage ("invalid operand for '%%%c'", code); 12000 return; 12001 } 12002 scalar_mode inner_mode = GET_MODE_INNER (GET_MODE (x)); 12003 asm_fprintf (f, "0x%wx", UINTVAL (elt) & GET_MODE_MASK (inner_mode)); 12004 } 12005 break; 12006 12007 case 'D': 12008 { 12009 /* Print a replicated constant in decimal, treating it as 12010 unsigned. */ 12011 if (!const_vec_duplicate_p (x, &elt) || !CONST_INT_P (elt)) 12012 { 12013 output_operand_lossage ("invalid operand for '%%%c'", code); 12014 return; 12015 } 12016 scalar_mode inner_mode = GET_MODE_INNER (GET_MODE (x)); 12017 asm_fprintf (f, "%wd", UINTVAL (elt) & GET_MODE_MASK (inner_mode)); 12018 } 12019 break; 12020 12021 case 'w': 12022 case 'x': 12023 if (x == const0_rtx 12024 || (CONST_DOUBLE_P (x) && aarch64_float_const_zero_rtx_p (x))) 12025 { 12026 asm_fprintf (f, "%czr", code); 12027 break; 12028 } 12029 12030 if (REG_P (x) && GP_REGNUM_P (REGNO (x))) 12031 { 12032 asm_fprintf (f, "%c%d", code, REGNO (x) - R0_REGNUM); 12033 break; 12034 } 12035 12036 if (REG_P (x) && REGNO (x) == SP_REGNUM) 12037 { 12038 asm_fprintf (f, "%ssp", code == 'w' ? "w" : ""); 12039 break; 12040 } 12041 12042 /* Fall through */ 12043 12044 case 0: 12045 if (x == NULL) 12046 { 12047 output_operand_lossage ("missing operand"); 12048 return; 12049 } 12050 12051 switch (GET_CODE (x)) 12052 { 12053 case REG: 12054 if (aarch64_sve_data_mode_p (GET_MODE (x))) 12055 { 12056 if (REG_NREGS (x) == 1) 12057 asm_fprintf (f, "z%d", REGNO (x) - V0_REGNUM); 12058 else 12059 { 12060 char suffix 12061 = sizetochar (GET_MODE_UNIT_BITSIZE (GET_MODE (x))); 12062 asm_fprintf (f, "{z%d.%c - z%d.%c}", 12063 REGNO (x) - V0_REGNUM, suffix, 12064 END_REGNO (x) - V0_REGNUM - 1, suffix); 12065 } 12066 } 12067 else 12068 asm_fprintf (f, "%s", reg_names [REGNO (x)]); 12069 break; 12070 12071 case MEM: 12072 output_address (GET_MODE (x), XEXP (x, 0)); 12073 break; 12074 12075 case LABEL_REF: 12076 case SYMBOL_REF: 12077 output_addr_const (asm_out_file, x); 12078 break; 12079 12080 case CONST_INT: 12081 asm_fprintf (f, "%wd", INTVAL (x)); 12082 break; 12083 12084 case CONST: 12085 if (!VECTOR_MODE_P (GET_MODE (x))) 12086 { 12087 output_addr_const (asm_out_file, x); 12088 break; 12089 } 12090 /* fall through */ 12091 12092 case CONST_VECTOR: 12093 if (!const_vec_duplicate_p (x, &elt)) 12094 { 12095 output_operand_lossage ("invalid vector constant"); 12096 return; 12097 } 12098 12099 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_INT) 12100 asm_fprintf (f, "%wd", INTVAL (elt)); 12101 else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_FLOAT 12102 && aarch64_print_vector_float_operand (f, x, false)) 12103 ; 12104 else 12105 { 12106 output_operand_lossage ("invalid vector constant"); 12107 return; 12108 } 12109 break; 12110 12111 case CONST_DOUBLE: 12112 /* Since we define TARGET_SUPPORTS_WIDE_INT we shouldn't ever 12113 be getting CONST_DOUBLEs holding integers. */ 12114 gcc_assert (GET_MODE (x) != VOIDmode); 12115 if (aarch64_float_const_zero_rtx_p (x)) 12116 { 12117 fputc ('0', f); 12118 break; 12119 } 12120 else if (aarch64_float_const_representable_p (x)) 12121 { 12122 #define buf_size 20 12123 char float_buf[buf_size] = {'\0'}; 12124 real_to_decimal_for_mode (float_buf, 12125 CONST_DOUBLE_REAL_VALUE (x), 12126 buf_size, buf_size, 12127 1, GET_MODE (x)); 12128 asm_fprintf (asm_out_file, "%s", float_buf); 12129 break; 12130 #undef buf_size 12131 } 12132 output_operand_lossage ("invalid constant"); 12133 return; 12134 default: 12135 output_operand_lossage ("invalid operand"); 12136 return; 12137 } 12138 break; 12139 12140 case 'A': 12141 if (GET_CODE (x) == HIGH) 12142 x = XEXP (x, 0); 12143 12144 switch (aarch64_classify_symbolic_expression (x)) 12145 { 12146 case SYMBOL_SMALL_GOT_4G: 12147 asm_fprintf (asm_out_file, ":got:"); 12148 break; 12149 12150 case SYMBOL_SMALL_TLSGD: 12151 asm_fprintf (asm_out_file, ":tlsgd:"); 12152 break; 12153 12154 case SYMBOL_SMALL_TLSDESC: 12155 asm_fprintf (asm_out_file, ":tlsdesc:"); 12156 break; 12157 12158 case SYMBOL_SMALL_TLSIE: 12159 asm_fprintf (asm_out_file, ":gottprel:"); 12160 break; 12161 12162 case SYMBOL_TLSLE24: 12163 asm_fprintf (asm_out_file, ":tprel:"); 12164 break; 12165 12166 case SYMBOL_TINY_GOT: 12167 gcc_unreachable (); 12168 break; 12169 12170 default: 12171 break; 12172 } 12173 output_addr_const (asm_out_file, x); 12174 break; 12175 12176 case 'L': 12177 switch (aarch64_classify_symbolic_expression (x)) 12178 { 12179 case SYMBOL_SMALL_GOT_4G: 12180 asm_fprintf (asm_out_file, ":got_lo12:"); 12181 break; 12182 12183 case SYMBOL_SMALL_TLSGD: 12184 asm_fprintf (asm_out_file, ":tlsgd_lo12:"); 12185 break; 12186 12187 case SYMBOL_SMALL_TLSDESC: 12188 asm_fprintf (asm_out_file, ":tlsdesc_lo12:"); 12189 break; 12190 12191 case SYMBOL_SMALL_TLSIE: 12192 asm_fprintf (asm_out_file, ":gottprel_lo12:"); 12193 break; 12194 12195 case SYMBOL_TLSLE12: 12196 asm_fprintf (asm_out_file, ":tprel_lo12:"); 12197 break; 12198 12199 case SYMBOL_TLSLE24: 12200 asm_fprintf (asm_out_file, ":tprel_lo12_nc:"); 12201 break; 12202 12203 case SYMBOL_TINY_GOT: 12204 asm_fprintf (asm_out_file, ":got:"); 12205 break; 12206 12207 case SYMBOL_TINY_TLSIE: 12208 asm_fprintf (asm_out_file, ":gottprel:"); 12209 break; 12210 12211 default: 12212 break; 12213 } 12214 output_addr_const (asm_out_file, x); 12215 break; 12216 12217 case 'G': 12218 switch (aarch64_classify_symbolic_expression (x)) 12219 { 12220 case SYMBOL_TLSLE24: 12221 asm_fprintf (asm_out_file, ":tprel_hi12:"); 12222 break; 12223 default: 12224 break; 12225 } 12226 output_addr_const (asm_out_file, x); 12227 break; 12228 12229 case 'k': 12230 { 12231 HOST_WIDE_INT cond_code; 12232 12233 if (!CONST_INT_P (x)) 12234 { 12235 output_operand_lossage ("invalid operand for '%%%c'", code); 12236 return; 12237 } 12238 12239 cond_code = INTVAL (x); 12240 gcc_assert (cond_code >= 0 && cond_code <= AARCH64_NV); 12241 asm_fprintf (f, "%d", aarch64_nzcv_codes[cond_code]); 12242 } 12243 break; 12244 12245 case 'y': 12246 case 'z': 12247 { 12248 machine_mode mode = GET_MODE (x); 12249 12250 if (!MEM_P (x) 12251 || (code == 'y' 12252 && maybe_ne (GET_MODE_SIZE (mode), 8) 12253 && maybe_ne (GET_MODE_SIZE (mode), 16))) 12254 { 12255 output_operand_lossage ("invalid operand for '%%%c'", code); 12256 return; 12257 } 12258 12259 if (!aarch64_print_address_internal (f, mode, XEXP (x, 0), 12260 code == 'y' 12261 ? ADDR_QUERY_LDP_STP_N 12262 : ADDR_QUERY_LDP_STP)) 12263 output_operand_lossage ("invalid operand prefix '%%%c'", code); 12264 } 12265 break; 12266 12267 default: 12268 output_operand_lossage ("invalid operand prefix '%%%c'", code); 12269 return; 12270 } 12271 } 12272 12273 /* Print address 'x' of a memory access with mode 'mode'. 12274 'op' is the context required by aarch64_classify_address. It can either be 12275 MEM for a normal memory access or PARALLEL for LDP/STP. */ 12276 static bool 12277 aarch64_print_address_internal (FILE *f, machine_mode mode, rtx x, 12278 aarch64_addr_query_type type) 12279 { 12280 struct aarch64_address_info addr; 12281 unsigned int size, vec_flags; 12282 12283 /* Check all addresses are Pmode - including ILP32. */ 12284 if (GET_MODE (x) != Pmode 12285 && (!CONST_INT_P (x) 12286 || trunc_int_for_mode (INTVAL (x), Pmode) != INTVAL (x))) 12287 { 12288 output_operand_lossage ("invalid address mode"); 12289 return false; 12290 } 12291 12292 if (aarch64_classify_address (&addr, x, mode, true, type)) 12293 switch (addr.type) 12294 { 12295 case ADDRESS_REG_IMM: 12296 if (known_eq (addr.const_offset, 0)) 12297 { 12298 asm_fprintf (f, "[%s]", reg_names[REGNO (addr.base)]); 12299 return true; 12300 } 12301 12302 vec_flags = aarch64_classify_vector_mode (mode); 12303 if (vec_flags & VEC_ANY_SVE) 12304 { 12305 HOST_WIDE_INT vnum 12306 = exact_div (addr.const_offset, 12307 aarch64_vl_bytes (mode, vec_flags)).to_constant (); 12308 asm_fprintf (f, "[%s, #%wd, mul vl]", 12309 reg_names[REGNO (addr.base)], vnum); 12310 return true; 12311 } 12312 12313 asm_fprintf (f, "[%s, %wd]", reg_names[REGNO (addr.base)], 12314 INTVAL (addr.offset)); 12315 return true; 12316 12317 case ADDRESS_REG_REG: 12318 if (addr.shift == 0) 12319 asm_fprintf (f, "[%s, %s]", reg_names [REGNO (addr.base)], 12320 reg_names [REGNO (addr.offset)]); 12321 else 12322 asm_fprintf (f, "[%s, %s, lsl %u]", reg_names [REGNO (addr.base)], 12323 reg_names [REGNO (addr.offset)], addr.shift); 12324 return true; 12325 12326 case ADDRESS_REG_UXTW: 12327 if (addr.shift == 0) 12328 asm_fprintf (f, "[%s, w%d, uxtw]", reg_names [REGNO (addr.base)], 12329 REGNO (addr.offset) - R0_REGNUM); 12330 else 12331 asm_fprintf (f, "[%s, w%d, uxtw %u]", reg_names [REGNO (addr.base)], 12332 REGNO (addr.offset) - R0_REGNUM, addr.shift); 12333 return true; 12334 12335 case ADDRESS_REG_SXTW: 12336 if (addr.shift == 0) 12337 asm_fprintf (f, "[%s, w%d, sxtw]", reg_names [REGNO (addr.base)], 12338 REGNO (addr.offset) - R0_REGNUM); 12339 else 12340 asm_fprintf (f, "[%s, w%d, sxtw %u]", reg_names [REGNO (addr.base)], 12341 REGNO (addr.offset) - R0_REGNUM, addr.shift); 12342 return true; 12343 12344 case ADDRESS_REG_WB: 12345 /* Writeback is only supported for fixed-width modes. */ 12346 size = GET_MODE_SIZE (mode).to_constant (); 12347 switch (GET_CODE (x)) 12348 { 12349 case PRE_INC: 12350 asm_fprintf (f, "[%s, %d]!", reg_names [REGNO (addr.base)], size); 12351 return true; 12352 case POST_INC: 12353 asm_fprintf (f, "[%s], %d", reg_names [REGNO (addr.base)], size); 12354 return true; 12355 case PRE_DEC: 12356 asm_fprintf (f, "[%s, -%d]!", reg_names [REGNO (addr.base)], size); 12357 return true; 12358 case POST_DEC: 12359 asm_fprintf (f, "[%s], -%d", reg_names [REGNO (addr.base)], size); 12360 return true; 12361 case PRE_MODIFY: 12362 asm_fprintf (f, "[%s, %wd]!", reg_names[REGNO (addr.base)], 12363 INTVAL (addr.offset)); 12364 return true; 12365 case POST_MODIFY: 12366 asm_fprintf (f, "[%s], %wd", reg_names[REGNO (addr.base)], 12367 INTVAL (addr.offset)); 12368 return true; 12369 default: 12370 break; 12371 } 12372 break; 12373 12374 case ADDRESS_LO_SUM: 12375 asm_fprintf (f, "[%s, #:lo12:", reg_names [REGNO (addr.base)]); 12376 output_addr_const (f, addr.offset); 12377 asm_fprintf (f, "]"); 12378 return true; 12379 12380 case ADDRESS_SYMBOLIC: 12381 output_addr_const (f, x); 12382 return true; 12383 } 12384 12385 return false; 12386 } 12387 12388 /* Print address 'x' of a memory access with mode 'mode'. */ 12389 static void 12390 aarch64_print_operand_address (FILE *f, machine_mode mode, rtx x) 12391 { 12392 if (!aarch64_print_address_internal (f, mode, x, ADDR_QUERY_ANY)) 12393 output_addr_const (f, x); 12394 } 12395 12396 /* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */ 12397 12398 static bool 12399 aarch64_output_addr_const_extra (FILE *file, rtx x) 12400 { 12401 if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_SALT_ADDR) 12402 { 12403 output_addr_const (file, XVECEXP (x, 0, 0)); 12404 return true; 12405 } 12406 return false; 12407 } 12408 12409 bool 12410 aarch64_label_mentioned_p (rtx x) 12411 { 12412 const char *fmt; 12413 int i; 12414 12415 if (LABEL_REF_P (x)) 12416 return true; 12417 12418 /* UNSPEC_TLS entries for a symbol include a LABEL_REF for the 12419 referencing instruction, but they are constant offsets, not 12420 symbols. */ 12421 if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS) 12422 return false; 12423 12424 fmt = GET_RTX_FORMAT (GET_CODE (x)); 12425 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) 12426 { 12427 if (fmt[i] == 'E') 12428 { 12429 int j; 12430 12431 for (j = XVECLEN (x, i) - 1; j >= 0; j--) 12432 if (aarch64_label_mentioned_p (XVECEXP (x, i, j))) 12433 return 1; 12434 } 12435 else if (fmt[i] == 'e' && aarch64_label_mentioned_p (XEXP (x, i))) 12436 return 1; 12437 } 12438 12439 return 0; 12440 } 12441 12442 /* Implement REGNO_REG_CLASS. */ 12443 12444 enum reg_class 12445 aarch64_regno_regclass (unsigned regno) 12446 { 12447 if (STUB_REGNUM_P (regno)) 12448 return STUB_REGS; 12449 12450 if (GP_REGNUM_P (regno)) 12451 return GENERAL_REGS; 12452 12453 if (regno == SP_REGNUM) 12454 return STACK_REG; 12455 12456 if (regno == FRAME_POINTER_REGNUM 12457 || regno == ARG_POINTER_REGNUM) 12458 return POINTER_REGS; 12459 12460 if (FP_REGNUM_P (regno)) 12461 return (FP_LO8_REGNUM_P (regno) ? FP_LO8_REGS 12462 : FP_LO_REGNUM_P (regno) ? FP_LO_REGS : FP_REGS); 12463 12464 if (PR_REGNUM_P (regno)) 12465 return PR_LO_REGNUM_P (regno) ? PR_LO_REGS : PR_HI_REGS; 12466 12467 if (regno == FFR_REGNUM || regno == FFRT_REGNUM) 12468 return FFR_REGS; 12469 12470 return NO_REGS; 12471 } 12472 12473 /* OFFSET is an address offset for mode MODE, which has SIZE bytes. 12474 If OFFSET is out of range, return an offset of an anchor point 12475 that is in range. Return 0 otherwise. */ 12476 12477 static HOST_WIDE_INT 12478 aarch64_anchor_offset (HOST_WIDE_INT offset, HOST_WIDE_INT size, 12479 machine_mode mode) 12480 { 12481 /* Does it look like we'll need a 16-byte load/store-pair operation? */ 12482 if (size > 16) 12483 return (offset + 0x400) & ~0x7f0; 12484 12485 /* For offsets that aren't a multiple of the access size, the limit is 12486 -256...255. */ 12487 if (offset & (size - 1)) 12488 { 12489 /* BLKmode typically uses LDP of X-registers. */ 12490 if (mode == BLKmode) 12491 return (offset + 512) & ~0x3ff; 12492 return (offset + 0x100) & ~0x1ff; 12493 } 12494 12495 /* Small negative offsets are supported. */ 12496 if (IN_RANGE (offset, -256, 0)) 12497 return 0; 12498 12499 if (mode == TImode || mode == TFmode) 12500 return (offset + 0x100) & ~0x1ff; 12501 12502 /* Use 12-bit offset by access size. */ 12503 return offset & (~0xfff * size); 12504 } 12505 12506 static rtx 12507 aarch64_legitimize_address (rtx x, rtx /* orig_x */, machine_mode mode) 12508 { 12509 /* Try to split X+CONST into Y=X+(CONST & ~mask), Y+(CONST&mask), 12510 where mask is selected by alignment and size of the offset. 12511 We try to pick as large a range for the offset as possible to 12512 maximize the chance of a CSE. However, for aligned addresses 12513 we limit the range to 4k so that structures with different sized 12514 elements are likely to use the same base. We need to be careful 12515 not to split a CONST for some forms of address expression, otherwise 12516 it will generate sub-optimal code. */ 12517 12518 if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1))) 12519 { 12520 rtx base = XEXP (x, 0); 12521 rtx offset_rtx = XEXP (x, 1); 12522 HOST_WIDE_INT offset = INTVAL (offset_rtx); 12523 12524 if (GET_CODE (base) == PLUS) 12525 { 12526 rtx op0 = XEXP (base, 0); 12527 rtx op1 = XEXP (base, 1); 12528 12529 /* Force any scaling into a temp for CSE. */ 12530 op0 = force_reg (Pmode, op0); 12531 op1 = force_reg (Pmode, op1); 12532 12533 /* Let the pointer register be in op0. */ 12534 if (REG_POINTER (op1)) 12535 std::swap (op0, op1); 12536 12537 /* If the pointer is virtual or frame related, then we know that 12538 virtual register instantiation or register elimination is going 12539 to apply a second constant. We want the two constants folded 12540 together easily. Therefore, emit as (OP0 + CONST) + OP1. */ 12541 if (virt_or_elim_regno_p (REGNO (op0))) 12542 { 12543 base = expand_binop (Pmode, add_optab, op0, offset_rtx, 12544 NULL_RTX, true, OPTAB_DIRECT); 12545 return gen_rtx_PLUS (Pmode, base, op1); 12546 } 12547 12548 /* Otherwise, in order to encourage CSE (and thence loop strength 12549 reduce) scaled addresses, emit as (OP0 + OP1) + CONST. */ 12550 base = expand_binop (Pmode, add_optab, op0, op1, 12551 NULL_RTX, true, OPTAB_DIRECT); 12552 x = gen_rtx_PLUS (Pmode, base, offset_rtx); 12553 } 12554 12555 HOST_WIDE_INT size; 12556 if (GET_MODE_SIZE (mode).is_constant (&size)) 12557 { 12558 HOST_WIDE_INT base_offset = aarch64_anchor_offset (offset, size, 12559 mode); 12560 if (base_offset != 0) 12561 { 12562 base = plus_constant (Pmode, base, base_offset); 12563 base = force_operand (base, NULL_RTX); 12564 return plus_constant (Pmode, base, offset - base_offset); 12565 } 12566 } 12567 } 12568 12569 return x; 12570 } 12571 12572 static reg_class_t 12573 aarch64_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, 12574 reg_class_t rclass, 12575 machine_mode mode, 12576 secondary_reload_info *sri) 12577 { 12578 /* Use aarch64_sve_reload_mem for SVE memory reloads that cannot use 12579 LDR and STR. See the comment at the head of aarch64-sve.md for 12580 more details about the big-endian handling. */ 12581 if (reg_class_subset_p (rclass, FP_REGS) 12582 && !((REG_P (x) && HARD_REGISTER_P (x)) 12583 || aarch64_simd_valid_immediate (x, NULL)) 12584 && mode != VNx16QImode) 12585 { 12586 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 12587 if ((vec_flags & VEC_SVE_DATA) 12588 && ((vec_flags & VEC_PARTIAL) || BYTES_BIG_ENDIAN)) 12589 { 12590 sri->icode = CODE_FOR_aarch64_sve_reload_mem; 12591 return NO_REGS; 12592 } 12593 } 12594 12595 /* If we have to disable direct literal pool loads and stores because the 12596 function is too big, then we need a scratch register. */ 12597 if (MEM_P (x) && SYMBOL_REF_P (x) && CONSTANT_POOL_ADDRESS_P (x) 12598 && (SCALAR_FLOAT_MODE_P (GET_MODE (x)) 12599 || targetm.vector_mode_supported_p (GET_MODE (x))) 12600 && !aarch64_pcrelative_literal_loads) 12601 { 12602 sri->icode = code_for_aarch64_reload_movcp (mode, DImode); 12603 return NO_REGS; 12604 } 12605 12606 /* Without the TARGET_SIMD instructions we cannot move a Q register 12607 to a Q register directly. We need a scratch. */ 12608 if (REG_P (x) && (mode == TFmode || mode == TImode) && mode == GET_MODE (x) 12609 && FP_REGNUM_P (REGNO (x)) && !TARGET_SIMD 12610 && reg_class_subset_p (rclass, FP_REGS)) 12611 { 12612 sri->icode = code_for_aarch64_reload_mov (mode); 12613 return NO_REGS; 12614 } 12615 12616 /* A TFmode or TImode memory access should be handled via an FP_REGS 12617 because AArch64 has richer addressing modes for LDR/STR instructions 12618 than LDP/STP instructions. */ 12619 if (TARGET_FLOAT && rclass == GENERAL_REGS 12620 && known_eq (GET_MODE_SIZE (mode), 16) && MEM_P (x)) 12621 return FP_REGS; 12622 12623 if (rclass == FP_REGS && (mode == TImode || mode == TFmode) && CONSTANT_P(x)) 12624 return GENERAL_REGS; 12625 12626 return NO_REGS; 12627 } 12628 12629 static bool 12630 aarch64_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) 12631 { 12632 gcc_assert (from == ARG_POINTER_REGNUM || from == FRAME_POINTER_REGNUM); 12633 12634 /* If we need a frame pointer, ARG_POINTER_REGNUM and FRAME_POINTER_REGNUM 12635 can only eliminate to HARD_FRAME_POINTER_REGNUM. */ 12636 if (frame_pointer_needed) 12637 return to == HARD_FRAME_POINTER_REGNUM; 12638 return true; 12639 } 12640 12641 poly_int64 12642 aarch64_initial_elimination_offset (unsigned from, unsigned to) 12643 { 12644 aarch64_frame &frame = cfun->machine->frame; 12645 12646 if (to == HARD_FRAME_POINTER_REGNUM) 12647 { 12648 if (from == ARG_POINTER_REGNUM) 12649 return frame.bytes_above_hard_fp; 12650 12651 if (from == FRAME_POINTER_REGNUM) 12652 return frame.bytes_above_hard_fp - frame.bytes_above_locals; 12653 } 12654 12655 if (to == STACK_POINTER_REGNUM) 12656 { 12657 if (from == FRAME_POINTER_REGNUM) 12658 return frame.frame_size - frame.bytes_above_locals; 12659 } 12660 12661 return frame.frame_size; 12662 } 12663 12664 12665 /* Get return address without mangling. */ 12666 12667 rtx 12668 aarch64_return_addr_rtx (void) 12669 { 12670 rtx val = get_hard_reg_initial_val (Pmode, LR_REGNUM); 12671 /* Note: aarch64_return_address_signing_enabled only 12672 works after cfun->machine->frame.laid_out is set, 12673 so here we don't know if the return address will 12674 be signed or not. */ 12675 rtx lr = gen_rtx_REG (Pmode, LR_REGNUM); 12676 emit_move_insn (lr, val); 12677 emit_insn (GEN_FCN (CODE_FOR_xpaclri) ()); 12678 return lr; 12679 } 12680 12681 12682 /* Implement RETURN_ADDR_RTX. We do not support moving back to a 12683 previous frame. */ 12684 12685 rtx 12686 aarch64_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) 12687 { 12688 if (count != 0) 12689 return const0_rtx; 12690 return aarch64_return_addr_rtx (); 12691 } 12692 12693 static void 12694 aarch64_asm_trampoline_template (FILE *f) 12695 { 12696 /* Even if the current function doesn't have branch protection, some 12697 later function might, so since this template is only generated once 12698 we have to add a BTI just in case. */ 12699 asm_fprintf (f, "\thint\t34 // bti c\n"); 12700 12701 if (TARGET_ILP32) 12702 { 12703 asm_fprintf (f, "\tldr\tw%d, .+20\n", IP1_REGNUM - R0_REGNUM); 12704 asm_fprintf (f, "\tldr\tw%d, .+20\n", STATIC_CHAIN_REGNUM - R0_REGNUM); 12705 } 12706 else 12707 { 12708 asm_fprintf (f, "\tldr\t%s, .+20\n", reg_names [IP1_REGNUM]); 12709 asm_fprintf (f, "\tldr\t%s, .+24\n", reg_names [STATIC_CHAIN_REGNUM]); 12710 } 12711 asm_fprintf (f, "\tbr\t%s\n", reg_names [IP1_REGNUM]); 12712 12713 /* We always emit a speculation barrier. 12714 This is because the same trampoline template is used for every nested 12715 function. Since nested functions are not particularly common or 12716 performant we don't worry too much about the extra instructions to copy 12717 around. 12718 This is not yet a problem, since we have not yet implemented function 12719 specific attributes to choose between hardening against straight line 12720 speculation or not, but such function specific attributes are likely to 12721 happen in the future. */ 12722 asm_fprintf (f, "\tdsb\tsy\n\tisb\n"); 12723 12724 assemble_aligned_integer (POINTER_BYTES, const0_rtx); 12725 assemble_aligned_integer (POINTER_BYTES, const0_rtx); 12726 } 12727 12728 static void 12729 aarch64_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) 12730 { 12731 rtx fnaddr, mem, a_tramp; 12732 const int tramp_code_sz = 24; 12733 12734 /* Don't need to copy the trailing D-words, we fill those in below. */ 12735 /* We create our own memory address in Pmode so that `emit_block_move` can 12736 use parts of the backend which expect Pmode addresses. */ 12737 rtx temp = convert_memory_address (Pmode, XEXP (m_tramp, 0)); 12738 emit_block_move (gen_rtx_MEM (BLKmode, temp), 12739 assemble_trampoline_template (), 12740 GEN_INT (tramp_code_sz), BLOCK_OP_NORMAL); 12741 mem = adjust_address (m_tramp, ptr_mode, tramp_code_sz); 12742 fnaddr = XEXP (DECL_RTL (fndecl), 0); 12743 if (GET_MODE (fnaddr) != ptr_mode) 12744 fnaddr = convert_memory_address (ptr_mode, fnaddr); 12745 emit_move_insn (mem, fnaddr); 12746 12747 mem = adjust_address (m_tramp, ptr_mode, tramp_code_sz + POINTER_BYTES); 12748 emit_move_insn (mem, chain_value); 12749 12750 /* XXX We should really define a "clear_cache" pattern and use 12751 gen_clear_cache(). */ 12752 a_tramp = XEXP (m_tramp, 0); 12753 maybe_emit_call_builtin___clear_cache (a_tramp, 12754 plus_constant (ptr_mode, 12755 a_tramp, 12756 TRAMPOLINE_SIZE)); 12757 } 12758 12759 static unsigned char 12760 aarch64_class_max_nregs (reg_class_t regclass, machine_mode mode) 12761 { 12762 /* ??? Logically we should only need to provide a value when 12763 HARD_REGNO_MODE_OK says that at least one register in REGCLASS 12764 can hold MODE, but at the moment we need to handle all modes. 12765 Just ignore any runtime parts for registers that can't store them. */ 12766 HOST_WIDE_INT lowest_size = constant_lower_bound (GET_MODE_SIZE (mode)); 12767 unsigned int nregs, vec_flags; 12768 switch (regclass) 12769 { 12770 case STUB_REGS: 12771 case TAILCALL_ADDR_REGS: 12772 case POINTER_REGS: 12773 case GENERAL_REGS: 12774 case ALL_REGS: 12775 case POINTER_AND_FP_REGS: 12776 case FP_REGS: 12777 case FP_LO_REGS: 12778 case FP_LO8_REGS: 12779 vec_flags = aarch64_classify_vector_mode (mode); 12780 if ((vec_flags & VEC_SVE_DATA) 12781 && constant_multiple_p (GET_MODE_SIZE (mode), 12782 aarch64_vl_bytes (mode, vec_flags), &nregs)) 12783 return nregs; 12784 return (vec_flags & VEC_ADVSIMD 12785 ? CEIL (lowest_size, UNITS_PER_VREG) 12786 : CEIL (lowest_size, UNITS_PER_WORD)); 12787 case STACK_REG: 12788 case PR_REGS: 12789 case PR_LO_REGS: 12790 case PR_HI_REGS: 12791 case FFR_REGS: 12792 case PR_AND_FFR_REGS: 12793 return 1; 12794 12795 case NO_REGS: 12796 return 0; 12797 12798 default: 12799 break; 12800 } 12801 gcc_unreachable (); 12802 } 12803 12804 static reg_class_t 12805 aarch64_preferred_reload_class (rtx x, reg_class_t regclass) 12806 { 12807 if (regclass == POINTER_REGS) 12808 return GENERAL_REGS; 12809 12810 if (regclass == STACK_REG) 12811 { 12812 if (REG_P(x) 12813 && reg_class_subset_p (REGNO_REG_CLASS (REGNO (x)), POINTER_REGS)) 12814 return regclass; 12815 12816 return NO_REGS; 12817 } 12818 12819 /* Register eliminiation can result in a request for 12820 SP+constant->FP_REGS. We cannot support such operations which 12821 use SP as source and an FP_REG as destination, so reject out 12822 right now. */ 12823 if (! reg_class_subset_p (regclass, GENERAL_REGS) && GET_CODE (x) == PLUS) 12824 { 12825 rtx lhs = XEXP (x, 0); 12826 12827 /* Look through a possible SUBREG introduced by ILP32. */ 12828 if (SUBREG_P (lhs)) 12829 lhs = SUBREG_REG (lhs); 12830 12831 gcc_assert (REG_P (lhs)); 12832 gcc_assert (reg_class_subset_p (REGNO_REG_CLASS (REGNO (lhs)), 12833 POINTER_REGS)); 12834 return NO_REGS; 12835 } 12836 12837 return regclass; 12838 } 12839 12840 void 12841 aarch64_asm_output_labelref (FILE* f, const char *name) 12842 { 12843 asm_fprintf (f, "%U%s", name); 12844 } 12845 12846 static void 12847 aarch64_elf_asm_constructor (rtx symbol, int priority) 12848 { 12849 if (priority == DEFAULT_INIT_PRIORITY) 12850 default_ctor_section_asm_out_constructor (symbol, priority); 12851 else 12852 { 12853 section *s; 12854 /* While priority is known to be in range [0, 65535], so 18 bytes 12855 would be enough, the compiler might not know that. To avoid 12856 -Wformat-truncation false positive, use a larger size. */ 12857 char buf[23]; 12858 snprintf (buf, sizeof (buf), ".init_array.%.5u", priority); 12859 s = get_section (buf, SECTION_WRITE | SECTION_NOTYPE, NULL); 12860 switch_to_section (s); 12861 assemble_align (POINTER_SIZE); 12862 assemble_aligned_integer (POINTER_BYTES, symbol); 12863 } 12864 } 12865 12866 static void 12867 aarch64_elf_asm_destructor (rtx symbol, int priority) 12868 { 12869 if (priority == DEFAULT_INIT_PRIORITY) 12870 default_dtor_section_asm_out_destructor (symbol, priority); 12871 else 12872 { 12873 section *s; 12874 /* While priority is known to be in range [0, 65535], so 18 bytes 12875 would be enough, the compiler might not know that. To avoid 12876 -Wformat-truncation false positive, use a larger size. */ 12877 char buf[23]; 12878 snprintf (buf, sizeof (buf), ".fini_array.%.5u", priority); 12879 s = get_section (buf, SECTION_WRITE | SECTION_NOTYPE, NULL); 12880 switch_to_section (s); 12881 assemble_align (POINTER_SIZE); 12882 assemble_aligned_integer (POINTER_BYTES, symbol); 12883 } 12884 } 12885 12886 const char* 12887 aarch64_output_casesi (rtx *operands) 12888 { 12889 char buf[100]; 12890 char label[100]; 12891 rtx diff_vec = PATTERN (NEXT_INSN (as_a <rtx_insn *> (operands[2]))); 12892 int index; 12893 static const char *const patterns[4][2] = 12894 { 12895 { 12896 "ldrb\t%w3, [%0,%w1,uxtw]", 12897 "add\t%3, %4, %w3, sxtb #2" 12898 }, 12899 { 12900 "ldrh\t%w3, [%0,%w1,uxtw #1]", 12901 "add\t%3, %4, %w3, sxth #2" 12902 }, 12903 { 12904 "ldr\t%w3, [%0,%w1,uxtw #2]", 12905 "add\t%3, %4, %w3, sxtw #2" 12906 }, 12907 /* We assume that DImode is only generated when not optimizing and 12908 that we don't really need 64-bit address offsets. That would 12909 imply an object file with 8GB of code in a single function! */ 12910 { 12911 "ldr\t%w3, [%0,%w1,uxtw #2]", 12912 "add\t%3, %4, %w3, sxtw #2" 12913 } 12914 }; 12915 12916 gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); 12917 12918 scalar_int_mode mode = as_a <scalar_int_mode> (GET_MODE (diff_vec)); 12919 index = exact_log2 (GET_MODE_SIZE (mode)); 12920 12921 gcc_assert (index >= 0 && index <= 3); 12922 12923 /* Need to implement table size reduction, by chaning the code below. */ 12924 output_asm_insn (patterns[index][0], operands); 12925 ASM_GENERATE_INTERNAL_LABEL (label, "Lrtx", CODE_LABEL_NUMBER (operands[2])); 12926 snprintf (buf, sizeof (buf), 12927 "adr\t%%4, %s", targetm.strip_name_encoding (label)); 12928 output_asm_insn (buf, operands); 12929 output_asm_insn (patterns[index][1], operands); 12930 output_asm_insn ("br\t%3", operands); 12931 output_asm_insn (aarch64_sls_barrier (aarch64_harden_sls_retbr_p ()), 12932 operands); 12933 assemble_label (asm_out_file, label); 12934 return ""; 12935 } 12936 12937 12938 /* Return size in bits of an arithmetic operand which is shifted/scaled and 12939 masked such that it is suitable for a UXTB, UXTH, or UXTW extend 12940 operator. */ 12941 12942 int 12943 aarch64_uxt_size (int shift, HOST_WIDE_INT mask) 12944 { 12945 if (shift >= 0 && shift <= 3) 12946 { 12947 int size; 12948 for (size = 8; size <= 32; size *= 2) 12949 { 12950 HOST_WIDE_INT bits = ((HOST_WIDE_INT)1U << size) - 1; 12951 if (mask == bits << shift) 12952 return size; 12953 } 12954 } 12955 return 0; 12956 } 12957 12958 /* Constant pools are per function only when PC relative 12959 literal loads are true or we are in the large memory 12960 model. */ 12961 12962 static inline bool 12963 aarch64_can_use_per_function_literal_pools_p (void) 12964 { 12965 return (aarch64_pcrelative_literal_loads 12966 || aarch64_cmodel == AARCH64_CMODEL_LARGE); 12967 } 12968 12969 static bool 12970 aarch64_use_blocks_for_constant_p (machine_mode, const_rtx) 12971 { 12972 /* We can't use blocks for constants when we're using a per-function 12973 constant pool. */ 12974 return !aarch64_can_use_per_function_literal_pools_p (); 12975 } 12976 12977 /* Select appropriate section for constants depending 12978 on where we place literal pools. */ 12979 12980 static section * 12981 aarch64_select_rtx_section (machine_mode mode, 12982 rtx x, 12983 unsigned HOST_WIDE_INT align) 12984 { 12985 if (aarch64_can_use_per_function_literal_pools_p ()) 12986 return function_section (current_function_decl); 12987 12988 return default_elf_select_rtx_section (mode, x, align); 12989 } 12990 12991 /* Implement ASM_OUTPUT_POOL_EPILOGUE. */ 12992 void 12993 aarch64_asm_output_pool_epilogue (FILE *f, const char *, tree, 12994 HOST_WIDE_INT offset) 12995 { 12996 /* When using per-function literal pools, we must ensure that any code 12997 section is aligned to the minimal instruction length, lest we get 12998 errors from the assembler re "unaligned instructions". */ 12999 if ((offset & 3) && aarch64_can_use_per_function_literal_pools_p ()) 13000 ASM_OUTPUT_ALIGN (f, 2); 13001 } 13002 13003 /* Costs. */ 13004 13005 /* Helper function for rtx cost calculation. Strip a shift expression 13006 from X. Returns the inner operand if successful, or the original 13007 expression on failure. */ 13008 static rtx 13009 aarch64_strip_shift (rtx x) 13010 { 13011 rtx op = x; 13012 13013 /* We accept both ROTATERT and ROTATE: since the RHS must be a constant 13014 we can convert both to ROR during final output. */ 13015 if ((GET_CODE (op) == ASHIFT 13016 || GET_CODE (op) == ASHIFTRT 13017 || GET_CODE (op) == LSHIFTRT 13018 || GET_CODE (op) == ROTATERT 13019 || GET_CODE (op) == ROTATE) 13020 && CONST_INT_P (XEXP (op, 1))) 13021 return XEXP (op, 0); 13022 13023 if (GET_CODE (op) == MULT 13024 && CONST_INT_P (XEXP (op, 1)) 13025 && ((unsigned) exact_log2 (INTVAL (XEXP (op, 1)))) < 64) 13026 return XEXP (op, 0); 13027 13028 return x; 13029 } 13030 13031 /* Helper function for rtx cost calculation. Strip an extend 13032 expression from X. Returns the inner operand if successful, or the 13033 original expression on failure. We deal with a number of possible 13034 canonicalization variations here. If STRIP_SHIFT is true, then 13035 we can strip off a shift also. */ 13036 static rtx 13037 aarch64_strip_extend (rtx x, bool strip_shift) 13038 { 13039 scalar_int_mode mode; 13040 rtx op = x; 13041 13042 if (!is_a <scalar_int_mode> (GET_MODE (op), &mode)) 13043 return op; 13044 13045 if (GET_CODE (op) == AND 13046 && GET_CODE (XEXP (op, 0)) == MULT 13047 && CONST_INT_P (XEXP (XEXP (op, 0), 1)) 13048 && CONST_INT_P (XEXP (op, 1)) 13049 && aarch64_uxt_size (exact_log2 (INTVAL (XEXP (XEXP (op, 0), 1))), 13050 INTVAL (XEXP (op, 1))) != 0) 13051 return XEXP (XEXP (op, 0), 0); 13052 13053 /* Now handle extended register, as this may also have an optional 13054 left shift by 1..4. */ 13055 if (strip_shift 13056 && GET_CODE (op) == ASHIFT 13057 && CONST_INT_P (XEXP (op, 1)) 13058 && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) <= 4) 13059 op = XEXP (op, 0); 13060 13061 if (GET_CODE (op) == ZERO_EXTEND 13062 || GET_CODE (op) == SIGN_EXTEND) 13063 op = XEXP (op, 0); 13064 13065 if (op != x) 13066 return op; 13067 13068 return x; 13069 } 13070 13071 /* Helper function for rtx cost calculation. Strip extension as well as any 13072 inner VEC_SELECT high-half from X. Returns the inner vector operand if 13073 successful, or the original expression on failure. */ 13074 static rtx 13075 aarch64_strip_extend_vec_half (rtx x) 13076 { 13077 if (GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND) 13078 { 13079 x = XEXP (x, 0); 13080 if (GET_CODE (x) == VEC_SELECT 13081 && vec_series_highpart_p (GET_MODE (x), GET_MODE (XEXP (x, 0)), 13082 XEXP (x, 1))) 13083 x = XEXP (x, 0); 13084 } 13085 return x; 13086 } 13087 13088 /* Helper function for rtx cost calculation. Strip VEC_DUPLICATE as well as 13089 any subsequent extend and VEC_SELECT from X. Returns the inner scalar 13090 operand if successful, or the original expression on failure. */ 13091 static rtx 13092 aarch64_strip_duplicate_vec_elt (rtx x) 13093 { 13094 if (GET_CODE (x) == VEC_DUPLICATE 13095 && is_a<scalar_mode> (GET_MODE (XEXP (x, 0)))) 13096 { 13097 x = XEXP (x, 0); 13098 if (GET_CODE (x) == VEC_SELECT) 13099 x = XEXP (x, 0); 13100 else if ((GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND) 13101 && GET_CODE (XEXP (x, 0)) == VEC_SELECT) 13102 x = XEXP (XEXP (x, 0), 0); 13103 } 13104 return x; 13105 } 13106 13107 /* Return true iff CODE is a shift supported in combination 13108 with arithmetic instructions. */ 13109 13110 static bool 13111 aarch64_shift_p (enum rtx_code code) 13112 { 13113 return code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT; 13114 } 13115 13116 13117 /* Return true iff X is a cheap shift without a sign extend. */ 13118 13119 static bool 13120 aarch64_cheap_mult_shift_p (rtx x) 13121 { 13122 rtx op0, op1; 13123 13124 op0 = XEXP (x, 0); 13125 op1 = XEXP (x, 1); 13126 13127 if (!(aarch64_tune_params.extra_tuning_flags 13128 & AARCH64_EXTRA_TUNE_CHEAP_SHIFT_EXTEND)) 13129 return false; 13130 13131 if (GET_CODE (op0) == SIGN_EXTEND) 13132 return false; 13133 13134 if (GET_CODE (x) == ASHIFT && CONST_INT_P (op1) 13135 && UINTVAL (op1) <= 4) 13136 return true; 13137 13138 if (GET_CODE (x) != MULT || !CONST_INT_P (op1)) 13139 return false; 13140 13141 HOST_WIDE_INT l2 = exact_log2 (INTVAL (op1)); 13142 13143 if (l2 > 0 && l2 <= 4) 13144 return true; 13145 13146 return false; 13147 } 13148 13149 /* Helper function for rtx cost calculation. Calculate the cost of 13150 a MULT or ASHIFT, which may be part of a compound PLUS/MINUS rtx. 13151 Return the calculated cost of the expression, recursing manually in to 13152 operands where needed. */ 13153 13154 static int 13155 aarch64_rtx_mult_cost (rtx x, enum rtx_code code, int outer, bool speed) 13156 { 13157 rtx op0, op1; 13158 const struct cpu_cost_table *extra_cost 13159 = aarch64_tune_params.insn_extra_cost; 13160 int cost = 0; 13161 bool compound_p = (outer == PLUS || outer == MINUS); 13162 machine_mode mode = GET_MODE (x); 13163 13164 gcc_checking_assert (code == MULT); 13165 13166 op0 = XEXP (x, 0); 13167 op1 = XEXP (x, 1); 13168 13169 if (VECTOR_MODE_P (mode)) 13170 { 13171 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 13172 if (vec_flags & VEC_ADVSIMD) 13173 { 13174 /* The select-operand-high-half versions of the instruction have the 13175 same cost as the three vector version - don't add the costs of the 13176 extension or selection into the costs of the multiply. */ 13177 op0 = aarch64_strip_extend_vec_half (op0); 13178 op1 = aarch64_strip_extend_vec_half (op1); 13179 /* The by-element versions of the instruction have the same costs as 13180 the normal 3-vector version. We make an assumption that the input 13181 to the VEC_DUPLICATE is already on the FP & SIMD side. This means 13182 costing of a MUL by element pre RA is a bit optimistic. */ 13183 op0 = aarch64_strip_duplicate_vec_elt (op0); 13184 op1 = aarch64_strip_duplicate_vec_elt (op1); 13185 } 13186 cost += rtx_cost (op0, mode, MULT, 0, speed); 13187 cost += rtx_cost (op1, mode, MULT, 1, speed); 13188 if (speed) 13189 { 13190 if (GET_CODE (x) == MULT) 13191 cost += extra_cost->vect.mult; 13192 /* This is to catch the SSRA costing currently flowing here. */ 13193 else 13194 cost += extra_cost->vect.alu; 13195 } 13196 return cost; 13197 } 13198 13199 /* Integer multiply/fma. */ 13200 if (GET_MODE_CLASS (mode) == MODE_INT) 13201 { 13202 /* The multiply will be canonicalized as a shift, cost it as such. */ 13203 if (aarch64_shift_p (GET_CODE (x)) 13204 || (CONST_INT_P (op1) 13205 && exact_log2 (INTVAL (op1)) > 0)) 13206 { 13207 bool is_extend = GET_CODE (op0) == ZERO_EXTEND 13208 || GET_CODE (op0) == SIGN_EXTEND; 13209 if (speed) 13210 { 13211 if (compound_p) 13212 { 13213 /* If the shift is considered cheap, 13214 then don't add any cost. */ 13215 if (aarch64_cheap_mult_shift_p (x)) 13216 ; 13217 else if (REG_P (op1)) 13218 /* ARITH + shift-by-register. */ 13219 cost += extra_cost->alu.arith_shift_reg; 13220 else if (is_extend) 13221 /* ARITH + extended register. We don't have a cost field 13222 for ARITH+EXTEND+SHIFT, so use extend_arith here. */ 13223 cost += extra_cost->alu.extend_arith; 13224 else 13225 /* ARITH + shift-by-immediate. */ 13226 cost += extra_cost->alu.arith_shift; 13227 } 13228 else 13229 /* LSL (immediate). */ 13230 cost += extra_cost->alu.shift; 13231 13232 } 13233 /* Strip extends as we will have costed them in the case above. */ 13234 if (is_extend) 13235 op0 = aarch64_strip_extend (op0, true); 13236 13237 cost += rtx_cost (op0, VOIDmode, code, 0, speed); 13238 13239 return cost; 13240 } 13241 13242 /* MNEG or [US]MNEGL. Extract the NEG operand and indicate that it's a 13243 compound and let the below cases handle it. After all, MNEG is a 13244 special-case alias of MSUB. */ 13245 if (GET_CODE (op0) == NEG) 13246 { 13247 op0 = XEXP (op0, 0); 13248 compound_p = true; 13249 } 13250 13251 /* Integer multiplies or FMAs have zero/sign extending variants. */ 13252 if ((GET_CODE (op0) == ZERO_EXTEND 13253 && GET_CODE (op1) == ZERO_EXTEND) 13254 || (GET_CODE (op0) == SIGN_EXTEND 13255 && GET_CODE (op1) == SIGN_EXTEND)) 13256 { 13257 cost += rtx_cost (XEXP (op0, 0), VOIDmode, MULT, 0, speed); 13258 cost += rtx_cost (XEXP (op1, 0), VOIDmode, MULT, 1, speed); 13259 13260 if (speed) 13261 { 13262 if (compound_p) 13263 /* SMADDL/UMADDL/UMSUBL/SMSUBL. */ 13264 cost += extra_cost->mult[0].extend_add; 13265 else 13266 /* MUL/SMULL/UMULL. */ 13267 cost += extra_cost->mult[0].extend; 13268 } 13269 13270 return cost; 13271 } 13272 13273 /* This is either an integer multiply or a MADD. In both cases 13274 we want to recurse and cost the operands. */ 13275 cost += rtx_cost (op0, mode, MULT, 0, speed); 13276 cost += rtx_cost (op1, mode, MULT, 1, speed); 13277 13278 if (speed) 13279 { 13280 if (compound_p) 13281 /* MADD/MSUB. */ 13282 cost += extra_cost->mult[mode == DImode].add; 13283 else 13284 /* MUL. */ 13285 cost += extra_cost->mult[mode == DImode].simple; 13286 } 13287 13288 return cost; 13289 } 13290 else 13291 { 13292 if (speed) 13293 { 13294 /* Floating-point FMA/FMUL can also support negations of the 13295 operands, unless the rounding mode is upward or downward in 13296 which case FNMUL is different than FMUL with operand negation. */ 13297 bool neg0 = GET_CODE (op0) == NEG; 13298 bool neg1 = GET_CODE (op1) == NEG; 13299 if (compound_p || !flag_rounding_math || (neg0 && neg1)) 13300 { 13301 if (neg0) 13302 op0 = XEXP (op0, 0); 13303 if (neg1) 13304 op1 = XEXP (op1, 0); 13305 } 13306 13307 if (compound_p) 13308 /* FMADD/FNMADD/FNMSUB/FMSUB. */ 13309 cost += extra_cost->fp[mode == DFmode].fma; 13310 else 13311 /* FMUL/FNMUL. */ 13312 cost += extra_cost->fp[mode == DFmode].mult; 13313 } 13314 13315 cost += rtx_cost (op0, mode, MULT, 0, speed); 13316 cost += rtx_cost (op1, mode, MULT, 1, speed); 13317 return cost; 13318 } 13319 } 13320 13321 static int 13322 aarch64_address_cost (rtx x, 13323 machine_mode mode, 13324 addr_space_t as ATTRIBUTE_UNUSED, 13325 bool speed) 13326 { 13327 enum rtx_code c = GET_CODE (x); 13328 const struct cpu_addrcost_table *addr_cost = aarch64_tune_params.addr_cost; 13329 struct aarch64_address_info info; 13330 int cost = 0; 13331 info.shift = 0; 13332 13333 if (!aarch64_classify_address (&info, x, mode, false)) 13334 { 13335 if (GET_CODE (x) == CONST || SYMBOL_REF_P (x)) 13336 { 13337 /* This is a CONST or SYMBOL ref which will be split 13338 in a different way depending on the code model in use. 13339 Cost it through the generic infrastructure. */ 13340 int cost_symbol_ref = rtx_cost (x, Pmode, MEM, 1, speed); 13341 /* Divide through by the cost of one instruction to 13342 bring it to the same units as the address costs. */ 13343 cost_symbol_ref /= COSTS_N_INSNS (1); 13344 /* The cost is then the cost of preparing the address, 13345 followed by an immediate (possibly 0) offset. */ 13346 return cost_symbol_ref + addr_cost->imm_offset; 13347 } 13348 else 13349 { 13350 /* This is most likely a jump table from a case 13351 statement. */ 13352 return addr_cost->register_offset; 13353 } 13354 } 13355 13356 switch (info.type) 13357 { 13358 case ADDRESS_LO_SUM: 13359 case ADDRESS_SYMBOLIC: 13360 case ADDRESS_REG_IMM: 13361 cost += addr_cost->imm_offset; 13362 break; 13363 13364 case ADDRESS_REG_WB: 13365 if (c == PRE_INC || c == PRE_DEC || c == PRE_MODIFY) 13366 cost += addr_cost->pre_modify; 13367 else if (c == POST_INC || c == POST_DEC || c == POST_MODIFY) 13368 { 13369 unsigned int nvectors = aarch64_ldn_stn_vectors (mode); 13370 if (nvectors == 3) 13371 cost += addr_cost->post_modify_ld3_st3; 13372 else if (nvectors == 4) 13373 cost += addr_cost->post_modify_ld4_st4; 13374 else 13375 cost += addr_cost->post_modify; 13376 } 13377 else 13378 gcc_unreachable (); 13379 13380 break; 13381 13382 case ADDRESS_REG_REG: 13383 cost += addr_cost->register_offset; 13384 break; 13385 13386 case ADDRESS_REG_SXTW: 13387 cost += addr_cost->register_sextend; 13388 break; 13389 13390 case ADDRESS_REG_UXTW: 13391 cost += addr_cost->register_zextend; 13392 break; 13393 13394 default: 13395 gcc_unreachable (); 13396 } 13397 13398 13399 if (info.shift > 0) 13400 { 13401 /* For the sake of calculating the cost of the shifted register 13402 component, we can treat same sized modes in the same way. */ 13403 if (known_eq (GET_MODE_BITSIZE (mode), 16)) 13404 cost += addr_cost->addr_scale_costs.hi; 13405 else if (known_eq (GET_MODE_BITSIZE (mode), 32)) 13406 cost += addr_cost->addr_scale_costs.si; 13407 else if (known_eq (GET_MODE_BITSIZE (mode), 64)) 13408 cost += addr_cost->addr_scale_costs.di; 13409 else 13410 /* We can't tell, or this is a 128-bit vector. */ 13411 cost += addr_cost->addr_scale_costs.ti; 13412 } 13413 13414 return cost; 13415 } 13416 13417 /* Return the cost of a branch. If SPEED_P is true then the compiler is 13418 optimizing for speed. If PREDICTABLE_P is true then the branch is predicted 13419 to be taken. */ 13420 13421 int 13422 aarch64_branch_cost (bool speed_p, bool predictable_p) 13423 { 13424 /* When optimizing for speed, use the cost of unpredictable branches. */ 13425 const struct cpu_branch_cost *branch_costs = 13426 aarch64_tune_params.branch_costs; 13427 13428 if (!speed_p || predictable_p) 13429 return branch_costs->predictable; 13430 else 13431 return branch_costs->unpredictable; 13432 } 13433 13434 /* Return true if X is a zero or sign extract 13435 usable in an ADD or SUB (extended register) instruction. */ 13436 static bool 13437 aarch64_rtx_arith_op_extract_p (rtx x) 13438 { 13439 /* The simple case <ARITH>, XD, XN, XM, [us]xt. 13440 No shift. */ 13441 if (GET_CODE (x) == SIGN_EXTEND 13442 || GET_CODE (x) == ZERO_EXTEND) 13443 return REG_P (XEXP (x, 0)); 13444 13445 return false; 13446 } 13447 13448 static bool 13449 aarch64_frint_unspec_p (unsigned int u) 13450 { 13451 switch (u) 13452 { 13453 case UNSPEC_FRINTZ: 13454 case UNSPEC_FRINTP: 13455 case UNSPEC_FRINTM: 13456 case UNSPEC_FRINTA: 13457 case UNSPEC_FRINTN: 13458 case UNSPEC_FRINTX: 13459 case UNSPEC_FRINTI: 13460 return true; 13461 13462 default: 13463 return false; 13464 } 13465 } 13466 13467 /* Return true iff X is an rtx that will match an extr instruction 13468 i.e. as described in the *extr<mode>5_insn family of patterns. 13469 OP0 and OP1 will be set to the operands of the shifts involved 13470 on success and will be NULL_RTX otherwise. */ 13471 13472 static bool 13473 aarch64_extr_rtx_p (rtx x, rtx *res_op0, rtx *res_op1) 13474 { 13475 rtx op0, op1; 13476 scalar_int_mode mode; 13477 if (!is_a <scalar_int_mode> (GET_MODE (x), &mode)) 13478 return false; 13479 13480 *res_op0 = NULL_RTX; 13481 *res_op1 = NULL_RTX; 13482 13483 if (GET_CODE (x) != IOR) 13484 return false; 13485 13486 op0 = XEXP (x, 0); 13487 op1 = XEXP (x, 1); 13488 13489 if ((GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT) 13490 || (GET_CODE (op1) == ASHIFT && GET_CODE (op0) == LSHIFTRT)) 13491 { 13492 /* Canonicalise locally to ashift in op0, lshiftrt in op1. */ 13493 if (GET_CODE (op1) == ASHIFT) 13494 std::swap (op0, op1); 13495 13496 if (!CONST_INT_P (XEXP (op0, 1)) || !CONST_INT_P (XEXP (op1, 1))) 13497 return false; 13498 13499 unsigned HOST_WIDE_INT shft_amnt_0 = UINTVAL (XEXP (op0, 1)); 13500 unsigned HOST_WIDE_INT shft_amnt_1 = UINTVAL (XEXP (op1, 1)); 13501 13502 if (shft_amnt_0 < GET_MODE_BITSIZE (mode) 13503 && shft_amnt_0 + shft_amnt_1 == GET_MODE_BITSIZE (mode)) 13504 { 13505 *res_op0 = XEXP (op0, 0); 13506 *res_op1 = XEXP (op1, 0); 13507 return true; 13508 } 13509 } 13510 13511 return false; 13512 } 13513 13514 /* Calculate the cost of calculating (if_then_else (OP0) (OP1) (OP2)), 13515 storing it in *COST. Result is true if the total cost of the operation 13516 has now been calculated. */ 13517 static bool 13518 aarch64_if_then_else_costs (rtx op0, rtx op1, rtx op2, int *cost, bool speed) 13519 { 13520 rtx inner; 13521 rtx comparator; 13522 enum rtx_code cmpcode; 13523 const struct cpu_cost_table *extra_cost 13524 = aarch64_tune_params.insn_extra_cost; 13525 13526 if (COMPARISON_P (op0)) 13527 { 13528 inner = XEXP (op0, 0); 13529 comparator = XEXP (op0, 1); 13530 cmpcode = GET_CODE (op0); 13531 } 13532 else 13533 { 13534 inner = op0; 13535 comparator = const0_rtx; 13536 cmpcode = NE; 13537 } 13538 13539 if (GET_CODE (op1) == PC || GET_CODE (op2) == PC) 13540 { 13541 /* Conditional branch. */ 13542 if (GET_MODE_CLASS (GET_MODE (inner)) == MODE_CC) 13543 return true; 13544 else 13545 { 13546 if (cmpcode == NE || cmpcode == EQ) 13547 { 13548 if (comparator == const0_rtx) 13549 { 13550 /* TBZ/TBNZ/CBZ/CBNZ. */ 13551 if (GET_CODE (inner) == ZERO_EXTRACT) 13552 /* TBZ/TBNZ. */ 13553 *cost += rtx_cost (XEXP (inner, 0), VOIDmode, 13554 ZERO_EXTRACT, 0, speed); 13555 else 13556 /* CBZ/CBNZ. */ 13557 *cost += rtx_cost (inner, VOIDmode, cmpcode, 0, speed); 13558 13559 return true; 13560 } 13561 if (register_operand (inner, VOIDmode) 13562 && aarch64_imm24 (comparator, VOIDmode)) 13563 { 13564 /* SUB and SUBS. */ 13565 *cost += COSTS_N_INSNS (2); 13566 if (speed) 13567 *cost += extra_cost->alu.arith * 2; 13568 return true; 13569 } 13570 } 13571 else if (cmpcode == LT || cmpcode == GE) 13572 { 13573 /* TBZ/TBNZ. */ 13574 if (comparator == const0_rtx) 13575 return true; 13576 } 13577 } 13578 } 13579 else if (GET_MODE_CLASS (GET_MODE (inner)) == MODE_CC) 13580 { 13581 /* CCMP. */ 13582 if (GET_CODE (op1) == COMPARE) 13583 { 13584 /* Increase cost of CCMP reg, 0, imm, CC to prefer CMP reg, 0. */ 13585 if (XEXP (op1, 1) == const0_rtx) 13586 *cost += 1; 13587 if (speed) 13588 { 13589 machine_mode mode = GET_MODE (XEXP (op1, 0)); 13590 13591 if (GET_MODE_CLASS (mode) == MODE_INT) 13592 *cost += extra_cost->alu.arith; 13593 else 13594 *cost += extra_cost->fp[mode == DFmode].compare; 13595 } 13596 return true; 13597 } 13598 13599 /* It's a conditional operation based on the status flags, 13600 so it must be some flavor of CSEL. */ 13601 13602 /* CSNEG, CSINV, and CSINC are handled for free as part of CSEL. */ 13603 if (GET_CODE (op1) == NEG 13604 || GET_CODE (op1) == NOT 13605 || (GET_CODE (op1) == PLUS && XEXP (op1, 1) == const1_rtx)) 13606 op1 = XEXP (op1, 0); 13607 else if (GET_CODE (op1) == ZERO_EXTEND && GET_CODE (op2) == ZERO_EXTEND) 13608 { 13609 /* CSEL with zero-extension (*cmovdi_insn_uxtw). */ 13610 op1 = XEXP (op1, 0); 13611 op2 = XEXP (op2, 0); 13612 } 13613 else if (GET_CODE (op1) == ZERO_EXTEND && op2 == const0_rtx) 13614 { 13615 inner = XEXP (op1, 0); 13616 if (GET_CODE (inner) == NEG || GET_CODE (inner) == NOT) 13617 /* CSINV/NEG with zero extend + const 0 (*csinv3_uxtw_insn3). */ 13618 op1 = XEXP (inner, 0); 13619 } 13620 13621 *cost += rtx_cost (op1, VOIDmode, IF_THEN_ELSE, 1, speed); 13622 *cost += rtx_cost (op2, VOIDmode, IF_THEN_ELSE, 2, speed); 13623 return true; 13624 } 13625 13626 /* We don't know what this is, cost all operands. */ 13627 return false; 13628 } 13629 13630 /* Check whether X is a bitfield operation of the form shift + extend that 13631 maps down to a UBFIZ/SBFIZ/UBFX/SBFX instruction. If so, return the 13632 operand to which the bitfield operation is applied. Otherwise return 13633 NULL_RTX. */ 13634 13635 static rtx 13636 aarch64_extend_bitfield_pattern_p (rtx x) 13637 { 13638 rtx_code outer_code = GET_CODE (x); 13639 machine_mode outer_mode = GET_MODE (x); 13640 13641 if (outer_code != ZERO_EXTEND && outer_code != SIGN_EXTEND 13642 && outer_mode != SImode && outer_mode != DImode) 13643 return NULL_RTX; 13644 13645 rtx inner = XEXP (x, 0); 13646 rtx_code inner_code = GET_CODE (inner); 13647 machine_mode inner_mode = GET_MODE (inner); 13648 rtx op = NULL_RTX; 13649 13650 switch (inner_code) 13651 { 13652 case ASHIFT: 13653 if (CONST_INT_P (XEXP (inner, 1)) 13654 && (inner_mode == QImode || inner_mode == HImode)) 13655 op = XEXP (inner, 0); 13656 break; 13657 case LSHIFTRT: 13658 if (outer_code == ZERO_EXTEND && CONST_INT_P (XEXP (inner, 1)) 13659 && (inner_mode == QImode || inner_mode == HImode)) 13660 op = XEXP (inner, 0); 13661 break; 13662 case ASHIFTRT: 13663 if (outer_code == SIGN_EXTEND && CONST_INT_P (XEXP (inner, 1)) 13664 && (inner_mode == QImode || inner_mode == HImode)) 13665 op = XEXP (inner, 0); 13666 break; 13667 default: 13668 break; 13669 } 13670 13671 return op; 13672 } 13673 13674 /* Return true if the mask and a shift amount from an RTX of the form 13675 (x << SHFT_AMNT) & MASK are valid to combine into a UBFIZ instruction of 13676 mode MODE. See the *andim_ashift<mode>_bfiz pattern. */ 13677 13678 bool 13679 aarch64_mask_and_shift_for_ubfiz_p (scalar_int_mode mode, rtx mask, 13680 rtx shft_amnt) 13681 { 13682 return CONST_INT_P (mask) && CONST_INT_P (shft_amnt) 13683 && INTVAL (mask) > 0 13684 && UINTVAL (shft_amnt) < GET_MODE_BITSIZE (mode) 13685 && exact_log2 ((UINTVAL (mask) >> UINTVAL (shft_amnt)) + 1) >= 0 13686 && (UINTVAL (mask) 13687 & ((HOST_WIDE_INT_1U << UINTVAL (shft_amnt)) - 1)) == 0; 13688 } 13689 13690 /* Return true if the masks and a shift amount from an RTX of the form 13691 ((x & MASK1) | ((y << SHIFT_AMNT) & MASK2)) are valid to combine into 13692 a BFI instruction of mode MODE. See *arch64_bfi patterns. */ 13693 13694 bool 13695 aarch64_masks_and_shift_for_bfi_p (scalar_int_mode mode, 13696 unsigned HOST_WIDE_INT mask1, 13697 unsigned HOST_WIDE_INT shft_amnt, 13698 unsigned HOST_WIDE_INT mask2) 13699 { 13700 unsigned HOST_WIDE_INT t; 13701 13702 /* Verify that there is no overlap in what bits are set in the two masks. */ 13703 if (mask1 != ~mask2) 13704 return false; 13705 13706 /* Verify that mask2 is not all zeros or ones. */ 13707 if (mask2 == 0 || mask2 == HOST_WIDE_INT_M1U) 13708 return false; 13709 13710 /* The shift amount should always be less than the mode size. */ 13711 gcc_assert (shft_amnt < GET_MODE_BITSIZE (mode)); 13712 13713 /* Verify that the mask being shifted is contiguous and would be in the 13714 least significant bits after shifting by shft_amnt. */ 13715 t = mask2 + (HOST_WIDE_INT_1U << shft_amnt); 13716 return (t == (t & -t)); 13717 } 13718 13719 /* Calculate the cost of calculating X, storing it in *COST. Result 13720 is true if the total cost of the operation has now been calculated. */ 13721 static bool 13722 aarch64_rtx_costs (rtx x, machine_mode mode, int outer ATTRIBUTE_UNUSED, 13723 int param ATTRIBUTE_UNUSED, int *cost, bool speed) 13724 { 13725 rtx op0, op1, op2; 13726 const struct cpu_cost_table *extra_cost 13727 = aarch64_tune_params.insn_extra_cost; 13728 rtx_code code = GET_CODE (x); 13729 scalar_int_mode int_mode; 13730 13731 /* By default, assume that everything has equivalent cost to the 13732 cheapest instruction. Any additional costs are applied as a delta 13733 above this default. */ 13734 *cost = COSTS_N_INSNS (1); 13735 13736 switch (code) 13737 { 13738 case SET: 13739 /* The cost depends entirely on the operands to SET. */ 13740 *cost = 0; 13741 op0 = SET_DEST (x); 13742 op1 = SET_SRC (x); 13743 13744 switch (GET_CODE (op0)) 13745 { 13746 case MEM: 13747 if (speed) 13748 { 13749 rtx address = XEXP (op0, 0); 13750 if (VECTOR_MODE_P (mode)) 13751 *cost += extra_cost->ldst.storev; 13752 else if (GET_MODE_CLASS (mode) == MODE_INT) 13753 *cost += extra_cost->ldst.store; 13754 else if (mode == SFmode) 13755 *cost += extra_cost->ldst.storef; 13756 else if (mode == DFmode) 13757 *cost += extra_cost->ldst.stored; 13758 13759 *cost += 13760 COSTS_N_INSNS (aarch64_address_cost (address, mode, 13761 0, speed)); 13762 } 13763 13764 *cost += rtx_cost (op1, mode, SET, 1, speed); 13765 return true; 13766 13767 case SUBREG: 13768 if (! REG_P (SUBREG_REG (op0))) 13769 *cost += rtx_cost (SUBREG_REG (op0), VOIDmode, SET, 0, speed); 13770 13771 /* Fall through. */ 13772 case REG: 13773 /* The cost is one per vector-register copied. */ 13774 if (VECTOR_MODE_P (GET_MODE (op0)) && REG_P (op1)) 13775 { 13776 int nregs = aarch64_hard_regno_nregs (V0_REGNUM, GET_MODE (op0)); 13777 *cost = COSTS_N_INSNS (nregs); 13778 } 13779 /* const0_rtx is in general free, but we will use an 13780 instruction to set a register to 0. */ 13781 else if (REG_P (op1) || op1 == const0_rtx) 13782 { 13783 /* The cost is 1 per register copied. */ 13784 int nregs = aarch64_hard_regno_nregs (R0_REGNUM, GET_MODE (op0)); 13785 *cost = COSTS_N_INSNS (nregs); 13786 } 13787 else 13788 /* Cost is just the cost of the RHS of the set. */ 13789 *cost += rtx_cost (op1, mode, SET, 1, speed); 13790 return true; 13791 13792 case ZERO_EXTRACT: 13793 case SIGN_EXTRACT: 13794 /* Bit-field insertion. Strip any redundant widening of 13795 the RHS to meet the width of the target. */ 13796 if (SUBREG_P (op1)) 13797 op1 = SUBREG_REG (op1); 13798 if ((GET_CODE (op1) == ZERO_EXTEND 13799 || GET_CODE (op1) == SIGN_EXTEND) 13800 && CONST_INT_P (XEXP (op0, 1)) 13801 && is_a <scalar_int_mode> (GET_MODE (XEXP (op1, 0)), &int_mode) 13802 && GET_MODE_BITSIZE (int_mode) >= INTVAL (XEXP (op0, 1))) 13803 op1 = XEXP (op1, 0); 13804 13805 if (CONST_INT_P (op1)) 13806 { 13807 /* MOV immediate is assumed to always be cheap. */ 13808 *cost = COSTS_N_INSNS (1); 13809 } 13810 else 13811 { 13812 /* BFM. */ 13813 if (speed) 13814 *cost += extra_cost->alu.bfi; 13815 *cost += rtx_cost (op1, VOIDmode, (enum rtx_code) code, 1, speed); 13816 } 13817 13818 return true; 13819 13820 default: 13821 /* We can't make sense of this, assume default cost. */ 13822 *cost = COSTS_N_INSNS (1); 13823 return false; 13824 } 13825 return false; 13826 13827 case CONST_INT: 13828 /* If an instruction can incorporate a constant within the 13829 instruction, the instruction's expression avoids calling 13830 rtx_cost() on the constant. If rtx_cost() is called on a 13831 constant, then it is usually because the constant must be 13832 moved into a register by one or more instructions. 13833 13834 The exception is constant 0, which can be expressed 13835 as XZR/WZR and is therefore free. The exception to this is 13836 if we have (set (reg) (const0_rtx)) in which case we must cost 13837 the move. However, we can catch that when we cost the SET, so 13838 we don't need to consider that here. */ 13839 if (x == const0_rtx) 13840 *cost = 0; 13841 else 13842 { 13843 /* To an approximation, building any other constant is 13844 proportionally expensive to the number of instructions 13845 required to build that constant. This is true whether we 13846 are compiling for SPEED or otherwise. */ 13847 if (!is_a <scalar_int_mode> (mode, &int_mode)) 13848 int_mode = word_mode; 13849 *cost = COSTS_N_INSNS (aarch64_internal_mov_immediate 13850 (NULL_RTX, x, false, int_mode)); 13851 } 13852 return true; 13853 13854 case CONST_DOUBLE: 13855 13856 /* First determine number of instructions to do the move 13857 as an integer constant. */ 13858 if (!aarch64_float_const_representable_p (x) 13859 && !aarch64_can_const_movi_rtx_p (x, mode) 13860 && aarch64_float_const_rtx_p (x)) 13861 { 13862 unsigned HOST_WIDE_INT ival; 13863 bool succeed = aarch64_reinterpret_float_as_int (x, &ival); 13864 gcc_assert (succeed); 13865 13866 scalar_int_mode imode = (mode == HFmode 13867 ? SImode 13868 : int_mode_for_mode (mode).require ()); 13869 int ncost = aarch64_internal_mov_immediate 13870 (NULL_RTX, gen_int_mode (ival, imode), false, imode); 13871 *cost += COSTS_N_INSNS (ncost); 13872 return true; 13873 } 13874 13875 if (speed) 13876 { 13877 /* mov[df,sf]_aarch64. */ 13878 if (aarch64_float_const_representable_p (x)) 13879 /* FMOV (scalar immediate). */ 13880 *cost += extra_cost->fp[mode == DFmode].fpconst; 13881 else if (!aarch64_float_const_zero_rtx_p (x)) 13882 { 13883 /* This will be a load from memory. */ 13884 if (mode == DFmode) 13885 *cost += extra_cost->ldst.loadd; 13886 else 13887 *cost += extra_cost->ldst.loadf; 13888 } 13889 else 13890 /* Otherwise this is +0.0. We get this using MOVI d0, #0 13891 or MOV v0.s[0], wzr - neither of which are modeled by the 13892 cost tables. Just use the default cost. */ 13893 { 13894 } 13895 } 13896 13897 return true; 13898 13899 case MEM: 13900 if (speed) 13901 { 13902 /* For loads we want the base cost of a load, plus an 13903 approximation for the additional cost of the addressing 13904 mode. */ 13905 rtx address = XEXP (x, 0); 13906 if (VECTOR_MODE_P (mode)) 13907 *cost += extra_cost->ldst.loadv; 13908 else if (GET_MODE_CLASS (mode) == MODE_INT) 13909 *cost += extra_cost->ldst.load; 13910 else if (mode == SFmode) 13911 *cost += extra_cost->ldst.loadf; 13912 else if (mode == DFmode) 13913 *cost += extra_cost->ldst.loadd; 13914 13915 *cost += 13916 COSTS_N_INSNS (aarch64_address_cost (address, mode, 13917 0, speed)); 13918 } 13919 13920 return true; 13921 13922 case NEG: 13923 op0 = XEXP (x, 0); 13924 13925 if (VECTOR_MODE_P (mode)) 13926 { 13927 if (speed) 13928 { 13929 /* FNEG. */ 13930 *cost += extra_cost->vect.alu; 13931 } 13932 return false; 13933 } 13934 13935 if (GET_MODE_CLASS (mode) == MODE_INT) 13936 { 13937 if (GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMPARE 13938 || GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMM_COMPARE) 13939 { 13940 /* CSETM. */ 13941 *cost += rtx_cost (XEXP (op0, 0), VOIDmode, NEG, 0, speed); 13942 return true; 13943 } 13944 13945 /* Cost this as SUB wzr, X. */ 13946 op0 = CONST0_RTX (mode); 13947 op1 = XEXP (x, 0); 13948 goto cost_minus; 13949 } 13950 13951 if (GET_MODE_CLASS (mode) == MODE_FLOAT) 13952 { 13953 /* Support (neg(fma...)) as a single instruction only if 13954 sign of zeros is unimportant. This matches the decision 13955 making in aarch64.md. */ 13956 if (GET_CODE (op0) == FMA && !HONOR_SIGNED_ZEROS (GET_MODE (op0))) 13957 { 13958 /* FNMADD. */ 13959 *cost = rtx_cost (op0, mode, NEG, 0, speed); 13960 return true; 13961 } 13962 if (GET_CODE (op0) == MULT) 13963 { 13964 /* FNMUL. */ 13965 *cost = rtx_cost (op0, mode, NEG, 0, speed); 13966 return true; 13967 } 13968 if (speed) 13969 /* FNEG. */ 13970 *cost += extra_cost->fp[mode == DFmode].neg; 13971 return false; 13972 } 13973 13974 return false; 13975 13976 case CLRSB: 13977 case CLZ: 13978 if (speed) 13979 { 13980 if (VECTOR_MODE_P (mode)) 13981 *cost += extra_cost->vect.alu; 13982 else 13983 *cost += extra_cost->alu.clz; 13984 } 13985 13986 return false; 13987 13988 case CTZ: 13989 *cost = COSTS_N_INSNS (2); 13990 13991 if (speed) 13992 *cost += extra_cost->alu.clz + extra_cost->alu.rev; 13993 return false; 13994 13995 case COMPARE: 13996 op0 = XEXP (x, 0); 13997 op1 = XEXP (x, 1); 13998 13999 if (op1 == const0_rtx 14000 && GET_CODE (op0) == AND) 14001 { 14002 x = op0; 14003 mode = GET_MODE (op0); 14004 goto cost_logic; 14005 } 14006 14007 if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT) 14008 { 14009 /* TODO: A write to the CC flags possibly costs extra, this 14010 needs encoding in the cost tables. */ 14011 14012 mode = GET_MODE (op0); 14013 /* ANDS. */ 14014 if (GET_CODE (op0) == AND) 14015 { 14016 x = op0; 14017 goto cost_logic; 14018 } 14019 14020 if (GET_CODE (op0) == PLUS) 14021 { 14022 /* ADDS (and CMN alias). */ 14023 x = op0; 14024 goto cost_plus; 14025 } 14026 14027 if (GET_CODE (op0) == MINUS) 14028 { 14029 /* SUBS. */ 14030 x = op0; 14031 goto cost_minus; 14032 } 14033 14034 if (GET_CODE (op0) == ZERO_EXTRACT && op1 == const0_rtx 14035 && GET_MODE (x) == CC_NZmode && CONST_INT_P (XEXP (op0, 1)) 14036 && CONST_INT_P (XEXP (op0, 2))) 14037 { 14038 /* COMPARE of ZERO_EXTRACT form of TST-immediate. 14039 Handle it here directly rather than going to cost_logic 14040 since we know the immediate generated for the TST is valid 14041 so we can avoid creating an intermediate rtx for it only 14042 for costing purposes. */ 14043 if (speed) 14044 *cost += extra_cost->alu.logical; 14045 14046 *cost += rtx_cost (XEXP (op0, 0), GET_MODE (op0), 14047 ZERO_EXTRACT, 0, speed); 14048 return true; 14049 } 14050 14051 if (GET_CODE (op1) == NEG) 14052 { 14053 /* CMN. */ 14054 if (speed) 14055 *cost += extra_cost->alu.arith; 14056 14057 *cost += rtx_cost (op0, mode, COMPARE, 0, speed); 14058 *cost += rtx_cost (XEXP (op1, 0), mode, NEG, 1, speed); 14059 return true; 14060 } 14061 14062 /* CMP. 14063 14064 Compare can freely swap the order of operands, and 14065 canonicalization puts the more complex operation first. 14066 But the integer MINUS logic expects the shift/extend 14067 operation in op1. */ 14068 if (! (REG_P (op0) 14069 || (SUBREG_P (op0) && REG_P (SUBREG_REG (op0))))) 14070 { 14071 op0 = XEXP (x, 1); 14072 op1 = XEXP (x, 0); 14073 } 14074 goto cost_minus; 14075 } 14076 14077 if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) 14078 { 14079 /* FCMP. */ 14080 if (speed) 14081 *cost += extra_cost->fp[mode == DFmode].compare; 14082 14083 if (CONST_DOUBLE_P (op1) && aarch64_float_const_zero_rtx_p (op1)) 14084 { 14085 *cost += rtx_cost (op0, VOIDmode, COMPARE, 0, speed); 14086 /* FCMP supports constant 0.0 for no extra cost. */ 14087 return true; 14088 } 14089 return false; 14090 } 14091 14092 if (VECTOR_MODE_P (mode)) 14093 { 14094 /* Vector compare. */ 14095 if (speed) 14096 *cost += extra_cost->vect.alu; 14097 14098 if (aarch64_float_const_zero_rtx_p (op1)) 14099 { 14100 /* Vector cm (eq|ge|gt|lt|le) supports constant 0.0 for no extra 14101 cost. */ 14102 return true; 14103 } 14104 return false; 14105 } 14106 return false; 14107 14108 case MINUS: 14109 { 14110 op0 = XEXP (x, 0); 14111 op1 = XEXP (x, 1); 14112 14113 cost_minus: 14114 if (VECTOR_MODE_P (mode)) 14115 { 14116 /* SUBL2 and SUBW2. */ 14117 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 14118 if (vec_flags & VEC_ADVSIMD) 14119 { 14120 /* The select-operand-high-half versions of the sub instruction 14121 have the same cost as the regular three vector version - 14122 don't add the costs of the select into the costs of the sub. 14123 */ 14124 op0 = aarch64_strip_extend_vec_half (op0); 14125 op1 = aarch64_strip_extend_vec_half (op1); 14126 } 14127 } 14128 14129 *cost += rtx_cost (op0, mode, MINUS, 0, speed); 14130 14131 /* Detect valid immediates. */ 14132 if ((GET_MODE_CLASS (mode) == MODE_INT 14133 || (GET_MODE_CLASS (mode) == MODE_CC 14134 && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)) 14135 && CONST_INT_P (op1) 14136 && aarch64_uimm12_shift (INTVAL (op1))) 14137 { 14138 if (speed) 14139 /* SUB(S) (immediate). */ 14140 *cost += extra_cost->alu.arith; 14141 return true; 14142 } 14143 14144 /* Look for SUB (extended register). */ 14145 if (is_a <scalar_int_mode> (mode) 14146 && aarch64_rtx_arith_op_extract_p (op1)) 14147 { 14148 if (speed) 14149 *cost += extra_cost->alu.extend_arith; 14150 14151 op1 = aarch64_strip_extend (op1, true); 14152 *cost += rtx_cost (op1, VOIDmode, 14153 (enum rtx_code) GET_CODE (op1), 0, speed); 14154 return true; 14155 } 14156 14157 rtx new_op1 = aarch64_strip_extend (op1, false); 14158 14159 /* Cost this as an FMA-alike operation. */ 14160 if ((GET_CODE (new_op1) == MULT 14161 || aarch64_shift_p (GET_CODE (new_op1))) 14162 && code != COMPARE) 14163 { 14164 *cost += aarch64_rtx_mult_cost (new_op1, MULT, 14165 (enum rtx_code) code, 14166 speed); 14167 return true; 14168 } 14169 14170 *cost += rtx_cost (new_op1, VOIDmode, MINUS, 1, speed); 14171 14172 if (speed) 14173 { 14174 if (VECTOR_MODE_P (mode)) 14175 { 14176 /* Vector SUB. */ 14177 *cost += extra_cost->vect.alu; 14178 } 14179 else if (GET_MODE_CLASS (mode) == MODE_INT) 14180 { 14181 /* SUB(S). */ 14182 *cost += extra_cost->alu.arith; 14183 } 14184 else if (GET_MODE_CLASS (mode) == MODE_FLOAT) 14185 { 14186 /* FSUB. */ 14187 *cost += extra_cost->fp[mode == DFmode].addsub; 14188 } 14189 } 14190 return true; 14191 } 14192 14193 case PLUS: 14194 { 14195 rtx new_op0; 14196 14197 op0 = XEXP (x, 0); 14198 op1 = XEXP (x, 1); 14199 14200 cost_plus: 14201 if (VECTOR_MODE_P (mode)) 14202 { 14203 /* ADDL2 and ADDW2. */ 14204 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 14205 if (vec_flags & VEC_ADVSIMD) 14206 { 14207 /* The select-operand-high-half versions of the add instruction 14208 have the same cost as the regular three vector version - 14209 don't add the costs of the select into the costs of the add. 14210 */ 14211 op0 = aarch64_strip_extend_vec_half (op0); 14212 op1 = aarch64_strip_extend_vec_half (op1); 14213 } 14214 } 14215 14216 if (GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMPARE 14217 || GET_RTX_CLASS (GET_CODE (op0)) == RTX_COMM_COMPARE) 14218 { 14219 /* CSINC. */ 14220 *cost += rtx_cost (XEXP (op0, 0), mode, PLUS, 0, speed); 14221 *cost += rtx_cost (op1, mode, PLUS, 1, speed); 14222 return true; 14223 } 14224 14225 if (GET_MODE_CLASS (mode) == MODE_INT 14226 && (aarch64_plus_immediate (op1, mode) 14227 || aarch64_sve_addvl_addpl_immediate (op1, mode))) 14228 { 14229 *cost += rtx_cost (op0, mode, PLUS, 0, speed); 14230 14231 if (speed) 14232 { 14233 /* ADD (immediate). */ 14234 *cost += extra_cost->alu.arith; 14235 14236 /* Some tunings prefer to not use the VL-based scalar ops. 14237 Increase the cost of the poly immediate to prevent their 14238 formation. */ 14239 if (GET_CODE (op1) == CONST_POLY_INT 14240 && (aarch64_tune_params.extra_tuning_flags 14241 & AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS)) 14242 *cost += COSTS_N_INSNS (1); 14243 } 14244 return true; 14245 } 14246 14247 *cost += rtx_cost (op1, mode, PLUS, 1, speed); 14248 14249 /* Look for ADD (extended register). */ 14250 if (is_a <scalar_int_mode> (mode) 14251 && aarch64_rtx_arith_op_extract_p (op0)) 14252 { 14253 if (speed) 14254 *cost += extra_cost->alu.extend_arith; 14255 14256 op0 = aarch64_strip_extend (op0, true); 14257 *cost += rtx_cost (op0, VOIDmode, 14258 (enum rtx_code) GET_CODE (op0), 0, speed); 14259 return true; 14260 } 14261 14262 /* Strip any extend, leave shifts behind as we will 14263 cost them through mult_cost. */ 14264 new_op0 = aarch64_strip_extend (op0, false); 14265 14266 if (GET_CODE (new_op0) == MULT 14267 || aarch64_shift_p (GET_CODE (new_op0))) 14268 { 14269 *cost += aarch64_rtx_mult_cost (new_op0, MULT, PLUS, 14270 speed); 14271 return true; 14272 } 14273 14274 *cost += rtx_cost (new_op0, VOIDmode, PLUS, 0, speed); 14275 14276 if (speed) 14277 { 14278 if (VECTOR_MODE_P (mode)) 14279 { 14280 /* Vector ADD. */ 14281 *cost += extra_cost->vect.alu; 14282 } 14283 else if (GET_MODE_CLASS (mode) == MODE_INT) 14284 { 14285 /* ADD. */ 14286 *cost += extra_cost->alu.arith; 14287 } 14288 else if (GET_MODE_CLASS (mode) == MODE_FLOAT) 14289 { 14290 /* FADD. */ 14291 *cost += extra_cost->fp[mode == DFmode].addsub; 14292 } 14293 } 14294 return true; 14295 } 14296 14297 case BSWAP: 14298 *cost = COSTS_N_INSNS (1); 14299 14300 if (speed) 14301 { 14302 if (VECTOR_MODE_P (mode)) 14303 *cost += extra_cost->vect.alu; 14304 else 14305 *cost += extra_cost->alu.rev; 14306 } 14307 return false; 14308 14309 case IOR: 14310 if (aarch_rev16_p (x)) 14311 { 14312 *cost = COSTS_N_INSNS (1); 14313 14314 if (speed) 14315 { 14316 if (VECTOR_MODE_P (mode)) 14317 *cost += extra_cost->vect.alu; 14318 else 14319 *cost += extra_cost->alu.rev; 14320 } 14321 return true; 14322 } 14323 14324 if (aarch64_extr_rtx_p (x, &op0, &op1)) 14325 { 14326 *cost += rtx_cost (op0, mode, IOR, 0, speed); 14327 *cost += rtx_cost (op1, mode, IOR, 1, speed); 14328 if (speed) 14329 *cost += extra_cost->alu.shift; 14330 14331 return true; 14332 } 14333 /* Fall through. */ 14334 case XOR: 14335 case AND: 14336 cost_logic: 14337 op0 = XEXP (x, 0); 14338 op1 = XEXP (x, 1); 14339 14340 if (VECTOR_MODE_P (mode)) 14341 { 14342 if (speed) 14343 *cost += extra_cost->vect.alu; 14344 return true; 14345 } 14346 14347 if (code == AND 14348 && GET_CODE (op0) == MULT 14349 && CONST_INT_P (XEXP (op0, 1)) 14350 && CONST_INT_P (op1) 14351 && aarch64_uxt_size (exact_log2 (INTVAL (XEXP (op0, 1))), 14352 INTVAL (op1)) != 0) 14353 { 14354 /* This is a UBFM/SBFM. */ 14355 *cost += rtx_cost (XEXP (op0, 0), mode, ZERO_EXTRACT, 0, speed); 14356 if (speed) 14357 *cost += extra_cost->alu.bfx; 14358 return true; 14359 } 14360 14361 if (is_int_mode (mode, &int_mode)) 14362 { 14363 if (CONST_INT_P (op1)) 14364 { 14365 /* We have a mask + shift version of a UBFIZ 14366 i.e. the *andim_ashift<mode>_bfiz pattern. */ 14367 if (GET_CODE (op0) == ASHIFT 14368 && aarch64_mask_and_shift_for_ubfiz_p (int_mode, op1, 14369 XEXP (op0, 1))) 14370 { 14371 *cost += rtx_cost (XEXP (op0, 0), int_mode, 14372 (enum rtx_code) code, 0, speed); 14373 if (speed) 14374 *cost += extra_cost->alu.bfx; 14375 14376 return true; 14377 } 14378 else if (aarch64_bitmask_imm (INTVAL (op1), int_mode)) 14379 { 14380 /* We possibly get the immediate for free, this is not 14381 modelled. */ 14382 *cost += rtx_cost (op0, int_mode, 14383 (enum rtx_code) code, 0, speed); 14384 if (speed) 14385 *cost += extra_cost->alu.logical; 14386 14387 return true; 14388 } 14389 } 14390 else 14391 { 14392 rtx new_op0 = op0; 14393 14394 /* Handle ORN, EON, or BIC. */ 14395 if (GET_CODE (op0) == NOT) 14396 op0 = XEXP (op0, 0); 14397 14398 new_op0 = aarch64_strip_shift (op0); 14399 14400 /* If we had a shift on op0 then this is a logical-shift- 14401 by-register/immediate operation. Otherwise, this is just 14402 a logical operation. */ 14403 if (speed) 14404 { 14405 if (new_op0 != op0) 14406 { 14407 /* Shift by immediate. */ 14408 if (CONST_INT_P (XEXP (op0, 1))) 14409 *cost += extra_cost->alu.log_shift; 14410 else 14411 *cost += extra_cost->alu.log_shift_reg; 14412 } 14413 else 14414 *cost += extra_cost->alu.logical; 14415 } 14416 14417 /* In both cases we want to cost both operands. */ 14418 *cost += rtx_cost (new_op0, int_mode, (enum rtx_code) code, 14419 0, speed); 14420 *cost += rtx_cost (op1, int_mode, (enum rtx_code) code, 14421 1, speed); 14422 14423 return true; 14424 } 14425 } 14426 return false; 14427 14428 case NOT: 14429 x = XEXP (x, 0); 14430 op0 = aarch64_strip_shift (x); 14431 14432 if (VECTOR_MODE_P (mode)) 14433 { 14434 /* Vector NOT. */ 14435 *cost += extra_cost->vect.alu; 14436 return false; 14437 } 14438 14439 /* MVN-shifted-reg. */ 14440 if (op0 != x) 14441 { 14442 *cost += rtx_cost (op0, mode, (enum rtx_code) code, 0, speed); 14443 14444 if (speed) 14445 *cost += extra_cost->alu.log_shift; 14446 14447 return true; 14448 } 14449 /* EON can have two forms: (xor (not a) b) but also (not (xor a b)). 14450 Handle the second form here taking care that 'a' in the above can 14451 be a shift. */ 14452 else if (GET_CODE (op0) == XOR) 14453 { 14454 rtx newop0 = XEXP (op0, 0); 14455 rtx newop1 = XEXP (op0, 1); 14456 rtx op0_stripped = aarch64_strip_shift (newop0); 14457 14458 *cost += rtx_cost (newop1, mode, (enum rtx_code) code, 1, speed); 14459 *cost += rtx_cost (op0_stripped, mode, XOR, 0, speed); 14460 14461 if (speed) 14462 { 14463 if (op0_stripped != newop0) 14464 *cost += extra_cost->alu.log_shift; 14465 else 14466 *cost += extra_cost->alu.logical; 14467 } 14468 14469 return true; 14470 } 14471 /* MVN. */ 14472 if (speed) 14473 *cost += extra_cost->alu.logical; 14474 14475 return false; 14476 14477 case ZERO_EXTEND: 14478 14479 op0 = XEXP (x, 0); 14480 /* If a value is written in SI mode, then zero extended to DI 14481 mode, the operation will in general be free as a write to 14482 a 'w' register implicitly zeroes the upper bits of an 'x' 14483 register. However, if this is 14484 14485 (set (reg) (zero_extend (reg))) 14486 14487 we must cost the explicit register move. */ 14488 if (mode == DImode 14489 && GET_MODE (op0) == SImode) 14490 { 14491 int op_cost = rtx_cost (op0, VOIDmode, ZERO_EXTEND, 0, speed); 14492 14493 /* If OP_COST is non-zero, then the cost of the zero extend 14494 is effectively the cost of the inner operation. Otherwise 14495 we have a MOV instruction and we take the cost from the MOV 14496 itself. This is true independently of whether we are 14497 optimizing for space or time. */ 14498 if (op_cost) 14499 *cost = op_cost; 14500 14501 return true; 14502 } 14503 else if (MEM_P (op0)) 14504 { 14505 /* All loads can zero extend to any size for free. */ 14506 *cost = rtx_cost (op0, VOIDmode, ZERO_EXTEND, param, speed); 14507 return true; 14508 } 14509 14510 op0 = aarch64_extend_bitfield_pattern_p (x); 14511 if (op0) 14512 { 14513 *cost += rtx_cost (op0, mode, ZERO_EXTEND, 0, speed); 14514 if (speed) 14515 *cost += extra_cost->alu.bfx; 14516 return true; 14517 } 14518 14519 if (speed) 14520 { 14521 if (VECTOR_MODE_P (mode)) 14522 { 14523 /* UMOV. */ 14524 *cost += extra_cost->vect.alu; 14525 } 14526 else 14527 { 14528 /* We generate an AND instead of UXTB/UXTH. */ 14529 *cost += extra_cost->alu.logical; 14530 } 14531 } 14532 return false; 14533 14534 case SIGN_EXTEND: 14535 if (MEM_P (XEXP (x, 0))) 14536 { 14537 /* LDRSH. */ 14538 if (speed) 14539 { 14540 rtx address = XEXP (XEXP (x, 0), 0); 14541 *cost += extra_cost->ldst.load_sign_extend; 14542 14543 *cost += 14544 COSTS_N_INSNS (aarch64_address_cost (address, mode, 14545 0, speed)); 14546 } 14547 return true; 14548 } 14549 14550 op0 = aarch64_extend_bitfield_pattern_p (x); 14551 if (op0) 14552 { 14553 *cost += rtx_cost (op0, mode, SIGN_EXTEND, 0, speed); 14554 if (speed) 14555 *cost += extra_cost->alu.bfx; 14556 return true; 14557 } 14558 14559 if (speed) 14560 { 14561 if (VECTOR_MODE_P (mode)) 14562 *cost += extra_cost->vect.alu; 14563 else 14564 *cost += extra_cost->alu.extend; 14565 } 14566 return false; 14567 14568 case ASHIFT: 14569 op0 = XEXP (x, 0); 14570 op1 = XEXP (x, 1); 14571 14572 if (CONST_INT_P (op1)) 14573 { 14574 if (speed) 14575 { 14576 if (VECTOR_MODE_P (mode)) 14577 { 14578 /* Vector shift (immediate). */ 14579 *cost += extra_cost->vect.alu; 14580 } 14581 else 14582 { 14583 /* LSL (immediate), UBMF, UBFIZ and friends. These are all 14584 aliases. */ 14585 *cost += extra_cost->alu.shift; 14586 } 14587 } 14588 14589 /* We can incorporate zero/sign extend for free. */ 14590 if (GET_CODE (op0) == ZERO_EXTEND 14591 || GET_CODE (op0) == SIGN_EXTEND) 14592 op0 = XEXP (op0, 0); 14593 14594 *cost += rtx_cost (op0, VOIDmode, ASHIFT, 0, speed); 14595 return true; 14596 } 14597 else 14598 { 14599 if (VECTOR_MODE_P (mode)) 14600 { 14601 if (speed) 14602 /* Vector shift (register). */ 14603 *cost += extra_cost->vect.alu; 14604 } 14605 else 14606 { 14607 if (speed) 14608 /* LSLV. */ 14609 *cost += extra_cost->alu.shift_reg; 14610 14611 if (GET_CODE (op1) == AND && REG_P (XEXP (op1, 0)) 14612 && CONST_INT_P (XEXP (op1, 1)) 14613 && known_eq (INTVAL (XEXP (op1, 1)), 14614 GET_MODE_BITSIZE (mode) - 1)) 14615 { 14616 *cost += rtx_cost (op0, mode, (rtx_code) code, 0, speed); 14617 /* We already demanded XEXP (op1, 0) to be REG_P, so 14618 don't recurse into it. */ 14619 return true; 14620 } 14621 } 14622 return false; /* All arguments need to be in registers. */ 14623 } 14624 14625 case ROTATE: 14626 case ROTATERT: 14627 case LSHIFTRT: 14628 case ASHIFTRT: 14629 op0 = XEXP (x, 0); 14630 op1 = XEXP (x, 1); 14631 14632 if (CONST_INT_P (op1)) 14633 { 14634 /* ASR (immediate) and friends. */ 14635 if (speed) 14636 { 14637 if (VECTOR_MODE_P (mode)) 14638 *cost += extra_cost->vect.alu; 14639 else 14640 *cost += extra_cost->alu.shift; 14641 } 14642 14643 *cost += rtx_cost (op0, mode, (enum rtx_code) code, 0, speed); 14644 return true; 14645 } 14646 else 14647 { 14648 if (VECTOR_MODE_P (mode)) 14649 { 14650 if (speed) 14651 /* Vector shift (register). */ 14652 *cost += extra_cost->vect.alu; 14653 } 14654 else 14655 { 14656 if (speed) 14657 /* ASR (register) and friends. */ 14658 *cost += extra_cost->alu.shift_reg; 14659 14660 if (GET_CODE (op1) == AND && REG_P (XEXP (op1, 0)) 14661 && CONST_INT_P (XEXP (op1, 1)) 14662 && known_eq (INTVAL (XEXP (op1, 1)), 14663 GET_MODE_BITSIZE (mode) - 1)) 14664 { 14665 *cost += rtx_cost (op0, mode, (rtx_code) code, 0, speed); 14666 /* We already demanded XEXP (op1, 0) to be REG_P, so 14667 don't recurse into it. */ 14668 return true; 14669 } 14670 } 14671 return false; /* All arguments need to be in registers. */ 14672 } 14673 14674 case SYMBOL_REF: 14675 14676 if (aarch64_cmodel == AARCH64_CMODEL_LARGE 14677 || aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC) 14678 { 14679 /* LDR. */ 14680 if (speed) 14681 *cost += extra_cost->ldst.load; 14682 } 14683 else if (aarch64_cmodel == AARCH64_CMODEL_SMALL 14684 || aarch64_cmodel == AARCH64_CMODEL_SMALL_PIC) 14685 { 14686 /* ADRP, followed by ADD. */ 14687 *cost += COSTS_N_INSNS (1); 14688 if (speed) 14689 *cost += 2 * extra_cost->alu.arith; 14690 } 14691 else if (aarch64_cmodel == AARCH64_CMODEL_TINY 14692 || aarch64_cmodel == AARCH64_CMODEL_TINY_PIC) 14693 { 14694 /* ADR. */ 14695 if (speed) 14696 *cost += extra_cost->alu.arith; 14697 } 14698 14699 if (flag_pic) 14700 { 14701 /* One extra load instruction, after accessing the GOT. */ 14702 *cost += COSTS_N_INSNS (1); 14703 if (speed) 14704 *cost += extra_cost->ldst.load; 14705 } 14706 return true; 14707 14708 case HIGH: 14709 case LO_SUM: 14710 /* ADRP/ADD (immediate). */ 14711 if (speed) 14712 *cost += extra_cost->alu.arith; 14713 return true; 14714 14715 case ZERO_EXTRACT: 14716 case SIGN_EXTRACT: 14717 /* UBFX/SBFX. */ 14718 if (speed) 14719 { 14720 if (VECTOR_MODE_P (mode)) 14721 *cost += extra_cost->vect.alu; 14722 else 14723 *cost += extra_cost->alu.bfx; 14724 } 14725 14726 /* We can trust that the immediates used will be correct (there 14727 are no by-register forms), so we need only cost op0. */ 14728 *cost += rtx_cost (XEXP (x, 0), VOIDmode, (enum rtx_code) code, 0, speed); 14729 return true; 14730 14731 case MULT: 14732 *cost += aarch64_rtx_mult_cost (x, MULT, 0, speed); 14733 /* aarch64_rtx_mult_cost always handles recursion to its 14734 operands. */ 14735 return true; 14736 14737 case MOD: 14738 /* We can expand signed mod by power of 2 using a NEGS, two parallel 14739 ANDs and a CSNEG. Assume here that CSNEG is the same as the cost of 14740 an unconditional negate. This case should only ever be reached through 14741 the set_smod_pow2_cheap check in expmed.cc. */ 14742 if (CONST_INT_P (XEXP (x, 1)) 14743 && exact_log2 (INTVAL (XEXP (x, 1))) > 0 14744 && (mode == SImode || mode == DImode)) 14745 { 14746 /* We expand to 4 instructions. Reset the baseline. */ 14747 *cost = COSTS_N_INSNS (4); 14748 14749 if (speed) 14750 *cost += 2 * extra_cost->alu.logical 14751 + 2 * extra_cost->alu.arith; 14752 14753 return true; 14754 } 14755 14756 /* Fall-through. */ 14757 case UMOD: 14758 if (speed) 14759 { 14760 /* Slighly prefer UMOD over SMOD. */ 14761 if (VECTOR_MODE_P (mode)) 14762 *cost += extra_cost->vect.alu; 14763 else if (GET_MODE_CLASS (mode) == MODE_INT) 14764 *cost += (extra_cost->mult[mode == DImode].add 14765 + extra_cost->mult[mode == DImode].idiv 14766 + (code == MOD ? 1 : 0)); 14767 } 14768 return false; /* All arguments need to be in registers. */ 14769 14770 case DIV: 14771 case UDIV: 14772 case SQRT: 14773 if (speed) 14774 { 14775 if (VECTOR_MODE_P (mode)) 14776 *cost += extra_cost->vect.alu; 14777 else if (GET_MODE_CLASS (mode) == MODE_INT) 14778 /* There is no integer SQRT, so only DIV and UDIV can get 14779 here. */ 14780 *cost += (extra_cost->mult[mode == DImode].idiv 14781 /* Slighly prefer UDIV over SDIV. */ 14782 + (code == DIV ? 1 : 0)); 14783 else 14784 *cost += extra_cost->fp[mode == DFmode].div; 14785 } 14786 return false; /* All arguments need to be in registers. */ 14787 14788 case IF_THEN_ELSE: 14789 return aarch64_if_then_else_costs (XEXP (x, 0), XEXP (x, 1), 14790 XEXP (x, 2), cost, speed); 14791 14792 case EQ: 14793 case NE: 14794 case GT: 14795 case GTU: 14796 case LT: 14797 case LTU: 14798 case GE: 14799 case GEU: 14800 case LE: 14801 case LEU: 14802 14803 return false; /* All arguments must be in registers. */ 14804 14805 case FMA: 14806 op0 = XEXP (x, 0); 14807 op1 = XEXP (x, 1); 14808 op2 = XEXP (x, 2); 14809 14810 if (speed) 14811 { 14812 if (VECTOR_MODE_P (mode)) 14813 *cost += extra_cost->vect.alu; 14814 else 14815 *cost += extra_cost->fp[mode == DFmode].fma; 14816 } 14817 14818 /* FMSUB, FNMADD, and FNMSUB are free. */ 14819 if (GET_CODE (op0) == NEG) 14820 op0 = XEXP (op0, 0); 14821 14822 if (GET_CODE (op2) == NEG) 14823 op2 = XEXP (op2, 0); 14824 14825 /* aarch64_fnma4_elt_to_64v2df has the NEG as operand 1, 14826 and the by-element operand as operand 0. */ 14827 if (GET_CODE (op1) == NEG) 14828 op1 = XEXP (op1, 0); 14829 14830 /* Catch vector-by-element operations. The by-element operand can 14831 either be (vec_duplicate (vec_select (x))) or just 14832 (vec_select (x)), depending on whether we are multiplying by 14833 a vector or a scalar. 14834 14835 Canonicalization is not very good in these cases, FMA4 will put the 14836 by-element operand as operand 0, FNMA4 will have it as operand 1. */ 14837 if (GET_CODE (op0) == VEC_DUPLICATE) 14838 op0 = XEXP (op0, 0); 14839 else if (GET_CODE (op1) == VEC_DUPLICATE) 14840 op1 = XEXP (op1, 0); 14841 14842 if (GET_CODE (op0) == VEC_SELECT) 14843 op0 = XEXP (op0, 0); 14844 else if (GET_CODE (op1) == VEC_SELECT) 14845 op1 = XEXP (op1, 0); 14846 14847 /* If the remaining parameters are not registers, 14848 get the cost to put them into registers. */ 14849 *cost += rtx_cost (op0, mode, FMA, 0, speed); 14850 *cost += rtx_cost (op1, mode, FMA, 1, speed); 14851 *cost += rtx_cost (op2, mode, FMA, 2, speed); 14852 return true; 14853 14854 case FLOAT: 14855 case UNSIGNED_FLOAT: 14856 if (speed) 14857 *cost += extra_cost->fp[mode == DFmode].fromint; 14858 return false; 14859 14860 case FLOAT_EXTEND: 14861 if (speed) 14862 { 14863 if (VECTOR_MODE_P (mode)) 14864 { 14865 /*Vector truncate. */ 14866 *cost += extra_cost->vect.alu; 14867 } 14868 else 14869 *cost += extra_cost->fp[mode == DFmode].widen; 14870 } 14871 return false; 14872 14873 case FLOAT_TRUNCATE: 14874 if (speed) 14875 { 14876 if (VECTOR_MODE_P (mode)) 14877 { 14878 /*Vector conversion. */ 14879 *cost += extra_cost->vect.alu; 14880 } 14881 else 14882 *cost += extra_cost->fp[mode == DFmode].narrow; 14883 } 14884 return false; 14885 14886 case FIX: 14887 case UNSIGNED_FIX: 14888 x = XEXP (x, 0); 14889 /* Strip the rounding part. They will all be implemented 14890 by the fcvt* family of instructions anyway. */ 14891 if (GET_CODE (x) == UNSPEC) 14892 { 14893 unsigned int uns_code = XINT (x, 1); 14894 14895 if (uns_code == UNSPEC_FRINTA 14896 || uns_code == UNSPEC_FRINTM 14897 || uns_code == UNSPEC_FRINTN 14898 || uns_code == UNSPEC_FRINTP 14899 || uns_code == UNSPEC_FRINTZ) 14900 x = XVECEXP (x, 0, 0); 14901 } 14902 14903 if (speed) 14904 { 14905 if (VECTOR_MODE_P (mode)) 14906 *cost += extra_cost->vect.alu; 14907 else 14908 *cost += extra_cost->fp[GET_MODE (x) == DFmode].toint; 14909 } 14910 14911 /* We can combine fmul by a power of 2 followed by a fcvt into a single 14912 fixed-point fcvt. */ 14913 if (GET_CODE (x) == MULT 14914 && ((VECTOR_MODE_P (mode) 14915 && aarch64_vec_fpconst_pow_of_2 (XEXP (x, 1)) > 0) 14916 || aarch64_fpconst_pow_of_2 (XEXP (x, 1)) > 0)) 14917 { 14918 *cost += rtx_cost (XEXP (x, 0), VOIDmode, (rtx_code) code, 14919 0, speed); 14920 return true; 14921 } 14922 14923 *cost += rtx_cost (x, VOIDmode, (enum rtx_code) code, 0, speed); 14924 return true; 14925 14926 case ABS: 14927 if (VECTOR_MODE_P (mode)) 14928 { 14929 /* ABS (vector). */ 14930 if (speed) 14931 *cost += extra_cost->vect.alu; 14932 } 14933 else if (GET_MODE_CLASS (mode) == MODE_FLOAT) 14934 { 14935 op0 = XEXP (x, 0); 14936 14937 /* FABD, which is analogous to FADD. */ 14938 if (GET_CODE (op0) == MINUS) 14939 { 14940 *cost += rtx_cost (XEXP (op0, 0), mode, MINUS, 0, speed); 14941 *cost += rtx_cost (XEXP (op0, 1), mode, MINUS, 1, speed); 14942 if (speed) 14943 *cost += extra_cost->fp[mode == DFmode].addsub; 14944 14945 return true; 14946 } 14947 /* Simple FABS is analogous to FNEG. */ 14948 if (speed) 14949 *cost += extra_cost->fp[mode == DFmode].neg; 14950 } 14951 else 14952 { 14953 /* Integer ABS will either be split to 14954 two arithmetic instructions, or will be an ABS 14955 (scalar), which we don't model. */ 14956 *cost = COSTS_N_INSNS (2); 14957 if (speed) 14958 *cost += 2 * extra_cost->alu.arith; 14959 } 14960 return false; 14961 14962 case SMAX: 14963 case SMIN: 14964 if (speed) 14965 { 14966 if (VECTOR_MODE_P (mode)) 14967 *cost += extra_cost->vect.alu; 14968 else 14969 { 14970 /* FMAXNM/FMINNM/FMAX/FMIN. 14971 TODO: This may not be accurate for all implementations, but 14972 we do not model this in the cost tables. */ 14973 *cost += extra_cost->fp[mode == DFmode].addsub; 14974 } 14975 } 14976 return false; 14977 14978 case UNSPEC: 14979 /* The floating point round to integer frint* instructions. */ 14980 if (aarch64_frint_unspec_p (XINT (x, 1))) 14981 { 14982 if (speed) 14983 *cost += extra_cost->fp[mode == DFmode].roundint; 14984 14985 return false; 14986 } 14987 14988 if (XINT (x, 1) == UNSPEC_RBIT) 14989 { 14990 if (speed) 14991 *cost += extra_cost->alu.rev; 14992 14993 return false; 14994 } 14995 break; 14996 14997 case TRUNCATE: 14998 14999 /* Decompose <su>muldi3_highpart. */ 15000 if (/* (truncate:DI */ 15001 mode == DImode 15002 /* (lshiftrt:TI */ 15003 && GET_MODE (XEXP (x, 0)) == TImode 15004 && GET_CODE (XEXP (x, 0)) == LSHIFTRT 15005 /* (mult:TI */ 15006 && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT 15007 /* (ANY_EXTEND:TI (reg:DI)) 15008 (ANY_EXTEND:TI (reg:DI))) */ 15009 && ((GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND 15010 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == ZERO_EXTEND) 15011 || (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND 15012 && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == SIGN_EXTEND)) 15013 && GET_MODE (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 0)) == DImode 15014 && GET_MODE (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0)) == DImode 15015 /* (const_int 64) */ 15016 && CONST_INT_P (XEXP (XEXP (x, 0), 1)) 15017 && UINTVAL (XEXP (XEXP (x, 0), 1)) == 64) 15018 { 15019 /* UMULH/SMULH. */ 15020 if (speed) 15021 *cost += extra_cost->mult[mode == DImode].extend; 15022 *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 0), 0), 15023 mode, MULT, 0, speed); 15024 *cost += rtx_cost (XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0), 15025 mode, MULT, 1, speed); 15026 return true; 15027 } 15028 break; 15029 case CONST_VECTOR: 15030 { 15031 /* Load using MOVI/MVNI. */ 15032 if (aarch64_simd_valid_immediate (x, NULL)) 15033 *cost = extra_cost->vect.movi; 15034 else /* Load using constant pool. */ 15035 *cost = extra_cost->ldst.load; 15036 break; 15037 } 15038 case VEC_CONCAT: 15039 /* depending on the operation, either DUP or INS. 15040 For now, keep default costing. */ 15041 break; 15042 case VEC_DUPLICATE: 15043 /* Load using a DUP. */ 15044 *cost = extra_cost->vect.dup; 15045 return false; 15046 case VEC_SELECT: 15047 { 15048 rtx op0 = XEXP (x, 0); 15049 *cost = rtx_cost (op0, GET_MODE (op0), VEC_SELECT, 0, speed); 15050 15051 /* cost subreg of 0 as free, otherwise as DUP */ 15052 rtx op1 = XEXP (x, 1); 15053 if (vec_series_lowpart_p (mode, GET_MODE (op1), op1)) 15054 ; 15055 else if (vec_series_highpart_p (mode, GET_MODE (op1), op1)) 15056 *cost = extra_cost->vect.dup; 15057 else 15058 *cost = extra_cost->vect.extract; 15059 return true; 15060 } 15061 default: 15062 break; 15063 } 15064 15065 if (dump_file 15066 && flag_aarch64_verbose_cost) 15067 fprintf (dump_file, 15068 "\nFailed to cost RTX. Assuming default cost.\n"); 15069 15070 return true; 15071 } 15072 15073 /* Wrapper around aarch64_rtx_costs, dumps the partial, or total cost 15074 calculated for X. This cost is stored in *COST. Returns true 15075 if the total cost of X was calculated. */ 15076 static bool 15077 aarch64_rtx_costs_wrapper (rtx x, machine_mode mode, int outer, 15078 int param, int *cost, bool speed) 15079 { 15080 bool result = aarch64_rtx_costs (x, mode, outer, param, cost, speed); 15081 15082 if (dump_file 15083 && flag_aarch64_verbose_cost) 15084 { 15085 print_rtl_single (dump_file, x); 15086 fprintf (dump_file, "\n%s cost: %d (%s)\n", 15087 speed ? "Hot" : "Cold", 15088 *cost, result ? "final" : "partial"); 15089 } 15090 15091 return result; 15092 } 15093 15094 static int 15095 aarch64_register_move_cost (machine_mode mode, 15096 reg_class_t from_i, reg_class_t to_i) 15097 { 15098 enum reg_class from = (enum reg_class) from_i; 15099 enum reg_class to = (enum reg_class) to_i; 15100 const struct cpu_regmove_cost *regmove_cost 15101 = aarch64_tune_params.regmove_cost; 15102 15103 /* Caller save and pointer regs are equivalent to GENERAL_REGS. */ 15104 if (to == TAILCALL_ADDR_REGS || to == POINTER_REGS 15105 || to == STUB_REGS) 15106 to = GENERAL_REGS; 15107 15108 if (from == TAILCALL_ADDR_REGS || from == POINTER_REGS 15109 || from == STUB_REGS) 15110 from = GENERAL_REGS; 15111 15112 /* Make RDFFR very expensive. In particular, if we know that the FFR 15113 contains a PTRUE (e.g. after a SETFFR), we must never use RDFFR 15114 as a way of obtaining a PTRUE. */ 15115 if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL 15116 && hard_reg_set_subset_p (reg_class_contents[from_i], 15117 reg_class_contents[FFR_REGS])) 15118 return 80; 15119 15120 /* Moving between GPR and stack cost is the same as GP2GP. */ 15121 if ((from == GENERAL_REGS && to == STACK_REG) 15122 || (to == GENERAL_REGS && from == STACK_REG)) 15123 return regmove_cost->GP2GP; 15124 15125 /* To/From the stack register, we move via the gprs. */ 15126 if (to == STACK_REG || from == STACK_REG) 15127 return aarch64_register_move_cost (mode, from, GENERAL_REGS) 15128 + aarch64_register_move_cost (mode, GENERAL_REGS, to); 15129 15130 if (known_eq (GET_MODE_SIZE (mode), 16)) 15131 { 15132 /* 128-bit operations on general registers require 2 instructions. */ 15133 if (from == GENERAL_REGS && to == GENERAL_REGS) 15134 return regmove_cost->GP2GP * 2; 15135 else if (from == GENERAL_REGS) 15136 return regmove_cost->GP2FP * 2; 15137 else if (to == GENERAL_REGS) 15138 return regmove_cost->FP2GP * 2; 15139 15140 /* When AdvSIMD instructions are disabled it is not possible to move 15141 a 128-bit value directly between Q registers. This is handled in 15142 secondary reload. A general register is used as a scratch to move 15143 the upper DI value and the lower DI value is moved directly, 15144 hence the cost is the sum of three moves. */ 15145 if (! TARGET_SIMD) 15146 return regmove_cost->GP2FP + regmove_cost->FP2GP + regmove_cost->FP2FP; 15147 15148 return regmove_cost->FP2FP; 15149 } 15150 15151 if (from == GENERAL_REGS && to == GENERAL_REGS) 15152 return regmove_cost->GP2GP; 15153 else if (from == GENERAL_REGS) 15154 return regmove_cost->GP2FP; 15155 else if (to == GENERAL_REGS) 15156 return regmove_cost->FP2GP; 15157 15158 return regmove_cost->FP2FP; 15159 } 15160 15161 /* Implements TARGET_MEMORY_MOVE_COST. */ 15162 static int 15163 aarch64_memory_move_cost (machine_mode mode, reg_class_t rclass_i, bool in) 15164 { 15165 enum reg_class rclass = (enum reg_class) rclass_i; 15166 if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL 15167 ? reg_classes_intersect_p (rclass, PR_REGS) 15168 : reg_class_subset_p (rclass, PR_REGS)) 15169 return (in 15170 ? aarch64_tune_params.memmov_cost.load_pred 15171 : aarch64_tune_params.memmov_cost.store_pred); 15172 15173 if (VECTOR_MODE_P (mode) || FLOAT_MODE_P (mode) 15174 ? reg_classes_intersect_p (rclass, FP_REGS) 15175 : reg_class_subset_p (rclass, FP_REGS)) 15176 return (in 15177 ? aarch64_tune_params.memmov_cost.load_fp 15178 : aarch64_tune_params.memmov_cost.store_fp); 15179 15180 return (in 15181 ? aarch64_tune_params.memmov_cost.load_int 15182 : aarch64_tune_params.memmov_cost.store_int); 15183 } 15184 15185 /* Implement TARGET_INIT_BUILTINS. */ 15186 static void 15187 aarch64_init_builtins () 15188 { 15189 aarch64_general_init_builtins (); 15190 aarch64_sve::init_builtins (); 15191 #ifdef SUBTARGET_INIT_BUILTINS 15192 SUBTARGET_INIT_BUILTINS; 15193 #endif 15194 } 15195 15196 /* Implement TARGET_FOLD_BUILTIN. */ 15197 static tree 15198 aarch64_fold_builtin (tree fndecl, int nargs, tree *args, bool) 15199 { 15200 unsigned int code = DECL_MD_FUNCTION_CODE (fndecl); 15201 unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; 15202 tree type = TREE_TYPE (TREE_TYPE (fndecl)); 15203 switch (code & AARCH64_BUILTIN_CLASS) 15204 { 15205 case AARCH64_BUILTIN_GENERAL: 15206 return aarch64_general_fold_builtin (subcode, type, nargs, args); 15207 15208 case AARCH64_BUILTIN_SVE: 15209 return NULL_TREE; 15210 } 15211 gcc_unreachable (); 15212 } 15213 15214 /* Implement TARGET_GIMPLE_FOLD_BUILTIN. */ 15215 static bool 15216 aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi) 15217 { 15218 gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi)); 15219 tree fndecl = gimple_call_fndecl (stmt); 15220 unsigned int code = DECL_MD_FUNCTION_CODE (fndecl); 15221 unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; 15222 gimple *new_stmt = NULL; 15223 switch (code & AARCH64_BUILTIN_CLASS) 15224 { 15225 case AARCH64_BUILTIN_GENERAL: 15226 new_stmt = aarch64_general_gimple_fold_builtin (subcode, stmt, gsi); 15227 break; 15228 15229 case AARCH64_BUILTIN_SVE: 15230 new_stmt = aarch64_sve::gimple_fold_builtin (subcode, gsi, stmt); 15231 break; 15232 } 15233 15234 if (!new_stmt) 15235 return false; 15236 15237 gsi_replace (gsi, new_stmt, true); 15238 return true; 15239 } 15240 15241 /* Implement TARGET_EXPAND_BUILTIN. */ 15242 static rtx 15243 aarch64_expand_builtin (tree exp, rtx target, rtx, machine_mode, int ignore) 15244 { 15245 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); 15246 unsigned int code = DECL_MD_FUNCTION_CODE (fndecl); 15247 unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; 15248 switch (code & AARCH64_BUILTIN_CLASS) 15249 { 15250 case AARCH64_BUILTIN_GENERAL: 15251 return aarch64_general_expand_builtin (subcode, exp, target, ignore); 15252 15253 case AARCH64_BUILTIN_SVE: 15254 return aarch64_sve::expand_builtin (subcode, exp, target); 15255 } 15256 gcc_unreachable (); 15257 } 15258 15259 /* Implement TARGET_BUILTIN_DECL. */ 15260 static tree 15261 aarch64_builtin_decl (unsigned int code, bool initialize_p) 15262 { 15263 unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; 15264 switch (code & AARCH64_BUILTIN_CLASS) 15265 { 15266 case AARCH64_BUILTIN_GENERAL: 15267 return aarch64_general_builtin_decl (subcode, initialize_p); 15268 15269 case AARCH64_BUILTIN_SVE: 15270 return aarch64_sve::builtin_decl (subcode, initialize_p); 15271 } 15272 gcc_unreachable (); 15273 } 15274 15275 /* Return true if it is safe and beneficial to use the approximate rsqrt optabs 15276 to optimize 1.0/sqrt. */ 15277 15278 static bool 15279 use_rsqrt_p (machine_mode mode) 15280 { 15281 return (!flag_trapping_math 15282 && flag_unsafe_math_optimizations 15283 && ((aarch64_tune_params.approx_modes->recip_sqrt 15284 & AARCH64_APPROX_MODE (mode)) 15285 || flag_mrecip_low_precision_sqrt)); 15286 } 15287 15288 /* Function to decide when to use the approximate reciprocal square root 15289 builtin. */ 15290 15291 static tree 15292 aarch64_builtin_reciprocal (tree fndecl) 15293 { 15294 machine_mode mode = TYPE_MODE (TREE_TYPE (fndecl)); 15295 15296 if (!use_rsqrt_p (mode)) 15297 return NULL_TREE; 15298 unsigned int code = DECL_MD_FUNCTION_CODE (fndecl); 15299 unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT; 15300 switch (code & AARCH64_BUILTIN_CLASS) 15301 { 15302 case AARCH64_BUILTIN_GENERAL: 15303 return aarch64_general_builtin_rsqrt (subcode); 15304 15305 case AARCH64_BUILTIN_SVE: 15306 return NULL_TREE; 15307 } 15308 gcc_unreachable (); 15309 } 15310 15311 /* Emit code to perform the floating-point operation: 15312 15313 DST = SRC1 * SRC2 15314 15315 where all three operands are already known to be registers. 15316 If the operation is an SVE one, PTRUE is a suitable all-true 15317 predicate. */ 15318 15319 static void 15320 aarch64_emit_mult (rtx dst, rtx ptrue, rtx src1, rtx src2) 15321 { 15322 if (ptrue) 15323 emit_insn (gen_aarch64_pred (UNSPEC_COND_FMUL, GET_MODE (dst), 15324 dst, ptrue, src1, src2, 15325 gen_int_mode (SVE_RELAXED_GP, SImode))); 15326 else 15327 emit_set_insn (dst, gen_rtx_MULT (GET_MODE (dst), src1, src2)); 15328 } 15329 15330 /* Emit instruction sequence to compute either the approximate square root 15331 or its approximate reciprocal, depending on the flag RECP, and return 15332 whether the sequence was emitted or not. */ 15333 15334 bool 15335 aarch64_emit_approx_sqrt (rtx dst, rtx src, bool recp) 15336 { 15337 machine_mode mode = GET_MODE (dst); 15338 15339 if (GET_MODE_INNER (mode) == HFmode) 15340 { 15341 gcc_assert (!recp); 15342 return false; 15343 } 15344 15345 if (!recp) 15346 { 15347 if (!(flag_mlow_precision_sqrt 15348 || (aarch64_tune_params.approx_modes->sqrt 15349 & AARCH64_APPROX_MODE (mode)))) 15350 return false; 15351 15352 if (!flag_finite_math_only 15353 || flag_trapping_math 15354 || !flag_unsafe_math_optimizations 15355 || optimize_function_for_size_p (cfun)) 15356 return false; 15357 } 15358 else 15359 /* Caller assumes we cannot fail. */ 15360 gcc_assert (use_rsqrt_p (mode)); 15361 15362 rtx pg = NULL_RTX; 15363 if (aarch64_sve_mode_p (mode)) 15364 pg = aarch64_ptrue_reg (aarch64_sve_pred_mode (mode)); 15365 machine_mode mmsk = (VECTOR_MODE_P (mode) 15366 ? related_int_vector_mode (mode).require () 15367 : int_mode_for_mode (mode).require ()); 15368 rtx xmsk = NULL_RTX; 15369 if (!recp) 15370 { 15371 /* When calculating the approximate square root, compare the 15372 argument with 0.0 and create a mask. */ 15373 rtx zero = CONST0_RTX (mode); 15374 if (pg) 15375 { 15376 xmsk = gen_reg_rtx (GET_MODE (pg)); 15377 rtx hint = gen_int_mode (SVE_KNOWN_PTRUE, SImode); 15378 emit_insn (gen_aarch64_pred_fcm (UNSPEC_COND_FCMNE, mode, 15379 xmsk, pg, hint, src, zero)); 15380 } 15381 else 15382 { 15383 xmsk = gen_reg_rtx (mmsk); 15384 emit_insn (gen_rtx_SET (xmsk, 15385 gen_rtx_NEG (mmsk, 15386 gen_rtx_EQ (mmsk, src, zero)))); 15387 } 15388 } 15389 15390 /* Estimate the approximate reciprocal square root. */ 15391 rtx xdst = gen_reg_rtx (mode); 15392 emit_insn (gen_aarch64_rsqrte (mode, xdst, src)); 15393 15394 /* Iterate over the series twice for SF and thrice for DF. */ 15395 int iterations = (GET_MODE_INNER (mode) == DFmode) ? 3 : 2; 15396 15397 /* Optionally iterate over the series once less for faster performance 15398 while sacrificing the accuracy. */ 15399 if ((recp && flag_mrecip_low_precision_sqrt) 15400 || (!recp && flag_mlow_precision_sqrt)) 15401 iterations--; 15402 15403 /* Iterate over the series to calculate the approximate reciprocal square 15404 root. */ 15405 rtx x1 = gen_reg_rtx (mode); 15406 while (iterations--) 15407 { 15408 rtx x2 = gen_reg_rtx (mode); 15409 aarch64_emit_mult (x2, pg, xdst, xdst); 15410 15411 emit_insn (gen_aarch64_rsqrts (mode, x1, src, x2)); 15412 15413 if (iterations > 0) 15414 aarch64_emit_mult (xdst, pg, xdst, x1); 15415 } 15416 15417 if (!recp) 15418 { 15419 if (pg) 15420 /* Multiply nonzero source values by the corresponding intermediate 15421 result elements, so that the final calculation is the approximate 15422 square root rather than its reciprocal. Select a zero result for 15423 zero source values, to avoid the Inf * 0 -> NaN that we'd get 15424 otherwise. */ 15425 emit_insn (gen_cond (UNSPEC_COND_FMUL, mode, 15426 xdst, xmsk, xdst, src, CONST0_RTX (mode))); 15427 else 15428 { 15429 /* Qualify the approximate reciprocal square root when the 15430 argument is 0.0 by squashing the intermediary result to 0.0. */ 15431 rtx xtmp = gen_reg_rtx (mmsk); 15432 emit_set_insn (xtmp, gen_rtx_AND (mmsk, gen_rtx_NOT (mmsk, xmsk), 15433 gen_rtx_SUBREG (mmsk, xdst, 0))); 15434 emit_move_insn (xdst, gen_rtx_SUBREG (mode, xtmp, 0)); 15435 15436 /* Calculate the approximate square root. */ 15437 aarch64_emit_mult (xdst, pg, xdst, src); 15438 } 15439 } 15440 15441 /* Finalize the approximation. */ 15442 aarch64_emit_mult (dst, pg, xdst, x1); 15443 15444 return true; 15445 } 15446 15447 /* Emit the instruction sequence to compute the approximation for the division 15448 of NUM by DEN in QUO and return whether the sequence was emitted or not. */ 15449 15450 bool 15451 aarch64_emit_approx_div (rtx quo, rtx num, rtx den) 15452 { 15453 machine_mode mode = GET_MODE (quo); 15454 15455 if (GET_MODE_INNER (mode) == HFmode) 15456 return false; 15457 15458 bool use_approx_division_p = (flag_mlow_precision_div 15459 || (aarch64_tune_params.approx_modes->division 15460 & AARCH64_APPROX_MODE (mode))); 15461 15462 if (!flag_finite_math_only 15463 || flag_trapping_math 15464 || !flag_unsafe_math_optimizations 15465 || optimize_function_for_size_p (cfun) 15466 || !use_approx_division_p) 15467 return false; 15468 15469 if (!TARGET_SIMD && VECTOR_MODE_P (mode)) 15470 return false; 15471 15472 rtx pg = NULL_RTX; 15473 if (aarch64_sve_mode_p (mode)) 15474 pg = aarch64_ptrue_reg (aarch64_sve_pred_mode (mode)); 15475 15476 /* Estimate the approximate reciprocal. */ 15477 rtx xrcp = gen_reg_rtx (mode); 15478 emit_insn (gen_aarch64_frecpe (mode, xrcp, den)); 15479 15480 /* Iterate over the series twice for SF and thrice for DF. */ 15481 int iterations = (GET_MODE_INNER (mode) == DFmode) ? 3 : 2; 15482 15483 /* Optionally iterate over the series less for faster performance, 15484 while sacrificing the accuracy. The default is 2 for DF and 1 for SF. */ 15485 if (flag_mlow_precision_div) 15486 iterations = (GET_MODE_INNER (mode) == DFmode 15487 ? aarch64_double_recp_precision 15488 : aarch64_float_recp_precision); 15489 15490 /* Iterate over the series to calculate the approximate reciprocal. */ 15491 rtx xtmp = gen_reg_rtx (mode); 15492 while (iterations--) 15493 { 15494 emit_insn (gen_aarch64_frecps (mode, xtmp, xrcp, den)); 15495 15496 if (iterations > 0) 15497 aarch64_emit_mult (xrcp, pg, xrcp, xtmp); 15498 } 15499 15500 if (num != CONST1_RTX (mode)) 15501 { 15502 /* As the approximate reciprocal of DEN is already calculated, only 15503 calculate the approximate division when NUM is not 1.0. */ 15504 rtx xnum = force_reg (mode, num); 15505 aarch64_emit_mult (xrcp, pg, xrcp, xnum); 15506 } 15507 15508 /* Finalize the approximation. */ 15509 aarch64_emit_mult (quo, pg, xrcp, xtmp); 15510 return true; 15511 } 15512 15513 /* Return the number of instructions that can be issued per cycle. */ 15514 static int 15515 aarch64_sched_issue_rate (void) 15516 { 15517 return aarch64_tune_params.issue_rate; 15518 } 15519 15520 /* Implement TARGET_SCHED_VARIABLE_ISSUE. */ 15521 static int 15522 aarch64_sched_variable_issue (FILE *, int, rtx_insn *insn, int more) 15523 { 15524 if (DEBUG_INSN_P (insn)) 15525 return more; 15526 15527 rtx_code code = GET_CODE (PATTERN (insn)); 15528 if (code == USE || code == CLOBBER) 15529 return more; 15530 15531 if (get_attr_type (insn) == TYPE_NO_INSN) 15532 return more; 15533 15534 return more - 1; 15535 } 15536 15537 static int 15538 aarch64_sched_first_cycle_multipass_dfa_lookahead (void) 15539 { 15540 int issue_rate = aarch64_sched_issue_rate (); 15541 15542 return issue_rate > 1 && !sched_fusion ? issue_rate : 0; 15543 } 15544 15545 15546 /* Implement TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD as 15547 autopref_multipass_dfa_lookahead_guard from haifa-sched.cc. It only 15548 has an effect if PARAM_SCHED_AUTOPREF_QUEUE_DEPTH > 0. */ 15549 15550 static int 15551 aarch64_first_cycle_multipass_dfa_lookahead_guard (rtx_insn *insn, 15552 int ready_index) 15553 { 15554 return autopref_multipass_dfa_lookahead_guard (insn, ready_index); 15555 } 15556 15557 15558 /* Vectorizer cost model target hooks. */ 15559 15560 /* If a vld1 from address ADDR should be recorded in vector_load_decls, 15561 return the decl that should be recorded. Return null otherwise. */ 15562 tree 15563 aarch64_vector_load_decl (tree addr) 15564 { 15565 if (TREE_CODE (addr) != ADDR_EXPR) 15566 return NULL_TREE; 15567 tree base = get_base_address (TREE_OPERAND (addr, 0)); 15568 if (TREE_CODE (base) != VAR_DECL) 15569 return NULL_TREE; 15570 return base; 15571 } 15572 15573 /* Return true if STMT_INFO accesses a decl that is known to be the 15574 argument to a vld1 in the same function. */ 15575 static bool 15576 aarch64_accesses_vector_load_decl_p (stmt_vec_info stmt_info) 15577 { 15578 if (!cfun->machine->vector_load_decls) 15579 return false; 15580 auto dr = STMT_VINFO_DATA_REF (stmt_info); 15581 if (!dr) 15582 return false; 15583 tree decl = aarch64_vector_load_decl (DR_BASE_ADDRESS (dr)); 15584 return decl && cfun->machine->vector_load_decls->contains (decl); 15585 } 15586 15587 /* Information about how the CPU would issue the scalar, Advanced SIMD 15588 or SVE version of a vector loop, using the scheme defined by the 15589 aarch64_base_vec_issue_info hierarchy of structures. */ 15590 class aarch64_vec_op_count 15591 { 15592 public: 15593 aarch64_vec_op_count () = default; 15594 aarch64_vec_op_count (const aarch64_vec_issue_info *, unsigned int, 15595 unsigned int = 1); 15596 15597 unsigned int vec_flags () const { return m_vec_flags; } 15598 unsigned int vf_factor () const { return m_vf_factor; } 15599 15600 const aarch64_base_vec_issue_info *base_issue_info () const; 15601 const aarch64_simd_vec_issue_info *simd_issue_info () const; 15602 const aarch64_sve_vec_issue_info *sve_issue_info () const; 15603 15604 fractional_cost rename_cycles_per_iter () const; 15605 fractional_cost min_nonpred_cycles_per_iter () const; 15606 fractional_cost min_pred_cycles_per_iter () const; 15607 fractional_cost min_cycles_per_iter () const; 15608 15609 void dump () const; 15610 15611 /* The number of individual "general" operations. See the comments 15612 in aarch64_base_vec_issue_info for details. */ 15613 unsigned int general_ops = 0; 15614 15615 /* The number of load and store operations, under the same scheme 15616 as above. */ 15617 unsigned int loads = 0; 15618 unsigned int stores = 0; 15619 15620 /* The minimum number of cycles needed to execute all loop-carried 15621 operations, which in the vector code become associated with 15622 reductions. */ 15623 unsigned int reduction_latency = 0; 15624 15625 /* The number of individual predicate operations. See the comments 15626 in aarch64_sve_vec_issue_info for details. */ 15627 unsigned int pred_ops = 0; 15628 15629 private: 15630 /* The issue information for the core. */ 15631 const aarch64_vec_issue_info *m_issue_info = nullptr; 15632 15633 /* - If M_VEC_FLAGS is zero then this structure describes scalar code 15634 - If M_VEC_FLAGS & VEC_ADVSIMD is nonzero then this structure describes 15635 Advanced SIMD code. 15636 - If M_VEC_FLAGS & VEC_ANY_SVE is nonzero then this structure describes 15637 SVE code. */ 15638 unsigned int m_vec_flags = 0; 15639 15640 /* Assume that, when the code is executing on the core described 15641 by M_ISSUE_INFO, one iteration of the loop will handle M_VF_FACTOR 15642 times more data than the vectorizer anticipates. 15643 15644 This is only ever different from 1 for SVE. It allows us to consider 15645 what would happen on a 256-bit SVE target even when the -mtune 15646 parameters say that the likely SVE length is 128 bits. */ 15647 unsigned int m_vf_factor = 1; 15648 }; 15649 15650 aarch64_vec_op_count:: 15651 aarch64_vec_op_count (const aarch64_vec_issue_info *issue_info, 15652 unsigned int vec_flags, unsigned int vf_factor) 15653 : m_issue_info (issue_info), 15654 m_vec_flags (vec_flags), 15655 m_vf_factor (vf_factor) 15656 { 15657 } 15658 15659 /* Return the base issue information (i.e. the parts that make sense 15660 for both scalar and vector code). Return null if we have no issue 15661 information. */ 15662 const aarch64_base_vec_issue_info * 15663 aarch64_vec_op_count::base_issue_info () const 15664 { 15665 if (auto *ret = simd_issue_info ()) 15666 return ret; 15667 return m_issue_info->scalar; 15668 } 15669 15670 /* If the structure describes vector code and we have associated issue 15671 information, return that issue information, otherwise return null. */ 15672 const aarch64_simd_vec_issue_info * 15673 aarch64_vec_op_count::simd_issue_info () const 15674 { 15675 if (auto *ret = sve_issue_info ()) 15676 return ret; 15677 if (m_vec_flags) 15678 return m_issue_info->advsimd; 15679 return nullptr; 15680 } 15681 15682 /* If the structure describes SVE code and we have associated issue 15683 information, return that issue information, otherwise return null. */ 15684 const aarch64_sve_vec_issue_info * 15685 aarch64_vec_op_count::sve_issue_info () const 15686 { 15687 if (m_vec_flags & VEC_ANY_SVE) 15688 return m_issue_info->sve; 15689 return nullptr; 15690 } 15691 15692 /* Estimate the minimum number of cycles per iteration needed to rename 15693 the instructions. 15694 15695 ??? For now this is done inline rather than via cost tables, since it 15696 isn't clear how it should be parameterized for the general case. */ 15697 fractional_cost 15698 aarch64_vec_op_count::rename_cycles_per_iter () const 15699 { 15700 if (sve_issue_info () == &neoverse512tvb_sve_issue_info 15701 || sve_issue_info () == &neoversen2_sve_issue_info 15702 || sve_issue_info () == &neoversev2_sve_issue_info) 15703 /* + 1 for an addition. We've already counted a general op for each 15704 store, so we don't need to account for stores separately. The branch 15705 reads no registers and so does not need to be counted either. 15706 15707 ??? This value is very much on the pessimistic side, but seems to work 15708 pretty well in practice. */ 15709 return { general_ops + loads + pred_ops + 1, 5 }; 15710 15711 return 0; 15712 } 15713 15714 /* Like min_cycles_per_iter, but excluding predicate operations. */ 15715 fractional_cost 15716 aarch64_vec_op_count::min_nonpred_cycles_per_iter () const 15717 { 15718 auto *issue_info = base_issue_info (); 15719 15720 fractional_cost cycles = MAX (reduction_latency, 1); 15721 cycles = std::max (cycles, { stores, issue_info->stores_per_cycle }); 15722 cycles = std::max (cycles, { loads + stores, 15723 issue_info->loads_stores_per_cycle }); 15724 cycles = std::max (cycles, { general_ops, 15725 issue_info->general_ops_per_cycle }); 15726 cycles = std::max (cycles, rename_cycles_per_iter ()); 15727 return cycles; 15728 } 15729 15730 /* Like min_cycles_per_iter, but including only the predicate operations. */ 15731 fractional_cost 15732 aarch64_vec_op_count::min_pred_cycles_per_iter () const 15733 { 15734 if (auto *issue_info = sve_issue_info ()) 15735 return { pred_ops, issue_info->pred_ops_per_cycle }; 15736 return 0; 15737 } 15738 15739 /* Estimate the minimum number of cycles needed to issue the operations. 15740 This is a very simplistic model! */ 15741 fractional_cost 15742 aarch64_vec_op_count::min_cycles_per_iter () const 15743 { 15744 return std::max (min_nonpred_cycles_per_iter (), 15745 min_pred_cycles_per_iter ()); 15746 } 15747 15748 /* Dump information about the structure. */ 15749 void 15750 aarch64_vec_op_count::dump () const 15751 { 15752 dump_printf_loc (MSG_NOTE, vect_location, 15753 " load operations = %d\n", loads); 15754 dump_printf_loc (MSG_NOTE, vect_location, 15755 " store operations = %d\n", stores); 15756 dump_printf_loc (MSG_NOTE, vect_location, 15757 " general operations = %d\n", general_ops); 15758 if (sve_issue_info ()) 15759 dump_printf_loc (MSG_NOTE, vect_location, 15760 " predicate operations = %d\n", pred_ops); 15761 dump_printf_loc (MSG_NOTE, vect_location, 15762 " reduction latency = %d\n", reduction_latency); 15763 if (auto rcpi = rename_cycles_per_iter ()) 15764 dump_printf_loc (MSG_NOTE, vect_location, 15765 " estimated cycles per iteration to rename = %f\n", 15766 rcpi.as_double ()); 15767 if (auto pred_cpi = min_pred_cycles_per_iter ()) 15768 { 15769 dump_printf_loc (MSG_NOTE, vect_location, 15770 " estimated min cycles per iteration" 15771 " without predication = %f\n", 15772 min_nonpred_cycles_per_iter ().as_double ()); 15773 dump_printf_loc (MSG_NOTE, vect_location, 15774 " estimated min cycles per iteration" 15775 " for predication = %f\n", pred_cpi.as_double ()); 15776 } 15777 if (auto cpi = min_cycles_per_iter ()) 15778 dump_printf_loc (MSG_NOTE, vect_location, 15779 " estimated min cycles per iteration = %f\n", 15780 cpi.as_double ()); 15781 } 15782 15783 /* Information about vector code that we're in the process of costing. */ 15784 class aarch64_vector_costs : public vector_costs 15785 { 15786 public: 15787 aarch64_vector_costs (vec_info *, bool); 15788 15789 unsigned int add_stmt_cost (int count, vect_cost_for_stmt kind, 15790 stmt_vec_info stmt_info, slp_tree, tree vectype, 15791 int misalign, 15792 vect_cost_model_location where) override; 15793 void finish_cost (const vector_costs *) override; 15794 bool better_main_loop_than_p (const vector_costs *other) const override; 15795 15796 private: 15797 void record_potential_advsimd_unrolling (loop_vec_info); 15798 void analyze_loop_vinfo (loop_vec_info); 15799 void count_ops (unsigned int, vect_cost_for_stmt, stmt_vec_info, 15800 aarch64_vec_op_count *); 15801 fractional_cost adjust_body_cost_sve (const aarch64_vec_op_count *, 15802 fractional_cost, unsigned int, 15803 unsigned int *, bool *); 15804 unsigned int adjust_body_cost (loop_vec_info, const aarch64_vector_costs *, 15805 unsigned int); 15806 bool prefer_unrolled_loop () const; 15807 unsigned int determine_suggested_unroll_factor (); 15808 15809 /* True if we have performed one-time initialization based on the 15810 vec_info. */ 15811 bool m_analyzed_vinfo = false; 15812 15813 /* This loop uses an average operation that is not supported by SVE, but is 15814 supported by Advanced SIMD and SVE2. */ 15815 bool m_has_avg = false; 15816 15817 /* True if the vector body contains a store to a decl and if the 15818 function is known to have a vld1 from the same decl. 15819 15820 In the Advanced SIMD ACLE, the recommended endian-agnostic way of 15821 initializing a vector is: 15822 15823 float f[4] = { elts }; 15824 float32x4_t x = vld1q_f32(f); 15825 15826 We should strongly prefer vectorization of the initialization of f, 15827 so that the store to f and the load back can be optimized away, 15828 leaving a vectorization of { elts }. */ 15829 bool m_stores_to_vector_load_decl = false; 15830 15831 /* - If M_VEC_FLAGS is zero then we're costing the original scalar code. 15832 - If M_VEC_FLAGS & VEC_ADVSIMD is nonzero then we're costing Advanced 15833 SIMD code. 15834 - If M_VEC_FLAGS & VEC_ANY_SVE is nonzero then we're costing SVE code. */ 15835 unsigned int m_vec_flags = 0; 15836 15837 /* At the moment, we do not model LDP and STP in the vector and scalar costs. 15838 This means that code such as: 15839 15840 a[0] = x; 15841 a[1] = x; 15842 15843 will be costed as two scalar instructions and two vector instructions 15844 (a scalar_to_vec and an unaligned_store). For SLP, the vector form 15845 wins if the costs are equal, because of the fact that the vector costs 15846 include constant initializations whereas the scalar costs don't. 15847 We would therefore tend to vectorize the code above, even though 15848 the scalar version can use a single STP. 15849 15850 We should eventually fix this and model LDP and STP in the main costs; 15851 see the comment in aarch64_sve_adjust_stmt_cost for some of the problems. 15852 Until then, we look specifically for code that does nothing more than 15853 STP-like operations. We cost them on that basis in addition to the 15854 normal latency-based costs. 15855 15856 If the scalar or vector code could be a sequence of STPs + 15857 initialization, this variable counts the cost of the sequence, 15858 with 2 units per instruction. The variable is ~0U for other 15859 kinds of code. */ 15860 unsigned int m_stp_sequence_cost = 0; 15861 15862 /* On some CPUs, SVE and Advanced SIMD provide the same theoretical vector 15863 throughput, such as 4x128 Advanced SIMD vs. 2x256 SVE. In those 15864 situations, we try to predict whether an Advanced SIMD implementation 15865 of the loop could be completely unrolled and become straight-line code. 15866 If so, it is generally better to use the Advanced SIMD version rather 15867 than length-agnostic SVE, since the SVE loop would execute an unknown 15868 number of times and so could not be completely unrolled in the same way. 15869 15870 If we're applying this heuristic, M_UNROLLED_ADVSIMD_NITERS is the 15871 number of Advanced SIMD loop iterations that would be unrolled and 15872 M_UNROLLED_ADVSIMD_STMTS estimates the total number of statements 15873 in the unrolled loop. Both values are zero if we're not applying 15874 the heuristic. */ 15875 unsigned HOST_WIDE_INT m_unrolled_advsimd_niters = 0; 15876 unsigned HOST_WIDE_INT m_unrolled_advsimd_stmts = 0; 15877 15878 /* If we're vectorizing a loop that executes a constant number of times, 15879 this variable gives the number of times that the vector loop would 15880 iterate, otherwise it is zero. */ 15881 uint64_t m_num_vector_iterations = 0; 15882 15883 /* Used only when vectorizing loops. Estimates the number and kind of 15884 operations that would be needed by one iteration of the scalar 15885 or vector loop. There is one entry for each tuning option of 15886 interest. */ 15887 auto_vec<aarch64_vec_op_count, 2> m_ops; 15888 }; 15889 15890 aarch64_vector_costs::aarch64_vector_costs (vec_info *vinfo, 15891 bool costing_for_scalar) 15892 : vector_costs (vinfo, costing_for_scalar), 15893 m_vec_flags (costing_for_scalar ? 0 15894 : aarch64_classify_vector_mode (vinfo->vector_mode)) 15895 { 15896 if (auto *issue_info = aarch64_tune_params.vec_costs->issue_info) 15897 { 15898 m_ops.quick_push ({ issue_info, m_vec_flags }); 15899 if (aarch64_tune_params.vec_costs == &neoverse512tvb_vector_cost) 15900 { 15901 unsigned int vf_factor = (m_vec_flags & VEC_ANY_SVE) ? 2 : 1; 15902 m_ops.quick_push ({ &neoversev1_vec_issue_info, m_vec_flags, 15903 vf_factor }); 15904 } 15905 } 15906 } 15907 15908 /* Implement TARGET_VECTORIZE_CREATE_COSTS. */ 15909 vector_costs * 15910 aarch64_vectorize_create_costs (vec_info *vinfo, bool costing_for_scalar) 15911 { 15912 return new aarch64_vector_costs (vinfo, costing_for_scalar); 15913 } 15914 15915 /* Return true if the current CPU should use the new costs defined 15916 in GCC 11. This should be removed for GCC 12 and above, with the 15917 costs applying to all CPUs instead. */ 15918 static bool 15919 aarch64_use_new_vector_costs_p () 15920 { 15921 return (aarch64_tune_params.extra_tuning_flags 15922 & AARCH64_EXTRA_TUNE_USE_NEW_VECTOR_COSTS); 15923 } 15924 15925 /* Return the appropriate SIMD costs for vectors of type VECTYPE. */ 15926 static const simd_vec_cost * 15927 aarch64_simd_vec_costs (tree vectype) 15928 { 15929 const cpu_vector_cost *costs = aarch64_tune_params.vec_costs; 15930 if (vectype != NULL 15931 && aarch64_sve_mode_p (TYPE_MODE (vectype)) 15932 && costs->sve != NULL) 15933 return costs->sve; 15934 return costs->advsimd; 15935 } 15936 15937 /* Return the appropriate SIMD costs for vectors with VEC_* flags FLAGS. */ 15938 static const simd_vec_cost * 15939 aarch64_simd_vec_costs_for_flags (unsigned int flags) 15940 { 15941 const cpu_vector_cost *costs = aarch64_tune_params.vec_costs; 15942 if ((flags & VEC_ANY_SVE) && costs->sve) 15943 return costs->sve; 15944 return costs->advsimd; 15945 } 15946 15947 /* If STMT_INFO is a memory reference, return the scalar memory type, 15948 otherwise return null. */ 15949 static tree 15950 aarch64_dr_type (stmt_vec_info stmt_info) 15951 { 15952 if (auto dr = STMT_VINFO_DATA_REF (stmt_info)) 15953 return TREE_TYPE (DR_REF (dr)); 15954 return NULL_TREE; 15955 } 15956 15957 /* Decide whether to use the unrolling heuristic described above 15958 m_unrolled_advsimd_niters, updating that field if so. LOOP_VINFO 15959 describes the loop that we're vectorizing. */ 15960 void 15961 aarch64_vector_costs:: 15962 record_potential_advsimd_unrolling (loop_vec_info loop_vinfo) 15963 { 15964 /* The heuristic only makes sense on targets that have the same 15965 vector throughput for SVE and Advanced SIMD. */ 15966 if (!(aarch64_tune_params.extra_tuning_flags 15967 & AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT)) 15968 return; 15969 15970 /* We only want to apply the heuristic if LOOP_VINFO is being 15971 vectorized for SVE. */ 15972 if (!(m_vec_flags & VEC_ANY_SVE)) 15973 return; 15974 15975 /* Check whether it is possible in principle to use Advanced SIMD 15976 instead. */ 15977 if (aarch64_autovec_preference == 2) 15978 return; 15979 15980 /* We don't want to apply the heuristic to outer loops, since it's 15981 harder to track two levels of unrolling. */ 15982 if (LOOP_VINFO_LOOP (loop_vinfo)->inner) 15983 return; 15984 15985 /* Only handle cases in which the number of Advanced SIMD iterations 15986 would be known at compile time but the number of SVE iterations 15987 would not. */ 15988 if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo) 15989 || aarch64_sve_vg.is_constant ()) 15990 return; 15991 15992 /* Guess how many times the Advanced SIMD loop would iterate and make 15993 sure that it is within the complete unrolling limit. Even if the 15994 number of iterations is small enough, the number of statements might 15995 not be, which is why we need to estimate the number of statements too. */ 15996 unsigned int estimated_vq = aarch64_estimated_sve_vq (); 15997 unsigned int advsimd_vf = CEIL (vect_vf_for_cost (loop_vinfo), estimated_vq); 15998 unsigned HOST_WIDE_INT unrolled_advsimd_niters 15999 = LOOP_VINFO_INT_NITERS (loop_vinfo) / advsimd_vf; 16000 if (unrolled_advsimd_niters > (unsigned int) param_max_completely_peel_times) 16001 return; 16002 16003 /* Record that we're applying the heuristic and should try to estimate 16004 the number of statements in the Advanced SIMD loop. */ 16005 m_unrolled_advsimd_niters = unrolled_advsimd_niters; 16006 } 16007 16008 /* Do one-time initialization of the aarch64_vector_costs given that we're 16009 costing the loop vectorization described by LOOP_VINFO. */ 16010 void 16011 aarch64_vector_costs::analyze_loop_vinfo (loop_vec_info loop_vinfo) 16012 { 16013 /* Record the number of times that the vector loop would execute, 16014 if known. */ 16015 class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); 16016 auto scalar_niters = max_stmt_executions_int (loop); 16017 if (scalar_niters >= 0) 16018 { 16019 unsigned int vf = vect_vf_for_cost (loop_vinfo); 16020 if (LOOP_VINFO_MASKS (loop_vinfo).is_empty ()) 16021 m_num_vector_iterations = scalar_niters / vf; 16022 else 16023 m_num_vector_iterations = CEIL (scalar_niters, vf); 16024 } 16025 16026 /* Detect whether we're vectorizing for SVE and should apply the unrolling 16027 heuristic described above m_unrolled_advsimd_niters. */ 16028 record_potential_advsimd_unrolling (loop_vinfo); 16029 16030 /* Record the issue information for any SVE WHILE instructions that the 16031 loop needs. */ 16032 if (!m_ops.is_empty () && !LOOP_VINFO_MASKS (loop_vinfo).is_empty ()) 16033 { 16034 unsigned int num_masks = 0; 16035 rgroup_controls *rgm; 16036 unsigned int num_vectors_m1; 16037 FOR_EACH_VEC_ELT (LOOP_VINFO_MASKS (loop_vinfo), num_vectors_m1, rgm) 16038 if (rgm->type) 16039 num_masks += num_vectors_m1 + 1; 16040 for (auto &ops : m_ops) 16041 if (auto *issue = ops.sve_issue_info ()) 16042 ops.pred_ops += num_masks * issue->while_pred_ops; 16043 } 16044 } 16045 16046 /* Implement targetm.vectorize.builtin_vectorization_cost. */ 16047 static int 16048 aarch64_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost, 16049 tree vectype, 16050 int misalign ATTRIBUTE_UNUSED) 16051 { 16052 unsigned elements; 16053 const cpu_vector_cost *costs = aarch64_tune_params.vec_costs; 16054 bool fp = false; 16055 16056 if (vectype != NULL) 16057 fp = FLOAT_TYPE_P (vectype); 16058 16059 const simd_vec_cost *simd_costs = aarch64_simd_vec_costs (vectype); 16060 16061 switch (type_of_cost) 16062 { 16063 case scalar_stmt: 16064 return fp ? costs->scalar_fp_stmt_cost : costs->scalar_int_stmt_cost; 16065 16066 case scalar_load: 16067 return costs->scalar_load_cost; 16068 16069 case scalar_store: 16070 return costs->scalar_store_cost; 16071 16072 case vector_stmt: 16073 return fp ? simd_costs->fp_stmt_cost 16074 : simd_costs->int_stmt_cost; 16075 16076 case vector_load: 16077 return simd_costs->align_load_cost; 16078 16079 case vector_store: 16080 return simd_costs->store_cost; 16081 16082 case vec_to_scalar: 16083 return simd_costs->vec_to_scalar_cost; 16084 16085 case scalar_to_vec: 16086 return simd_costs->scalar_to_vec_cost; 16087 16088 case unaligned_load: 16089 case vector_gather_load: 16090 return simd_costs->unalign_load_cost; 16091 16092 case unaligned_store: 16093 case vector_scatter_store: 16094 return simd_costs->unalign_store_cost; 16095 16096 case cond_branch_taken: 16097 return costs->cond_taken_branch_cost; 16098 16099 case cond_branch_not_taken: 16100 return costs->cond_not_taken_branch_cost; 16101 16102 case vec_perm: 16103 return simd_costs->permute_cost; 16104 16105 case vec_promote_demote: 16106 return fp ? simd_costs->fp_stmt_cost 16107 : simd_costs->int_stmt_cost; 16108 16109 case vec_construct: 16110 elements = estimated_poly_value (TYPE_VECTOR_SUBPARTS (vectype)); 16111 return elements / 2 + 1; 16112 16113 default: 16114 gcc_unreachable (); 16115 } 16116 } 16117 16118 /* Return true if an access of kind KIND for STMT_INFO represents one 16119 vector of an LD[234] or ST[234] operation. Return the total number of 16120 vectors (2, 3 or 4) if so, otherwise return a value outside that range. */ 16121 static int 16122 aarch64_ld234_st234_vectors (vect_cost_for_stmt kind, stmt_vec_info stmt_info) 16123 { 16124 if ((kind == vector_load 16125 || kind == unaligned_load 16126 || kind == vector_store 16127 || kind == unaligned_store) 16128 && STMT_VINFO_DATA_REF (stmt_info)) 16129 { 16130 stmt_info = DR_GROUP_FIRST_ELEMENT (stmt_info); 16131 if (stmt_info 16132 && STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) == VMAT_LOAD_STORE_LANES) 16133 return DR_GROUP_SIZE (stmt_info); 16134 } 16135 return 0; 16136 } 16137 16138 /* Return true if creating multiple copies of STMT_INFO for Advanced SIMD 16139 vectors would produce a series of LDP or STP operations. KIND is the 16140 kind of statement that STMT_INFO represents. */ 16141 static bool 16142 aarch64_advsimd_ldp_stp_p (enum vect_cost_for_stmt kind, 16143 stmt_vec_info stmt_info) 16144 { 16145 switch (kind) 16146 { 16147 case vector_load: 16148 case vector_store: 16149 case unaligned_load: 16150 case unaligned_store: 16151 break; 16152 16153 default: 16154 return false; 16155 } 16156 16157 if (aarch64_tune_params.extra_tuning_flags 16158 & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS) 16159 return false; 16160 16161 return is_gimple_assign (stmt_info->stmt); 16162 } 16163 16164 /* Return true if STMT_INFO is the second part of a two-statement multiply-add 16165 or multiply-subtract sequence that might be suitable for fusing into a 16166 single instruction. If VEC_FLAGS is zero, analyze the operation as 16167 a scalar one, otherwise analyze it as an operation on vectors with those 16168 VEC_* flags. */ 16169 static bool 16170 aarch64_multiply_add_p (vec_info *vinfo, stmt_vec_info stmt_info, 16171 unsigned int vec_flags) 16172 { 16173 gassign *assign = dyn_cast<gassign *> (stmt_info->stmt); 16174 if (!assign) 16175 return false; 16176 tree_code code = gimple_assign_rhs_code (assign); 16177 if (code != PLUS_EXPR && code != MINUS_EXPR) 16178 return false; 16179 16180 if (CONSTANT_CLASS_P (gimple_assign_rhs1 (assign)) 16181 || CONSTANT_CLASS_P (gimple_assign_rhs2 (assign))) 16182 return false; 16183 16184 for (int i = 1; i < 3; ++i) 16185 { 16186 tree rhs = gimple_op (assign, i); 16187 /* ??? Should we try to check for a single use as well? */ 16188 if (TREE_CODE (rhs) != SSA_NAME) 16189 continue; 16190 16191 stmt_vec_info def_stmt_info = vinfo->lookup_def (rhs); 16192 if (!def_stmt_info 16193 || STMT_VINFO_DEF_TYPE (def_stmt_info) != vect_internal_def) 16194 continue; 16195 gassign *rhs_assign = dyn_cast<gassign *> (def_stmt_info->stmt); 16196 if (!rhs_assign || gimple_assign_rhs_code (rhs_assign) != MULT_EXPR) 16197 continue; 16198 16199 if (vec_flags & VEC_ADVSIMD) 16200 { 16201 /* Scalar and SVE code can tie the result to any FMLA input (or none, 16202 although that requires a MOVPRFX for SVE). However, Advanced SIMD 16203 only supports MLA forms, so will require a move if the result 16204 cannot be tied to the accumulator. The most important case in 16205 which this is true is when the accumulator input is invariant. */ 16206 rhs = gimple_op (assign, 3 - i); 16207 if (TREE_CODE (rhs) != SSA_NAME) 16208 return false; 16209 def_stmt_info = vinfo->lookup_def (rhs); 16210 if (!def_stmt_info 16211 || STMT_VINFO_DEF_TYPE (def_stmt_info) == vect_external_def) 16212 return false; 16213 } 16214 16215 return true; 16216 } 16217 return false; 16218 } 16219 16220 /* We are considering implementing STMT_INFO using SVE. If STMT_INFO is an 16221 in-loop reduction that SVE supports directly, return its latency in cycles, 16222 otherwise return zero. SVE_COSTS specifies the latencies of the relevant 16223 instructions. */ 16224 static unsigned int 16225 aarch64_sve_in_loop_reduction_latency (vec_info *vinfo, 16226 stmt_vec_info stmt_info, 16227 const sve_vec_cost *sve_costs) 16228 { 16229 switch (vect_reduc_type (vinfo, stmt_info)) 16230 { 16231 case EXTRACT_LAST_REDUCTION: 16232 return sve_costs->clast_cost; 16233 16234 case FOLD_LEFT_REDUCTION: 16235 switch (TYPE_MODE (TREE_TYPE (gimple_get_lhs (stmt_info->stmt)))) 16236 { 16237 case E_HFmode: 16238 case E_BFmode: 16239 return sve_costs->fadda_f16_cost; 16240 16241 case E_SFmode: 16242 return sve_costs->fadda_f32_cost; 16243 16244 case E_DFmode: 16245 return sve_costs->fadda_f64_cost; 16246 16247 default: 16248 break; 16249 } 16250 break; 16251 } 16252 16253 return 0; 16254 } 16255 16256 /* STMT_INFO describes a loop-carried operation in the original scalar code 16257 that we are considering implementing as a reduction. Return one of the 16258 following values, depending on VEC_FLAGS: 16259 16260 - If VEC_FLAGS is zero, return the loop carry latency of the original 16261 scalar operation. 16262 16263 - If VEC_FLAGS & VEC_ADVSIMD, return the loop carry latency of the 16264 Advanced SIMD implementation. 16265 16266 - If VEC_FLAGS & VEC_ANY_SVE, return the loop carry latency of the 16267 SVE implementation. */ 16268 static unsigned int 16269 aarch64_in_loop_reduction_latency (vec_info *vinfo, stmt_vec_info stmt_info, 16270 unsigned int vec_flags) 16271 { 16272 const cpu_vector_cost *vec_costs = aarch64_tune_params.vec_costs; 16273 const sve_vec_cost *sve_costs = nullptr; 16274 if (vec_flags & VEC_ANY_SVE) 16275 sve_costs = aarch64_tune_params.vec_costs->sve; 16276 16277 /* If the caller is asking for the SVE latency, check for forms of reduction 16278 that only SVE can handle directly. */ 16279 if (sve_costs) 16280 { 16281 unsigned int latency 16282 = aarch64_sve_in_loop_reduction_latency (vinfo, stmt_info, sve_costs); 16283 if (latency) 16284 return latency; 16285 } 16286 16287 /* Handle scalar costs. */ 16288 bool is_float = FLOAT_TYPE_P (TREE_TYPE (gimple_get_lhs (stmt_info->stmt))); 16289 if (vec_flags == 0) 16290 { 16291 if (is_float) 16292 return vec_costs->scalar_fp_stmt_cost; 16293 return vec_costs->scalar_int_stmt_cost; 16294 } 16295 16296 /* Otherwise, the loop body just contains normal integer or FP operations, 16297 with a vector reduction outside the loop. */ 16298 const simd_vec_cost *simd_costs 16299 = aarch64_simd_vec_costs_for_flags (vec_flags); 16300 if (is_float) 16301 return simd_costs->fp_stmt_cost; 16302 return simd_costs->int_stmt_cost; 16303 } 16304 16305 /* STMT_COST is the cost calculated by aarch64_builtin_vectorization_cost 16306 for STMT_INFO, which has cost kind KIND. If this is a scalar operation, 16307 try to subdivide the target-independent categorization provided by KIND 16308 to get a more accurate cost. */ 16309 static fractional_cost 16310 aarch64_detect_scalar_stmt_subtype (vec_info *vinfo, vect_cost_for_stmt kind, 16311 stmt_vec_info stmt_info, 16312 fractional_cost stmt_cost) 16313 { 16314 /* Detect an extension of a loaded value. In general, we'll be able to fuse 16315 the extension with the load. */ 16316 if (kind == scalar_stmt && vect_is_extending_load (vinfo, stmt_info)) 16317 return 0; 16318 16319 return stmt_cost; 16320 } 16321 16322 /* STMT_COST is the cost calculated by aarch64_builtin_vectorization_cost 16323 for the vectorized form of STMT_INFO, which has cost kind KIND and which 16324 when vectorized would operate on vector type VECTYPE. Try to subdivide 16325 the target-independent categorization provided by KIND to get a more 16326 accurate cost. WHERE specifies where the cost associated with KIND 16327 occurs. */ 16328 static fractional_cost 16329 aarch64_detect_vector_stmt_subtype (vec_info *vinfo, vect_cost_for_stmt kind, 16330 stmt_vec_info stmt_info, tree vectype, 16331 enum vect_cost_model_location where, 16332 fractional_cost stmt_cost) 16333 { 16334 const simd_vec_cost *simd_costs = aarch64_simd_vec_costs (vectype); 16335 const sve_vec_cost *sve_costs = nullptr; 16336 if (aarch64_sve_mode_p (TYPE_MODE (vectype))) 16337 sve_costs = aarch64_tune_params.vec_costs->sve; 16338 16339 /* It's generally better to avoid costing inductions, since the induction 16340 will usually be hidden by other operations. This is particularly true 16341 for things like COND_REDUCTIONS. */ 16342 if (is_a<gphi *> (stmt_info->stmt)) 16343 return 0; 16344 16345 /* Detect cases in which vec_to_scalar is describing the extraction of a 16346 vector element in preparation for a scalar store. The store itself is 16347 costed separately. */ 16348 if (vect_is_store_elt_extraction (kind, stmt_info)) 16349 return simd_costs->store_elt_extra_cost; 16350 16351 /* Detect SVE gather loads, which are costed as a single scalar_load 16352 for each element. We therefore need to divide the full-instruction 16353 cost by the number of elements in the vector. */ 16354 if (kind == scalar_load 16355 && sve_costs 16356 && STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) == VMAT_GATHER_SCATTER) 16357 { 16358 unsigned int nunits = vect_nunits_for_cost (vectype); 16359 if (GET_MODE_UNIT_BITSIZE (TYPE_MODE (vectype)) == 64) 16360 return { sve_costs->gather_load_x64_cost, nunits }; 16361 return { sve_costs->gather_load_x32_cost, nunits }; 16362 } 16363 16364 /* Detect cases in which a scalar_store is really storing one element 16365 in a scatter operation. */ 16366 if (kind == scalar_store 16367 && sve_costs 16368 && STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) == VMAT_GATHER_SCATTER) 16369 return sve_costs->scatter_store_elt_cost; 16370 16371 /* Detect cases in which vec_to_scalar represents an in-loop reduction. */ 16372 if (kind == vec_to_scalar 16373 && where == vect_body 16374 && sve_costs) 16375 { 16376 unsigned int latency 16377 = aarch64_sve_in_loop_reduction_latency (vinfo, stmt_info, sve_costs); 16378 if (latency) 16379 return latency; 16380 } 16381 16382 /* Detect cases in which vec_to_scalar represents a single reduction 16383 instruction like FADDP or MAXV. */ 16384 if (kind == vec_to_scalar 16385 && where == vect_epilogue 16386 && vect_is_reduction (stmt_info)) 16387 switch (GET_MODE_INNER (TYPE_MODE (vectype))) 16388 { 16389 case E_QImode: 16390 return simd_costs->reduc_i8_cost; 16391 16392 case E_HImode: 16393 return simd_costs->reduc_i16_cost; 16394 16395 case E_SImode: 16396 return simd_costs->reduc_i32_cost; 16397 16398 case E_DImode: 16399 return simd_costs->reduc_i64_cost; 16400 16401 case E_HFmode: 16402 case E_BFmode: 16403 return simd_costs->reduc_f16_cost; 16404 16405 case E_SFmode: 16406 return simd_costs->reduc_f32_cost; 16407 16408 case E_DFmode: 16409 return simd_costs->reduc_f64_cost; 16410 16411 default: 16412 break; 16413 } 16414 16415 /* Otherwise stick with the original categorization. */ 16416 return stmt_cost; 16417 } 16418 16419 /* STMT_COST is the cost calculated by aarch64_builtin_vectorization_cost 16420 for STMT_INFO, which has cost kind KIND and which when vectorized would 16421 operate on vector type VECTYPE. Adjust the cost as necessary for SVE 16422 targets. */ 16423 static fractional_cost 16424 aarch64_sve_adjust_stmt_cost (class vec_info *vinfo, vect_cost_for_stmt kind, 16425 stmt_vec_info stmt_info, tree vectype, 16426 fractional_cost stmt_cost) 16427 { 16428 /* Unlike vec_promote_demote, vector_stmt conversions do not change the 16429 vector register size or number of units. Integer promotions of this 16430 type therefore map to SXT[BHW] or UXT[BHW]. 16431 16432 Most loads have extending forms that can do the sign or zero extension 16433 on the fly. Optimistically assume that a load followed by an extension 16434 will fold to this form during combine, and that the extension therefore 16435 comes for free. */ 16436 if (kind == vector_stmt && vect_is_extending_load (vinfo, stmt_info)) 16437 stmt_cost = 0; 16438 16439 /* For similar reasons, vector_stmt integer truncations are a no-op, 16440 because we can just ignore the unused upper bits of the source. */ 16441 if (kind == vector_stmt && vect_is_integer_truncation (stmt_info)) 16442 stmt_cost = 0; 16443 16444 /* Advanced SIMD can load and store pairs of registers using LDP and STP, 16445 but there are no equivalent instructions for SVE. This means that 16446 (all other things being equal) 128-bit SVE needs twice as many load 16447 and store instructions as Advanced SIMD in order to process vector pairs. 16448 16449 Also, scalar code can often use LDP and STP to access pairs of values, 16450 so it is too simplistic to say that one SVE load or store replaces 16451 VF scalar loads and stores. 16452 16453 Ideally we would account for this in the scalar and Advanced SIMD 16454 costs by making suitable load/store pairs as cheap as a single 16455 load/store. However, that would be a very invasive change and in 16456 practice it tends to stress other parts of the cost model too much. 16457 E.g. stores of scalar constants currently count just a store, 16458 whereas stores of vector constants count a store and a vec_init. 16459 This is an artificial distinction for AArch64, where stores of 16460 nonzero scalar constants need the same kind of register invariant 16461 as vector stores. 16462 16463 An alternative would be to double the cost of any SVE loads and stores 16464 that could be paired in Advanced SIMD (and possibly also paired in 16465 scalar code). But this tends to stress other parts of the cost model 16466 in the same way. It also means that we can fall back to Advanced SIMD 16467 even if full-loop predication would have been useful. 16468 16469 Here we go for a more conservative version: double the costs of SVE 16470 loads and stores if one iteration of the scalar loop processes enough 16471 elements for it to use a whole number of Advanced SIMD LDP or STP 16472 instructions. This makes it very likely that the VF would be 1 for 16473 Advanced SIMD, and so no epilogue should be needed. */ 16474 if (STMT_VINFO_GROUPED_ACCESS (stmt_info)) 16475 { 16476 stmt_vec_info first = DR_GROUP_FIRST_ELEMENT (stmt_info); 16477 unsigned int count = DR_GROUP_SIZE (first) - DR_GROUP_GAP (first); 16478 unsigned int elt_bits = GET_MODE_UNIT_BITSIZE (TYPE_MODE (vectype)); 16479 if (multiple_p (count * elt_bits, 256) 16480 && aarch64_advsimd_ldp_stp_p (kind, stmt_info)) 16481 stmt_cost *= 2; 16482 } 16483 16484 return stmt_cost; 16485 } 16486 16487 /* STMT_COST is the cost calculated for STMT_INFO, which has cost kind KIND 16488 and which when vectorized would operate on vector type VECTYPE. Add the 16489 cost of any embedded operations. */ 16490 static fractional_cost 16491 aarch64_adjust_stmt_cost (vect_cost_for_stmt kind, stmt_vec_info stmt_info, 16492 tree vectype, fractional_cost stmt_cost) 16493 { 16494 if (vectype) 16495 { 16496 const simd_vec_cost *simd_costs = aarch64_simd_vec_costs (vectype); 16497 16498 /* Detect cases in which a vector load or store represents an 16499 LD[234] or ST[234] instruction. */ 16500 switch (aarch64_ld234_st234_vectors (kind, stmt_info)) 16501 { 16502 case 2: 16503 stmt_cost += simd_costs->ld2_st2_permute_cost; 16504 break; 16505 16506 case 3: 16507 stmt_cost += simd_costs->ld3_st3_permute_cost; 16508 break; 16509 16510 case 4: 16511 stmt_cost += simd_costs->ld4_st4_permute_cost; 16512 break; 16513 } 16514 16515 if (kind == vector_stmt || kind == vec_to_scalar) 16516 if (tree cmp_type = vect_embedded_comparison_type (stmt_info)) 16517 { 16518 if (FLOAT_TYPE_P (cmp_type)) 16519 stmt_cost += simd_costs->fp_stmt_cost; 16520 else 16521 stmt_cost += simd_costs->int_stmt_cost; 16522 } 16523 } 16524 16525 if (kind == scalar_stmt) 16526 if (tree cmp_type = vect_embedded_comparison_type (stmt_info)) 16527 { 16528 if (FLOAT_TYPE_P (cmp_type)) 16529 stmt_cost += aarch64_tune_params.vec_costs->scalar_fp_stmt_cost; 16530 else 16531 stmt_cost += aarch64_tune_params.vec_costs->scalar_int_stmt_cost; 16532 } 16533 16534 return stmt_cost; 16535 } 16536 16537 /* COUNT, KIND and STMT_INFO are the same as for vector_costs::add_stmt_cost 16538 and they describe an operation in the body of a vector loop. Record issue 16539 information relating to the vector operation in OPS. */ 16540 void 16541 aarch64_vector_costs::count_ops (unsigned int count, vect_cost_for_stmt kind, 16542 stmt_vec_info stmt_info, 16543 aarch64_vec_op_count *ops) 16544 { 16545 const aarch64_base_vec_issue_info *base_issue = ops->base_issue_info (); 16546 if (!base_issue) 16547 return; 16548 const aarch64_simd_vec_issue_info *simd_issue = ops->simd_issue_info (); 16549 const aarch64_sve_vec_issue_info *sve_issue = ops->sve_issue_info (); 16550 16551 /* Calculate the minimum cycles per iteration imposed by a reduction 16552 operation. */ 16553 if ((kind == scalar_stmt || kind == vector_stmt || kind == vec_to_scalar) 16554 && vect_is_reduction (stmt_info)) 16555 { 16556 unsigned int base 16557 = aarch64_in_loop_reduction_latency (m_vinfo, stmt_info, m_vec_flags); 16558 16559 /* ??? Ideally we'd do COUNT reductions in parallel, but unfortunately 16560 that's not yet the case. */ 16561 ops->reduction_latency = MAX (ops->reduction_latency, base * count); 16562 } 16563 16564 /* Assume that multiply-adds will become a single operation. */ 16565 if (stmt_info && aarch64_multiply_add_p (m_vinfo, stmt_info, m_vec_flags)) 16566 return; 16567 16568 /* Count the basic operation cost associated with KIND. */ 16569 switch (kind) 16570 { 16571 case cond_branch_taken: 16572 case cond_branch_not_taken: 16573 case vector_gather_load: 16574 case vector_scatter_store: 16575 /* We currently don't expect these to be used in a loop body. */ 16576 break; 16577 16578 case vec_perm: 16579 case vec_promote_demote: 16580 case vec_construct: 16581 case vec_to_scalar: 16582 case scalar_to_vec: 16583 case vector_stmt: 16584 case scalar_stmt: 16585 ops->general_ops += count; 16586 break; 16587 16588 case scalar_load: 16589 case vector_load: 16590 case unaligned_load: 16591 ops->loads += count; 16592 if (m_vec_flags || FLOAT_TYPE_P (aarch64_dr_type (stmt_info))) 16593 ops->general_ops += base_issue->fp_simd_load_general_ops * count; 16594 break; 16595 16596 case vector_store: 16597 case unaligned_store: 16598 case scalar_store: 16599 ops->stores += count; 16600 if (m_vec_flags || FLOAT_TYPE_P (aarch64_dr_type (stmt_info))) 16601 ops->general_ops += base_issue->fp_simd_store_general_ops * count; 16602 break; 16603 } 16604 16605 /* Add any embedded comparison operations. */ 16606 if ((kind == scalar_stmt || kind == vector_stmt || kind == vec_to_scalar) 16607 && vect_embedded_comparison_type (stmt_info)) 16608 ops->general_ops += count; 16609 16610 /* COND_REDUCTIONS need two sets of VEC_COND_EXPRs, whereas so far we 16611 have only accounted for one. */ 16612 if ((kind == vector_stmt || kind == vec_to_scalar) 16613 && vect_reduc_type (m_vinfo, stmt_info) == COND_REDUCTION) 16614 ops->general_ops += count; 16615 16616 /* Count the predicate operations needed by an SVE comparison. */ 16617 if (sve_issue && (kind == vector_stmt || kind == vec_to_scalar)) 16618 if (tree type = vect_comparison_type (stmt_info)) 16619 { 16620 unsigned int base = (FLOAT_TYPE_P (type) 16621 ? sve_issue->fp_cmp_pred_ops 16622 : sve_issue->int_cmp_pred_ops); 16623 ops->pred_ops += base * count; 16624 } 16625 16626 /* Add any extra overhead associated with LD[234] and ST[234] operations. */ 16627 if (simd_issue) 16628 switch (aarch64_ld234_st234_vectors (kind, stmt_info)) 16629 { 16630 case 2: 16631 ops->general_ops += simd_issue->ld2_st2_general_ops * count; 16632 break; 16633 16634 case 3: 16635 ops->general_ops += simd_issue->ld3_st3_general_ops * count; 16636 break; 16637 16638 case 4: 16639 ops->general_ops += simd_issue->ld4_st4_general_ops * count; 16640 break; 16641 } 16642 16643 /* Add any overhead associated with gather loads and scatter stores. */ 16644 if (sve_issue 16645 && (kind == scalar_load || kind == scalar_store) 16646 && STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) == VMAT_GATHER_SCATTER) 16647 { 16648 unsigned int pairs = CEIL (count, 2); 16649 ops->pred_ops += sve_issue->gather_scatter_pair_pred_ops * pairs; 16650 ops->general_ops += sve_issue->gather_scatter_pair_general_ops * pairs; 16651 } 16652 } 16653 16654 /* Return true if STMT_INFO contains a memory access and if the constant 16655 component of the memory address is aligned to SIZE bytes. */ 16656 static bool 16657 aarch64_aligned_constant_offset_p (stmt_vec_info stmt_info, 16658 poly_uint64 size) 16659 { 16660 if (!STMT_VINFO_DATA_REF (stmt_info)) 16661 return false; 16662 16663 if (auto first_stmt = DR_GROUP_FIRST_ELEMENT (stmt_info)) 16664 stmt_info = first_stmt; 16665 tree constant_offset = DR_INIT (STMT_VINFO_DATA_REF (stmt_info)); 16666 /* Needed for gathers & scatters, for example. */ 16667 if (!constant_offset) 16668 return false; 16669 16670 return multiple_p (wi::to_poly_offset (constant_offset), size); 16671 } 16672 16673 /* Check if a scalar or vector stmt could be part of a region of code 16674 that does nothing more than store values to memory, in the scalar 16675 case using STP. Return the cost of the stmt if so, counting 2 for 16676 one instruction. Return ~0U otherwise. 16677 16678 The arguments are a subset of those passed to add_stmt_cost. */ 16679 unsigned int 16680 aarch64_stp_sequence_cost (unsigned int count, vect_cost_for_stmt kind, 16681 stmt_vec_info stmt_info, tree vectype) 16682 { 16683 /* Code that stores vector constants uses a vector_load to create 16684 the constant. We don't apply the heuristic to that case for two 16685 main reasons: 16686 16687 - At the moment, STPs are only formed via peephole2, and the 16688 constant scalar moves would often come between STRs and so 16689 prevent STP formation. 16690 16691 - The scalar code also has to load the constant somehow, and that 16692 isn't costed. */ 16693 switch (kind) 16694 { 16695 case scalar_to_vec: 16696 /* Count 2 insns for a GPR->SIMD dup and 1 insn for a FPR->SIMD dup. */ 16697 return (FLOAT_TYPE_P (vectype) ? 2 : 4) * count; 16698 16699 case vec_construct: 16700 if (FLOAT_TYPE_P (vectype)) 16701 /* Count 1 insn for the maximum number of FP->SIMD INS 16702 instructions. */ 16703 return (vect_nunits_for_cost (vectype) - 1) * 2 * count; 16704 16705 /* Count 2 insns for a GPR->SIMD move and 2 insns for the 16706 maximum number of GPR->SIMD INS instructions. */ 16707 return vect_nunits_for_cost (vectype) * 4 * count; 16708 16709 case vector_store: 16710 case unaligned_store: 16711 /* Count 1 insn per vector if we can't form STP Q pairs. */ 16712 if (aarch64_sve_mode_p (TYPE_MODE (vectype))) 16713 return count * 2; 16714 if (aarch64_tune_params.extra_tuning_flags 16715 & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS) 16716 return count * 2; 16717 16718 if (stmt_info) 16719 { 16720 /* Assume we won't be able to use STP if the constant offset 16721 component of the address is misaligned. ??? This could be 16722 removed if we formed STP pairs earlier, rather than relying 16723 on peephole2. */ 16724 auto size = GET_MODE_SIZE (TYPE_MODE (vectype)); 16725 if (!aarch64_aligned_constant_offset_p (stmt_info, size)) 16726 return count * 2; 16727 } 16728 return CEIL (count, 2) * 2; 16729 16730 case scalar_store: 16731 if (stmt_info && STMT_VINFO_DATA_REF (stmt_info)) 16732 { 16733 /* Check for a mode in which STP pairs can be formed. */ 16734 auto size = GET_MODE_SIZE (TYPE_MODE (aarch64_dr_type (stmt_info))); 16735 if (maybe_ne (size, 4) && maybe_ne (size, 8)) 16736 return ~0U; 16737 16738 /* Assume we won't be able to use STP if the constant offset 16739 component of the address is misaligned. ??? This could be 16740 removed if we formed STP pairs earlier, rather than relying 16741 on peephole2. */ 16742 if (!aarch64_aligned_constant_offset_p (stmt_info, size)) 16743 return ~0U; 16744 } 16745 return count; 16746 16747 default: 16748 return ~0U; 16749 } 16750 } 16751 16752 unsigned 16753 aarch64_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind, 16754 stmt_vec_info stmt_info, slp_tree, 16755 tree vectype, int misalign, 16756 vect_cost_model_location where) 16757 { 16758 fractional_cost stmt_cost 16759 = aarch64_builtin_vectorization_cost (kind, vectype, misalign); 16760 16761 bool in_inner_loop_p = (where == vect_body 16762 && stmt_info 16763 && stmt_in_inner_loop_p (m_vinfo, stmt_info)); 16764 16765 /* Do one-time initialization based on the vinfo. */ 16766 loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (m_vinfo); 16767 if (!m_analyzed_vinfo && aarch64_use_new_vector_costs_p ()) 16768 { 16769 if (loop_vinfo) 16770 analyze_loop_vinfo (loop_vinfo); 16771 16772 m_analyzed_vinfo = true; 16773 } 16774 16775 /* Apply the heuristic described above m_stp_sequence_cost. */ 16776 if (m_stp_sequence_cost != ~0U) 16777 { 16778 uint64_t cost = aarch64_stp_sequence_cost (count, kind, 16779 stmt_info, vectype); 16780 m_stp_sequence_cost = MIN (m_stp_sequence_cost + cost, ~0U); 16781 } 16782 16783 /* Try to get a more accurate cost by looking at STMT_INFO instead 16784 of just looking at KIND. */ 16785 if (stmt_info && aarch64_use_new_vector_costs_p ()) 16786 { 16787 /* If we scalarize a strided store, the vectorizer costs one 16788 vec_to_scalar for each element. However, we can store the first 16789 element using an FP store without a separate extract step. */ 16790 if (vect_is_store_elt_extraction (kind, stmt_info)) 16791 count -= 1; 16792 16793 stmt_cost = aarch64_detect_scalar_stmt_subtype (m_vinfo, kind, 16794 stmt_info, stmt_cost); 16795 16796 if (vectype && m_vec_flags) 16797 stmt_cost = aarch64_detect_vector_stmt_subtype (m_vinfo, kind, 16798 stmt_info, vectype, 16799 where, stmt_cost); 16800 } 16801 16802 /* Do any SVE-specific adjustments to the cost. */ 16803 if (stmt_info && vectype && aarch64_sve_mode_p (TYPE_MODE (vectype))) 16804 stmt_cost = aarch64_sve_adjust_stmt_cost (m_vinfo, kind, stmt_info, 16805 vectype, stmt_cost); 16806 16807 if (stmt_info && aarch64_use_new_vector_costs_p ()) 16808 { 16809 /* Account for any extra "embedded" costs that apply additively 16810 to the base cost calculated above. */ 16811 stmt_cost = aarch64_adjust_stmt_cost (kind, stmt_info, vectype, 16812 stmt_cost); 16813 16814 /* If we're recording a nonzero vector loop body cost for the 16815 innermost loop, also estimate the operations that would need 16816 to be issued by all relevant implementations of the loop. */ 16817 if (loop_vinfo 16818 && (m_costing_for_scalar || where == vect_body) 16819 && (!LOOP_VINFO_LOOP (loop_vinfo)->inner || in_inner_loop_p) 16820 && stmt_cost != 0) 16821 for (auto &ops : m_ops) 16822 count_ops (count, kind, stmt_info, &ops); 16823 16824 /* If we're applying the SVE vs. Advanced SIMD unrolling heuristic, 16825 estimate the number of statements in the unrolled Advanced SIMD 16826 loop. For simplicitly, we assume that one iteration of the 16827 Advanced SIMD loop would need the same number of statements 16828 as one iteration of the SVE loop. */ 16829 if (where == vect_body && m_unrolled_advsimd_niters) 16830 m_unrolled_advsimd_stmts += count * m_unrolled_advsimd_niters; 16831 16832 /* Detect the use of an averaging operation. */ 16833 gimple *stmt = stmt_info->stmt; 16834 if (is_gimple_call (stmt) 16835 && gimple_call_internal_p (stmt)) 16836 { 16837 switch (gimple_call_internal_fn (stmt)) 16838 { 16839 case IFN_AVG_FLOOR: 16840 case IFN_AVG_CEIL: 16841 m_has_avg = true; 16842 default: 16843 break; 16844 } 16845 } 16846 } 16847 16848 /* If the statement stores to a decl that is known to be the argument 16849 to a vld1 in the same function, ignore the store for costing purposes. 16850 See the comment above m_stores_to_vector_load_decl for more details. */ 16851 if (stmt_info 16852 && (kind == vector_store || kind == unaligned_store) 16853 && aarch64_accesses_vector_load_decl_p (stmt_info)) 16854 { 16855 stmt_cost = 0; 16856 m_stores_to_vector_load_decl = true; 16857 } 16858 16859 return record_stmt_cost (stmt_info, where, (count * stmt_cost).ceil ()); 16860 } 16861 16862 /* Return true if (a) we're applying the Advanced SIMD vs. SVE unrolling 16863 heuristic described above m_unrolled_advsimd_niters and (b) the heuristic 16864 says that we should prefer the Advanced SIMD loop. */ 16865 bool 16866 aarch64_vector_costs::prefer_unrolled_loop () const 16867 { 16868 if (!m_unrolled_advsimd_stmts) 16869 return false; 16870 16871 if (dump_enabled_p ()) 16872 dump_printf_loc (MSG_NOTE, vect_location, "Number of insns in" 16873 " unrolled Advanced SIMD loop = " 16874 HOST_WIDE_INT_PRINT_UNSIGNED "\n", 16875 m_unrolled_advsimd_stmts); 16876 16877 /* The balance here is tricky. On the one hand, we can't be sure whether 16878 the code is vectorizable with Advanced SIMD or not. However, even if 16879 it isn't vectorizable with Advanced SIMD, there's a possibility that 16880 the scalar code could also be unrolled. Some of the code might then 16881 benefit from SLP, or from using LDP and STP. We therefore apply 16882 the heuristic regardless of can_use_advsimd_p. */ 16883 return (m_unrolled_advsimd_stmts 16884 && (m_unrolled_advsimd_stmts 16885 <= (unsigned int) param_max_completely_peeled_insns)); 16886 } 16887 16888 /* Subroutine of adjust_body_cost for handling SVE. Use ISSUE_INFO to work out 16889 how fast the SVE code can be issued and compare it to the equivalent value 16890 for scalar code (SCALAR_CYCLES_PER_ITER). If COULD_USE_ADVSIMD is true, 16891 also compare it to the issue rate of Advanced SIMD code 16892 (ADVSIMD_CYCLES_PER_ITER). 16893 16894 ORIG_BODY_COST is the cost originally passed to adjust_body_cost and 16895 *BODY_COST is the current value of the adjusted cost. *SHOULD_DISPARAGE 16896 is true if we think the loop body is too expensive. */ 16897 16898 fractional_cost 16899 aarch64_vector_costs:: 16900 adjust_body_cost_sve (const aarch64_vec_op_count *ops, 16901 fractional_cost scalar_cycles_per_iter, 16902 unsigned int orig_body_cost, unsigned int *body_cost, 16903 bool *should_disparage) 16904 { 16905 if (dump_enabled_p ()) 16906 ops->dump (); 16907 16908 fractional_cost sve_pred_cycles_per_iter = ops->min_pred_cycles_per_iter (); 16909 fractional_cost sve_cycles_per_iter = ops->min_cycles_per_iter (); 16910 16911 /* If the scalar version of the loop could issue at least as 16912 quickly as the predicate parts of the SVE loop, make the SVE loop 16913 prohibitively expensive. In this case vectorization is adding an 16914 overhead that the original scalar code didn't have. 16915 16916 This is mostly intended to detect cases in which WHILELOs dominate 16917 for very tight loops, which is something that normal latency-based 16918 costs would not model. Adding this kind of cliffedge would be 16919 too drastic for scalar_cycles_per_iter vs. sve_cycles_per_iter; 16920 code in the caller handles that case in a more conservative way. */ 16921 fractional_cost sve_estimate = sve_pred_cycles_per_iter + 1; 16922 if (scalar_cycles_per_iter < sve_estimate) 16923 { 16924 unsigned int min_cost 16925 = orig_body_cost * estimated_poly_value (BYTES_PER_SVE_VECTOR); 16926 if (*body_cost < min_cost) 16927 { 16928 if (dump_enabled_p ()) 16929 dump_printf_loc (MSG_NOTE, vect_location, 16930 "Increasing body cost to %d because the" 16931 " scalar code could issue within the limit" 16932 " imposed by predicate operations\n", 16933 min_cost); 16934 *body_cost = min_cost; 16935 *should_disparage = true; 16936 } 16937 } 16938 16939 return sve_cycles_per_iter; 16940 } 16941 16942 unsigned int 16943 aarch64_vector_costs::determine_suggested_unroll_factor () 16944 { 16945 bool sve = m_vec_flags & VEC_ANY_SVE; 16946 /* If we are trying to unroll an Advanced SIMD main loop that contains 16947 an averaging operation that we do not support with SVE and we might use a 16948 predicated epilogue, we need to be conservative and block unrolling as 16949 this might lead to a less optimal loop for the first and only epilogue 16950 using the original loop's vectorization factor. 16951 TODO: Remove this constraint when we add support for multiple epilogue 16952 vectorization. */ 16953 if (!sve && !TARGET_SVE2 && m_has_avg) 16954 return 1; 16955 16956 unsigned int max_unroll_factor = 1; 16957 for (auto vec_ops : m_ops) 16958 { 16959 aarch64_simd_vec_issue_info const *vec_issue 16960 = vec_ops.simd_issue_info (); 16961 if (!vec_issue) 16962 return 1; 16963 /* Limit unroll factor to a value adjustable by the user, the default 16964 value is 4. */ 16965 unsigned int unroll_factor = aarch64_vect_unroll_limit; 16966 unsigned int factor 16967 = vec_ops.reduction_latency > 1 ? vec_ops.reduction_latency : 1; 16968 unsigned int temp; 16969 16970 /* Sanity check, this should never happen. */ 16971 if ((vec_ops.stores + vec_ops.loads + vec_ops.general_ops) == 0) 16972 return 1; 16973 16974 /* Check stores. */ 16975 if (vec_ops.stores > 0) 16976 { 16977 temp = CEIL (factor * vec_issue->stores_per_cycle, 16978 vec_ops.stores); 16979 unroll_factor = MIN (unroll_factor, temp); 16980 } 16981 16982 /* Check loads + stores. */ 16983 if (vec_ops.loads > 0) 16984 { 16985 temp = CEIL (factor * vec_issue->loads_stores_per_cycle, 16986 vec_ops.loads + vec_ops.stores); 16987 unroll_factor = MIN (unroll_factor, temp); 16988 } 16989 16990 /* Check general ops. */ 16991 if (vec_ops.general_ops > 0) 16992 { 16993 temp = CEIL (factor * vec_issue->general_ops_per_cycle, 16994 vec_ops.general_ops); 16995 unroll_factor = MIN (unroll_factor, temp); 16996 } 16997 max_unroll_factor = MAX (max_unroll_factor, unroll_factor); 16998 } 16999 17000 /* Make sure unroll factor is power of 2. */ 17001 return 1 << ceil_log2 (max_unroll_factor); 17002 } 17003 17004 /* BODY_COST is the cost of a vector loop body. Adjust the cost as necessary 17005 and return the new cost. */ 17006 unsigned int 17007 aarch64_vector_costs:: 17008 adjust_body_cost (loop_vec_info loop_vinfo, 17009 const aarch64_vector_costs *scalar_costs, 17010 unsigned int body_cost) 17011 { 17012 if (scalar_costs->m_ops.is_empty () || m_ops.is_empty ()) 17013 return body_cost; 17014 17015 const auto &scalar_ops = scalar_costs->m_ops[0]; 17016 const auto &vector_ops = m_ops[0]; 17017 unsigned int estimated_vf = vect_vf_for_cost (loop_vinfo); 17018 unsigned int orig_body_cost = body_cost; 17019 bool should_disparage = false; 17020 17021 if (dump_enabled_p ()) 17022 dump_printf_loc (MSG_NOTE, vect_location, 17023 "Original vector body cost = %d\n", body_cost); 17024 17025 fractional_cost scalar_cycles_per_iter 17026 = scalar_ops.min_cycles_per_iter () * estimated_vf; 17027 17028 fractional_cost vector_cycles_per_iter = vector_ops.min_cycles_per_iter (); 17029 17030 if (dump_enabled_p ()) 17031 { 17032 if (IN_RANGE (m_num_vector_iterations, 0, 65536)) 17033 dump_printf_loc (MSG_NOTE, vect_location, 17034 "Vector loop iterates at most %wd times\n", 17035 m_num_vector_iterations); 17036 dump_printf_loc (MSG_NOTE, vect_location, "Scalar issue estimate:\n"); 17037 scalar_ops.dump (); 17038 dump_printf_loc (MSG_NOTE, vect_location, 17039 " estimated cycles per vector iteration" 17040 " (for VF %d) = %f\n", 17041 estimated_vf, scalar_cycles_per_iter.as_double ()); 17042 } 17043 17044 if (vector_ops.sve_issue_info ()) 17045 { 17046 if (dump_enabled_p ()) 17047 dump_printf_loc (MSG_NOTE, vect_location, "SVE issue estimate:\n"); 17048 vector_cycles_per_iter 17049 = adjust_body_cost_sve (&vector_ops, scalar_cycles_per_iter, 17050 orig_body_cost, &body_cost, &should_disparage); 17051 17052 if (aarch64_tune_params.vec_costs == &neoverse512tvb_vector_cost) 17053 { 17054 /* Also take Neoverse V1 tuning into account, doubling the 17055 scalar and Advanced SIMD estimates to account for the 17056 doubling in SVE vector length. */ 17057 if (dump_enabled_p ()) 17058 dump_printf_loc (MSG_NOTE, vect_location, 17059 "Neoverse V1 estimate:\n"); 17060 auto vf_factor = m_ops[1].vf_factor (); 17061 adjust_body_cost_sve (&m_ops[1], scalar_cycles_per_iter * vf_factor, 17062 orig_body_cost, &body_cost, &should_disparage); 17063 } 17064 } 17065 else 17066 { 17067 if (dump_enabled_p ()) 17068 { 17069 dump_printf_loc (MSG_NOTE, vect_location, 17070 "Vector issue estimate:\n"); 17071 vector_ops.dump (); 17072 } 17073 } 17074 17075 /* Decide whether to stick to latency-based costs or whether to try to 17076 take issue rates into account. */ 17077 unsigned int threshold = aarch64_loop_vect_issue_rate_niters; 17078 if (m_vec_flags & VEC_ANY_SVE) 17079 threshold = CEIL (threshold, aarch64_estimated_sve_vq ()); 17080 17081 if (m_num_vector_iterations >= 1 17082 && m_num_vector_iterations < threshold) 17083 { 17084 if (dump_enabled_p ()) 17085 dump_printf_loc (MSG_NOTE, vect_location, 17086 "Low iteration count, so using pure latency" 17087 " costs\n"); 17088 } 17089 /* Increase the cost of the vector code if it looks like the scalar code 17090 could issue more quickly. These values are only rough estimates, 17091 so minor differences should only result in minor changes. */ 17092 else if (scalar_cycles_per_iter < vector_cycles_per_iter) 17093 { 17094 body_cost = fractional_cost::scale (body_cost, vector_cycles_per_iter, 17095 scalar_cycles_per_iter); 17096 if (dump_enabled_p ()) 17097 dump_printf_loc (MSG_NOTE, vect_location, 17098 "Increasing body cost to %d because scalar code" 17099 " would issue more quickly\n", body_cost); 17100 } 17101 /* In general, it's expected that the proposed vector code would be able 17102 to issue more quickly than the original scalar code. This should 17103 already be reflected to some extent in the latency-based costs. 17104 17105 However, the latency-based costs effectively assume that the scalar 17106 code and the vector code execute serially, which tends to underplay 17107 one important case: if the real (non-serialized) execution time of 17108 a scalar iteration is dominated by loop-carried dependencies, 17109 and if the vector code is able to reduce both the length of 17110 the loop-carried dependencies *and* the number of cycles needed 17111 to issue the code in general, we can be more confident that the 17112 vector code is an improvement, even if adding the other (non-loop-carried) 17113 latencies tends to hide this saving. We therefore reduce the cost of the 17114 vector loop body in proportion to the saving. */ 17115 else if (scalar_ops.reduction_latency > vector_ops.reduction_latency 17116 && scalar_ops.reduction_latency == scalar_cycles_per_iter 17117 && scalar_cycles_per_iter > vector_cycles_per_iter 17118 && !should_disparage) 17119 { 17120 body_cost = fractional_cost::scale (body_cost, vector_cycles_per_iter, 17121 scalar_cycles_per_iter); 17122 if (dump_enabled_p ()) 17123 dump_printf_loc (MSG_NOTE, vect_location, 17124 "Decreasing body cost to %d account for smaller" 17125 " reduction latency\n", body_cost); 17126 } 17127 17128 return body_cost; 17129 } 17130 17131 void 17132 aarch64_vector_costs::finish_cost (const vector_costs *uncast_scalar_costs) 17133 { 17134 auto *scalar_costs 17135 = static_cast<const aarch64_vector_costs *> (uncast_scalar_costs); 17136 loop_vec_info loop_vinfo = dyn_cast<loop_vec_info> (m_vinfo); 17137 if (loop_vinfo 17138 && m_vec_flags 17139 && aarch64_use_new_vector_costs_p ()) 17140 { 17141 m_costs[vect_body] = adjust_body_cost (loop_vinfo, scalar_costs, 17142 m_costs[vect_body]); 17143 m_suggested_unroll_factor = determine_suggested_unroll_factor (); 17144 } 17145 17146 /* Apply the heuristic described above m_stp_sequence_cost. Prefer 17147 the scalar code in the event of a tie, since there is more chance 17148 of scalar code being optimized with surrounding operations. 17149 17150 In addition, if the vector body is a simple store to a decl that 17151 is elsewhere loaded using vld1, strongly prefer the vector form, 17152 to the extent of giving the prologue a zero cost. See the comment 17153 above m_stores_to_vector_load_decl for details. */ 17154 if (!loop_vinfo 17155 && scalar_costs 17156 && m_stp_sequence_cost != ~0U) 17157 { 17158 if (m_stores_to_vector_load_decl) 17159 m_costs[vect_prologue] = 0; 17160 else if (m_stp_sequence_cost >= scalar_costs->m_stp_sequence_cost) 17161 m_costs[vect_body] = 2 * scalar_costs->total_cost (); 17162 } 17163 17164 vector_costs::finish_cost (scalar_costs); 17165 } 17166 17167 bool 17168 aarch64_vector_costs:: 17169 better_main_loop_than_p (const vector_costs *uncast_other) const 17170 { 17171 auto other = static_cast<const aarch64_vector_costs *> (uncast_other); 17172 17173 auto this_loop_vinfo = as_a<loop_vec_info> (this->m_vinfo); 17174 auto other_loop_vinfo = as_a<loop_vec_info> (other->m_vinfo); 17175 17176 if (dump_enabled_p ()) 17177 dump_printf_loc (MSG_NOTE, vect_location, 17178 "Comparing two main loops (%s at VF %d vs %s at VF %d)\n", 17179 GET_MODE_NAME (this_loop_vinfo->vector_mode), 17180 vect_vf_for_cost (this_loop_vinfo), 17181 GET_MODE_NAME (other_loop_vinfo->vector_mode), 17182 vect_vf_for_cost (other_loop_vinfo)); 17183 17184 /* Apply the unrolling heuristic described above 17185 m_unrolled_advsimd_niters. */ 17186 if (bool (m_unrolled_advsimd_stmts) 17187 != bool (other->m_unrolled_advsimd_stmts)) 17188 { 17189 bool this_prefer_unrolled = this->prefer_unrolled_loop (); 17190 bool other_prefer_unrolled = other->prefer_unrolled_loop (); 17191 if (this_prefer_unrolled != other_prefer_unrolled) 17192 { 17193 if (dump_enabled_p ()) 17194 dump_printf_loc (MSG_NOTE, vect_location, 17195 "Preferring Advanced SIMD loop because" 17196 " it can be unrolled\n"); 17197 return other_prefer_unrolled; 17198 } 17199 } 17200 17201 for (unsigned int i = 0; i < m_ops.length (); ++i) 17202 { 17203 if (dump_enabled_p ()) 17204 { 17205 if (i) 17206 dump_printf_loc (MSG_NOTE, vect_location, 17207 "Reconsidering with subtuning %d\n", i); 17208 dump_printf_loc (MSG_NOTE, vect_location, 17209 "Issue info for %s loop:\n", 17210 GET_MODE_NAME (this_loop_vinfo->vector_mode)); 17211 this->m_ops[i].dump (); 17212 dump_printf_loc (MSG_NOTE, vect_location, 17213 "Issue info for %s loop:\n", 17214 GET_MODE_NAME (other_loop_vinfo->vector_mode)); 17215 other->m_ops[i].dump (); 17216 } 17217 17218 auto this_estimated_vf = (vect_vf_for_cost (this_loop_vinfo) 17219 * this->m_ops[i].vf_factor ()); 17220 auto other_estimated_vf = (vect_vf_for_cost (other_loop_vinfo) 17221 * other->m_ops[i].vf_factor ()); 17222 17223 /* If it appears that one loop could process the same amount of data 17224 in fewer cycles, prefer that loop over the other one. */ 17225 fractional_cost this_cost 17226 = this->m_ops[i].min_cycles_per_iter () * other_estimated_vf; 17227 fractional_cost other_cost 17228 = other->m_ops[i].min_cycles_per_iter () * this_estimated_vf; 17229 if (dump_enabled_p ()) 17230 { 17231 dump_printf_loc (MSG_NOTE, vect_location, 17232 "Weighted cycles per iteration of %s loop ~= %f\n", 17233 GET_MODE_NAME (this_loop_vinfo->vector_mode), 17234 this_cost.as_double ()); 17235 dump_printf_loc (MSG_NOTE, vect_location, 17236 "Weighted cycles per iteration of %s loop ~= %f\n", 17237 GET_MODE_NAME (other_loop_vinfo->vector_mode), 17238 other_cost.as_double ()); 17239 } 17240 if (this_cost != other_cost) 17241 { 17242 if (dump_enabled_p ()) 17243 dump_printf_loc (MSG_NOTE, vect_location, 17244 "Preferring loop with lower cycles" 17245 " per iteration\n"); 17246 return this_cost < other_cost; 17247 } 17248 17249 /* If the issue rate of SVE code is limited by predicate operations 17250 (i.e. if sve_pred_cycles_per_iter > sve_nonpred_cycles_per_iter), 17251 and if Advanced SIMD code could issue within the limit imposed 17252 by the predicate operations, the predicate operations are adding an 17253 overhead that the original code didn't have and so we should prefer 17254 the Advanced SIMD version. */ 17255 auto better_pred_limit_p = [](const aarch64_vec_op_count &a, 17256 const aarch64_vec_op_count &b) -> bool 17257 { 17258 if (a.pred_ops == 0 17259 && (b.min_pred_cycles_per_iter () 17260 > b.min_nonpred_cycles_per_iter ())) 17261 { 17262 if (dump_enabled_p ()) 17263 dump_printf_loc (MSG_NOTE, vect_location, 17264 "Preferring Advanced SIMD loop since" 17265 " SVE loop is predicate-limited\n"); 17266 return true; 17267 } 17268 return false; 17269 }; 17270 if (better_pred_limit_p (this->m_ops[i], other->m_ops[i])) 17271 return true; 17272 if (better_pred_limit_p (other->m_ops[i], this->m_ops[i])) 17273 return false; 17274 } 17275 17276 return vector_costs::better_main_loop_than_p (other); 17277 } 17278 17279 static void initialize_aarch64_code_model (struct gcc_options *); 17280 17281 /* Parse the TO_PARSE string and put the architecture struct that it 17282 selects into RES and the architectural features into ISA_FLAGS. 17283 Return an aarch64_parse_opt_result describing the parse result. 17284 If there is an error parsing, RES and ISA_FLAGS are left unchanged. 17285 When the TO_PARSE string contains an invalid extension, 17286 a copy of the string is created and stored to INVALID_EXTENSION. */ 17287 17288 static enum aarch64_parse_opt_result 17289 aarch64_parse_arch (const char *to_parse, const struct processor **res, 17290 uint64_t *isa_flags, std::string *invalid_extension) 17291 { 17292 const char *ext; 17293 const struct processor *arch; 17294 size_t len; 17295 17296 ext = strchr (to_parse, '+'); 17297 17298 if (ext != NULL) 17299 len = ext - to_parse; 17300 else 17301 len = strlen (to_parse); 17302 17303 if (len == 0) 17304 return AARCH64_PARSE_MISSING_ARG; 17305 17306 17307 /* Loop through the list of supported ARCHes to find a match. */ 17308 for (arch = all_architectures; arch->name != NULL; arch++) 17309 { 17310 if (strlen (arch->name) == len 17311 && strncmp (arch->name, to_parse, len) == 0) 17312 { 17313 uint64_t isa_temp = arch->flags; 17314 17315 if (ext != NULL) 17316 { 17317 /* TO_PARSE string contains at least one extension. */ 17318 enum aarch64_parse_opt_result ext_res 17319 = aarch64_parse_extension (ext, &isa_temp, invalid_extension); 17320 17321 if (ext_res != AARCH64_PARSE_OK) 17322 return ext_res; 17323 } 17324 /* Extension parsing was successful. Confirm the result 17325 arch and ISA flags. */ 17326 *res = arch; 17327 *isa_flags = isa_temp; 17328 return AARCH64_PARSE_OK; 17329 } 17330 } 17331 17332 /* ARCH name not found in list. */ 17333 return AARCH64_PARSE_INVALID_ARG; 17334 } 17335 17336 /* Parse the TO_PARSE string and put the result tuning in RES and the 17337 architecture flags in ISA_FLAGS. Return an aarch64_parse_opt_result 17338 describing the parse result. If there is an error parsing, RES and 17339 ISA_FLAGS are left unchanged. 17340 When the TO_PARSE string contains an invalid extension, 17341 a copy of the string is created and stored to INVALID_EXTENSION. */ 17342 17343 static enum aarch64_parse_opt_result 17344 aarch64_parse_cpu (const char *to_parse, const struct processor **res, 17345 uint64_t *isa_flags, std::string *invalid_extension) 17346 { 17347 const char *ext; 17348 const struct processor *cpu; 17349 size_t len; 17350 17351 ext = strchr (to_parse, '+'); 17352 17353 if (ext != NULL) 17354 len = ext - to_parse; 17355 else 17356 len = strlen (to_parse); 17357 17358 if (len == 0) 17359 return AARCH64_PARSE_MISSING_ARG; 17360 17361 17362 /* Loop through the list of supported CPUs to find a match. */ 17363 for (cpu = all_cores; cpu->name != NULL; cpu++) 17364 { 17365 if (strlen (cpu->name) == len && strncmp (cpu->name, to_parse, len) == 0) 17366 { 17367 uint64_t isa_temp = cpu->flags; 17368 17369 17370 if (ext != NULL) 17371 { 17372 /* TO_PARSE string contains at least one extension. */ 17373 enum aarch64_parse_opt_result ext_res 17374 = aarch64_parse_extension (ext, &isa_temp, invalid_extension); 17375 17376 if (ext_res != AARCH64_PARSE_OK) 17377 return ext_res; 17378 } 17379 /* Extension parsing was successfull. Confirm the result 17380 cpu and ISA flags. */ 17381 *res = cpu; 17382 *isa_flags = isa_temp; 17383 return AARCH64_PARSE_OK; 17384 } 17385 } 17386 17387 /* CPU name not found in list. */ 17388 return AARCH64_PARSE_INVALID_ARG; 17389 } 17390 17391 /* Parse the TO_PARSE string and put the cpu it selects into RES. 17392 Return an aarch64_parse_opt_result describing the parse result. 17393 If the parsing fails the RES does not change. */ 17394 17395 static enum aarch64_parse_opt_result 17396 aarch64_parse_tune (const char *to_parse, const struct processor **res) 17397 { 17398 const struct processor *cpu; 17399 17400 /* Loop through the list of supported CPUs to find a match. */ 17401 for (cpu = all_cores; cpu->name != NULL; cpu++) 17402 { 17403 if (strcmp (cpu->name, to_parse) == 0) 17404 { 17405 *res = cpu; 17406 return AARCH64_PARSE_OK; 17407 } 17408 } 17409 17410 /* CPU name not found in list. */ 17411 return AARCH64_PARSE_INVALID_ARG; 17412 } 17413 17414 /* Parse TOKEN, which has length LENGTH to see if it is an option 17415 described in FLAG. If it is, return the index bit for that fusion type. 17416 If not, error (printing OPTION_NAME) and return zero. */ 17417 17418 static unsigned int 17419 aarch64_parse_one_option_token (const char *token, 17420 size_t length, 17421 const struct aarch64_flag_desc *flag, 17422 const char *option_name) 17423 { 17424 for (; flag->name != NULL; flag++) 17425 { 17426 if (length == strlen (flag->name) 17427 && !strncmp (flag->name, token, length)) 17428 return flag->flag; 17429 } 17430 17431 error ("unknown flag passed in %<-moverride=%s%> (%s)", option_name, token); 17432 return 0; 17433 } 17434 17435 /* Parse OPTION which is a comma-separated list of flags to enable. 17436 FLAGS gives the list of flags we understand, INITIAL_STATE gives any 17437 default state we inherit from the CPU tuning structures. OPTION_NAME 17438 gives the top-level option we are parsing in the -moverride string, 17439 for use in error messages. */ 17440 17441 static unsigned int 17442 aarch64_parse_boolean_options (const char *option, 17443 const struct aarch64_flag_desc *flags, 17444 unsigned int initial_state, 17445 const char *option_name) 17446 { 17447 const char separator = '.'; 17448 const char* specs = option; 17449 const char* ntoken = option; 17450 unsigned int found_flags = initial_state; 17451 17452 while ((ntoken = strchr (specs, separator))) 17453 { 17454 size_t token_length = ntoken - specs; 17455 unsigned token_ops = aarch64_parse_one_option_token (specs, 17456 token_length, 17457 flags, 17458 option_name); 17459 /* If we find "none" (or, for simplicity's sake, an error) anywhere 17460 in the token stream, reset the supported operations. So: 17461 17462 adrp+add.cmp+branch.none.adrp+add 17463 17464 would have the result of turning on only adrp+add fusion. */ 17465 if (!token_ops) 17466 found_flags = 0; 17467 17468 found_flags |= token_ops; 17469 specs = ++ntoken; 17470 } 17471 17472 /* We ended with a comma, print something. */ 17473 if (!(*specs)) 17474 { 17475 error ("%qs string ill-formed", option_name); 17476 return 0; 17477 } 17478 17479 /* We still have one more token to parse. */ 17480 size_t token_length = strlen (specs); 17481 unsigned token_ops = aarch64_parse_one_option_token (specs, 17482 token_length, 17483 flags, 17484 option_name); 17485 if (!token_ops) 17486 found_flags = 0; 17487 17488 found_flags |= token_ops; 17489 return found_flags; 17490 } 17491 17492 /* Support for overriding instruction fusion. */ 17493 17494 static void 17495 aarch64_parse_fuse_string (const char *fuse_string, 17496 struct tune_params *tune) 17497 { 17498 tune->fusible_ops = aarch64_parse_boolean_options (fuse_string, 17499 aarch64_fusible_pairs, 17500 tune->fusible_ops, 17501 "fuse="); 17502 } 17503 17504 /* Support for overriding other tuning flags. */ 17505 17506 static void 17507 aarch64_parse_tune_string (const char *tune_string, 17508 struct tune_params *tune) 17509 { 17510 tune->extra_tuning_flags 17511 = aarch64_parse_boolean_options (tune_string, 17512 aarch64_tuning_flags, 17513 tune->extra_tuning_flags, 17514 "tune="); 17515 } 17516 17517 /* Parse the sve_width tuning moverride string in TUNE_STRING. 17518 Accept the valid SVE vector widths allowed by 17519 aarch64_sve_vector_bits_enum and use it to override sve_width 17520 in TUNE. */ 17521 17522 static void 17523 aarch64_parse_sve_width_string (const char *tune_string, 17524 struct tune_params *tune) 17525 { 17526 int width = -1; 17527 17528 int n = sscanf (tune_string, "%d", &width); 17529 if (n == EOF) 17530 { 17531 error ("invalid format for %<sve_width%>"); 17532 return; 17533 } 17534 switch (width) 17535 { 17536 case SVE_128: 17537 case SVE_256: 17538 case SVE_512: 17539 case SVE_1024: 17540 case SVE_2048: 17541 break; 17542 default: 17543 error ("invalid %<sve_width%> value: %d", width); 17544 } 17545 tune->sve_width = (enum aarch64_sve_vector_bits_enum) width; 17546 } 17547 17548 /* Parse TOKEN, which has length LENGTH to see if it is a tuning option 17549 we understand. If it is, extract the option string and handoff to 17550 the appropriate function. */ 17551 17552 void 17553 aarch64_parse_one_override_token (const char* token, 17554 size_t length, 17555 struct tune_params *tune) 17556 { 17557 const struct aarch64_tuning_override_function *fn 17558 = aarch64_tuning_override_functions; 17559 17560 const char *option_part = strchr (token, '='); 17561 if (!option_part) 17562 { 17563 error ("tuning string missing in option (%s)", token); 17564 return; 17565 } 17566 17567 /* Get the length of the option name. */ 17568 length = option_part - token; 17569 /* Skip the '=' to get to the option string. */ 17570 option_part++; 17571 17572 for (; fn->name != NULL; fn++) 17573 { 17574 if (!strncmp (fn->name, token, length)) 17575 { 17576 fn->parse_override (option_part, tune); 17577 return; 17578 } 17579 } 17580 17581 error ("unknown tuning option (%s)",token); 17582 return; 17583 } 17584 17585 /* A checking mechanism for the implementation of the tls size. */ 17586 17587 static void 17588 initialize_aarch64_tls_size (struct gcc_options *opts) 17589 { 17590 if (aarch64_tls_size == 0) 17591 aarch64_tls_size = 24; 17592 17593 switch (opts->x_aarch64_cmodel_var) 17594 { 17595 case AARCH64_CMODEL_TINY: 17596 /* Both the default and maximum TLS size allowed under tiny is 1M which 17597 needs two instructions to address, so we clamp the size to 24. */ 17598 if (aarch64_tls_size > 24) 17599 aarch64_tls_size = 24; 17600 break; 17601 case AARCH64_CMODEL_SMALL: 17602 /* The maximum TLS size allowed under small is 4G. */ 17603 if (aarch64_tls_size > 32) 17604 aarch64_tls_size = 32; 17605 break; 17606 case AARCH64_CMODEL_LARGE: 17607 /* The maximum TLS size allowed under large is 16E. 17608 FIXME: 16E should be 64bit, we only support 48bit offset now. */ 17609 if (aarch64_tls_size > 48) 17610 aarch64_tls_size = 48; 17611 break; 17612 default: 17613 gcc_unreachable (); 17614 } 17615 17616 return; 17617 } 17618 17619 /* Parse STRING looking for options in the format: 17620 string :: option:string 17621 option :: name=substring 17622 name :: {a-z} 17623 substring :: defined by option. */ 17624 17625 static void 17626 aarch64_parse_override_string (const char* input_string, 17627 struct tune_params* tune) 17628 { 17629 const char separator = ':'; 17630 size_t string_length = strlen (input_string) + 1; 17631 char *string_root = (char *) xmalloc (sizeof (*string_root) * string_length); 17632 char *string = string_root; 17633 strncpy (string, input_string, string_length); 17634 string[string_length - 1] = '\0'; 17635 17636 char* ntoken = string; 17637 17638 while ((ntoken = strchr (string, separator))) 17639 { 17640 size_t token_length = ntoken - string; 17641 /* Make this substring look like a string. */ 17642 *ntoken = '\0'; 17643 aarch64_parse_one_override_token (string, token_length, tune); 17644 string = ++ntoken; 17645 } 17646 17647 /* One last option to parse. */ 17648 aarch64_parse_one_override_token (string, strlen (string), tune); 17649 free (string_root); 17650 } 17651 17652 /* Adjust CURRENT_TUNE (a generic tuning struct) with settings that 17653 are best for a generic target with the currently-enabled architecture 17654 extensions. */ 17655 static void 17656 aarch64_adjust_generic_arch_tuning (struct tune_params ¤t_tune) 17657 { 17658 /* Neoverse V1 is the only core that is known to benefit from 17659 AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS. There is therefore no 17660 point enabling it for SVE2 and above. */ 17661 if (TARGET_SVE2) 17662 current_tune.extra_tuning_flags 17663 &= ~AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS; 17664 } 17665 17666 static void 17667 aarch64_override_options_after_change_1 (struct gcc_options *opts) 17668 { 17669 if (accepted_branch_protection_string) 17670 { 17671 opts->x_aarch64_branch_protection_string 17672 = xstrdup (accepted_branch_protection_string); 17673 } 17674 17675 /* PR 70044: We have to be careful about being called multiple times for the 17676 same function. This means all changes should be repeatable. */ 17677 17678 /* Set aarch64_use_frame_pointer based on -fno-omit-frame-pointer. 17679 Disable the frame pointer flag so the mid-end will not use a frame 17680 pointer in leaf functions in order to support -fomit-leaf-frame-pointer. 17681 Set x_flag_omit_frame_pointer to the special value 2 to differentiate 17682 between -fomit-frame-pointer (1) and -fno-omit-frame-pointer (2). */ 17683 aarch64_use_frame_pointer = opts->x_flag_omit_frame_pointer != 1; 17684 if (opts->x_flag_omit_frame_pointer == 0) 17685 opts->x_flag_omit_frame_pointer = 2; 17686 17687 /* If not optimizing for size, set the default 17688 alignment to what the target wants. */ 17689 if (!opts->x_optimize_size) 17690 { 17691 if (opts->x_flag_align_loops && !opts->x_str_align_loops) 17692 opts->x_str_align_loops = aarch64_tune_params.loop_align; 17693 if (opts->x_flag_align_jumps && !opts->x_str_align_jumps) 17694 opts->x_str_align_jumps = aarch64_tune_params.jump_align; 17695 if (opts->x_flag_align_functions && !opts->x_str_align_functions) 17696 opts->x_str_align_functions = aarch64_tune_params.function_align; 17697 } 17698 17699 /* We default to no pc-relative literal loads. */ 17700 17701 aarch64_pcrelative_literal_loads = false; 17702 17703 /* If -mpc-relative-literal-loads is set on the command line, this 17704 implies that the user asked for PC relative literal loads. */ 17705 if (opts->x_pcrelative_literal_loads == 1) 17706 aarch64_pcrelative_literal_loads = true; 17707 17708 /* In the tiny memory model it makes no sense to disallow PC relative 17709 literal pool loads. */ 17710 if (aarch64_cmodel == AARCH64_CMODEL_TINY 17711 || aarch64_cmodel == AARCH64_CMODEL_TINY_PIC) 17712 aarch64_pcrelative_literal_loads = true; 17713 17714 /* When enabling the lower precision Newton series for the square root, also 17715 enable it for the reciprocal square root, since the latter is an 17716 intermediary step for the former. */ 17717 if (flag_mlow_precision_sqrt) 17718 flag_mrecip_low_precision_sqrt = true; 17719 } 17720 17721 /* 'Unpack' up the internal tuning structs and update the options 17722 in OPTS. The caller must have set up selected_tune and selected_arch 17723 as all the other target-specific codegen decisions are 17724 derived from them. */ 17725 17726 void 17727 aarch64_override_options_internal (struct gcc_options *opts) 17728 { 17729 aarch64_tune_flags = selected_tune->flags; 17730 aarch64_tune = selected_tune->sched_core; 17731 /* Make a copy of the tuning parameters attached to the core, which 17732 we may later overwrite. */ 17733 aarch64_tune_params = *(selected_tune->tune); 17734 aarch64_architecture_version = selected_arch->architecture_version; 17735 if (selected_tune->tune == &generic_tunings) 17736 aarch64_adjust_generic_arch_tuning (aarch64_tune_params); 17737 17738 if (opts->x_aarch64_override_tune_string) 17739 aarch64_parse_override_string (opts->x_aarch64_override_tune_string, 17740 &aarch64_tune_params); 17741 17742 /* This target defaults to strict volatile bitfields. */ 17743 if (opts->x_flag_strict_volatile_bitfields < 0 && abi_version_at_least (2)) 17744 opts->x_flag_strict_volatile_bitfields = 1; 17745 17746 if (aarch64_stack_protector_guard == SSP_GLOBAL 17747 && opts->x_aarch64_stack_protector_guard_offset_str) 17748 { 17749 error ("incompatible options %<-mstack-protector-guard=global%> and " 17750 "%<-mstack-protector-guard-offset=%s%>", 17751 aarch64_stack_protector_guard_offset_str); 17752 } 17753 17754 if (aarch64_stack_protector_guard == SSP_SYSREG 17755 && !(opts->x_aarch64_stack_protector_guard_offset_str 17756 && opts->x_aarch64_stack_protector_guard_reg_str)) 17757 { 17758 error ("both %<-mstack-protector-guard-offset%> and " 17759 "%<-mstack-protector-guard-reg%> must be used " 17760 "with %<-mstack-protector-guard=sysreg%>"); 17761 } 17762 17763 if (opts->x_aarch64_stack_protector_guard_reg_str) 17764 { 17765 if (strlen (opts->x_aarch64_stack_protector_guard_reg_str) > 100) 17766 error ("specify a system register with a small string length"); 17767 } 17768 17769 if (opts->x_aarch64_stack_protector_guard_offset_str) 17770 { 17771 char *end; 17772 const char *str = aarch64_stack_protector_guard_offset_str; 17773 errno = 0; 17774 long offs = strtol (aarch64_stack_protector_guard_offset_str, &end, 0); 17775 if (!*str || *end || errno) 17776 error ("%qs is not a valid offset in %qs", str, 17777 "-mstack-protector-guard-offset="); 17778 aarch64_stack_protector_guard_offset = offs; 17779 } 17780 17781 if ((flag_sanitize & SANITIZE_SHADOW_CALL_STACK) 17782 && !fixed_regs[R18_REGNUM]) 17783 error ("%<-fsanitize=shadow-call-stack%> requires %<-ffixed-x18%>"); 17784 17785 initialize_aarch64_code_model (opts); 17786 initialize_aarch64_tls_size (opts); 17787 17788 int queue_depth = 0; 17789 switch (aarch64_tune_params.autoprefetcher_model) 17790 { 17791 case tune_params::AUTOPREFETCHER_OFF: 17792 queue_depth = -1; 17793 break; 17794 case tune_params::AUTOPREFETCHER_WEAK: 17795 queue_depth = 0; 17796 break; 17797 case tune_params::AUTOPREFETCHER_STRONG: 17798 queue_depth = max_insn_queue_index + 1; 17799 break; 17800 default: 17801 gcc_unreachable (); 17802 } 17803 17804 /* We don't mind passing in global_options_set here as we don't use 17805 the *options_set structs anyway. */ 17806 SET_OPTION_IF_UNSET (opts, &global_options_set, 17807 param_sched_autopref_queue_depth, queue_depth); 17808 17809 /* If using Advanced SIMD only for autovectorization disable SVE vector costs 17810 comparison. */ 17811 if (aarch64_autovec_preference == 1) 17812 SET_OPTION_IF_UNSET (opts, &global_options_set, 17813 aarch64_sve_compare_costs, 0); 17814 17815 /* Set up parameters to be used in prefetching algorithm. Do not 17816 override the defaults unless we are tuning for a core we have 17817 researched values for. */ 17818 if (aarch64_tune_params.prefetch->num_slots > 0) 17819 SET_OPTION_IF_UNSET (opts, &global_options_set, 17820 param_simultaneous_prefetches, 17821 aarch64_tune_params.prefetch->num_slots); 17822 if (aarch64_tune_params.prefetch->l1_cache_size >= 0) 17823 SET_OPTION_IF_UNSET (opts, &global_options_set, 17824 param_l1_cache_size, 17825 aarch64_tune_params.prefetch->l1_cache_size); 17826 if (aarch64_tune_params.prefetch->l1_cache_line_size >= 0) 17827 SET_OPTION_IF_UNSET (opts, &global_options_set, 17828 param_l1_cache_line_size, 17829 aarch64_tune_params.prefetch->l1_cache_line_size); 17830 17831 if (aarch64_tune_params.prefetch->l1_cache_line_size >= 0) 17832 { 17833 SET_OPTION_IF_UNSET (opts, &global_options_set, 17834 param_destruct_interfere_size, 17835 aarch64_tune_params.prefetch->l1_cache_line_size); 17836 SET_OPTION_IF_UNSET (opts, &global_options_set, 17837 param_construct_interfere_size, 17838 aarch64_tune_params.prefetch->l1_cache_line_size); 17839 } 17840 else 17841 { 17842 /* For a generic AArch64 target, cover the current range of cache line 17843 sizes. */ 17844 SET_OPTION_IF_UNSET (opts, &global_options_set, 17845 param_destruct_interfere_size, 17846 256); 17847 SET_OPTION_IF_UNSET (opts, &global_options_set, 17848 param_construct_interfere_size, 17849 64); 17850 } 17851 17852 if (aarch64_tune_params.prefetch->l2_cache_size >= 0) 17853 SET_OPTION_IF_UNSET (opts, &global_options_set, 17854 param_l2_cache_size, 17855 aarch64_tune_params.prefetch->l2_cache_size); 17856 if (!aarch64_tune_params.prefetch->prefetch_dynamic_strides) 17857 SET_OPTION_IF_UNSET (opts, &global_options_set, 17858 param_prefetch_dynamic_strides, 0); 17859 if (aarch64_tune_params.prefetch->minimum_stride >= 0) 17860 SET_OPTION_IF_UNSET (opts, &global_options_set, 17861 param_prefetch_minimum_stride, 17862 aarch64_tune_params.prefetch->minimum_stride); 17863 17864 /* Use the alternative scheduling-pressure algorithm by default. */ 17865 SET_OPTION_IF_UNSET (opts, &global_options_set, 17866 param_sched_pressure_algorithm, 17867 SCHED_PRESSURE_MODEL); 17868 17869 /* Validate the guard size. */ 17870 int guard_size = param_stack_clash_protection_guard_size; 17871 17872 if (guard_size != 12 && guard_size != 16) 17873 error ("only values 12 (4 KB) and 16 (64 KB) are supported for guard " 17874 "size. Given value %d (%llu KB) is out of range", 17875 guard_size, (1ULL << guard_size) / 1024ULL); 17876 17877 /* Enforce that interval is the same size as size so the mid-end does the 17878 right thing. */ 17879 SET_OPTION_IF_UNSET (opts, &global_options_set, 17880 param_stack_clash_protection_probe_interval, 17881 guard_size); 17882 17883 /* The maybe_set calls won't update the value if the user has explicitly set 17884 one. Which means we need to validate that probing interval and guard size 17885 are equal. */ 17886 int probe_interval 17887 = param_stack_clash_protection_probe_interval; 17888 if (guard_size != probe_interval) 17889 error ("stack clash guard size %<%d%> must be equal to probing interval " 17890 "%<%d%>", guard_size, probe_interval); 17891 17892 /* Enable sw prefetching at specified optimization level for 17893 CPUS that have prefetch. Lower optimization level threshold by 1 17894 when profiling is enabled. */ 17895 if (opts->x_flag_prefetch_loop_arrays < 0 17896 && !opts->x_optimize_size 17897 && aarch64_tune_params.prefetch->default_opt_level >= 0 17898 && opts->x_optimize >= aarch64_tune_params.prefetch->default_opt_level) 17899 opts->x_flag_prefetch_loop_arrays = 1; 17900 17901 if (opts->x_aarch64_arch_string == NULL) 17902 opts->x_aarch64_arch_string = selected_arch->name; 17903 if (opts->x_aarch64_cpu_string == NULL) 17904 opts->x_aarch64_cpu_string = selected_cpu->name; 17905 if (opts->x_aarch64_tune_string == NULL) 17906 opts->x_aarch64_tune_string = selected_tune->name; 17907 17908 aarch64_override_options_after_change_1 (opts); 17909 } 17910 17911 /* Print a hint with a suggestion for a core or architecture name that 17912 most closely resembles what the user passed in STR. ARCH is true if 17913 the user is asking for an architecture name. ARCH is false if the user 17914 is asking for a core name. */ 17915 17916 static void 17917 aarch64_print_hint_for_core_or_arch (const char *str, bool arch) 17918 { 17919 auto_vec<const char *> candidates; 17920 const struct processor *entry = arch ? all_architectures : all_cores; 17921 for (; entry->name != NULL; entry++) 17922 candidates.safe_push (entry->name); 17923 17924 #ifdef HAVE_LOCAL_CPU_DETECT 17925 /* Add also "native" as possible value. */ 17926 if (arch) 17927 candidates.safe_push ("native"); 17928 #endif 17929 17930 char *s; 17931 const char *hint = candidates_list_and_hint (str, s, candidates); 17932 if (hint) 17933 inform (input_location, "valid arguments are: %s;" 17934 " did you mean %qs?", s, hint); 17935 else 17936 inform (input_location, "valid arguments are: %s", s); 17937 17938 XDELETEVEC (s); 17939 } 17940 17941 /* Print a hint with a suggestion for a core name that most closely resembles 17942 what the user passed in STR. */ 17943 17944 inline static void 17945 aarch64_print_hint_for_core (const char *str) 17946 { 17947 aarch64_print_hint_for_core_or_arch (str, false); 17948 } 17949 17950 /* Print a hint with a suggestion for an architecture name that most closely 17951 resembles what the user passed in STR. */ 17952 17953 inline static void 17954 aarch64_print_hint_for_arch (const char *str) 17955 { 17956 aarch64_print_hint_for_core_or_arch (str, true); 17957 } 17958 17959 17960 /* Print a hint with a suggestion for an extension name 17961 that most closely resembles what the user passed in STR. */ 17962 17963 void 17964 aarch64_print_hint_for_extensions (const std::string &str) 17965 { 17966 auto_vec<const char *> candidates; 17967 aarch64_get_all_extension_candidates (&candidates); 17968 char *s; 17969 const char *hint = candidates_list_and_hint (str.c_str (), s, candidates); 17970 if (hint) 17971 inform (input_location, "valid arguments are: %s;" 17972 " did you mean %qs?", s, hint); 17973 else 17974 inform (input_location, "valid arguments are: %s", s); 17975 17976 XDELETEVEC (s); 17977 } 17978 17979 /* Validate a command-line -mcpu option. Parse the cpu and extensions (if any) 17980 specified in STR and throw errors if appropriate. Put the results if 17981 they are valid in RES and ISA_FLAGS. Return whether the option is 17982 valid. */ 17983 17984 static bool 17985 aarch64_validate_mcpu (const char *str, const struct processor **res, 17986 uint64_t *isa_flags) 17987 { 17988 std::string invalid_extension; 17989 enum aarch64_parse_opt_result parse_res 17990 = aarch64_parse_cpu (str, res, isa_flags, &invalid_extension); 17991 17992 if (parse_res == AARCH64_PARSE_OK) 17993 return true; 17994 17995 switch (parse_res) 17996 { 17997 case AARCH64_PARSE_MISSING_ARG: 17998 error ("missing cpu name in %<-mcpu=%s%>", str); 17999 break; 18000 case AARCH64_PARSE_INVALID_ARG: 18001 error ("unknown value %qs for %<-mcpu%>", str); 18002 aarch64_print_hint_for_core (str); 18003 break; 18004 case AARCH64_PARSE_INVALID_FEATURE: 18005 error ("invalid feature modifier %qs in %<-mcpu=%s%>", 18006 invalid_extension.c_str (), str); 18007 aarch64_print_hint_for_extensions (invalid_extension); 18008 break; 18009 default: 18010 gcc_unreachable (); 18011 } 18012 18013 return false; 18014 } 18015 18016 /* Straight line speculation indicators. */ 18017 enum aarch64_sls_hardening_type 18018 { 18019 SLS_NONE = 0, 18020 SLS_RETBR = 1, 18021 SLS_BLR = 2, 18022 SLS_ALL = 3, 18023 }; 18024 static enum aarch64_sls_hardening_type aarch64_sls_hardening; 18025 18026 /* Return whether we should mitigatate Straight Line Speculation for the RET 18027 and BR instructions. */ 18028 bool 18029 aarch64_harden_sls_retbr_p (void) 18030 { 18031 return aarch64_sls_hardening & SLS_RETBR; 18032 } 18033 18034 /* Return whether we should mitigatate Straight Line Speculation for the BLR 18035 instruction. */ 18036 bool 18037 aarch64_harden_sls_blr_p (void) 18038 { 18039 return aarch64_sls_hardening & SLS_BLR; 18040 } 18041 18042 /* As of yet we only allow setting these options globally, in the future we may 18043 allow setting them per function. */ 18044 static void 18045 aarch64_validate_sls_mitigation (const char *const_str) 18046 { 18047 char *token_save = NULL; 18048 char *str = NULL; 18049 18050 if (strcmp (const_str, "none") == 0) 18051 { 18052 aarch64_sls_hardening = SLS_NONE; 18053 return; 18054 } 18055 if (strcmp (const_str, "all") == 0) 18056 { 18057 aarch64_sls_hardening = SLS_ALL; 18058 return; 18059 } 18060 18061 char *str_root = xstrdup (const_str); 18062 str = strtok_r (str_root, ",", &token_save); 18063 if (!str) 18064 error ("invalid argument given to %<-mharden-sls=%>"); 18065 18066 int temp = SLS_NONE; 18067 while (str) 18068 { 18069 if (strcmp (str, "blr") == 0) 18070 temp |= SLS_BLR; 18071 else if (strcmp (str, "retbr") == 0) 18072 temp |= SLS_RETBR; 18073 else if (strcmp (str, "none") == 0 || strcmp (str, "all") == 0) 18074 { 18075 error ("%qs must be by itself for %<-mharden-sls=%>", str); 18076 break; 18077 } 18078 else 18079 { 18080 error ("invalid argument %<%s%> for %<-mharden-sls=%>", str); 18081 break; 18082 } 18083 str = strtok_r (NULL, ",", &token_save); 18084 } 18085 aarch64_sls_hardening = (aarch64_sls_hardening_type) temp; 18086 free (str_root); 18087 } 18088 18089 /* Parses CONST_STR for branch protection features specified in 18090 aarch64_branch_protect_types, and set any global variables required. Returns 18091 the parsing result and assigns LAST_STR to the last processed token from 18092 CONST_STR so that it can be used for error reporting. */ 18093 18094 static enum 18095 aarch64_parse_opt_result aarch64_parse_branch_protection (const char *const_str, 18096 char** last_str) 18097 { 18098 char *str_root = xstrdup (const_str); 18099 char* token_save = NULL; 18100 char *str = strtok_r (str_root, "+", &token_save); 18101 enum aarch64_parse_opt_result res = AARCH64_PARSE_OK; 18102 if (!str) 18103 res = AARCH64_PARSE_MISSING_ARG; 18104 else 18105 { 18106 char *next_str = strtok_r (NULL, "+", &token_save); 18107 /* Reset the branch protection features to their defaults. */ 18108 aarch64_handle_no_branch_protection (NULL, NULL); 18109 18110 while (str && res == AARCH64_PARSE_OK) 18111 { 18112 const aarch64_branch_protect_type* type = aarch64_branch_protect_types; 18113 bool found = false; 18114 /* Search for this type. */ 18115 while (type && type->name && !found && res == AARCH64_PARSE_OK) 18116 { 18117 if (strcmp (str, type->name) == 0) 18118 { 18119 found = true; 18120 res = type->handler (str, next_str); 18121 str = next_str; 18122 next_str = strtok_r (NULL, "+", &token_save); 18123 } 18124 else 18125 type++; 18126 } 18127 if (found && res == AARCH64_PARSE_OK) 18128 { 18129 bool found_subtype = true; 18130 /* Loop through each token until we find one that isn't a 18131 subtype. */ 18132 while (found_subtype) 18133 { 18134 found_subtype = false; 18135 const aarch64_branch_protect_type *subtype = type->subtypes; 18136 /* Search for the subtype. */ 18137 while (str && subtype && subtype->name && !found_subtype 18138 && res == AARCH64_PARSE_OK) 18139 { 18140 if (strcmp (str, subtype->name) == 0) 18141 { 18142 found_subtype = true; 18143 res = subtype->handler (str, next_str); 18144 str = next_str; 18145 next_str = strtok_r (NULL, "+", &token_save); 18146 } 18147 else 18148 subtype++; 18149 } 18150 } 18151 } 18152 else if (!found) 18153 res = AARCH64_PARSE_INVALID_ARG; 18154 } 18155 } 18156 /* Copy the last processed token into the argument to pass it back. 18157 Used by option and attribute validation to print the offending token. */ 18158 if (last_str) 18159 { 18160 if (str) strcpy (*last_str, str); 18161 else *last_str = NULL; 18162 } 18163 if (res == AARCH64_PARSE_OK) 18164 { 18165 /* If needed, alloc the accepted string then copy in const_str. 18166 Used by override_option_after_change_1. */ 18167 if (!accepted_branch_protection_string) 18168 accepted_branch_protection_string = (char *) xmalloc ( 18169 BRANCH_PROTECT_STR_MAX 18170 + 1); 18171 strncpy (accepted_branch_protection_string, const_str, 18172 BRANCH_PROTECT_STR_MAX + 1); 18173 /* Forcibly null-terminate. */ 18174 accepted_branch_protection_string[BRANCH_PROTECT_STR_MAX] = '\0'; 18175 } 18176 return res; 18177 } 18178 18179 static bool 18180 aarch64_validate_mbranch_protection (const char *const_str) 18181 { 18182 char *str = (char *) xmalloc (strlen (const_str)); 18183 enum aarch64_parse_opt_result res = 18184 aarch64_parse_branch_protection (const_str, &str); 18185 if (res == AARCH64_PARSE_INVALID_ARG) 18186 error ("invalid argument %<%s%> for %<-mbranch-protection=%>", str); 18187 else if (res == AARCH64_PARSE_MISSING_ARG) 18188 error ("missing argument for %<-mbranch-protection=%>"); 18189 free (str); 18190 return res == AARCH64_PARSE_OK; 18191 } 18192 18193 /* Validate a command-line -march option. Parse the arch and extensions 18194 (if any) specified in STR and throw errors if appropriate. Put the 18195 results, if they are valid, in RES and ISA_FLAGS. Return whether the 18196 option is valid. */ 18197 18198 static bool 18199 aarch64_validate_march (const char *str, const struct processor **res, 18200 uint64_t *isa_flags) 18201 { 18202 std::string invalid_extension; 18203 enum aarch64_parse_opt_result parse_res 18204 = aarch64_parse_arch (str, res, isa_flags, &invalid_extension); 18205 18206 if (parse_res == AARCH64_PARSE_OK) 18207 return true; 18208 18209 switch (parse_res) 18210 { 18211 case AARCH64_PARSE_MISSING_ARG: 18212 error ("missing arch name in %<-march=%s%>", str); 18213 break; 18214 case AARCH64_PARSE_INVALID_ARG: 18215 error ("unknown value %qs for %<-march%>", str); 18216 aarch64_print_hint_for_arch (str); 18217 break; 18218 case AARCH64_PARSE_INVALID_FEATURE: 18219 error ("invalid feature modifier %qs in %<-march=%s%>", 18220 invalid_extension.c_str (), str); 18221 aarch64_print_hint_for_extensions (invalid_extension); 18222 break; 18223 default: 18224 gcc_unreachable (); 18225 } 18226 18227 return false; 18228 } 18229 18230 /* Validate a command-line -mtune option. Parse the cpu 18231 specified in STR and throw errors if appropriate. Put the 18232 result, if it is valid, in RES. Return whether the option is 18233 valid. */ 18234 18235 static bool 18236 aarch64_validate_mtune (const char *str, const struct processor **res) 18237 { 18238 enum aarch64_parse_opt_result parse_res 18239 = aarch64_parse_tune (str, res); 18240 18241 if (parse_res == AARCH64_PARSE_OK) 18242 return true; 18243 18244 switch (parse_res) 18245 { 18246 case AARCH64_PARSE_MISSING_ARG: 18247 error ("missing cpu name in %<-mtune=%s%>", str); 18248 break; 18249 case AARCH64_PARSE_INVALID_ARG: 18250 error ("unknown value %qs for %<-mtune%>", str); 18251 aarch64_print_hint_for_core (str); 18252 break; 18253 default: 18254 gcc_unreachable (); 18255 } 18256 return false; 18257 } 18258 18259 static_assert (TARGET_CPU_generic < TARGET_CPU_MASK, 18260 "TARGET_CPU_NBITS is big enough"); 18261 18262 /* Return the CPU corresponding to the enum CPU. 18263 If it doesn't specify a cpu, return the default. */ 18264 18265 static const struct processor * 18266 aarch64_get_tune_cpu (enum aarch64_processor cpu) 18267 { 18268 if (cpu != aarch64_none) 18269 return &all_cores[cpu]; 18270 18271 /* The & TARGET_CPU_MASK is to extract the bottom TARGET_CPU_NBITS bits that 18272 encode the default cpu as selected by the --with-cpu GCC configure option 18273 in config.gcc. 18274 ???: The whole TARGET_CPU_DEFAULT and AARCH64_CPU_DEFAULT_FLAGS 18275 flags mechanism should be reworked to make it more sane. */ 18276 return &all_cores[TARGET_CPU_DEFAULT & TARGET_CPU_MASK]; 18277 } 18278 18279 /* Return the architecture corresponding to the enum ARCH. 18280 If it doesn't specify a valid architecture, return the default. */ 18281 18282 static const struct processor * 18283 aarch64_get_arch (enum aarch64_arch arch) 18284 { 18285 if (arch != aarch64_no_arch) 18286 return &all_architectures[arch]; 18287 18288 const struct processor *cpu 18289 = &all_cores[TARGET_CPU_DEFAULT & TARGET_CPU_MASK]; 18290 18291 return &all_architectures[cpu->arch]; 18292 } 18293 18294 /* Return the VG value associated with -msve-vector-bits= value VALUE. */ 18295 18296 static poly_uint16 18297 aarch64_convert_sve_vector_bits (aarch64_sve_vector_bits_enum value) 18298 { 18299 /* 128-bit SVE and Advanced SIMD modes use different register layouts 18300 on big-endian targets, so we would need to forbid subregs that convert 18301 from one to the other. By default a reinterpret sequence would then 18302 involve a store to memory in one mode and a load back in the other. 18303 Even if we optimize that sequence using reverse instructions, 18304 it would still be a significant potential overhead. 18305 18306 For now, it seems better to generate length-agnostic code for that 18307 case instead. */ 18308 if (value == SVE_SCALABLE 18309 || (value == SVE_128 && BYTES_BIG_ENDIAN)) 18310 return poly_uint16 (2, 2); 18311 else 18312 return (int) value / 64; 18313 } 18314 18315 /* Implement TARGET_OPTION_OVERRIDE. This is called once in the beginning 18316 and is used to parse the -m{cpu,tune,arch} strings and setup the initial 18317 tuning structs. In particular it must set selected_tune and 18318 aarch64_isa_flags that define the available ISA features and tuning 18319 decisions. It must also set selected_arch as this will be used to 18320 output the .arch asm tags for each function. */ 18321 18322 static void 18323 aarch64_override_options (void) 18324 { 18325 uint64_t cpu_isa = 0; 18326 uint64_t arch_isa = 0; 18327 aarch64_isa_flags = 0; 18328 18329 bool valid_cpu = true; 18330 bool valid_tune = true; 18331 bool valid_arch = true; 18332 18333 selected_cpu = NULL; 18334 selected_arch = NULL; 18335 selected_tune = NULL; 18336 18337 if (aarch64_harden_sls_string) 18338 aarch64_validate_sls_mitigation (aarch64_harden_sls_string); 18339 18340 if (aarch64_branch_protection_string) 18341 aarch64_validate_mbranch_protection (aarch64_branch_protection_string); 18342 18343 /* -mcpu=CPU is shorthand for -march=ARCH_FOR_CPU, -mtune=CPU. 18344 If either of -march or -mtune is given, they override their 18345 respective component of -mcpu. */ 18346 if (aarch64_cpu_string) 18347 valid_cpu = aarch64_validate_mcpu (aarch64_cpu_string, &selected_cpu, 18348 &cpu_isa); 18349 18350 if (aarch64_arch_string) 18351 valid_arch = aarch64_validate_march (aarch64_arch_string, &selected_arch, 18352 &arch_isa); 18353 18354 if (aarch64_tune_string) 18355 valid_tune = aarch64_validate_mtune (aarch64_tune_string, &selected_tune); 18356 18357 #ifdef SUBTARGET_OVERRIDE_OPTIONS 18358 SUBTARGET_OVERRIDE_OPTIONS; 18359 #endif 18360 18361 /* If the user did not specify a processor, choose the default 18362 one for them. This will be the CPU set during configuration using 18363 --with-cpu, otherwise it is "generic". */ 18364 if (!selected_cpu) 18365 { 18366 if (selected_arch) 18367 { 18368 selected_cpu = &all_cores[selected_arch->ident]; 18369 aarch64_isa_flags = arch_isa; 18370 explicit_arch = selected_arch->arch; 18371 } 18372 else 18373 { 18374 /* Get default configure-time CPU. */ 18375 selected_cpu = aarch64_get_tune_cpu (aarch64_none); 18376 aarch64_isa_flags = TARGET_CPU_DEFAULT >> TARGET_CPU_NBITS; 18377 } 18378 18379 if (selected_tune) 18380 explicit_tune_core = selected_tune->ident; 18381 } 18382 /* If both -mcpu and -march are specified check that they are architecturally 18383 compatible, warn if they're not and prefer the -march ISA flags. */ 18384 else if (selected_arch) 18385 { 18386 if (selected_arch->arch != selected_cpu->arch) 18387 { 18388 warning (0, "switch %<-mcpu=%s%> conflicts with %<-march=%s%> switch", 18389 aarch64_cpu_string, 18390 aarch64_arch_string); 18391 } 18392 aarch64_isa_flags = arch_isa; 18393 explicit_arch = selected_arch->arch; 18394 explicit_tune_core = selected_tune ? selected_tune->ident 18395 : selected_cpu->ident; 18396 } 18397 else 18398 { 18399 /* -mcpu but no -march. */ 18400 aarch64_isa_flags = cpu_isa; 18401 explicit_tune_core = selected_tune ? selected_tune->ident 18402 : selected_cpu->ident; 18403 gcc_assert (selected_cpu); 18404 selected_arch = &all_architectures[selected_cpu->arch]; 18405 explicit_arch = selected_arch->arch; 18406 } 18407 18408 /* Set the arch as well as we will need it when outputing 18409 the .arch directive in assembly. */ 18410 if (!selected_arch) 18411 { 18412 gcc_assert (selected_cpu); 18413 selected_arch = &all_architectures[selected_cpu->arch]; 18414 } 18415 18416 if (!selected_tune) 18417 selected_tune = selected_cpu; 18418 18419 if (aarch64_enable_bti == 2) 18420 { 18421 #ifdef TARGET_ENABLE_BTI 18422 aarch64_enable_bti = 1; 18423 #else 18424 aarch64_enable_bti = 0; 18425 #endif 18426 } 18427 18428 /* Return address signing is currently not supported for ILP32 targets. For 18429 LP64 targets use the configured option in the absence of a command-line 18430 option for -mbranch-protection. */ 18431 if (!TARGET_ILP32 && accepted_branch_protection_string == NULL) 18432 { 18433 #ifdef TARGET_ENABLE_PAC_RET 18434 aarch64_ra_sign_scope = AARCH64_FUNCTION_NON_LEAF; 18435 #else 18436 aarch64_ra_sign_scope = AARCH64_FUNCTION_NONE; 18437 #endif 18438 } 18439 18440 #ifndef HAVE_AS_MABI_OPTION 18441 /* The compiler may have been configured with 2.23.* binutils, which does 18442 not have support for ILP32. */ 18443 if (TARGET_ILP32) 18444 error ("assembler does not support %<-mabi=ilp32%>"); 18445 #endif 18446 18447 /* Convert -msve-vector-bits to a VG count. */ 18448 aarch64_sve_vg = aarch64_convert_sve_vector_bits (aarch64_sve_vector_bits); 18449 18450 if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE && TARGET_ILP32) 18451 sorry ("return address signing is only supported for %<-mabi=lp64%>"); 18452 18453 /* Make sure we properly set up the explicit options. */ 18454 if ((aarch64_cpu_string && valid_cpu) 18455 || (aarch64_tune_string && valid_tune)) 18456 gcc_assert (explicit_tune_core != aarch64_none); 18457 18458 if ((aarch64_cpu_string && valid_cpu) 18459 || (aarch64_arch_string && valid_arch)) 18460 gcc_assert (explicit_arch != aarch64_no_arch); 18461 18462 /* The pass to insert speculation tracking runs before 18463 shrink-wrapping and the latter does not know how to update the 18464 tracking status. So disable it in this case. */ 18465 if (aarch64_track_speculation) 18466 flag_shrink_wrap = 0; 18467 18468 aarch64_override_options_internal (&global_options); 18469 18470 /* Save these options as the default ones in case we push and pop them later 18471 while processing functions with potential target attributes. */ 18472 target_option_default_node = target_option_current_node 18473 = build_target_option_node (&global_options, &global_options_set); 18474 } 18475 18476 /* Implement targetm.override_options_after_change. */ 18477 18478 static void 18479 aarch64_override_options_after_change (void) 18480 { 18481 aarch64_override_options_after_change_1 (&global_options); 18482 } 18483 18484 /* Implement the TARGET_OFFLOAD_OPTIONS hook. */ 18485 static char * 18486 aarch64_offload_options (void) 18487 { 18488 if (TARGET_ILP32) 18489 return xstrdup ("-foffload-abi=ilp32"); 18490 else 18491 return xstrdup ("-foffload-abi=lp64"); 18492 } 18493 18494 static struct machine_function * 18495 aarch64_init_machine_status (void) 18496 { 18497 struct machine_function *machine; 18498 machine = ggc_cleared_alloc<machine_function> (); 18499 return machine; 18500 } 18501 18502 void 18503 aarch64_init_expanders (void) 18504 { 18505 init_machine_status = aarch64_init_machine_status; 18506 } 18507 18508 /* A checking mechanism for the implementation of the various code models. */ 18509 static void 18510 initialize_aarch64_code_model (struct gcc_options *opts) 18511 { 18512 aarch64_cmodel = opts->x_aarch64_cmodel_var; 18513 switch (opts->x_aarch64_cmodel_var) 18514 { 18515 case AARCH64_CMODEL_TINY: 18516 if (opts->x_flag_pic) 18517 aarch64_cmodel = AARCH64_CMODEL_TINY_PIC; 18518 break; 18519 case AARCH64_CMODEL_SMALL: 18520 if (opts->x_flag_pic) 18521 { 18522 #ifdef HAVE_AS_SMALL_PIC_RELOCS 18523 aarch64_cmodel = (flag_pic == 2 18524 ? AARCH64_CMODEL_SMALL_PIC 18525 : AARCH64_CMODEL_SMALL_SPIC); 18526 #else 18527 aarch64_cmodel = AARCH64_CMODEL_SMALL_PIC; 18528 #endif 18529 } 18530 break; 18531 case AARCH64_CMODEL_LARGE: 18532 if (opts->x_flag_pic) 18533 sorry ("code model %qs with %<-f%s%>", "large", 18534 opts->x_flag_pic > 1 ? "PIC" : "pic"); 18535 if (opts->x_aarch64_abi == AARCH64_ABI_ILP32) 18536 sorry ("code model %qs not supported in ilp32 mode", "large"); 18537 break; 18538 case AARCH64_CMODEL_TINY_PIC: 18539 case AARCH64_CMODEL_SMALL_PIC: 18540 case AARCH64_CMODEL_SMALL_SPIC: 18541 gcc_unreachable (); 18542 } 18543 } 18544 18545 /* Implement TARGET_OPTION_SAVE. */ 18546 18547 static void 18548 aarch64_option_save (struct cl_target_option *ptr, struct gcc_options *opts, 18549 struct gcc_options */* opts_set */) 18550 { 18551 ptr->x_aarch64_override_tune_string = opts->x_aarch64_override_tune_string; 18552 ptr->x_aarch64_branch_protection_string 18553 = opts->x_aarch64_branch_protection_string; 18554 } 18555 18556 /* Implements TARGET_OPTION_RESTORE. Restore the backend codegen decisions 18557 using the information saved in PTR. */ 18558 18559 static void 18560 aarch64_option_restore (struct gcc_options *opts, 18561 struct gcc_options */* opts_set */, 18562 struct cl_target_option *ptr) 18563 { 18564 opts->x_explicit_arch = ptr->x_explicit_arch; 18565 selected_arch = aarch64_get_arch (ptr->x_explicit_arch); 18566 opts->x_explicit_tune_core = ptr->x_explicit_tune_core; 18567 if (opts->x_explicit_tune_core == aarch64_none 18568 && opts->x_explicit_arch != aarch64_no_arch) 18569 selected_tune = &all_cores[selected_arch->ident]; 18570 else 18571 selected_tune = aarch64_get_tune_cpu (ptr->x_explicit_tune_core); 18572 opts->x_aarch64_override_tune_string = ptr->x_aarch64_override_tune_string; 18573 opts->x_aarch64_branch_protection_string 18574 = ptr->x_aarch64_branch_protection_string; 18575 if (opts->x_aarch64_branch_protection_string) 18576 { 18577 aarch64_parse_branch_protection (opts->x_aarch64_branch_protection_string, 18578 NULL); 18579 } 18580 18581 aarch64_override_options_internal (opts); 18582 } 18583 18584 /* Implement TARGET_OPTION_PRINT. */ 18585 18586 static void 18587 aarch64_option_print (FILE *file, int indent, struct cl_target_option *ptr) 18588 { 18589 const struct processor *cpu 18590 = aarch64_get_tune_cpu (ptr->x_explicit_tune_core); 18591 uint64_t isa_flags = ptr->x_aarch64_isa_flags; 18592 const struct processor *arch = aarch64_get_arch (ptr->x_explicit_arch); 18593 std::string extension 18594 = aarch64_get_extension_string_for_isa_flags (isa_flags, arch->flags); 18595 18596 fprintf (file, "%*sselected tune = %s\n", indent, "", cpu->name); 18597 fprintf (file, "%*sselected arch = %s%s\n", indent, "", 18598 arch->name, extension.c_str ()); 18599 } 18600 18601 static GTY(()) tree aarch64_previous_fndecl; 18602 18603 void 18604 aarch64_reset_previous_fndecl (void) 18605 { 18606 aarch64_previous_fndecl = NULL; 18607 } 18608 18609 /* Restore or save the TREE_TARGET_GLOBALS from or to NEW_TREE. 18610 Used by aarch64_set_current_function and aarch64_pragma_target_parse to 18611 make sure optab availability predicates are recomputed when necessary. */ 18612 18613 void 18614 aarch64_save_restore_target_globals (tree new_tree) 18615 { 18616 if (TREE_TARGET_GLOBALS (new_tree)) 18617 restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); 18618 else if (new_tree == target_option_default_node) 18619 restore_target_globals (&default_target_globals); 18620 else 18621 TREE_TARGET_GLOBALS (new_tree) = save_target_globals_default_opts (); 18622 } 18623 18624 /* Implement TARGET_SET_CURRENT_FUNCTION. Unpack the codegen decisions 18625 like tuning and ISA features from the DECL_FUNCTION_SPECIFIC_TARGET 18626 of the function, if such exists. This function may be called multiple 18627 times on a single function so use aarch64_previous_fndecl to avoid 18628 setting up identical state. */ 18629 18630 static void 18631 aarch64_set_current_function (tree fndecl) 18632 { 18633 if (!fndecl || fndecl == aarch64_previous_fndecl) 18634 return; 18635 18636 tree old_tree = (aarch64_previous_fndecl 18637 ? DECL_FUNCTION_SPECIFIC_TARGET (aarch64_previous_fndecl) 18638 : NULL_TREE); 18639 18640 tree new_tree = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); 18641 18642 /* If current function has no attributes but the previous one did, 18643 use the default node. */ 18644 if (!new_tree && old_tree) 18645 new_tree = target_option_default_node; 18646 18647 /* If nothing to do, return. #pragma GCC reset or #pragma GCC pop to 18648 the default have been handled by aarch64_save_restore_target_globals from 18649 aarch64_pragma_target_parse. */ 18650 if (old_tree == new_tree) 18651 return; 18652 18653 aarch64_previous_fndecl = fndecl; 18654 18655 /* First set the target options. */ 18656 cl_target_option_restore (&global_options, &global_options_set, 18657 TREE_TARGET_OPTION (new_tree)); 18658 18659 aarch64_save_restore_target_globals (new_tree); 18660 } 18661 18662 /* Enum describing the various ways we can handle attributes. 18663 In many cases we can reuse the generic option handling machinery. */ 18664 18665 enum aarch64_attr_opt_type 18666 { 18667 aarch64_attr_mask, /* Attribute should set a bit in target_flags. */ 18668 aarch64_attr_bool, /* Attribute sets or unsets a boolean variable. */ 18669 aarch64_attr_enum, /* Attribute sets an enum variable. */ 18670 aarch64_attr_custom /* Attribute requires a custom handling function. */ 18671 }; 18672 18673 /* All the information needed to handle a target attribute. 18674 NAME is the name of the attribute. 18675 ATTR_TYPE specifies the type of behavior of the attribute as described 18676 in the definition of enum aarch64_attr_opt_type. 18677 ALLOW_NEG is true if the attribute supports a "no-" form. 18678 HANDLER is the function that takes the attribute string as an argument 18679 It is needed only when the ATTR_TYPE is aarch64_attr_custom. 18680 OPT_NUM is the enum specifying the option that the attribute modifies. 18681 This is needed for attributes that mirror the behavior of a command-line 18682 option, that is it has ATTR_TYPE aarch64_attr_mask, aarch64_attr_bool or 18683 aarch64_attr_enum. */ 18684 18685 struct aarch64_attribute_info 18686 { 18687 const char *name; 18688 enum aarch64_attr_opt_type attr_type; 18689 bool allow_neg; 18690 bool (*handler) (const char *); 18691 enum opt_code opt_num; 18692 }; 18693 18694 /* Handle the ARCH_STR argument to the arch= target attribute. */ 18695 18696 static bool 18697 aarch64_handle_attr_arch (const char *str) 18698 { 18699 const struct processor *tmp_arch = NULL; 18700 std::string invalid_extension; 18701 enum aarch64_parse_opt_result parse_res 18702 = aarch64_parse_arch (str, &tmp_arch, &aarch64_isa_flags, &invalid_extension); 18703 18704 if (parse_res == AARCH64_PARSE_OK) 18705 { 18706 gcc_assert (tmp_arch); 18707 selected_arch = tmp_arch; 18708 explicit_arch = selected_arch->arch; 18709 return true; 18710 } 18711 18712 switch (parse_res) 18713 { 18714 case AARCH64_PARSE_MISSING_ARG: 18715 error ("missing name in %<target(\"arch=\")%> pragma or attribute"); 18716 break; 18717 case AARCH64_PARSE_INVALID_ARG: 18718 error ("invalid name %qs in %<target(\"arch=\")%> pragma or attribute", str); 18719 aarch64_print_hint_for_arch (str); 18720 break; 18721 case AARCH64_PARSE_INVALID_FEATURE: 18722 error ("invalid feature modifier %s of value %qs in " 18723 "%<target()%> pragma or attribute", invalid_extension.c_str (), str); 18724 aarch64_print_hint_for_extensions (invalid_extension); 18725 break; 18726 default: 18727 gcc_unreachable (); 18728 } 18729 18730 return false; 18731 } 18732 18733 /* Handle the argument CPU_STR to the cpu= target attribute. */ 18734 18735 static bool 18736 aarch64_handle_attr_cpu (const char *str) 18737 { 18738 const struct processor *tmp_cpu = NULL; 18739 std::string invalid_extension; 18740 enum aarch64_parse_opt_result parse_res 18741 = aarch64_parse_cpu (str, &tmp_cpu, &aarch64_isa_flags, &invalid_extension); 18742 18743 if (parse_res == AARCH64_PARSE_OK) 18744 { 18745 gcc_assert (tmp_cpu); 18746 selected_tune = tmp_cpu; 18747 explicit_tune_core = selected_tune->ident; 18748 18749 selected_arch = &all_architectures[tmp_cpu->arch]; 18750 explicit_arch = selected_arch->arch; 18751 return true; 18752 } 18753 18754 switch (parse_res) 18755 { 18756 case AARCH64_PARSE_MISSING_ARG: 18757 error ("missing name in %<target(\"cpu=\")%> pragma or attribute"); 18758 break; 18759 case AARCH64_PARSE_INVALID_ARG: 18760 error ("invalid name %qs in %<target(\"cpu=\")%> pragma or attribute", str); 18761 aarch64_print_hint_for_core (str); 18762 break; 18763 case AARCH64_PARSE_INVALID_FEATURE: 18764 error ("invalid feature modifier %qs of value %qs in " 18765 "%<target()%> pragma or attribute", invalid_extension.c_str (), str); 18766 aarch64_print_hint_for_extensions (invalid_extension); 18767 break; 18768 default: 18769 gcc_unreachable (); 18770 } 18771 18772 return false; 18773 } 18774 18775 /* Handle the argument STR to the branch-protection= attribute. */ 18776 18777 static bool 18778 aarch64_handle_attr_branch_protection (const char* str) 18779 { 18780 char *err_str = (char *) xmalloc (strlen (str) + 1); 18781 enum aarch64_parse_opt_result res = aarch64_parse_branch_protection (str, 18782 &err_str); 18783 bool success = false; 18784 switch (res) 18785 { 18786 case AARCH64_PARSE_MISSING_ARG: 18787 error ("missing argument to %<target(\"branch-protection=\")%> pragma or" 18788 " attribute"); 18789 break; 18790 case AARCH64_PARSE_INVALID_ARG: 18791 error ("invalid protection type %qs in %<target(\"branch-protection" 18792 "=\")%> pragma or attribute", err_str); 18793 break; 18794 case AARCH64_PARSE_OK: 18795 success = true; 18796 /* Fall through. */ 18797 case AARCH64_PARSE_INVALID_FEATURE: 18798 break; 18799 default: 18800 gcc_unreachable (); 18801 } 18802 free (err_str); 18803 return success; 18804 } 18805 18806 /* Handle the argument STR to the tune= target attribute. */ 18807 18808 static bool 18809 aarch64_handle_attr_tune (const char *str) 18810 { 18811 const struct processor *tmp_tune = NULL; 18812 enum aarch64_parse_opt_result parse_res 18813 = aarch64_parse_tune (str, &tmp_tune); 18814 18815 if (parse_res == AARCH64_PARSE_OK) 18816 { 18817 gcc_assert (tmp_tune); 18818 selected_tune = tmp_tune; 18819 explicit_tune_core = selected_tune->ident; 18820 return true; 18821 } 18822 18823 switch (parse_res) 18824 { 18825 case AARCH64_PARSE_INVALID_ARG: 18826 error ("invalid name %qs in %<target(\"tune=\")%> pragma or attribute", str); 18827 aarch64_print_hint_for_core (str); 18828 break; 18829 default: 18830 gcc_unreachable (); 18831 } 18832 18833 return false; 18834 } 18835 18836 /* Parse an architecture extensions target attribute string specified in STR. 18837 For example "+fp+nosimd". Show any errors if needed. Return TRUE 18838 if successful. Update aarch64_isa_flags to reflect the ISA features 18839 modified. */ 18840 18841 static bool 18842 aarch64_handle_attr_isa_flags (char *str) 18843 { 18844 enum aarch64_parse_opt_result parse_res; 18845 uint64_t isa_flags = aarch64_isa_flags; 18846 18847 /* We allow "+nothing" in the beginning to clear out all architectural 18848 features if the user wants to handpick specific features. */ 18849 if (strncmp ("+nothing", str, 8) == 0) 18850 { 18851 isa_flags = 0; 18852 str += 8; 18853 } 18854 18855 std::string invalid_extension; 18856 parse_res = aarch64_parse_extension (str, &isa_flags, &invalid_extension); 18857 18858 if (parse_res == AARCH64_PARSE_OK) 18859 { 18860 aarch64_isa_flags = isa_flags; 18861 return true; 18862 } 18863 18864 switch (parse_res) 18865 { 18866 case AARCH64_PARSE_MISSING_ARG: 18867 error ("missing value in %<target()%> pragma or attribute"); 18868 break; 18869 18870 case AARCH64_PARSE_INVALID_FEATURE: 18871 error ("invalid feature modifier %qs of value %qs in " 18872 "%<target()%> pragma or attribute", invalid_extension.c_str (), str); 18873 break; 18874 18875 default: 18876 gcc_unreachable (); 18877 } 18878 18879 return false; 18880 } 18881 18882 /* The target attributes that we support. On top of these we also support just 18883 ISA extensions, like __attribute__ ((target ("+crc"))), but that case is 18884 handled explicitly in aarch64_process_one_target_attr. */ 18885 18886 static const struct aarch64_attribute_info aarch64_attributes[] = 18887 { 18888 { "general-regs-only", aarch64_attr_mask, false, NULL, 18889 OPT_mgeneral_regs_only }, 18890 { "fix-cortex-a53-835769", aarch64_attr_bool, true, NULL, 18891 OPT_mfix_cortex_a53_835769 }, 18892 { "fix-cortex-a53-843419", aarch64_attr_bool, true, NULL, 18893 OPT_mfix_cortex_a53_843419 }, 18894 { "cmodel", aarch64_attr_enum, false, NULL, OPT_mcmodel_ }, 18895 { "strict-align", aarch64_attr_mask, true, NULL, OPT_mstrict_align }, 18896 { "omit-leaf-frame-pointer", aarch64_attr_bool, true, NULL, 18897 OPT_momit_leaf_frame_pointer }, 18898 { "tls-dialect", aarch64_attr_enum, false, NULL, OPT_mtls_dialect_ }, 18899 { "arch", aarch64_attr_custom, false, aarch64_handle_attr_arch, 18900 OPT_march_ }, 18901 { "cpu", aarch64_attr_custom, false, aarch64_handle_attr_cpu, OPT_mcpu_ }, 18902 { "tune", aarch64_attr_custom, false, aarch64_handle_attr_tune, 18903 OPT_mtune_ }, 18904 { "branch-protection", aarch64_attr_custom, false, 18905 aarch64_handle_attr_branch_protection, OPT_mbranch_protection_ }, 18906 { "sign-return-address", aarch64_attr_enum, false, NULL, 18907 OPT_msign_return_address_ }, 18908 { "outline-atomics", aarch64_attr_bool, true, NULL, 18909 OPT_moutline_atomics}, 18910 { NULL, aarch64_attr_custom, false, NULL, OPT____ } 18911 }; 18912 18913 /* Parse ARG_STR which contains the definition of one target attribute. 18914 Show appropriate errors if any or return true if the attribute is valid. */ 18915 18916 static bool 18917 aarch64_process_one_target_attr (char *arg_str) 18918 { 18919 bool invert = false; 18920 18921 size_t len = strlen (arg_str); 18922 18923 if (len == 0) 18924 { 18925 error ("malformed %<target()%> pragma or attribute"); 18926 return false; 18927 } 18928 18929 char *str_to_check = (char *) alloca (len + 1); 18930 strcpy (str_to_check, arg_str); 18931 18932 /* We have something like __attribute__ ((target ("+fp+nosimd"))). 18933 It is easier to detect and handle it explicitly here rather than going 18934 through the machinery for the rest of the target attributes in this 18935 function. */ 18936 if (*str_to_check == '+') 18937 return aarch64_handle_attr_isa_flags (str_to_check); 18938 18939 if (len > 3 && startswith (str_to_check, "no-")) 18940 { 18941 invert = true; 18942 str_to_check += 3; 18943 } 18944 char *arg = strchr (str_to_check, '='); 18945 18946 /* If we found opt=foo then terminate STR_TO_CHECK at the '=' 18947 and point ARG to "foo". */ 18948 if (arg) 18949 { 18950 *arg = '\0'; 18951 arg++; 18952 } 18953 const struct aarch64_attribute_info *p_attr; 18954 bool found = false; 18955 for (p_attr = aarch64_attributes; p_attr->name; p_attr++) 18956 { 18957 /* If the names don't match up, or the user has given an argument 18958 to an attribute that doesn't accept one, or didn't give an argument 18959 to an attribute that expects one, fail to match. */ 18960 if (strcmp (str_to_check, p_attr->name) != 0) 18961 continue; 18962 18963 found = true; 18964 bool attr_need_arg_p = p_attr->attr_type == aarch64_attr_custom 18965 || p_attr->attr_type == aarch64_attr_enum; 18966 18967 if (attr_need_arg_p ^ (arg != NULL)) 18968 { 18969 error ("pragma or attribute %<target(\"%s\")%> does not accept an argument", str_to_check); 18970 return false; 18971 } 18972 18973 /* If the name matches but the attribute does not allow "no-" versions 18974 then we can't match. */ 18975 if (invert && !p_attr->allow_neg) 18976 { 18977 error ("pragma or attribute %<target(\"%s\")%> does not allow a negated form", str_to_check); 18978 return false; 18979 } 18980 18981 switch (p_attr->attr_type) 18982 { 18983 /* Has a custom handler registered. 18984 For example, cpu=, arch=, tune=. */ 18985 case aarch64_attr_custom: 18986 gcc_assert (p_attr->handler); 18987 if (!p_attr->handler (arg)) 18988 return false; 18989 break; 18990 18991 /* Either set or unset a boolean option. */ 18992 case aarch64_attr_bool: 18993 { 18994 struct cl_decoded_option decoded; 18995 18996 generate_option (p_attr->opt_num, NULL, !invert, 18997 CL_TARGET, &decoded); 18998 aarch64_handle_option (&global_options, &global_options_set, 18999 &decoded, input_location); 19000 break; 19001 } 19002 /* Set or unset a bit in the target_flags. aarch64_handle_option 19003 should know what mask to apply given the option number. */ 19004 case aarch64_attr_mask: 19005 { 19006 struct cl_decoded_option decoded; 19007 /* We only need to specify the option number. 19008 aarch64_handle_option will know which mask to apply. */ 19009 decoded.opt_index = p_attr->opt_num; 19010 decoded.value = !invert; 19011 aarch64_handle_option (&global_options, &global_options_set, 19012 &decoded, input_location); 19013 break; 19014 } 19015 /* Use the option setting machinery to set an option to an enum. */ 19016 case aarch64_attr_enum: 19017 { 19018 gcc_assert (arg); 19019 bool valid; 19020 int value; 19021 valid = opt_enum_arg_to_value (p_attr->opt_num, arg, 19022 &value, CL_TARGET); 19023 if (valid) 19024 { 19025 set_option (&global_options, NULL, p_attr->opt_num, value, 19026 NULL, DK_UNSPECIFIED, input_location, 19027 global_dc); 19028 } 19029 else 19030 { 19031 error ("pragma or attribute %<target(\"%s=%s\")%> is not valid", str_to_check, arg); 19032 } 19033 break; 19034 } 19035 default: 19036 gcc_unreachable (); 19037 } 19038 } 19039 19040 /* If we reached here we either have found an attribute and validated 19041 it or didn't match any. If we matched an attribute but its arguments 19042 were malformed we will have returned false already. */ 19043 return found; 19044 } 19045 19046 /* Count how many times the character C appears in 19047 NULL-terminated string STR. */ 19048 19049 static unsigned int 19050 num_occurences_in_str (char c, char *str) 19051 { 19052 unsigned int res = 0; 19053 while (*str != '\0') 19054 { 19055 if (*str == c) 19056 res++; 19057 19058 str++; 19059 } 19060 19061 return res; 19062 } 19063 19064 /* Parse the tree in ARGS that contains the target attribute information 19065 and update the global target options space. */ 19066 19067 bool 19068 aarch64_process_target_attr (tree args) 19069 { 19070 if (TREE_CODE (args) == TREE_LIST) 19071 { 19072 do 19073 { 19074 tree head = TREE_VALUE (args); 19075 if (head) 19076 { 19077 if (!aarch64_process_target_attr (head)) 19078 return false; 19079 } 19080 args = TREE_CHAIN (args); 19081 } while (args); 19082 19083 return true; 19084 } 19085 19086 if (TREE_CODE (args) != STRING_CST) 19087 { 19088 error ("attribute %<target%> argument not a string"); 19089 return false; 19090 } 19091 19092 size_t len = strlen (TREE_STRING_POINTER (args)); 19093 char *str_to_check = (char *) alloca (len + 1); 19094 strcpy (str_to_check, TREE_STRING_POINTER (args)); 19095 19096 if (len == 0) 19097 { 19098 error ("malformed %<target()%> pragma or attribute"); 19099 return false; 19100 } 19101 19102 /* Used to catch empty spaces between commas i.e. 19103 attribute ((target ("attr1,,attr2"))). */ 19104 unsigned int num_commas = num_occurences_in_str (',', str_to_check); 19105 19106 /* Handle multiple target attributes separated by ','. */ 19107 char *token = strtok_r (str_to_check, ",", &str_to_check); 19108 19109 unsigned int num_attrs = 0; 19110 while (token) 19111 { 19112 num_attrs++; 19113 if (!aarch64_process_one_target_attr (token)) 19114 { 19115 /* Check if token is possibly an arch extension without 19116 leading '+'. */ 19117 uint64_t isa_temp = 0; 19118 auto with_plus = std::string ("+") + token; 19119 enum aarch64_parse_opt_result ext_res 19120 = aarch64_parse_extension (with_plus.c_str (), &isa_temp, nullptr); 19121 19122 if (ext_res == AARCH64_PARSE_OK) 19123 error ("arch extension %<%s%> should be prefixed by %<+%>", 19124 token); 19125 else 19126 error ("pragma or attribute %<target(\"%s\")%> is not valid", token); 19127 return false; 19128 } 19129 19130 token = strtok_r (NULL, ",", &str_to_check); 19131 } 19132 19133 if (num_attrs != num_commas + 1) 19134 { 19135 error ("malformed %<target(\"%s\")%> pragma or attribute", TREE_STRING_POINTER (args)); 19136 return false; 19137 } 19138 19139 return true; 19140 } 19141 19142 /* Implement TARGET_OPTION_VALID_ATTRIBUTE_P. This is used to 19143 process attribute ((target ("..."))). */ 19144 19145 static bool 19146 aarch64_option_valid_attribute_p (tree fndecl, tree, tree args, int) 19147 { 19148 struct cl_target_option cur_target; 19149 bool ret; 19150 tree old_optimize; 19151 tree new_target, new_optimize; 19152 tree existing_target = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); 19153 19154 /* If what we're processing is the current pragma string then the 19155 target option node is already stored in target_option_current_node 19156 by aarch64_pragma_target_parse in aarch64-c.cc. Use that to avoid 19157 having to re-parse the string. This is especially useful to keep 19158 arm_neon.h compile times down since that header contains a lot 19159 of intrinsics enclosed in pragmas. */ 19160 if (!existing_target && args == current_target_pragma) 19161 { 19162 DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = target_option_current_node; 19163 return true; 19164 } 19165 tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); 19166 19167 old_optimize 19168 = build_optimization_node (&global_options, &global_options_set); 19169 func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); 19170 19171 /* If the function changed the optimization levels as well as setting 19172 target options, start with the optimizations specified. */ 19173 if (func_optimize && func_optimize != old_optimize) 19174 cl_optimization_restore (&global_options, &global_options_set, 19175 TREE_OPTIMIZATION (func_optimize)); 19176 19177 /* Save the current target options to restore at the end. */ 19178 cl_target_option_save (&cur_target, &global_options, &global_options_set); 19179 19180 /* If fndecl already has some target attributes applied to it, unpack 19181 them so that we add this attribute on top of them, rather than 19182 overwriting them. */ 19183 if (existing_target) 19184 { 19185 struct cl_target_option *existing_options 19186 = TREE_TARGET_OPTION (existing_target); 19187 19188 if (existing_options) 19189 cl_target_option_restore (&global_options, &global_options_set, 19190 existing_options); 19191 } 19192 else 19193 cl_target_option_restore (&global_options, &global_options_set, 19194 TREE_TARGET_OPTION (target_option_current_node)); 19195 19196 ret = aarch64_process_target_attr (args); 19197 19198 /* Set up any additional state. */ 19199 if (ret) 19200 { 19201 aarch64_override_options_internal (&global_options); 19202 /* Initialize SIMD builtins if we haven't already. 19203 Set current_target_pragma to NULL for the duration so that 19204 the builtin initialization code doesn't try to tag the functions 19205 being built with the attributes specified by any current pragma, thus 19206 going into an infinite recursion. */ 19207 if (TARGET_SIMD) 19208 { 19209 tree saved_current_target_pragma = current_target_pragma; 19210 current_target_pragma = NULL; 19211 aarch64_init_simd_builtins (); 19212 current_target_pragma = saved_current_target_pragma; 19213 } 19214 new_target = build_target_option_node (&global_options, 19215 &global_options_set); 19216 } 19217 else 19218 new_target = NULL; 19219 19220 new_optimize = build_optimization_node (&global_options, 19221 &global_options_set); 19222 19223 if (fndecl && ret) 19224 { 19225 DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target; 19226 19227 if (old_optimize != new_optimize) 19228 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl) = new_optimize; 19229 } 19230 19231 cl_target_option_restore (&global_options, &global_options_set, &cur_target); 19232 19233 if (old_optimize != new_optimize) 19234 cl_optimization_restore (&global_options, &global_options_set, 19235 TREE_OPTIMIZATION (old_optimize)); 19236 return ret; 19237 } 19238 19239 /* Helper for aarch64_can_inline_p. In the case where CALLER and CALLEE are 19240 tri-bool options (yes, no, don't care) and the default value is 19241 DEF, determine whether to reject inlining. */ 19242 19243 static bool 19244 aarch64_tribools_ok_for_inlining_p (int caller, int callee, 19245 int dont_care, int def) 19246 { 19247 /* If the callee doesn't care, always allow inlining. */ 19248 if (callee == dont_care) 19249 return true; 19250 19251 /* If the caller doesn't care, always allow inlining. */ 19252 if (caller == dont_care) 19253 return true; 19254 19255 /* Otherwise, allow inlining if either the callee and caller values 19256 agree, or if the callee is using the default value. */ 19257 return (callee == caller || callee == def); 19258 } 19259 19260 /* Implement TARGET_CAN_INLINE_P. Decide whether it is valid 19261 to inline CALLEE into CALLER based on target-specific info. 19262 Make sure that the caller and callee have compatible architectural 19263 features. Then go through the other possible target attributes 19264 and see if they can block inlining. Try not to reject always_inline 19265 callees unless they are incompatible architecturally. */ 19266 19267 static bool 19268 aarch64_can_inline_p (tree caller, tree callee) 19269 { 19270 tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET (caller); 19271 tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (callee); 19272 19273 struct cl_target_option *caller_opts 19274 = TREE_TARGET_OPTION (caller_tree ? caller_tree 19275 : target_option_default_node); 19276 19277 struct cl_target_option *callee_opts 19278 = TREE_TARGET_OPTION (callee_tree ? callee_tree 19279 : target_option_default_node); 19280 19281 /* Callee's ISA flags should be a subset of the caller's. */ 19282 if ((caller_opts->x_aarch64_isa_flags & callee_opts->x_aarch64_isa_flags) 19283 != callee_opts->x_aarch64_isa_flags) 19284 return false; 19285 19286 /* Allow non-strict aligned functions inlining into strict 19287 aligned ones. */ 19288 if ((TARGET_STRICT_ALIGN_P (caller_opts->x_target_flags) 19289 != TARGET_STRICT_ALIGN_P (callee_opts->x_target_flags)) 19290 && !(!TARGET_STRICT_ALIGN_P (callee_opts->x_target_flags) 19291 && TARGET_STRICT_ALIGN_P (caller_opts->x_target_flags))) 19292 return false; 19293 19294 bool always_inline = lookup_attribute ("always_inline", 19295 DECL_ATTRIBUTES (callee)); 19296 19297 /* If the architectural features match up and the callee is always_inline 19298 then the other attributes don't matter. */ 19299 if (always_inline) 19300 return true; 19301 19302 if (caller_opts->x_aarch64_cmodel_var 19303 != callee_opts->x_aarch64_cmodel_var) 19304 return false; 19305 19306 if (caller_opts->x_aarch64_tls_dialect 19307 != callee_opts->x_aarch64_tls_dialect) 19308 return false; 19309 19310 /* Honour explicit requests to workaround errata. */ 19311 if (!aarch64_tribools_ok_for_inlining_p ( 19312 caller_opts->x_aarch64_fix_a53_err835769, 19313 callee_opts->x_aarch64_fix_a53_err835769, 19314 2, TARGET_FIX_ERR_A53_835769_DEFAULT)) 19315 return false; 19316 19317 if (!aarch64_tribools_ok_for_inlining_p ( 19318 caller_opts->x_aarch64_fix_a53_err843419, 19319 callee_opts->x_aarch64_fix_a53_err843419, 19320 2, TARGET_FIX_ERR_A53_843419)) 19321 return false; 19322 19323 /* If the user explicitly specified -momit-leaf-frame-pointer for the 19324 caller and calle and they don't match up, reject inlining. */ 19325 if (!aarch64_tribools_ok_for_inlining_p ( 19326 caller_opts->x_flag_omit_leaf_frame_pointer, 19327 callee_opts->x_flag_omit_leaf_frame_pointer, 19328 2, 1)) 19329 return false; 19330 19331 /* If the callee has specific tuning overrides, respect them. */ 19332 if (callee_opts->x_aarch64_override_tune_string != NULL 19333 && caller_opts->x_aarch64_override_tune_string == NULL) 19334 return false; 19335 19336 /* If the user specified tuning override strings for the 19337 caller and callee and they don't match up, reject inlining. 19338 We just do a string compare here, we don't analyze the meaning 19339 of the string, as it would be too costly for little gain. */ 19340 if (callee_opts->x_aarch64_override_tune_string 19341 && caller_opts->x_aarch64_override_tune_string 19342 && (strcmp (callee_opts->x_aarch64_override_tune_string, 19343 caller_opts->x_aarch64_override_tune_string) != 0)) 19344 return false; 19345 19346 return true; 19347 } 19348 19349 /* Return the ID of the TLDESC ABI, initializing the descriptor if hasn't 19350 been already. */ 19351 19352 unsigned int 19353 aarch64_tlsdesc_abi_id () 19354 { 19355 predefined_function_abi &tlsdesc_abi = function_abis[ARM_PCS_TLSDESC]; 19356 if (!tlsdesc_abi.initialized_p ()) 19357 { 19358 HARD_REG_SET full_reg_clobbers; 19359 CLEAR_HARD_REG_SET (full_reg_clobbers); 19360 SET_HARD_REG_BIT (full_reg_clobbers, R0_REGNUM); 19361 SET_HARD_REG_BIT (full_reg_clobbers, CC_REGNUM); 19362 for (int regno = P0_REGNUM; regno <= P15_REGNUM; ++regno) 19363 SET_HARD_REG_BIT (full_reg_clobbers, regno); 19364 tlsdesc_abi.initialize (ARM_PCS_TLSDESC, full_reg_clobbers); 19365 } 19366 return tlsdesc_abi.id (); 19367 } 19368 19369 /* Return true if SYMBOL_REF X binds locally. */ 19370 19371 static bool 19372 aarch64_symbol_binds_local_p (const_rtx x) 19373 { 19374 return (SYMBOL_REF_DECL (x) 19375 ? targetm.binds_local_p (SYMBOL_REF_DECL (x)) 19376 : SYMBOL_REF_LOCAL_P (x)); 19377 } 19378 19379 /* Return true if SYMBOL_REF X is thread local */ 19380 static bool 19381 aarch64_tls_symbol_p (rtx x) 19382 { 19383 if (! TARGET_HAVE_TLS) 19384 return false; 19385 19386 x = strip_salt (x); 19387 if (!SYMBOL_REF_P (x)) 19388 return false; 19389 19390 return SYMBOL_REF_TLS_MODEL (x) != 0; 19391 } 19392 19393 /* Classify a TLS symbol into one of the TLS kinds. */ 19394 enum aarch64_symbol_type 19395 aarch64_classify_tls_symbol (rtx x) 19396 { 19397 enum tls_model tls_kind = tls_symbolic_operand_type (x); 19398 19399 switch (tls_kind) 19400 { 19401 case TLS_MODEL_GLOBAL_DYNAMIC: 19402 case TLS_MODEL_LOCAL_DYNAMIC: 19403 return TARGET_TLS_DESC ? SYMBOL_SMALL_TLSDESC : SYMBOL_SMALL_TLSGD; 19404 19405 case TLS_MODEL_INITIAL_EXEC: 19406 switch (aarch64_cmodel) 19407 { 19408 case AARCH64_CMODEL_TINY: 19409 case AARCH64_CMODEL_TINY_PIC: 19410 return SYMBOL_TINY_TLSIE; 19411 default: 19412 return SYMBOL_SMALL_TLSIE; 19413 } 19414 19415 case TLS_MODEL_LOCAL_EXEC: 19416 if (aarch64_tls_size == 12) 19417 return SYMBOL_TLSLE12; 19418 else if (aarch64_tls_size == 24) 19419 return SYMBOL_TLSLE24; 19420 else if (aarch64_tls_size == 32) 19421 return SYMBOL_TLSLE32; 19422 else if (aarch64_tls_size == 48) 19423 return SYMBOL_TLSLE48; 19424 else 19425 gcc_unreachable (); 19426 19427 case TLS_MODEL_EMULATED: 19428 case TLS_MODEL_NONE: 19429 return SYMBOL_FORCE_TO_MEM; 19430 19431 default: 19432 gcc_unreachable (); 19433 } 19434 } 19435 19436 /* Return the correct method for accessing X + OFFSET, where X is either 19437 a SYMBOL_REF or LABEL_REF. */ 19438 19439 enum aarch64_symbol_type 19440 aarch64_classify_symbol (rtx x, HOST_WIDE_INT offset) 19441 { 19442 x = strip_salt (x); 19443 19444 if (LABEL_REF_P (x)) 19445 { 19446 switch (aarch64_cmodel) 19447 { 19448 case AARCH64_CMODEL_LARGE: 19449 return SYMBOL_FORCE_TO_MEM; 19450 19451 case AARCH64_CMODEL_TINY_PIC: 19452 case AARCH64_CMODEL_TINY: 19453 return SYMBOL_TINY_ABSOLUTE; 19454 19455 case AARCH64_CMODEL_SMALL_SPIC: 19456 case AARCH64_CMODEL_SMALL_PIC: 19457 case AARCH64_CMODEL_SMALL: 19458 return SYMBOL_SMALL_ABSOLUTE; 19459 19460 default: 19461 gcc_unreachable (); 19462 } 19463 } 19464 19465 if (SYMBOL_REF_P (x)) 19466 { 19467 if (aarch64_tls_symbol_p (x)) 19468 return aarch64_classify_tls_symbol (x); 19469 19470 switch (aarch64_cmodel) 19471 { 19472 case AARCH64_CMODEL_TINY_PIC: 19473 case AARCH64_CMODEL_TINY: 19474 /* With -fPIC non-local symbols use the GOT. For orthogonality 19475 always use the GOT for extern weak symbols. */ 19476 if ((flag_pic || SYMBOL_REF_WEAK (x)) 19477 && !aarch64_symbol_binds_local_p (x)) 19478 return SYMBOL_TINY_GOT; 19479 19480 /* When we retrieve symbol + offset address, we have to make sure 19481 the offset does not cause overflow of the final address. But 19482 we have no way of knowing the address of symbol at compile time 19483 so we can't accurately say if the distance between the PC and 19484 symbol + offset is outside the addressible range of +/-1MB in the 19485 TINY code model. So we limit the maximum offset to +/-64KB and 19486 assume the offset to the symbol is not larger than +/-(1MB - 64KB). 19487 If offset_within_block_p is true we allow larger offsets. */ 19488 if (!(IN_RANGE (offset, -0x10000, 0x10000) 19489 || offset_within_block_p (x, offset))) 19490 return SYMBOL_FORCE_TO_MEM; 19491 19492 return SYMBOL_TINY_ABSOLUTE; 19493 19494 19495 case AARCH64_CMODEL_SMALL_SPIC: 19496 case AARCH64_CMODEL_SMALL_PIC: 19497 case AARCH64_CMODEL_SMALL: 19498 if ((flag_pic || SYMBOL_REF_WEAK (x)) 19499 && !aarch64_symbol_binds_local_p (x)) 19500 return aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC 19501 ? SYMBOL_SMALL_GOT_28K : SYMBOL_SMALL_GOT_4G; 19502 19503 /* Same reasoning as the tiny code model, but the offset cap here is 19504 1MB, allowing +/-3.9GB for the offset to the symbol. */ 19505 if (!(IN_RANGE (offset, -0x100000, 0x100000) 19506 || offset_within_block_p (x, offset))) 19507 return SYMBOL_FORCE_TO_MEM; 19508 19509 return SYMBOL_SMALL_ABSOLUTE; 19510 19511 case AARCH64_CMODEL_LARGE: 19512 /* This is alright even in PIC code as the constant 19513 pool reference is always PC relative and within 19514 the same translation unit. */ 19515 if (!aarch64_pcrelative_literal_loads && CONSTANT_POOL_ADDRESS_P (x)) 19516 return SYMBOL_SMALL_ABSOLUTE; 19517 else 19518 return SYMBOL_FORCE_TO_MEM; 19519 19520 default: 19521 gcc_unreachable (); 19522 } 19523 } 19524 19525 /* By default push everything into the constant pool. */ 19526 return SYMBOL_FORCE_TO_MEM; 19527 } 19528 19529 bool 19530 aarch64_constant_address_p (rtx x) 19531 { 19532 return (CONSTANT_P (x) && memory_address_p (DImode, x)); 19533 } 19534 19535 bool 19536 aarch64_legitimate_pic_operand_p (rtx x) 19537 { 19538 poly_int64 offset; 19539 x = strip_offset_and_salt (x, &offset); 19540 if (SYMBOL_REF_P (x)) 19541 return false; 19542 19543 return true; 19544 } 19545 19546 /* Implement TARGET_LEGITIMATE_CONSTANT_P hook. Return true for constants 19547 that should be rematerialized rather than spilled. */ 19548 19549 static bool 19550 aarch64_legitimate_constant_p (machine_mode mode, rtx x) 19551 { 19552 /* Support CSE and rematerialization of common constants. */ 19553 if (CONST_INT_P (x) 19554 || (CONST_DOUBLE_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT)) 19555 return true; 19556 19557 /* Only accept variable-length vector constants if they can be 19558 handled directly. 19559 19560 ??? It would be possible (but complex) to handle rematerialization 19561 of other constants via secondary reloads. */ 19562 if (!GET_MODE_SIZE (mode).is_constant ()) 19563 return aarch64_simd_valid_immediate (x, NULL); 19564 19565 /* Otherwise, accept any CONST_VECTOR that, if all else fails, can at 19566 least be forced to memory and loaded from there. */ 19567 if (CONST_VECTOR_P (x)) 19568 return !targetm.cannot_force_const_mem (mode, x); 19569 19570 /* Do not allow vector struct mode constants for Advanced SIMD. 19571 We could support 0 and -1 easily, but they need support in 19572 aarch64-simd.md. */ 19573 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 19574 if (vec_flags == (VEC_ADVSIMD | VEC_STRUCT)) 19575 return false; 19576 19577 if (GET_CODE (x) == HIGH) 19578 x = XEXP (x, 0); 19579 19580 /* Accept polynomial constants that can be calculated by using the 19581 destination of a move as the sole temporary. Constants that 19582 require a second temporary cannot be rematerialized (they can't be 19583 forced to memory and also aren't legitimate constants). */ 19584 poly_int64 offset; 19585 if (poly_int_rtx_p (x, &offset)) 19586 return aarch64_offset_temporaries (false, offset) <= 1; 19587 19588 /* If an offset is being added to something else, we need to allow the 19589 base to be moved into the destination register, meaning that there 19590 are no free temporaries for the offset. */ 19591 x = strip_offset_and_salt (x, &offset); 19592 if (!offset.is_constant () && aarch64_offset_temporaries (true, offset) > 0) 19593 return false; 19594 19595 /* Do not allow const (plus (anchor_symbol, const_int)). */ 19596 if (maybe_ne (offset, 0) && SYMBOL_REF_P (x) && SYMBOL_REF_ANCHOR_P (x)) 19597 return false; 19598 19599 /* Treat symbols as constants. Avoid TLS symbols as they are complex, 19600 so spilling them is better than rematerialization. */ 19601 if (SYMBOL_REF_P (x) && !SYMBOL_REF_TLS_MODEL (x)) 19602 return true; 19603 19604 /* Label references are always constant. */ 19605 if (LABEL_REF_P (x)) 19606 return true; 19607 19608 return false; 19609 } 19610 19611 rtx 19612 aarch64_load_tp (rtx target) 19613 { 19614 if (!target 19615 || GET_MODE (target) != Pmode 19616 || !register_operand (target, Pmode)) 19617 target = gen_reg_rtx (Pmode); 19618 19619 /* Can return in any reg. */ 19620 emit_insn (gen_aarch64_load_tp_hard (target)); 19621 return target; 19622 } 19623 19624 /* On AAPCS systems, this is the "struct __va_list". */ 19625 static GTY(()) tree va_list_type; 19626 19627 /* Implement TARGET_BUILD_BUILTIN_VA_LIST. 19628 Return the type to use as __builtin_va_list. 19629 19630 AAPCS64 \S 7.1.4 requires that va_list be a typedef for a type defined as: 19631 19632 struct __va_list 19633 { 19634 void *__stack; 19635 void *__gr_top; 19636 void *__vr_top; 19637 int __gr_offs; 19638 int __vr_offs; 19639 }; */ 19640 19641 static tree 19642 aarch64_build_builtin_va_list (void) 19643 { 19644 tree va_list_name; 19645 tree f_stack, f_grtop, f_vrtop, f_groff, f_vroff; 19646 19647 /* Create the type. */ 19648 va_list_type = lang_hooks.types.make_type (RECORD_TYPE); 19649 /* Give it the required name. */ 19650 va_list_name = build_decl (BUILTINS_LOCATION, 19651 TYPE_DECL, 19652 get_identifier ("__va_list"), 19653 va_list_type); 19654 DECL_ARTIFICIAL (va_list_name) = 1; 19655 TYPE_NAME (va_list_type) = va_list_name; 19656 TYPE_STUB_DECL (va_list_type) = va_list_name; 19657 19658 /* Create the fields. */ 19659 f_stack = build_decl (BUILTINS_LOCATION, 19660 FIELD_DECL, get_identifier ("__stack"), 19661 ptr_type_node); 19662 f_grtop = build_decl (BUILTINS_LOCATION, 19663 FIELD_DECL, get_identifier ("__gr_top"), 19664 ptr_type_node); 19665 f_vrtop = build_decl (BUILTINS_LOCATION, 19666 FIELD_DECL, get_identifier ("__vr_top"), 19667 ptr_type_node); 19668 f_groff = build_decl (BUILTINS_LOCATION, 19669 FIELD_DECL, get_identifier ("__gr_offs"), 19670 integer_type_node); 19671 f_vroff = build_decl (BUILTINS_LOCATION, 19672 FIELD_DECL, get_identifier ("__vr_offs"), 19673 integer_type_node); 19674 19675 /* Tell tree-stdarg pass about our internal offset fields. 19676 NOTE: va_list_gpr/fpr_counter_field are only used for tree comparision 19677 purpose to identify whether the code is updating va_list internal 19678 offset fields through irregular way. */ 19679 va_list_gpr_counter_field = f_groff; 19680 va_list_fpr_counter_field = f_vroff; 19681 19682 DECL_ARTIFICIAL (f_stack) = 1; 19683 DECL_ARTIFICIAL (f_grtop) = 1; 19684 DECL_ARTIFICIAL (f_vrtop) = 1; 19685 DECL_ARTIFICIAL (f_groff) = 1; 19686 DECL_ARTIFICIAL (f_vroff) = 1; 19687 19688 DECL_FIELD_CONTEXT (f_stack) = va_list_type; 19689 DECL_FIELD_CONTEXT (f_grtop) = va_list_type; 19690 DECL_FIELD_CONTEXT (f_vrtop) = va_list_type; 19691 DECL_FIELD_CONTEXT (f_groff) = va_list_type; 19692 DECL_FIELD_CONTEXT (f_vroff) = va_list_type; 19693 19694 TYPE_FIELDS (va_list_type) = f_stack; 19695 DECL_CHAIN (f_stack) = f_grtop; 19696 DECL_CHAIN (f_grtop) = f_vrtop; 19697 DECL_CHAIN (f_vrtop) = f_groff; 19698 DECL_CHAIN (f_groff) = f_vroff; 19699 19700 /* Compute its layout. */ 19701 layout_type (va_list_type); 19702 19703 return va_list_type; 19704 } 19705 19706 /* Implement TARGET_EXPAND_BUILTIN_VA_START. */ 19707 static void 19708 aarch64_expand_builtin_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED) 19709 { 19710 const CUMULATIVE_ARGS *cum; 19711 tree f_stack, f_grtop, f_vrtop, f_groff, f_vroff; 19712 tree stack, grtop, vrtop, groff, vroff; 19713 tree t; 19714 int gr_save_area_size = cfun->va_list_gpr_size; 19715 int vr_save_area_size = cfun->va_list_fpr_size; 19716 int vr_offset; 19717 19718 cum = &crtl->args.info; 19719 if (cfun->va_list_gpr_size) 19720 gr_save_area_size = MIN ((NUM_ARG_REGS - cum->aapcs_ncrn) * UNITS_PER_WORD, 19721 cfun->va_list_gpr_size); 19722 if (cfun->va_list_fpr_size) 19723 vr_save_area_size = MIN ((NUM_FP_ARG_REGS - cum->aapcs_nvrn) 19724 * UNITS_PER_VREG, cfun->va_list_fpr_size); 19725 19726 if (!TARGET_FLOAT) 19727 { 19728 gcc_assert (cum->aapcs_nvrn == 0); 19729 vr_save_area_size = 0; 19730 } 19731 19732 f_stack = TYPE_FIELDS (va_list_type_node); 19733 f_grtop = DECL_CHAIN (f_stack); 19734 f_vrtop = DECL_CHAIN (f_grtop); 19735 f_groff = DECL_CHAIN (f_vrtop); 19736 f_vroff = DECL_CHAIN (f_groff); 19737 19738 stack = build3 (COMPONENT_REF, TREE_TYPE (f_stack), valist, f_stack, 19739 NULL_TREE); 19740 grtop = build3 (COMPONENT_REF, TREE_TYPE (f_grtop), valist, f_grtop, 19741 NULL_TREE); 19742 vrtop = build3 (COMPONENT_REF, TREE_TYPE (f_vrtop), valist, f_vrtop, 19743 NULL_TREE); 19744 groff = build3 (COMPONENT_REF, TREE_TYPE (f_groff), valist, f_groff, 19745 NULL_TREE); 19746 vroff = build3 (COMPONENT_REF, TREE_TYPE (f_vroff), valist, f_vroff, 19747 NULL_TREE); 19748 19749 /* Emit code to initialize STACK, which points to the next varargs stack 19750 argument. CUM->AAPCS_STACK_SIZE gives the number of stack words used 19751 by named arguments. STACK is 8-byte aligned. */ 19752 t = make_tree (TREE_TYPE (stack), virtual_incoming_args_rtx); 19753 if (cum->aapcs_stack_size > 0) 19754 t = fold_build_pointer_plus_hwi (t, cum->aapcs_stack_size * UNITS_PER_WORD); 19755 t = build2 (MODIFY_EXPR, TREE_TYPE (stack), stack, t); 19756 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 19757 19758 /* Emit code to initialize GRTOP, the top of the GR save area. 19759 virtual_incoming_args_rtx should have been 16 byte aligned. */ 19760 t = make_tree (TREE_TYPE (grtop), virtual_incoming_args_rtx); 19761 t = build2 (MODIFY_EXPR, TREE_TYPE (grtop), grtop, t); 19762 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 19763 19764 /* Emit code to initialize VRTOP, the top of the VR save area. 19765 This address is gr_save_area_bytes below GRTOP, rounded 19766 down to the next 16-byte boundary. */ 19767 t = make_tree (TREE_TYPE (vrtop), virtual_incoming_args_rtx); 19768 vr_offset = ROUND_UP (gr_save_area_size, 19769 STACK_BOUNDARY / BITS_PER_UNIT); 19770 19771 if (vr_offset) 19772 t = fold_build_pointer_plus_hwi (t, -vr_offset); 19773 t = build2 (MODIFY_EXPR, TREE_TYPE (vrtop), vrtop, t); 19774 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 19775 19776 /* Emit code to initialize GROFF, the offset from GRTOP of the 19777 next GPR argument. */ 19778 t = build2 (MODIFY_EXPR, TREE_TYPE (groff), groff, 19779 build_int_cst (TREE_TYPE (groff), -gr_save_area_size)); 19780 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 19781 19782 /* Likewise emit code to initialize VROFF, the offset from FTOP 19783 of the next VR argument. */ 19784 t = build2 (MODIFY_EXPR, TREE_TYPE (vroff), vroff, 19785 build_int_cst (TREE_TYPE (vroff), -vr_save_area_size)); 19786 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 19787 } 19788 19789 /* Implement TARGET_GIMPLIFY_VA_ARG_EXPR. */ 19790 19791 static tree 19792 aarch64_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, 19793 gimple_seq *post_p ATTRIBUTE_UNUSED) 19794 { 19795 tree addr; 19796 bool indirect_p; 19797 bool is_ha; /* is HFA or HVA. */ 19798 bool dw_align; /* double-word align. */ 19799 machine_mode ag_mode = VOIDmode; 19800 int nregs; 19801 machine_mode mode; 19802 19803 tree f_stack, f_grtop, f_vrtop, f_groff, f_vroff; 19804 tree stack, f_top, f_off, off, arg, roundup, on_stack; 19805 HOST_WIDE_INT size, rsize, adjust, align; 19806 tree t, u, cond1, cond2; 19807 19808 indirect_p = pass_va_arg_by_reference (type); 19809 if (indirect_p) 19810 type = build_pointer_type (type); 19811 19812 mode = TYPE_MODE (type); 19813 19814 f_stack = TYPE_FIELDS (va_list_type_node); 19815 f_grtop = DECL_CHAIN (f_stack); 19816 f_vrtop = DECL_CHAIN (f_grtop); 19817 f_groff = DECL_CHAIN (f_vrtop); 19818 f_vroff = DECL_CHAIN (f_groff); 19819 19820 stack = build3 (COMPONENT_REF, TREE_TYPE (f_stack), unshare_expr (valist), 19821 f_stack, NULL_TREE); 19822 size = int_size_in_bytes (type); 19823 19824 unsigned int abi_break; 19825 align 19826 = aarch64_function_arg_alignment (mode, type, &abi_break) / BITS_PER_UNIT; 19827 19828 dw_align = false; 19829 adjust = 0; 19830 if (aarch64_vfp_is_call_or_return_candidate (mode, type, &ag_mode, &nregs, 19831 &is_ha, false)) 19832 { 19833 /* No frontends can create types with variable-sized modes, so we 19834 shouldn't be asked to pass or return them. */ 19835 unsigned int ag_size = GET_MODE_SIZE (ag_mode).to_constant (); 19836 19837 /* TYPE passed in fp/simd registers. */ 19838 if (!TARGET_FLOAT) 19839 aarch64_err_no_fpadvsimd (mode); 19840 19841 f_top = build3 (COMPONENT_REF, TREE_TYPE (f_vrtop), 19842 unshare_expr (valist), f_vrtop, NULL_TREE); 19843 f_off = build3 (COMPONENT_REF, TREE_TYPE (f_vroff), 19844 unshare_expr (valist), f_vroff, NULL_TREE); 19845 19846 rsize = nregs * UNITS_PER_VREG; 19847 19848 if (is_ha) 19849 { 19850 if (BYTES_BIG_ENDIAN && ag_size < UNITS_PER_VREG) 19851 adjust = UNITS_PER_VREG - ag_size; 19852 } 19853 else if (BLOCK_REG_PADDING (mode, type, 1) == PAD_DOWNWARD 19854 && size < UNITS_PER_VREG) 19855 { 19856 adjust = UNITS_PER_VREG - size; 19857 } 19858 } 19859 else 19860 { 19861 /* TYPE passed in general registers. */ 19862 f_top = build3 (COMPONENT_REF, TREE_TYPE (f_grtop), 19863 unshare_expr (valist), f_grtop, NULL_TREE); 19864 f_off = build3 (COMPONENT_REF, TREE_TYPE (f_groff), 19865 unshare_expr (valist), f_groff, NULL_TREE); 19866 rsize = ROUND_UP (size, UNITS_PER_WORD); 19867 nregs = rsize / UNITS_PER_WORD; 19868 19869 if (align > 8) 19870 { 19871 if (abi_break && warn_psabi) 19872 inform (input_location, "parameter passing for argument of type " 19873 "%qT changed in GCC 9.1", type); 19874 dw_align = true; 19875 } 19876 19877 if (BLOCK_REG_PADDING (mode, type, 1) == PAD_DOWNWARD 19878 && size < UNITS_PER_WORD) 19879 { 19880 adjust = UNITS_PER_WORD - size; 19881 } 19882 } 19883 19884 /* Get a local temporary for the field value. */ 19885 off = get_initialized_tmp_var (f_off, pre_p, NULL); 19886 19887 /* Emit code to branch if off >= 0. */ 19888 t = build2 (GE_EXPR, boolean_type_node, off, 19889 build_int_cst (TREE_TYPE (off), 0)); 19890 cond1 = build3 (COND_EXPR, ptr_type_node, t, NULL_TREE, NULL_TREE); 19891 19892 if (dw_align) 19893 { 19894 /* Emit: offs = (offs + 15) & -16. */ 19895 t = build2 (PLUS_EXPR, TREE_TYPE (off), off, 19896 build_int_cst (TREE_TYPE (off), 15)); 19897 t = build2 (BIT_AND_EXPR, TREE_TYPE (off), t, 19898 build_int_cst (TREE_TYPE (off), -16)); 19899 roundup = build2 (MODIFY_EXPR, TREE_TYPE (off), off, t); 19900 } 19901 else 19902 roundup = NULL; 19903 19904 /* Update ap.__[g|v]r_offs */ 19905 t = build2 (PLUS_EXPR, TREE_TYPE (off), off, 19906 build_int_cst (TREE_TYPE (off), rsize)); 19907 t = build2 (MODIFY_EXPR, TREE_TYPE (f_off), unshare_expr (f_off), t); 19908 19909 /* String up. */ 19910 if (roundup) 19911 t = build2 (COMPOUND_EXPR, TREE_TYPE (t), roundup, t); 19912 19913 /* [cond2] if (ap.__[g|v]r_offs > 0) */ 19914 u = build2 (GT_EXPR, boolean_type_node, unshare_expr (f_off), 19915 build_int_cst (TREE_TYPE (f_off), 0)); 19916 cond2 = build3 (COND_EXPR, ptr_type_node, u, NULL_TREE, NULL_TREE); 19917 19918 /* String up: make sure the assignment happens before the use. */ 19919 t = build2 (COMPOUND_EXPR, TREE_TYPE (cond2), t, cond2); 19920 COND_EXPR_ELSE (cond1) = t; 19921 19922 /* Prepare the trees handling the argument that is passed on the stack; 19923 the top level node will store in ON_STACK. */ 19924 arg = get_initialized_tmp_var (stack, pre_p, NULL); 19925 if (align > 8) 19926 { 19927 /* if (alignof(type) > 8) (arg = arg + 15) & -16; */ 19928 t = fold_build_pointer_plus_hwi (arg, 15); 19929 t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t, 19930 build_int_cst (TREE_TYPE (t), -16)); 19931 roundup = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg, t); 19932 } 19933 else 19934 roundup = NULL; 19935 /* Advance ap.__stack */ 19936 t = fold_build_pointer_plus_hwi (arg, size + 7); 19937 t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t, 19938 build_int_cst (TREE_TYPE (t), -8)); 19939 t = build2 (MODIFY_EXPR, TREE_TYPE (stack), unshare_expr (stack), t); 19940 /* String up roundup and advance. */ 19941 if (roundup) 19942 t = build2 (COMPOUND_EXPR, TREE_TYPE (t), roundup, t); 19943 /* String up with arg */ 19944 on_stack = build2 (COMPOUND_EXPR, TREE_TYPE (arg), t, arg); 19945 /* Big-endianness related address adjustment. */ 19946 if (BLOCK_REG_PADDING (mode, type, 1) == PAD_DOWNWARD 19947 && size < UNITS_PER_WORD) 19948 { 19949 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (arg), arg, 19950 size_int (UNITS_PER_WORD - size)); 19951 on_stack = build2 (COMPOUND_EXPR, TREE_TYPE (arg), on_stack, t); 19952 } 19953 19954 COND_EXPR_THEN (cond1) = unshare_expr (on_stack); 19955 COND_EXPR_THEN (cond2) = unshare_expr (on_stack); 19956 19957 /* Adjustment to OFFSET in the case of BIG_ENDIAN. */ 19958 t = off; 19959 if (adjust) 19960 t = build2 (PREINCREMENT_EXPR, TREE_TYPE (off), off, 19961 build_int_cst (TREE_TYPE (off), adjust)); 19962 19963 t = fold_convert (sizetype, t); 19964 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (f_top), f_top, t); 19965 19966 if (is_ha) 19967 { 19968 /* type ha; // treat as "struct {ftype field[n];}" 19969 ... [computing offs] 19970 for (i = 0; i <nregs; ++i, offs += 16) 19971 ha.field[i] = *((ftype *)(ap.__vr_top + offs)); 19972 return ha; */ 19973 int i; 19974 tree tmp_ha, field_t, field_ptr_t; 19975 19976 /* Declare a local variable. */ 19977 tmp_ha = create_tmp_var_raw (type, "ha"); 19978 gimple_add_tmp_var (tmp_ha); 19979 19980 /* Establish the base type. */ 19981 switch (ag_mode) 19982 { 19983 case E_SFmode: 19984 field_t = float_type_node; 19985 field_ptr_t = float_ptr_type_node; 19986 break; 19987 case E_DFmode: 19988 field_t = double_type_node; 19989 field_ptr_t = double_ptr_type_node; 19990 break; 19991 case E_TFmode: 19992 field_t = long_double_type_node; 19993 field_ptr_t = long_double_ptr_type_node; 19994 break; 19995 case E_HFmode: 19996 field_t = aarch64_fp16_type_node; 19997 field_ptr_t = aarch64_fp16_ptr_type_node; 19998 break; 19999 case E_BFmode: 20000 field_t = aarch64_bf16_type_node; 20001 field_ptr_t = aarch64_bf16_ptr_type_node; 20002 break; 20003 case E_V2SImode: 20004 case E_V4SImode: 20005 { 20006 tree innertype = make_signed_type (GET_MODE_PRECISION (SImode)); 20007 field_t = build_vector_type_for_mode (innertype, ag_mode); 20008 field_ptr_t = build_pointer_type (field_t); 20009 } 20010 break; 20011 default: 20012 gcc_assert (0); 20013 } 20014 20015 /* *(field_ptr_t)&ha = *((field_ptr_t)vr_saved_area */ 20016 TREE_ADDRESSABLE (tmp_ha) = 1; 20017 tmp_ha = build1 (ADDR_EXPR, field_ptr_t, tmp_ha); 20018 addr = t; 20019 t = fold_convert (field_ptr_t, addr); 20020 t = build2 (MODIFY_EXPR, field_t, 20021 build1 (INDIRECT_REF, field_t, tmp_ha), 20022 build1 (INDIRECT_REF, field_t, t)); 20023 20024 /* ha.field[i] = *((field_ptr_t)vr_saved_area + i) */ 20025 for (i = 1; i < nregs; ++i) 20026 { 20027 addr = fold_build_pointer_plus_hwi (addr, UNITS_PER_VREG); 20028 u = fold_convert (field_ptr_t, addr); 20029 u = build2 (MODIFY_EXPR, field_t, 20030 build2 (MEM_REF, field_t, tmp_ha, 20031 build_int_cst (field_ptr_t, 20032 (i * 20033 int_size_in_bytes (field_t)))), 20034 build1 (INDIRECT_REF, field_t, u)); 20035 t = build2 (COMPOUND_EXPR, TREE_TYPE (t), t, u); 20036 } 20037 20038 u = fold_convert (TREE_TYPE (f_top), tmp_ha); 20039 t = build2 (COMPOUND_EXPR, TREE_TYPE (f_top), t, u); 20040 } 20041 20042 COND_EXPR_ELSE (cond2) = t; 20043 addr = fold_convert (build_pointer_type (type), cond1); 20044 addr = build_va_arg_indirect_ref (addr); 20045 20046 if (indirect_p) 20047 addr = build_va_arg_indirect_ref (addr); 20048 20049 return addr; 20050 } 20051 20052 /* Implement TARGET_SETUP_INCOMING_VARARGS. */ 20053 20054 static void 20055 aarch64_setup_incoming_varargs (cumulative_args_t cum_v, 20056 const function_arg_info &arg, 20057 int *pretend_size ATTRIBUTE_UNUSED, int no_rtl) 20058 { 20059 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 20060 CUMULATIVE_ARGS local_cum; 20061 int gr_saved = cfun->va_list_gpr_size; 20062 int vr_saved = cfun->va_list_fpr_size; 20063 20064 /* The caller has advanced CUM up to, but not beyond, the last named 20065 argument. Advance a local copy of CUM past the last "real" named 20066 argument, to find out how many registers are left over. */ 20067 local_cum = *cum; 20068 aarch64_function_arg_advance (pack_cumulative_args(&local_cum), arg); 20069 20070 /* Found out how many registers we need to save. 20071 Honor tree-stdvar analysis results. */ 20072 if (cfun->va_list_gpr_size) 20073 gr_saved = MIN (NUM_ARG_REGS - local_cum.aapcs_ncrn, 20074 cfun->va_list_gpr_size / UNITS_PER_WORD); 20075 if (cfun->va_list_fpr_size) 20076 vr_saved = MIN (NUM_FP_ARG_REGS - local_cum.aapcs_nvrn, 20077 cfun->va_list_fpr_size / UNITS_PER_VREG); 20078 20079 if (!TARGET_FLOAT) 20080 { 20081 gcc_assert (local_cum.aapcs_nvrn == 0); 20082 vr_saved = 0; 20083 } 20084 20085 if (!no_rtl) 20086 { 20087 if (gr_saved > 0) 20088 { 20089 rtx ptr, mem; 20090 20091 /* virtual_incoming_args_rtx should have been 16-byte aligned. */ 20092 ptr = plus_constant (Pmode, virtual_incoming_args_rtx, 20093 - gr_saved * UNITS_PER_WORD); 20094 mem = gen_frame_mem (BLKmode, ptr); 20095 set_mem_alias_set (mem, get_varargs_alias_set ()); 20096 20097 move_block_from_reg (local_cum.aapcs_ncrn + R0_REGNUM, 20098 mem, gr_saved); 20099 } 20100 if (vr_saved > 0) 20101 { 20102 /* We can't use move_block_from_reg, because it will use 20103 the wrong mode, storing D regs only. */ 20104 machine_mode mode = TImode; 20105 int off, i, vr_start; 20106 20107 /* Set OFF to the offset from virtual_incoming_args_rtx of 20108 the first vector register. The VR save area lies below 20109 the GR one, and is aligned to 16 bytes. */ 20110 off = -ROUND_UP (gr_saved * UNITS_PER_WORD, 20111 STACK_BOUNDARY / BITS_PER_UNIT); 20112 off -= vr_saved * UNITS_PER_VREG; 20113 20114 vr_start = V0_REGNUM + local_cum.aapcs_nvrn; 20115 for (i = 0; i < vr_saved; ++i) 20116 { 20117 rtx ptr, mem; 20118 20119 ptr = plus_constant (Pmode, virtual_incoming_args_rtx, off); 20120 mem = gen_frame_mem (mode, ptr); 20121 set_mem_alias_set (mem, get_varargs_alias_set ()); 20122 aarch64_emit_move (mem, gen_rtx_REG (mode, vr_start + i)); 20123 off += UNITS_PER_VREG; 20124 } 20125 } 20126 } 20127 20128 /* We don't save the size into *PRETEND_SIZE because we want to avoid 20129 any complication of having crtl->args.pretend_args_size changed. */ 20130 cfun->machine->frame.saved_varargs_size 20131 = (ROUND_UP (gr_saved * UNITS_PER_WORD, 20132 STACK_BOUNDARY / BITS_PER_UNIT) 20133 + vr_saved * UNITS_PER_VREG); 20134 } 20135 20136 static void 20137 aarch64_conditional_register_usage (void) 20138 { 20139 int i; 20140 if (!TARGET_FLOAT) 20141 { 20142 for (i = V0_REGNUM; i <= V31_REGNUM; i++) 20143 { 20144 fixed_regs[i] = 1; 20145 call_used_regs[i] = 1; 20146 } 20147 } 20148 if (!TARGET_SVE) 20149 for (i = P0_REGNUM; i <= P15_REGNUM; i++) 20150 { 20151 fixed_regs[i] = 1; 20152 call_used_regs[i] = 1; 20153 } 20154 20155 /* Only allow the FFR and FFRT to be accessed via special patterns. */ 20156 CLEAR_HARD_REG_BIT (operand_reg_set, FFR_REGNUM); 20157 CLEAR_HARD_REG_BIT (operand_reg_set, FFRT_REGNUM); 20158 20159 /* When tracking speculation, we need a couple of call-clobbered registers 20160 to track the speculation state. It would be nice to just use 20161 IP0 and IP1, but currently there are numerous places that just 20162 assume these registers are free for other uses (eg pointer 20163 authentication). */ 20164 if (aarch64_track_speculation) 20165 { 20166 fixed_regs[SPECULATION_TRACKER_REGNUM] = 1; 20167 call_used_regs[SPECULATION_TRACKER_REGNUM] = 1; 20168 fixed_regs[SPECULATION_SCRATCH_REGNUM] = 1; 20169 call_used_regs[SPECULATION_SCRATCH_REGNUM] = 1; 20170 } 20171 } 20172 20173 /* Implement TARGET_MEMBER_TYPE_FORCES_BLK. */ 20174 20175 bool 20176 aarch64_member_type_forces_blk (const_tree field_or_array, machine_mode mode) 20177 { 20178 /* For records we're passed a FIELD_DECL, for arrays we're passed 20179 an ARRAY_TYPE. In both cases we're interested in the TREE_TYPE. */ 20180 const_tree type = TREE_TYPE (field_or_array); 20181 20182 /* Assign BLKmode to anything that contains multiple SVE predicates. 20183 For structures, the "multiple" case is indicated by MODE being 20184 VOIDmode. */ 20185 unsigned int num_zr, num_pr; 20186 if (aarch64_sve::builtin_type_p (type, &num_zr, &num_pr) && num_pr != 0) 20187 { 20188 if (TREE_CODE (field_or_array) == ARRAY_TYPE) 20189 return !simple_cst_equal (TYPE_SIZE (field_or_array), 20190 TYPE_SIZE (type)); 20191 return mode == VOIDmode; 20192 } 20193 20194 return default_member_type_forces_blk (field_or_array, mode); 20195 } 20196 20197 /* Bitmasks that indicate whether earlier versions of GCC would have 20198 taken a different path through the ABI logic. This should result in 20199 a -Wpsabi warning if the earlier path led to a different ABI decision. 20200 20201 WARN_PSABI_EMPTY_CXX17_BASE 20202 Indicates that the type includes an artificial empty C++17 base field 20203 that, prior to GCC 10.1, would prevent the type from being treated as 20204 a HFA or HVA. See PR94383 for details. 20205 20206 WARN_PSABI_NO_UNIQUE_ADDRESS 20207 Indicates that the type includes an empty [[no_unique_address]] field 20208 that, prior to GCC 10.1, would prevent the type from being treated as 20209 a HFA or HVA. */ 20210 const unsigned int WARN_PSABI_EMPTY_CXX17_BASE = 1U << 0; 20211 const unsigned int WARN_PSABI_NO_UNIQUE_ADDRESS = 1U << 1; 20212 const unsigned int WARN_PSABI_ZERO_WIDTH_BITFIELD = 1U << 2; 20213 20214 /* Walk down the type tree of TYPE counting consecutive base elements. 20215 If *MODEP is VOIDmode, then set it to the first valid floating point 20216 type. If a non-floating point type is found, or if a floating point 20217 type that doesn't match a non-VOIDmode *MODEP is found, then return -1, 20218 otherwise return the count in the sub-tree. 20219 20220 The WARN_PSABI_FLAGS argument allows the caller to check whether this 20221 function has changed its behavior relative to earlier versions of GCC. 20222 Normally the argument should be nonnull and point to a zero-initialized 20223 variable. The function then records whether the ABI decision might 20224 be affected by a known fix to the ABI logic, setting the associated 20225 WARN_PSABI_* bits if so. 20226 20227 When the argument is instead a null pointer, the function tries to 20228 simulate the behavior of GCC before all such ABI fixes were made. 20229 This is useful to check whether the function returns something 20230 different after the ABI fixes. */ 20231 static int 20232 aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep, 20233 unsigned int *warn_psabi_flags) 20234 { 20235 machine_mode mode; 20236 HOST_WIDE_INT size; 20237 20238 if (aarch64_sve::builtin_type_p (type)) 20239 return -1; 20240 20241 switch (TREE_CODE (type)) 20242 { 20243 case REAL_TYPE: 20244 mode = TYPE_MODE (type); 20245 if (mode != DFmode && mode != SFmode 20246 && mode != TFmode && mode != HFmode) 20247 return -1; 20248 20249 if (*modep == VOIDmode) 20250 *modep = mode; 20251 20252 if (*modep == mode) 20253 return 1; 20254 20255 break; 20256 20257 case COMPLEX_TYPE: 20258 mode = TYPE_MODE (TREE_TYPE (type)); 20259 if (mode != DFmode && mode != SFmode 20260 && mode != TFmode && mode != HFmode) 20261 return -1; 20262 20263 if (*modep == VOIDmode) 20264 *modep = mode; 20265 20266 if (*modep == mode) 20267 return 2; 20268 20269 break; 20270 20271 case VECTOR_TYPE: 20272 /* Use V2SImode and V4SImode as representatives of all 64-bit 20273 and 128-bit vector types. */ 20274 size = int_size_in_bytes (type); 20275 switch (size) 20276 { 20277 case 8: 20278 mode = V2SImode; 20279 break; 20280 case 16: 20281 mode = V4SImode; 20282 break; 20283 default: 20284 return -1; 20285 } 20286 20287 if (*modep == VOIDmode) 20288 *modep = mode; 20289 20290 /* Vector modes are considered to be opaque: two vectors are 20291 equivalent for the purposes of being homogeneous aggregates 20292 if they are the same size. */ 20293 if (*modep == mode) 20294 return 1; 20295 20296 break; 20297 20298 case ARRAY_TYPE: 20299 { 20300 int count; 20301 tree index = TYPE_DOMAIN (type); 20302 20303 /* Can't handle incomplete types nor sizes that are not 20304 fixed. */ 20305 if (!COMPLETE_TYPE_P (type) 20306 || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) 20307 return -1; 20308 20309 count = aapcs_vfp_sub_candidate (TREE_TYPE (type), modep, 20310 warn_psabi_flags); 20311 if (count == -1 20312 || !index 20313 || !TYPE_MAX_VALUE (index) 20314 || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index)) 20315 || !TYPE_MIN_VALUE (index) 20316 || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index)) 20317 || count < 0) 20318 return -1; 20319 20320 count *= (1 + tree_to_uhwi (TYPE_MAX_VALUE (index)) 20321 - tree_to_uhwi (TYPE_MIN_VALUE (index))); 20322 20323 /* There must be no padding. */ 20324 if (maybe_ne (wi::to_poly_wide (TYPE_SIZE (type)), 20325 count * GET_MODE_BITSIZE (*modep))) 20326 return -1; 20327 20328 return count; 20329 } 20330 20331 case RECORD_TYPE: 20332 { 20333 int count = 0; 20334 int sub_count; 20335 tree field; 20336 20337 /* Can't handle incomplete types nor sizes that are not 20338 fixed. */ 20339 if (!COMPLETE_TYPE_P (type) 20340 || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) 20341 return -1; 20342 20343 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) 20344 { 20345 if (TREE_CODE (field) != FIELD_DECL) 20346 continue; 20347 20348 if (DECL_FIELD_ABI_IGNORED (field)) 20349 { 20350 /* See whether this is something that earlier versions of 20351 GCC failed to ignore. */ 20352 unsigned int flag; 20353 if (lookup_attribute ("no_unique_address", 20354 DECL_ATTRIBUTES (field))) 20355 flag = WARN_PSABI_NO_UNIQUE_ADDRESS; 20356 else if (cxx17_empty_base_field_p (field)) 20357 flag = WARN_PSABI_EMPTY_CXX17_BASE; 20358 else 20359 /* No compatibility problem. */ 20360 continue; 20361 20362 /* Simulate the old behavior when WARN_PSABI_FLAGS is null. */ 20363 if (warn_psabi_flags) 20364 { 20365 *warn_psabi_flags |= flag; 20366 continue; 20367 } 20368 } 20369 /* A zero-width bitfield may affect layout in some 20370 circumstances, but adds no members. The determination 20371 of whether or not a type is an HFA is performed after 20372 layout is complete, so if the type still looks like an 20373 HFA afterwards, it is still classed as one. This is 20374 potentially an ABI break for the hard-float ABI. */ 20375 else if (DECL_BIT_FIELD (field) 20376 && integer_zerop (DECL_SIZE (field))) 20377 { 20378 /* Prior to GCC-12 these fields were striped early, 20379 hiding them from the back-end entirely and 20380 resulting in the correct behaviour for argument 20381 passing. Simulate that old behaviour without 20382 generating a warning. */ 20383 if (DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field)) 20384 continue; 20385 if (warn_psabi_flags) 20386 { 20387 *warn_psabi_flags |= WARN_PSABI_ZERO_WIDTH_BITFIELD; 20388 continue; 20389 } 20390 } 20391 20392 sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep, 20393 warn_psabi_flags); 20394 if (sub_count < 0) 20395 return -1; 20396 count += sub_count; 20397 } 20398 20399 /* There must be no padding. */ 20400 if (maybe_ne (wi::to_poly_wide (TYPE_SIZE (type)), 20401 count * GET_MODE_BITSIZE (*modep))) 20402 return -1; 20403 20404 return count; 20405 } 20406 20407 case UNION_TYPE: 20408 case QUAL_UNION_TYPE: 20409 { 20410 /* These aren't very interesting except in a degenerate case. */ 20411 int count = 0; 20412 int sub_count; 20413 tree field; 20414 20415 /* Can't handle incomplete types nor sizes that are not 20416 fixed. */ 20417 if (!COMPLETE_TYPE_P (type) 20418 || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) 20419 return -1; 20420 20421 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) 20422 { 20423 if (TREE_CODE (field) != FIELD_DECL) 20424 continue; 20425 20426 sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep, 20427 warn_psabi_flags); 20428 if (sub_count < 0) 20429 return -1; 20430 count = count > sub_count ? count : sub_count; 20431 } 20432 20433 /* There must be no padding. */ 20434 if (maybe_ne (wi::to_poly_wide (TYPE_SIZE (type)), 20435 count * GET_MODE_BITSIZE (*modep))) 20436 return -1; 20437 20438 return count; 20439 } 20440 20441 default: 20442 break; 20443 } 20444 20445 return -1; 20446 } 20447 20448 /* Return TRUE if the type, as described by TYPE and MODE, is a short vector 20449 type as described in AAPCS64 \S 4.1.2. 20450 20451 See the comment above aarch64_composite_type_p for the notes on MODE. */ 20452 20453 static bool 20454 aarch64_short_vector_p (const_tree type, 20455 machine_mode mode) 20456 { 20457 poly_int64 size = -1; 20458 20459 if (type && TREE_CODE (type) == VECTOR_TYPE) 20460 { 20461 if (aarch64_sve::builtin_type_p (type)) 20462 return false; 20463 size = int_size_in_bytes (type); 20464 } 20465 else if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT 20466 || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) 20467 { 20468 /* The containing "else if" is too loose: it means that we look at TYPE 20469 if the type is a vector type (good), but that we otherwise ignore TYPE 20470 and look only at the mode. This is wrong because the type describes 20471 the language-level information whereas the mode is purely an internal 20472 GCC concept. We can therefore reach here for types that are not 20473 vectors in the AAPCS64 sense. 20474 20475 We can't "fix" that for the traditional Advanced SIMD vector modes 20476 without breaking backwards compatibility. However, there's no such 20477 baggage for the structure modes, which were introduced in GCC 12. */ 20478 if (aarch64_advsimd_struct_mode_p (mode)) 20479 return false; 20480 20481 /* For similar reasons, rely only on the type, not the mode, when 20482 processing SVE types. */ 20483 if (type && aarch64_some_values_include_pst_objects_p (type)) 20484 /* Leave later code to report an error if SVE is disabled. */ 20485 gcc_assert (!TARGET_SVE || aarch64_sve_mode_p (mode)); 20486 else 20487 size = GET_MODE_SIZE (mode); 20488 } 20489 if (known_eq (size, 8) || known_eq (size, 16)) 20490 { 20491 /* 64-bit and 128-bit vectors should only acquire an SVE mode if 20492 they are being treated as scalable AAPCS64 types. */ 20493 gcc_assert (!aarch64_sve_mode_p (mode) 20494 && !aarch64_advsimd_struct_mode_p (mode)); 20495 return true; 20496 } 20497 return false; 20498 } 20499 20500 /* Return TRUE if the type, as described by TYPE and MODE, is a composite 20501 type as described in AAPCS64 \S 4.3. This includes aggregate, union and 20502 array types. The C99 floating-point complex types are also considered 20503 as composite types, according to AAPCS64 \S 7.1.1. The complex integer 20504 types, which are GCC extensions and out of the scope of AAPCS64, are 20505 treated as composite types here as well. 20506 20507 Note that MODE itself is not sufficient in determining whether a type 20508 is such a composite type or not. This is because 20509 stor-layout.cc:compute_record_mode may have already changed the MODE 20510 (BLKmode) of a RECORD_TYPE TYPE to some other mode. For example, a 20511 structure with only one field may have its MODE set to the mode of the 20512 field. Also an integer mode whose size matches the size of the 20513 RECORD_TYPE type may be used to substitute the original mode 20514 (i.e. BLKmode) in certain circumstances. In other words, MODE cannot be 20515 solely relied on. */ 20516 20517 static bool 20518 aarch64_composite_type_p (const_tree type, 20519 machine_mode mode) 20520 { 20521 if (aarch64_short_vector_p (type, mode)) 20522 return false; 20523 20524 if (type && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)) 20525 return true; 20526 20527 if (mode == BLKmode 20528 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT 20529 || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT) 20530 return true; 20531 20532 return false; 20533 } 20534 20535 /* Return TRUE if an argument, whose type is described by TYPE and MODE, 20536 shall be passed or returned in simd/fp register(s) (providing these 20537 parameter passing registers are available). 20538 20539 Upon successful return, *COUNT returns the number of needed registers, 20540 *BASE_MODE returns the mode of the individual register and when IS_HA 20541 is not NULL, *IS_HA indicates whether or not the argument is a homogeneous 20542 floating-point aggregate or a homogeneous short-vector aggregate. 20543 20544 SILENT_P is true if the function should refrain from reporting any 20545 diagnostics. This should only be used if the caller is certain that 20546 any ABI decisions would eventually come through this function with 20547 SILENT_P set to false. */ 20548 20549 static bool 20550 aarch64_vfp_is_call_or_return_candidate (machine_mode mode, 20551 const_tree type, 20552 machine_mode *base_mode, 20553 int *count, 20554 bool *is_ha, 20555 bool silent_p) 20556 { 20557 if (is_ha != NULL) *is_ha = false; 20558 20559 machine_mode new_mode = VOIDmode; 20560 bool composite_p = aarch64_composite_type_p (type, mode); 20561 20562 if ((!composite_p && GET_MODE_CLASS (mode) == MODE_FLOAT) 20563 || aarch64_short_vector_p (type, mode)) 20564 { 20565 *count = 1; 20566 new_mode = mode; 20567 } 20568 else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) 20569 { 20570 if (is_ha != NULL) *is_ha = true; 20571 *count = 2; 20572 new_mode = GET_MODE_INNER (mode); 20573 } 20574 else if (type && composite_p) 20575 { 20576 unsigned int warn_psabi_flags = 0; 20577 int ag_count = aapcs_vfp_sub_candidate (type, &new_mode, 20578 &warn_psabi_flags); 20579 if (ag_count > 0 && ag_count <= HA_MAX_NUM_FLDS) 20580 { 20581 static unsigned last_reported_type_uid; 20582 unsigned uid = TYPE_UID (TYPE_MAIN_VARIANT (type)); 20583 int alt; 20584 if (!silent_p 20585 && warn_psabi 20586 && warn_psabi_flags 20587 && uid != last_reported_type_uid 20588 && ((alt = aapcs_vfp_sub_candidate (type, &new_mode, NULL)) 20589 != ag_count)) 20590 { 20591 const char *url10 20592 = CHANGES_ROOT_URL "gcc-10/changes.html#empty_base"; 20593 const char *url12 20594 = CHANGES_ROOT_URL "gcc-12/changes.html#zero_width_bitfields"; 20595 gcc_assert (alt == -1); 20596 last_reported_type_uid = uid; 20597 /* Use TYPE_MAIN_VARIANT to strip any redundant const 20598 qualification. */ 20599 if (warn_psabi_flags & WARN_PSABI_NO_UNIQUE_ADDRESS) 20600 inform (input_location, "parameter passing for argument of " 20601 "type %qT with %<[[no_unique_address]]%> members " 20602 "changed %{in GCC 10.1%}", 20603 TYPE_MAIN_VARIANT (type), url10); 20604 else if (warn_psabi_flags & WARN_PSABI_EMPTY_CXX17_BASE) 20605 inform (input_location, "parameter passing for argument of " 20606 "type %qT when C++17 is enabled changed to match " 20607 "C++14 %{in GCC 10.1%}", 20608 TYPE_MAIN_VARIANT (type), url10); 20609 else if (warn_psabi_flags & WARN_PSABI_ZERO_WIDTH_BITFIELD) 20610 inform (input_location, "parameter passing for argument of " 20611 "type %qT changed %{in GCC 12.1%}", 20612 TYPE_MAIN_VARIANT (type), url12); 20613 } 20614 20615 if (is_ha != NULL) *is_ha = true; 20616 *count = ag_count; 20617 } 20618 else 20619 return false; 20620 } 20621 else 20622 return false; 20623 20624 gcc_assert (!aarch64_sve_mode_p (new_mode)); 20625 *base_mode = new_mode; 20626 return true; 20627 } 20628 20629 /* Implement TARGET_STRUCT_VALUE_RTX. */ 20630 20631 static rtx 20632 aarch64_struct_value_rtx (tree fndecl ATTRIBUTE_UNUSED, 20633 int incoming ATTRIBUTE_UNUSED) 20634 { 20635 return gen_rtx_REG (Pmode, AARCH64_STRUCT_VALUE_REGNUM); 20636 } 20637 20638 /* Implements target hook vector_mode_supported_p. */ 20639 static bool 20640 aarch64_vector_mode_supported_p (machine_mode mode) 20641 { 20642 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 20643 return vec_flags != 0 && (vec_flags & VEC_STRUCT) == 0; 20644 } 20645 20646 /* Return the full-width SVE vector mode for element mode MODE, if one 20647 exists. */ 20648 opt_machine_mode 20649 aarch64_full_sve_mode (scalar_mode mode) 20650 { 20651 switch (mode) 20652 { 20653 case E_DFmode: 20654 return VNx2DFmode; 20655 case E_SFmode: 20656 return VNx4SFmode; 20657 case E_HFmode: 20658 return VNx8HFmode; 20659 case E_BFmode: 20660 return VNx8BFmode; 20661 case E_DImode: 20662 return VNx2DImode; 20663 case E_SImode: 20664 return VNx4SImode; 20665 case E_HImode: 20666 return VNx8HImode; 20667 case E_QImode: 20668 return VNx16QImode; 20669 default: 20670 return opt_machine_mode (); 20671 } 20672 } 20673 20674 /* Return the 128-bit Advanced SIMD vector mode for element mode MODE, 20675 if it exists. */ 20676 opt_machine_mode 20677 aarch64_vq_mode (scalar_mode mode) 20678 { 20679 switch (mode) 20680 { 20681 case E_DFmode: 20682 return V2DFmode; 20683 case E_SFmode: 20684 return V4SFmode; 20685 case E_HFmode: 20686 return V8HFmode; 20687 case E_BFmode: 20688 return V8BFmode; 20689 case E_SImode: 20690 return V4SImode; 20691 case E_HImode: 20692 return V8HImode; 20693 case E_QImode: 20694 return V16QImode; 20695 case E_DImode: 20696 return V2DImode; 20697 default: 20698 return opt_machine_mode (); 20699 } 20700 } 20701 20702 /* Return appropriate SIMD container 20703 for MODE within a vector of WIDTH bits. */ 20704 static machine_mode 20705 aarch64_simd_container_mode (scalar_mode mode, poly_int64 width) 20706 { 20707 if (TARGET_SVE 20708 && maybe_ne (width, 128) 20709 && known_eq (width, BITS_PER_SVE_VECTOR)) 20710 return aarch64_full_sve_mode (mode).else_mode (word_mode); 20711 20712 gcc_assert (known_eq (width, 64) || known_eq (width, 128)); 20713 if (TARGET_SIMD) 20714 { 20715 if (known_eq (width, 128)) 20716 return aarch64_vq_mode (mode).else_mode (word_mode); 20717 else 20718 switch (mode) 20719 { 20720 case E_SFmode: 20721 return V2SFmode; 20722 case E_HFmode: 20723 return V4HFmode; 20724 case E_BFmode: 20725 return V4BFmode; 20726 case E_SImode: 20727 return V2SImode; 20728 case E_HImode: 20729 return V4HImode; 20730 case E_QImode: 20731 return V8QImode; 20732 default: 20733 break; 20734 } 20735 } 20736 return word_mode; 20737 } 20738 20739 /* Compare an SVE mode SVE_M and an Advanced SIMD mode ASIMD_M 20740 and return whether the SVE mode should be preferred over the 20741 Advanced SIMD one in aarch64_autovectorize_vector_modes. */ 20742 static bool 20743 aarch64_cmp_autovec_modes (machine_mode sve_m, machine_mode asimd_m) 20744 { 20745 /* Take into account the aarch64-autovec-preference param if non-zero. */ 20746 bool only_asimd_p = aarch64_autovec_preference == 1; 20747 bool only_sve_p = aarch64_autovec_preference == 2; 20748 20749 if (only_asimd_p) 20750 return false; 20751 if (only_sve_p) 20752 return true; 20753 20754 /* The preference in case of a tie in costs. */ 20755 bool prefer_asimd = aarch64_autovec_preference == 3; 20756 bool prefer_sve = aarch64_autovec_preference == 4; 20757 20758 poly_int64 nunits_sve = GET_MODE_NUNITS (sve_m); 20759 poly_int64 nunits_asimd = GET_MODE_NUNITS (asimd_m); 20760 /* If the CPU information does not have an SVE width registered use the 20761 generic poly_int comparison that prefers SVE. If a preference is 20762 explicitly requested avoid this path. */ 20763 if (aarch64_tune_params.sve_width == SVE_SCALABLE 20764 && !prefer_asimd 20765 && !prefer_sve) 20766 return maybe_gt (nunits_sve, nunits_asimd); 20767 20768 /* Otherwise estimate the runtime width of the modes involved. */ 20769 HOST_WIDE_INT est_sve = estimated_poly_value (nunits_sve); 20770 HOST_WIDE_INT est_asimd = estimated_poly_value (nunits_asimd); 20771 20772 /* Preferring SVE means picking it first unless the Advanced SIMD mode 20773 is clearly wider. */ 20774 if (prefer_sve) 20775 return est_sve >= est_asimd; 20776 /* Conversely, preferring Advanced SIMD means picking SVE only if SVE 20777 is clearly wider. */ 20778 if (prefer_asimd) 20779 return est_sve > est_asimd; 20780 20781 /* In the default case prefer Advanced SIMD over SVE in case of a tie. */ 20782 return est_sve > est_asimd; 20783 } 20784 20785 /* Return 128-bit container as the preferred SIMD mode for MODE. */ 20786 static machine_mode 20787 aarch64_preferred_simd_mode (scalar_mode mode) 20788 { 20789 /* Take into account explicit auto-vectorization ISA preferences through 20790 aarch64_cmp_autovec_modes. */ 20791 if (TARGET_SVE && aarch64_cmp_autovec_modes (VNx16QImode, V16QImode)) 20792 return aarch64_full_sve_mode (mode).else_mode (word_mode); 20793 if (TARGET_SIMD) 20794 return aarch64_vq_mode (mode).else_mode (word_mode); 20795 return word_mode; 20796 } 20797 20798 /* Return a list of possible vector sizes for the vectorizer 20799 to iterate over. */ 20800 static unsigned int 20801 aarch64_autovectorize_vector_modes (vector_modes *modes, bool) 20802 { 20803 static const machine_mode sve_modes[] = { 20804 /* Try using full vectors for all element types. */ 20805 VNx16QImode, 20806 20807 /* Try using 16-bit containers for 8-bit elements and full vectors 20808 for wider elements. */ 20809 VNx8QImode, 20810 20811 /* Try using 32-bit containers for 8-bit and 16-bit elements and 20812 full vectors for wider elements. */ 20813 VNx4QImode, 20814 20815 /* Try using 64-bit containers for all element types. */ 20816 VNx2QImode 20817 }; 20818 20819 static const machine_mode advsimd_modes[] = { 20820 /* Try using 128-bit vectors for all element types. */ 20821 V16QImode, 20822 20823 /* Try using 64-bit vectors for 8-bit elements and 128-bit vectors 20824 for wider elements. */ 20825 V8QImode, 20826 20827 /* Try using 64-bit vectors for 16-bit elements and 128-bit vectors 20828 for wider elements. 20829 20830 TODO: We could support a limited form of V4QImode too, so that 20831 we use 32-bit vectors for 8-bit elements. */ 20832 V4HImode, 20833 20834 /* Try using 64-bit vectors for 32-bit elements and 128-bit vectors 20835 for 64-bit elements. 20836 20837 TODO: We could similarly support limited forms of V2QImode and V2HImode 20838 for this case. */ 20839 V2SImode 20840 }; 20841 20842 /* Try using N-byte SVE modes only after trying N-byte Advanced SIMD mode. 20843 This is because: 20844 20845 - If we can't use N-byte Advanced SIMD vectors then the placement 20846 doesn't matter; we'll just continue as though the Advanced SIMD 20847 entry didn't exist. 20848 20849 - If an SVE main loop with N bytes ends up being cheaper than an 20850 Advanced SIMD main loop with N bytes then by default we'll replace 20851 the Advanced SIMD version with the SVE one. 20852 20853 - If an Advanced SIMD main loop with N bytes ends up being cheaper 20854 than an SVE main loop with N bytes then by default we'll try to 20855 use the SVE loop to vectorize the epilogue instead. */ 20856 20857 bool only_asimd_p = aarch64_autovec_preference == 1; 20858 bool only_sve_p = aarch64_autovec_preference == 2; 20859 20860 unsigned int sve_i = (TARGET_SVE && !only_asimd_p) ? 0 : ARRAY_SIZE (sve_modes); 20861 unsigned int advsimd_i = 0; 20862 20863 while (!only_sve_p && advsimd_i < ARRAY_SIZE (advsimd_modes)) 20864 { 20865 if (sve_i < ARRAY_SIZE (sve_modes) 20866 && aarch64_cmp_autovec_modes (sve_modes[sve_i], 20867 advsimd_modes[advsimd_i])) 20868 modes->safe_push (sve_modes[sve_i++]); 20869 else 20870 modes->safe_push (advsimd_modes[advsimd_i++]); 20871 } 20872 while (sve_i < ARRAY_SIZE (sve_modes)) 20873 modes->safe_push (sve_modes[sve_i++]); 20874 20875 unsigned int flags = 0; 20876 /* Consider enabling VECT_COMPARE_COSTS for SVE, both so that we 20877 can compare SVE against Advanced SIMD and so that we can compare 20878 multiple SVE vectorization approaches against each other. There's 20879 not really any point doing this for Advanced SIMD only, since the 20880 first mode that works should always be the best. */ 20881 if (TARGET_SVE && aarch64_sve_compare_costs) 20882 flags |= VECT_COMPARE_COSTS; 20883 return flags; 20884 } 20885 20886 /* Implement TARGET_MANGLE_TYPE. */ 20887 20888 static const char * 20889 aarch64_mangle_type (const_tree type) 20890 { 20891 /* The AArch64 ABI documents say that "__va_list" has to be 20892 mangled as if it is in the "std" namespace. */ 20893 if (lang_hooks.types_compatible_p (CONST_CAST_TREE (type), va_list_type)) 20894 return "St9__va_list"; 20895 20896 /* Half-precision floating point types. */ 20897 if (TREE_CODE (type) == REAL_TYPE && TYPE_PRECISION (type) == 16) 20898 { 20899 if (TYPE_MODE (type) == BFmode) 20900 return "u6__bf16"; 20901 else 20902 return "Dh"; 20903 } 20904 20905 /* Mangle AArch64-specific internal types. TYPE_NAME is non-NULL_TREE for 20906 builtin types. */ 20907 if (TYPE_NAME (type) != NULL) 20908 { 20909 const char *res; 20910 if ((res = aarch64_general_mangle_builtin_type (type)) 20911 || (res = aarch64_sve::mangle_builtin_type (type))) 20912 return res; 20913 } 20914 20915 /* Use the default mangling. */ 20916 return NULL; 20917 } 20918 20919 /* Implement TARGET_VERIFY_TYPE_CONTEXT. */ 20920 20921 static bool 20922 aarch64_verify_type_context (location_t loc, type_context_kind context, 20923 const_tree type, bool silent_p) 20924 { 20925 return aarch64_sve::verify_type_context (loc, context, type, silent_p); 20926 } 20927 20928 /* Find the first rtx_insn before insn that will generate an assembly 20929 instruction. */ 20930 20931 static rtx_insn * 20932 aarch64_prev_real_insn (rtx_insn *insn) 20933 { 20934 if (!insn) 20935 return NULL; 20936 20937 do 20938 { 20939 insn = prev_real_insn (insn); 20940 } 20941 while (insn && recog_memoized (insn) < 0); 20942 20943 return insn; 20944 } 20945 20946 static bool 20947 is_madd_op (enum attr_type t1) 20948 { 20949 unsigned int i; 20950 /* A number of these may be AArch32 only. */ 20951 enum attr_type mlatypes[] = { 20952 TYPE_MLA, TYPE_MLAS, TYPE_SMLAD, TYPE_SMLADX, TYPE_SMLAL, TYPE_SMLALD, 20953 TYPE_SMLALS, TYPE_SMLALXY, TYPE_SMLAWX, TYPE_SMLAWY, TYPE_SMLAXY, 20954 TYPE_SMMLA, TYPE_UMLAL, TYPE_UMLALS,TYPE_SMLSD, TYPE_SMLSDX, TYPE_SMLSLD 20955 }; 20956 20957 for (i = 0; i < sizeof (mlatypes) / sizeof (enum attr_type); i++) 20958 { 20959 if (t1 == mlatypes[i]) 20960 return true; 20961 } 20962 20963 return false; 20964 } 20965 20966 /* Check if there is a register dependency between a load and the insn 20967 for which we hold recog_data. */ 20968 20969 static bool 20970 dep_between_memop_and_curr (rtx memop) 20971 { 20972 rtx load_reg; 20973 int opno; 20974 20975 gcc_assert (GET_CODE (memop) == SET); 20976 20977 if (!REG_P (SET_DEST (memop))) 20978 return false; 20979 20980 load_reg = SET_DEST (memop); 20981 for (opno = 1; opno < recog_data.n_operands; opno++) 20982 { 20983 rtx operand = recog_data.operand[opno]; 20984 if (REG_P (operand) 20985 && reg_overlap_mentioned_p (load_reg, operand)) 20986 return true; 20987 20988 } 20989 return false; 20990 } 20991 20992 20993 /* When working around the Cortex-A53 erratum 835769, 20994 given rtx_insn INSN, return true if it is a 64-bit multiply-accumulate 20995 instruction and has a preceding memory instruction such that a NOP 20996 should be inserted between them. */ 20997 20998 bool 20999 aarch64_madd_needs_nop (rtx_insn* insn) 21000 { 21001 enum attr_type attr_type; 21002 rtx_insn *prev; 21003 rtx body; 21004 21005 if (!TARGET_FIX_ERR_A53_835769) 21006 return false; 21007 21008 if (!INSN_P (insn) || recog_memoized (insn) < 0) 21009 return false; 21010 21011 attr_type = get_attr_type (insn); 21012 if (!is_madd_op (attr_type)) 21013 return false; 21014 21015 prev = aarch64_prev_real_insn (insn); 21016 /* aarch64_prev_real_insn can call recog_memoized on insns other than INSN. 21017 Restore recog state to INSN to avoid state corruption. */ 21018 extract_constrain_insn_cached (insn); 21019 21020 if (!prev || !contains_mem_rtx_p (PATTERN (prev))) 21021 return false; 21022 21023 body = single_set (prev); 21024 21025 /* If the previous insn is a memory op and there is no dependency between 21026 it and the DImode madd, emit a NOP between them. If body is NULL then we 21027 have a complex memory operation, probably a load/store pair. 21028 Be conservative for now and emit a NOP. */ 21029 if (GET_MODE (recog_data.operand[0]) == DImode 21030 && (!body || !dep_between_memop_and_curr (body))) 21031 return true; 21032 21033 return false; 21034 21035 } 21036 21037 21038 /* Implement FINAL_PRESCAN_INSN. */ 21039 21040 void 21041 aarch64_final_prescan_insn (rtx_insn *insn) 21042 { 21043 if (aarch64_madd_needs_nop (insn)) 21044 fprintf (asm_out_file, "\tnop // between mem op and mult-accumulate\n"); 21045 } 21046 21047 21048 /* Return true if BASE_OR_STEP is a valid immediate operand for an SVE INDEX 21049 instruction. */ 21050 21051 bool 21052 aarch64_sve_index_immediate_p (rtx base_or_step) 21053 { 21054 return (CONST_INT_P (base_or_step) 21055 && IN_RANGE (INTVAL (base_or_step), -16, 15)); 21056 } 21057 21058 /* Return true if X is a valid immediate for the SVE ADD and SUB instructions 21059 when applied to mode MODE. Negate X first if NEGATE_P is true. */ 21060 21061 bool 21062 aarch64_sve_arith_immediate_p (machine_mode mode, rtx x, bool negate_p) 21063 { 21064 rtx elt = unwrap_const_vec_duplicate (x); 21065 if (!CONST_INT_P (elt)) 21066 return false; 21067 21068 HOST_WIDE_INT val = INTVAL (elt); 21069 if (negate_p) 21070 val = -val; 21071 val &= GET_MODE_MASK (GET_MODE_INNER (mode)); 21072 21073 if (val & 0xff) 21074 return IN_RANGE (val, 0, 0xff); 21075 return IN_RANGE (val, 0, 0xff00); 21076 } 21077 21078 /* Return true if X is a valid immediate for the SVE SQADD and SQSUB 21079 instructions when applied to mode MODE. Negate X first if NEGATE_P 21080 is true. */ 21081 21082 bool 21083 aarch64_sve_sqadd_sqsub_immediate_p (machine_mode mode, rtx x, bool negate_p) 21084 { 21085 if (!aarch64_sve_arith_immediate_p (mode, x, negate_p)) 21086 return false; 21087 21088 /* After the optional negation, the immediate must be nonnegative. 21089 E.g. a saturating add of -127 must be done via SQSUB Zn.B, Zn.B, #127 21090 instead of SQADD Zn.B, Zn.B, #129. */ 21091 rtx elt = unwrap_const_vec_duplicate (x); 21092 return negate_p == (INTVAL (elt) < 0); 21093 } 21094 21095 /* Return true if X is a valid immediate operand for an SVE logical 21096 instruction such as AND. */ 21097 21098 bool 21099 aarch64_sve_bitmask_immediate_p (rtx x) 21100 { 21101 rtx elt; 21102 21103 return (const_vec_duplicate_p (x, &elt) 21104 && CONST_INT_P (elt) 21105 && aarch64_bitmask_imm (INTVAL (elt), 21106 GET_MODE_INNER (GET_MODE (x)))); 21107 } 21108 21109 /* Return true if X is a valid immediate for the SVE DUP and CPY 21110 instructions. */ 21111 21112 bool 21113 aarch64_sve_dup_immediate_p (rtx x) 21114 { 21115 x = aarch64_bit_representation (unwrap_const_vec_duplicate (x)); 21116 if (!CONST_INT_P (x)) 21117 return false; 21118 21119 HOST_WIDE_INT val = INTVAL (x); 21120 if (val & 0xff) 21121 return IN_RANGE (val, -0x80, 0x7f); 21122 return IN_RANGE (val, -0x8000, 0x7f00); 21123 } 21124 21125 /* Return true if X is a valid immediate operand for an SVE CMP instruction. 21126 SIGNED_P says whether the operand is signed rather than unsigned. */ 21127 21128 bool 21129 aarch64_sve_cmp_immediate_p (rtx x, bool signed_p) 21130 { 21131 x = unwrap_const_vec_duplicate (x); 21132 return (CONST_INT_P (x) 21133 && (signed_p 21134 ? IN_RANGE (INTVAL (x), -16, 15) 21135 : IN_RANGE (INTVAL (x), 0, 127))); 21136 } 21137 21138 /* Return true if X is a valid immediate operand for an SVE FADD or FSUB 21139 instruction. Negate X first if NEGATE_P is true. */ 21140 21141 bool 21142 aarch64_sve_float_arith_immediate_p (rtx x, bool negate_p) 21143 { 21144 rtx elt; 21145 REAL_VALUE_TYPE r; 21146 21147 if (!const_vec_duplicate_p (x, &elt) 21148 || !CONST_DOUBLE_P (elt)) 21149 return false; 21150 21151 r = *CONST_DOUBLE_REAL_VALUE (elt); 21152 21153 if (negate_p) 21154 r = real_value_negate (&r); 21155 21156 if (real_equal (&r, &dconst1)) 21157 return true; 21158 if (real_equal (&r, &dconsthalf)) 21159 return true; 21160 return false; 21161 } 21162 21163 /* Return true if X is a valid immediate operand for an SVE FMUL 21164 instruction. */ 21165 21166 bool 21167 aarch64_sve_float_mul_immediate_p (rtx x) 21168 { 21169 rtx elt; 21170 21171 return (const_vec_duplicate_p (x, &elt) 21172 && CONST_DOUBLE_P (elt) 21173 && (real_equal (CONST_DOUBLE_REAL_VALUE (elt), &dconsthalf) 21174 || real_equal (CONST_DOUBLE_REAL_VALUE (elt), &dconst2))); 21175 } 21176 21177 /* Return true if replicating VAL32 is a valid 2-byte or 4-byte immediate 21178 for the Advanced SIMD operation described by WHICH and INSN. If INFO 21179 is nonnull, use it to describe valid immediates. */ 21180 static bool 21181 aarch64_advsimd_valid_immediate_hs (unsigned int val32, 21182 simd_immediate_info *info, 21183 enum simd_immediate_check which, 21184 simd_immediate_info::insn_type insn) 21185 { 21186 /* Try a 4-byte immediate with LSL. */ 21187 for (unsigned int shift = 0; shift < 32; shift += 8) 21188 if ((val32 & (0xff << shift)) == val32) 21189 { 21190 if (info) 21191 *info = simd_immediate_info (SImode, val32 >> shift, insn, 21192 simd_immediate_info::LSL, shift); 21193 return true; 21194 } 21195 21196 /* Try a 2-byte immediate with LSL. */ 21197 unsigned int imm16 = val32 & 0xffff; 21198 if (imm16 == (val32 >> 16)) 21199 for (unsigned int shift = 0; shift < 16; shift += 8) 21200 if ((imm16 & (0xff << shift)) == imm16) 21201 { 21202 if (info) 21203 *info = simd_immediate_info (HImode, imm16 >> shift, insn, 21204 simd_immediate_info::LSL, shift); 21205 return true; 21206 } 21207 21208 /* Try a 4-byte immediate with MSL, except for cases that MVN 21209 can handle. */ 21210 if (which == AARCH64_CHECK_MOV) 21211 for (unsigned int shift = 8; shift < 24; shift += 8) 21212 { 21213 unsigned int low = (1 << shift) - 1; 21214 if (((val32 & (0xff << shift)) | low) == val32) 21215 { 21216 if (info) 21217 *info = simd_immediate_info (SImode, val32 >> shift, insn, 21218 simd_immediate_info::MSL, shift); 21219 return true; 21220 } 21221 } 21222 21223 return false; 21224 } 21225 21226 /* Return true if replicating VAL64 is a valid immediate for the 21227 Advanced SIMD operation described by WHICH. If INFO is nonnull, 21228 use it to describe valid immediates. */ 21229 static bool 21230 aarch64_advsimd_valid_immediate (unsigned HOST_WIDE_INT val64, 21231 simd_immediate_info *info, 21232 enum simd_immediate_check which) 21233 { 21234 unsigned int val32 = val64 & 0xffffffff; 21235 unsigned int val16 = val64 & 0xffff; 21236 unsigned int val8 = val64 & 0xff; 21237 21238 if (val32 == (val64 >> 32)) 21239 { 21240 if ((which & AARCH64_CHECK_ORR) != 0 21241 && aarch64_advsimd_valid_immediate_hs (val32, info, which, 21242 simd_immediate_info::MOV)) 21243 return true; 21244 21245 if ((which & AARCH64_CHECK_BIC) != 0 21246 && aarch64_advsimd_valid_immediate_hs (~val32, info, which, 21247 simd_immediate_info::MVN)) 21248 return true; 21249 21250 /* Try using a replicated byte. */ 21251 if (which == AARCH64_CHECK_MOV 21252 && val16 == (val32 >> 16) 21253 && val8 == (val16 >> 8)) 21254 { 21255 if (info) 21256 *info = simd_immediate_info (QImode, val8); 21257 return true; 21258 } 21259 } 21260 21261 /* Try using a bit-to-bytemask. */ 21262 if (which == AARCH64_CHECK_MOV) 21263 { 21264 unsigned int i; 21265 for (i = 0; i < 64; i += 8) 21266 { 21267 unsigned char byte = (val64 >> i) & 0xff; 21268 if (byte != 0 && byte != 0xff) 21269 break; 21270 } 21271 if (i == 64) 21272 { 21273 if (info) 21274 *info = simd_immediate_info (DImode, val64); 21275 return true; 21276 } 21277 } 21278 return false; 21279 } 21280 21281 /* Return true if replicating VAL64 gives a valid immediate for an SVE MOV 21282 instruction. If INFO is nonnull, use it to describe valid immediates. */ 21283 21284 static bool 21285 aarch64_sve_valid_immediate (unsigned HOST_WIDE_INT val64, 21286 simd_immediate_info *info) 21287 { 21288 scalar_int_mode mode = DImode; 21289 unsigned int val32 = val64 & 0xffffffff; 21290 if (val32 == (val64 >> 32)) 21291 { 21292 mode = SImode; 21293 unsigned int val16 = val32 & 0xffff; 21294 if (val16 == (val32 >> 16)) 21295 { 21296 mode = HImode; 21297 unsigned int val8 = val16 & 0xff; 21298 if (val8 == (val16 >> 8)) 21299 mode = QImode; 21300 } 21301 } 21302 HOST_WIDE_INT val = trunc_int_for_mode (val64, mode); 21303 if (IN_RANGE (val, -0x80, 0x7f)) 21304 { 21305 /* DUP with no shift. */ 21306 if (info) 21307 *info = simd_immediate_info (mode, val); 21308 return true; 21309 } 21310 if ((val & 0xff) == 0 && IN_RANGE (val, -0x8000, 0x7f00)) 21311 { 21312 /* DUP with LSL #8. */ 21313 if (info) 21314 *info = simd_immediate_info (mode, val); 21315 return true; 21316 } 21317 if (aarch64_bitmask_imm (val64, mode)) 21318 { 21319 /* DUPM. */ 21320 if (info) 21321 *info = simd_immediate_info (mode, val); 21322 return true; 21323 } 21324 return false; 21325 } 21326 21327 /* Return true if X is an UNSPEC_PTRUE constant of the form: 21328 21329 (const (unspec [PATTERN ZERO] UNSPEC_PTRUE)) 21330 21331 where PATTERN is the svpattern as a CONST_INT and where ZERO 21332 is a zero constant of the required PTRUE mode (which can have 21333 fewer elements than X's mode, if zero bits are significant). 21334 21335 If so, and if INFO is nonnull, describe the immediate in INFO. */ 21336 bool 21337 aarch64_sve_ptrue_svpattern_p (rtx x, struct simd_immediate_info *info) 21338 { 21339 if (GET_CODE (x) != CONST) 21340 return false; 21341 21342 x = XEXP (x, 0); 21343 if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_PTRUE) 21344 return false; 21345 21346 if (info) 21347 { 21348 aarch64_svpattern pattern 21349 = (aarch64_svpattern) INTVAL (XVECEXP (x, 0, 0)); 21350 machine_mode pred_mode = GET_MODE (XVECEXP (x, 0, 1)); 21351 scalar_int_mode int_mode = aarch64_sve_element_int_mode (pred_mode); 21352 *info = simd_immediate_info (int_mode, pattern); 21353 } 21354 return true; 21355 } 21356 21357 /* Return true if X is a valid SVE predicate. If INFO is nonnull, use 21358 it to describe valid immediates. */ 21359 21360 static bool 21361 aarch64_sve_pred_valid_immediate (rtx x, simd_immediate_info *info) 21362 { 21363 if (aarch64_sve_ptrue_svpattern_p (x, info)) 21364 return true; 21365 21366 if (x == CONST0_RTX (GET_MODE (x))) 21367 { 21368 if (info) 21369 *info = simd_immediate_info (DImode, 0); 21370 return true; 21371 } 21372 21373 /* Analyze the value as a VNx16BImode. This should be relatively 21374 efficient, since rtx_vector_builder has enough built-in capacity 21375 to store all VLA predicate constants without needing the heap. */ 21376 rtx_vector_builder builder; 21377 if (!aarch64_get_sve_pred_bits (builder, x)) 21378 return false; 21379 21380 unsigned int elt_size = aarch64_widest_sve_pred_elt_size (builder); 21381 if (int vl = aarch64_partial_ptrue_length (builder, elt_size)) 21382 { 21383 machine_mode mode = aarch64_sve_pred_mode (elt_size).require (); 21384 aarch64_svpattern pattern = aarch64_svpattern_for_vl (mode, vl); 21385 if (pattern != AARCH64_NUM_SVPATTERNS) 21386 { 21387 if (info) 21388 { 21389 scalar_int_mode int_mode = aarch64_sve_element_int_mode (mode); 21390 *info = simd_immediate_info (int_mode, pattern); 21391 } 21392 return true; 21393 } 21394 } 21395 return false; 21396 } 21397 21398 /* Return true if OP is a valid SIMD immediate for the operation 21399 described by WHICH. If INFO is nonnull, use it to describe valid 21400 immediates. */ 21401 bool 21402 aarch64_simd_valid_immediate (rtx op, simd_immediate_info *info, 21403 enum simd_immediate_check which) 21404 { 21405 machine_mode mode = GET_MODE (op); 21406 unsigned int vec_flags = aarch64_classify_vector_mode (mode); 21407 if (vec_flags == 0 || vec_flags == (VEC_ADVSIMD | VEC_STRUCT)) 21408 return false; 21409 21410 if (vec_flags & VEC_SVE_PRED) 21411 return aarch64_sve_pred_valid_immediate (op, info); 21412 21413 scalar_mode elt_mode = GET_MODE_INNER (mode); 21414 rtx base, step; 21415 unsigned int n_elts; 21416 if (CONST_VECTOR_P (op) 21417 && CONST_VECTOR_DUPLICATE_P (op)) 21418 n_elts = CONST_VECTOR_NPATTERNS (op); 21419 else if ((vec_flags & VEC_SVE_DATA) 21420 && const_vec_series_p (op, &base, &step)) 21421 { 21422 gcc_assert (GET_MODE_CLASS (mode) == MODE_VECTOR_INT); 21423 if (!aarch64_sve_index_immediate_p (base) 21424 || !aarch64_sve_index_immediate_p (step)) 21425 return false; 21426 21427 if (info) 21428 { 21429 /* Get the corresponding container mode. E.g. an INDEX on V2SI 21430 should yield two integer values per 128-bit block, meaning 21431 that we need to treat it in the same way as V2DI and then 21432 ignore the upper 32 bits of each element. */ 21433 elt_mode = aarch64_sve_container_int_mode (mode); 21434 *info = simd_immediate_info (elt_mode, base, step); 21435 } 21436 return true; 21437 } 21438 else if (CONST_VECTOR_P (op) 21439 && CONST_VECTOR_NUNITS (op).is_constant (&n_elts)) 21440 /* N_ELTS set above. */; 21441 else 21442 return false; 21443 21444 scalar_float_mode elt_float_mode; 21445 if (n_elts == 1 21446 && is_a <scalar_float_mode> (elt_mode, &elt_float_mode)) 21447 { 21448 rtx elt = CONST_VECTOR_ENCODED_ELT (op, 0); 21449 if (aarch64_float_const_zero_rtx_p (elt) 21450 || aarch64_float_const_representable_p (elt)) 21451 { 21452 if (info) 21453 *info = simd_immediate_info (elt_float_mode, elt); 21454 return true; 21455 } 21456 } 21457 21458 /* If all elements in an SVE vector have the same value, we have a free 21459 choice between using the element mode and using the container mode. 21460 Using the element mode means that unused parts of the vector are 21461 duplicates of the used elements, while using the container mode means 21462 that the unused parts are an extension of the used elements. Using the 21463 element mode is better for (say) VNx4HI 0x101, since 0x01010101 is valid 21464 for its container mode VNx4SI while 0x00000101 isn't. 21465 21466 If not all elements in an SVE vector have the same value, we need the 21467 transition from one element to the next to occur at container boundaries. 21468 E.g. a fixed-length VNx4HI containing { 1, 2, 3, 4 } should be treated 21469 in the same way as a VNx4SI containing { 1, 2, 3, 4 }. */ 21470 scalar_int_mode elt_int_mode; 21471 if ((vec_flags & VEC_SVE_DATA) && n_elts > 1) 21472 elt_int_mode = aarch64_sve_container_int_mode (mode); 21473 else 21474 elt_int_mode = int_mode_for_mode (elt_mode).require (); 21475 21476 unsigned int elt_size = GET_MODE_SIZE (elt_int_mode); 21477 if (elt_size > 8) 21478 return false; 21479 21480 /* Expand the vector constant out into a byte vector, with the least 21481 significant byte of the register first. */ 21482 auto_vec<unsigned char, 16> bytes; 21483 bytes.reserve (n_elts * elt_size); 21484 for (unsigned int i = 0; i < n_elts; i++) 21485 { 21486 /* The vector is provided in gcc endian-neutral fashion. 21487 For aarch64_be Advanced SIMD, it must be laid out in the vector 21488 register in reverse order. */ 21489 bool swap_p = ((vec_flags & VEC_ADVSIMD) != 0 && BYTES_BIG_ENDIAN); 21490 rtx elt = CONST_VECTOR_ELT (op, swap_p ? (n_elts - 1 - i) : i); 21491 21492 if (elt_mode != elt_int_mode) 21493 elt = gen_lowpart (elt_int_mode, elt); 21494 21495 if (!CONST_INT_P (elt)) 21496 return false; 21497 21498 unsigned HOST_WIDE_INT elt_val = INTVAL (elt); 21499 for (unsigned int byte = 0; byte < elt_size; byte++) 21500 { 21501 bytes.quick_push (elt_val & 0xff); 21502 elt_val >>= BITS_PER_UNIT; 21503 } 21504 } 21505 21506 /* The immediate must repeat every eight bytes. */ 21507 unsigned int nbytes = bytes.length (); 21508 for (unsigned i = 8; i < nbytes; ++i) 21509 if (bytes[i] != bytes[i - 8]) 21510 return false; 21511 21512 /* Get the repeating 8-byte value as an integer. No endian correction 21513 is needed here because bytes is already in lsb-first order. */ 21514 unsigned HOST_WIDE_INT val64 = 0; 21515 for (unsigned int i = 0; i < 8; i++) 21516 val64 |= ((unsigned HOST_WIDE_INT) bytes[i % nbytes] 21517 << (i * BITS_PER_UNIT)); 21518 21519 if (vec_flags & VEC_SVE_DATA) 21520 return aarch64_sve_valid_immediate (val64, info); 21521 else 21522 return aarch64_advsimd_valid_immediate (val64, info, which); 21523 } 21524 21525 /* Check whether X is a VEC_SERIES-like constant that starts at 0 and 21526 has a step in the range of INDEX. Return the index expression if so, 21527 otherwise return null. */ 21528 rtx 21529 aarch64_check_zero_based_sve_index_immediate (rtx x) 21530 { 21531 rtx base, step; 21532 if (const_vec_series_p (x, &base, &step) 21533 && base == const0_rtx 21534 && aarch64_sve_index_immediate_p (step)) 21535 return step; 21536 return NULL_RTX; 21537 } 21538 21539 /* Check of immediate shift constants are within range. */ 21540 bool 21541 aarch64_simd_shift_imm_p (rtx x, machine_mode mode, bool left) 21542 { 21543 x = unwrap_const_vec_duplicate (x); 21544 if (!CONST_INT_P (x)) 21545 return false; 21546 int bit_width = GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT; 21547 if (left) 21548 return IN_RANGE (INTVAL (x), 0, bit_width - 1); 21549 else 21550 return IN_RANGE (INTVAL (x), 1, bit_width); 21551 } 21552 21553 /* Return the bitmask CONST_INT to select the bits required by a zero extract 21554 operation of width WIDTH at bit position POS. */ 21555 21556 rtx 21557 aarch64_mask_from_zextract_ops (rtx width, rtx pos) 21558 { 21559 gcc_assert (CONST_INT_P (width)); 21560 gcc_assert (CONST_INT_P (pos)); 21561 21562 unsigned HOST_WIDE_INT mask 21563 = ((unsigned HOST_WIDE_INT) 1 << UINTVAL (width)) - 1; 21564 return GEN_INT (mask << UINTVAL (pos)); 21565 } 21566 21567 bool 21568 aarch64_mov_operand_p (rtx x, machine_mode mode) 21569 { 21570 if (GET_CODE (x) == HIGH 21571 && aarch64_valid_symref (XEXP (x, 0), GET_MODE (XEXP (x, 0)))) 21572 return true; 21573 21574 if (CONST_INT_P (x)) 21575 return true; 21576 21577 if (VECTOR_MODE_P (GET_MODE (x))) 21578 { 21579 /* Require predicate constants to be VNx16BI before RA, so that we 21580 force everything to have a canonical form. */ 21581 if (!lra_in_progress 21582 && !reload_completed 21583 && GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_BOOL 21584 && GET_MODE (x) != VNx16BImode) 21585 return false; 21586 21587 return aarch64_simd_valid_immediate (x, NULL); 21588 } 21589 21590 /* Remove UNSPEC_SALT_ADDR before checking symbol reference. */ 21591 x = strip_salt (x); 21592 21593 /* GOT accesses are valid moves. */ 21594 if (SYMBOL_REF_P (x) 21595 && aarch64_classify_symbolic_expression (x) == SYMBOL_SMALL_GOT_4G) 21596 return true; 21597 21598 if (SYMBOL_REF_P (x) && mode == DImode && CONSTANT_ADDRESS_P (x)) 21599 return true; 21600 21601 if (TARGET_SVE && aarch64_sve_cnt_immediate_p (x)) 21602 return true; 21603 21604 return aarch64_classify_symbolic_expression (x) 21605 == SYMBOL_TINY_ABSOLUTE; 21606 } 21607 21608 /* Create a 0 constant that is based on V4SI to allow CSE to optimally share 21609 the constant creation. */ 21610 21611 rtx 21612 aarch64_gen_shareable_zero (machine_mode mode) 21613 { 21614 machine_mode zmode = V4SImode; 21615 rtx tmp = gen_reg_rtx (zmode); 21616 emit_move_insn (tmp, CONST0_RTX (zmode)); 21617 return lowpart_subreg (mode, tmp, zmode); 21618 } 21619 21620 /* Return a const_int vector of VAL. */ 21621 rtx 21622 aarch64_simd_gen_const_vector_dup (machine_mode mode, HOST_WIDE_INT val) 21623 { 21624 rtx c = gen_int_mode (val, GET_MODE_INNER (mode)); 21625 return gen_const_vec_duplicate (mode, c); 21626 } 21627 21628 /* Check OP is a legal scalar immediate for the MOVI instruction. */ 21629 21630 bool 21631 aarch64_simd_scalar_immediate_valid_for_move (rtx op, scalar_int_mode mode) 21632 { 21633 machine_mode vmode; 21634 21635 vmode = aarch64_simd_container_mode (mode, 64); 21636 rtx op_v = aarch64_simd_gen_const_vector_dup (vmode, INTVAL (op)); 21637 return aarch64_simd_valid_immediate (op_v, NULL); 21638 } 21639 21640 /* Construct and return a PARALLEL RTX vector with elements numbering the 21641 lanes of either the high (HIGH == TRUE) or low (HIGH == FALSE) half of 21642 the vector - from the perspective of the architecture. This does not 21643 line up with GCC's perspective on lane numbers, so we end up with 21644 different masks depending on our target endian-ness. The diagram 21645 below may help. We must draw the distinction when building masks 21646 which select one half of the vector. An instruction selecting 21647 architectural low-lanes for a big-endian target, must be described using 21648 a mask selecting GCC high-lanes. 21649 21650 Big-Endian Little-Endian 21651 21652 GCC 0 1 2 3 3 2 1 0 21653 | x | x | x | x | | x | x | x | x | 21654 Architecture 3 2 1 0 3 2 1 0 21655 21656 Low Mask: { 2, 3 } { 0, 1 } 21657 High Mask: { 0, 1 } { 2, 3 } 21658 21659 MODE Is the mode of the vector and NUNITS is the number of units in it. */ 21660 21661 rtx 21662 aarch64_simd_vect_par_cnst_half (machine_mode mode, int nunits, bool high) 21663 { 21664 rtvec v = rtvec_alloc (nunits / 2); 21665 int high_base = nunits / 2; 21666 int low_base = 0; 21667 int base; 21668 rtx t1; 21669 int i; 21670 21671 if (BYTES_BIG_ENDIAN) 21672 base = high ? low_base : high_base; 21673 else 21674 base = high ? high_base : low_base; 21675 21676 for (i = 0; i < nunits / 2; i++) 21677 RTVEC_ELT (v, i) = GEN_INT (base + i); 21678 21679 t1 = gen_rtx_PARALLEL (mode, v); 21680 return t1; 21681 } 21682 21683 /* Check OP for validity as a PARALLEL RTX vector with elements 21684 numbering the lanes of either the high (HIGH == TRUE) or low lanes, 21685 from the perspective of the architecture. See the diagram above 21686 aarch64_simd_vect_par_cnst_half for more details. */ 21687 21688 bool 21689 aarch64_simd_check_vect_par_cnst_half (rtx op, machine_mode mode, 21690 bool high) 21691 { 21692 int nelts; 21693 if (!VECTOR_MODE_P (mode) || !GET_MODE_NUNITS (mode).is_constant (&nelts)) 21694 return false; 21695 21696 rtx ideal = aarch64_simd_vect_par_cnst_half (mode, nelts, high); 21697 HOST_WIDE_INT count_op = XVECLEN (op, 0); 21698 HOST_WIDE_INT count_ideal = XVECLEN (ideal, 0); 21699 int i = 0; 21700 21701 if (count_op != count_ideal) 21702 return false; 21703 21704 for (i = 0; i < count_ideal; i++) 21705 { 21706 rtx elt_op = XVECEXP (op, 0, i); 21707 rtx elt_ideal = XVECEXP (ideal, 0, i); 21708 21709 if (!CONST_INT_P (elt_op) 21710 || INTVAL (elt_ideal) != INTVAL (elt_op)) 21711 return false; 21712 } 21713 return true; 21714 } 21715 21716 /* Return a PARALLEL containing NELTS elements, with element I equal 21717 to BASE + I * STEP. */ 21718 21719 rtx 21720 aarch64_gen_stepped_int_parallel (unsigned int nelts, int base, int step) 21721 { 21722 rtvec vec = rtvec_alloc (nelts); 21723 for (unsigned int i = 0; i < nelts; ++i) 21724 RTVEC_ELT (vec, i) = gen_int_mode (base + i * step, DImode); 21725 return gen_rtx_PARALLEL (VOIDmode, vec); 21726 } 21727 21728 /* Return true if OP is a PARALLEL of CONST_INTs that form a linear 21729 series with step STEP. */ 21730 21731 bool 21732 aarch64_stepped_int_parallel_p (rtx op, int step) 21733 { 21734 if (GET_CODE (op) != PARALLEL || !CONST_INT_P (XVECEXP (op, 0, 0))) 21735 return false; 21736 21737 unsigned HOST_WIDE_INT base = UINTVAL (XVECEXP (op, 0, 0)); 21738 for (int i = 1; i < XVECLEN (op, 0); ++i) 21739 if (!CONST_INT_P (XVECEXP (op, 0, i)) 21740 || UINTVAL (XVECEXP (op, 0, i)) != base + i * step) 21741 return false; 21742 21743 return true; 21744 } 21745 21746 /* Bounds-check lanes. Ensure OPERAND lies between LOW (inclusive) and 21747 HIGH (exclusive). */ 21748 void 21749 aarch64_simd_lane_bounds (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high, 21750 const_tree exp) 21751 { 21752 HOST_WIDE_INT lane; 21753 gcc_assert (CONST_INT_P (operand)); 21754 lane = INTVAL (operand); 21755 21756 if (lane < low || lane >= high) 21757 { 21758 if (exp) 21759 error_at (EXPR_LOCATION (exp), "lane %wd out of range %wd - %wd", 21760 lane, low, high - 1); 21761 else 21762 error ("lane %wd out of range %wd - %wd", lane, low, high - 1); 21763 } 21764 } 21765 21766 /* Peform endian correction on lane number N, which indexes a vector 21767 of mode MODE, and return the result as an SImode rtx. */ 21768 21769 rtx 21770 aarch64_endian_lane_rtx (machine_mode mode, unsigned int n) 21771 { 21772 return gen_int_mode (ENDIAN_LANE_N (GET_MODE_NUNITS (mode), n), SImode); 21773 } 21774 21775 /* Return TRUE if OP is a valid vector addressing mode. */ 21776 21777 bool 21778 aarch64_simd_mem_operand_p (rtx op) 21779 { 21780 return MEM_P (op) && (GET_CODE (XEXP (op, 0)) == POST_INC 21781 || REG_P (XEXP (op, 0))); 21782 } 21783 21784 /* Return true if OP is a valid MEM operand for an SVE LD1R instruction. */ 21785 21786 bool 21787 aarch64_sve_ld1r_operand_p (rtx op) 21788 { 21789 struct aarch64_address_info addr; 21790 scalar_mode mode; 21791 21792 return (MEM_P (op) 21793 && is_a <scalar_mode> (GET_MODE (op), &mode) 21794 && aarch64_classify_address (&addr, XEXP (op, 0), mode, false) 21795 && addr.type == ADDRESS_REG_IMM 21796 && offset_6bit_unsigned_scaled_p (mode, addr.const_offset)); 21797 } 21798 21799 /* Return true if OP is a valid MEM operand for an SVE LD1R{Q,O} instruction 21800 where the size of the read data is specified by `mode` and the size of the 21801 vector elements are specified by `elem_mode`. */ 21802 bool 21803 aarch64_sve_ld1rq_ld1ro_operand_p (rtx op, machine_mode mode, 21804 scalar_mode elem_mode) 21805 { 21806 struct aarch64_address_info addr; 21807 if (!MEM_P (op) 21808 || !aarch64_classify_address (&addr, XEXP (op, 0), elem_mode, false)) 21809 return false; 21810 21811 if (addr.type == ADDRESS_REG_IMM) 21812 return offset_4bit_signed_scaled_p (mode, addr.const_offset); 21813 21814 if (addr.type == ADDRESS_REG_REG) 21815 return (1U << addr.shift) == GET_MODE_SIZE (elem_mode); 21816 21817 return false; 21818 } 21819 21820 /* Return true if OP is a valid MEM operand for an SVE LD1RQ instruction. */ 21821 bool 21822 aarch64_sve_ld1rq_operand_p (rtx op) 21823 { 21824 return aarch64_sve_ld1rq_ld1ro_operand_p (op, TImode, 21825 GET_MODE_INNER (GET_MODE (op))); 21826 } 21827 21828 /* Return true if OP is a valid MEM operand for an SVE LD1RO instruction for 21829 accessing a vector where the element size is specified by `elem_mode`. */ 21830 bool 21831 aarch64_sve_ld1ro_operand_p (rtx op, scalar_mode elem_mode) 21832 { 21833 return aarch64_sve_ld1rq_ld1ro_operand_p (op, OImode, elem_mode); 21834 } 21835 21836 /* Return true if OP is a valid MEM operand for an SVE LDFF1 instruction. */ 21837 bool 21838 aarch64_sve_ldff1_operand_p (rtx op) 21839 { 21840 if (!MEM_P (op)) 21841 return false; 21842 21843 struct aarch64_address_info addr; 21844 if (!aarch64_classify_address (&addr, XEXP (op, 0), GET_MODE (op), false)) 21845 return false; 21846 21847 if (addr.type == ADDRESS_REG_IMM) 21848 return known_eq (addr.const_offset, 0); 21849 21850 return addr.type == ADDRESS_REG_REG; 21851 } 21852 21853 /* Return true if OP is a valid MEM operand for an SVE LDNF1 instruction. */ 21854 bool 21855 aarch64_sve_ldnf1_operand_p (rtx op) 21856 { 21857 struct aarch64_address_info addr; 21858 21859 return (MEM_P (op) 21860 && aarch64_classify_address (&addr, XEXP (op, 0), 21861 GET_MODE (op), false) 21862 && addr.type == ADDRESS_REG_IMM); 21863 } 21864 21865 /* Return true if OP is a valid MEM operand for an SVE LDR instruction. 21866 The conditions for STR are the same. */ 21867 bool 21868 aarch64_sve_ldr_operand_p (rtx op) 21869 { 21870 struct aarch64_address_info addr; 21871 21872 return (MEM_P (op) 21873 && aarch64_classify_address (&addr, XEXP (op, 0), GET_MODE (op), 21874 false, ADDR_QUERY_ANY) 21875 && addr.type == ADDRESS_REG_IMM); 21876 } 21877 21878 /* Return true if OP is a valid address for an SVE PRF[BHWD] instruction, 21879 addressing memory of mode MODE. */ 21880 bool 21881 aarch64_sve_prefetch_operand_p (rtx op, machine_mode mode) 21882 { 21883 struct aarch64_address_info addr; 21884 if (!aarch64_classify_address (&addr, op, mode, false, ADDR_QUERY_ANY)) 21885 return false; 21886 21887 if (addr.type == ADDRESS_REG_IMM) 21888 return offset_6bit_signed_scaled_p (mode, addr.const_offset); 21889 21890 return addr.type == ADDRESS_REG_REG; 21891 } 21892 21893 /* Return true if OP is a valid MEM operand for an SVE_STRUCT mode. 21894 We need to be able to access the individual pieces, so the range 21895 is different from LD[234] and ST[234]. */ 21896 bool 21897 aarch64_sve_struct_memory_operand_p (rtx op) 21898 { 21899 if (!MEM_P (op)) 21900 return false; 21901 21902 machine_mode mode = GET_MODE (op); 21903 struct aarch64_address_info addr; 21904 if (!aarch64_classify_address (&addr, XEXP (op, 0), SVE_BYTE_MODE, false, 21905 ADDR_QUERY_ANY) 21906 || addr.type != ADDRESS_REG_IMM) 21907 return false; 21908 21909 poly_int64 first = addr.const_offset; 21910 poly_int64 last = first + GET_MODE_SIZE (mode) - BYTES_PER_SVE_VECTOR; 21911 return (offset_4bit_signed_scaled_p (SVE_BYTE_MODE, first) 21912 && offset_4bit_signed_scaled_p (SVE_BYTE_MODE, last)); 21913 } 21914 21915 /* Emit a register copy from operand to operand, taking care not to 21916 early-clobber source registers in the process. 21917 21918 COUNT is the number of components into which the copy needs to be 21919 decomposed. */ 21920 void 21921 aarch64_simd_emit_reg_reg_move (rtx *operands, machine_mode mode, 21922 unsigned int count) 21923 { 21924 unsigned int i; 21925 int rdest = REGNO (operands[0]); 21926 int rsrc = REGNO (operands[1]); 21927 21928 if (!reg_overlap_mentioned_p (operands[0], operands[1]) 21929 || rdest < rsrc) 21930 for (i = 0; i < count; i++) 21931 emit_move_insn (gen_rtx_REG (mode, rdest + i), 21932 gen_rtx_REG (mode, rsrc + i)); 21933 else 21934 for (i = 0; i < count; i++) 21935 emit_move_insn (gen_rtx_REG (mode, rdest + count - i - 1), 21936 gen_rtx_REG (mode, rsrc + count - i - 1)); 21937 } 21938 21939 /* Compute and return the length of aarch64_simd_reglist<mode>, where <mode> is 21940 one of VSTRUCT modes: OI, CI, or XI. */ 21941 int 21942 aarch64_simd_attr_length_rglist (machine_mode mode) 21943 { 21944 /* This is only used (and only meaningful) for Advanced SIMD, not SVE. */ 21945 return (GET_MODE_SIZE (mode).to_constant () / UNITS_PER_VREG) * 4; 21946 } 21947 21948 /* Implement target hook TARGET_VECTOR_ALIGNMENT. The AAPCS64 sets the maximum 21949 alignment of a vector to 128 bits. SVE predicates have an alignment of 21950 16 bits. */ 21951 static HOST_WIDE_INT 21952 aarch64_simd_vector_alignment (const_tree type) 21953 { 21954 /* ??? Checking the mode isn't ideal, but VECTOR_BOOLEAN_TYPE_P can 21955 be set for non-predicate vectors of booleans. Modes are the most 21956 direct way we have of identifying real SVE predicate types. */ 21957 if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_VECTOR_BOOL) 21958 return 16; 21959 widest_int min_size 21960 = constant_lower_bound (wi::to_poly_widest (TYPE_SIZE (type))); 21961 return wi::umin (min_size, 128).to_uhwi (); 21962 } 21963 21964 /* Implement target hook TARGET_VECTORIZE_PREFERRED_VECTOR_ALIGNMENT. */ 21965 static poly_uint64 21966 aarch64_vectorize_preferred_vector_alignment (const_tree type) 21967 { 21968 if (aarch64_sve_data_mode_p (TYPE_MODE (type))) 21969 { 21970 /* If the length of the vector is a fixed power of 2, try to align 21971 to that length, otherwise don't try to align at all. */ 21972 HOST_WIDE_INT result; 21973 if (!GET_MODE_BITSIZE (TYPE_MODE (type)).is_constant (&result) 21974 || !pow2p_hwi (result)) 21975 result = TYPE_ALIGN (TREE_TYPE (type)); 21976 return result; 21977 } 21978 return TYPE_ALIGN (type); 21979 } 21980 21981 /* Implement target hook TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE. */ 21982 static bool 21983 aarch64_simd_vector_alignment_reachable (const_tree type, bool is_packed) 21984 { 21985 if (is_packed) 21986 return false; 21987 21988 /* For fixed-length vectors, check that the vectorizer will aim for 21989 full-vector alignment. This isn't true for generic GCC vectors 21990 that are wider than the ABI maximum of 128 bits. */ 21991 poly_uint64 preferred_alignment = 21992 aarch64_vectorize_preferred_vector_alignment (type); 21993 if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST 21994 && maybe_ne (wi::to_widest (TYPE_SIZE (type)), 21995 preferred_alignment)) 21996 return false; 21997 21998 /* Vectors whose size is <= BIGGEST_ALIGNMENT are naturally aligned. */ 21999 return true; 22000 } 22001 22002 /* Return true if the vector misalignment factor is supported by the 22003 target. */ 22004 static bool 22005 aarch64_builtin_support_vector_misalignment (machine_mode mode, 22006 const_tree type, int misalignment, 22007 bool is_packed) 22008 { 22009 if (TARGET_SIMD && STRICT_ALIGNMENT) 22010 { 22011 /* Return if movmisalign pattern is not supported for this mode. */ 22012 if (optab_handler (movmisalign_optab, mode) == CODE_FOR_nothing) 22013 return false; 22014 22015 /* Misalignment factor is unknown at compile time. */ 22016 if (misalignment == -1) 22017 return false; 22018 } 22019 return default_builtin_support_vector_misalignment (mode, type, misalignment, 22020 is_packed); 22021 } 22022 22023 /* If VALS is a vector constant that can be loaded into a register 22024 using DUP, generate instructions to do so and return an RTX to 22025 assign to the register. Otherwise return NULL_RTX. */ 22026 static rtx 22027 aarch64_simd_dup_constant (rtx vals) 22028 { 22029 machine_mode mode = GET_MODE (vals); 22030 machine_mode inner_mode = GET_MODE_INNER (mode); 22031 rtx x; 22032 22033 if (!const_vec_duplicate_p (vals, &x)) 22034 return NULL_RTX; 22035 22036 /* We can load this constant by using DUP and a constant in a 22037 single ARM register. This will be cheaper than a vector 22038 load. */ 22039 x = copy_to_mode_reg (inner_mode, x); 22040 return gen_vec_duplicate (mode, x); 22041 } 22042 22043 22044 /* Generate code to load VALS, which is a PARALLEL containing only 22045 constants (for vec_init) or CONST_VECTOR, efficiently into a 22046 register. Returns an RTX to copy into the register, or NULL_RTX 22047 for a PARALLEL that cannot be converted into a CONST_VECTOR. */ 22048 static rtx 22049 aarch64_simd_make_constant (rtx vals) 22050 { 22051 machine_mode mode = GET_MODE (vals); 22052 rtx const_dup; 22053 rtx const_vec = NULL_RTX; 22054 int n_const = 0; 22055 int i; 22056 22057 if (CONST_VECTOR_P (vals)) 22058 const_vec = vals; 22059 else if (GET_CODE (vals) == PARALLEL) 22060 { 22061 /* A CONST_VECTOR must contain only CONST_INTs and 22062 CONST_DOUBLEs, but CONSTANT_P allows more (e.g. SYMBOL_REF). 22063 Only store valid constants in a CONST_VECTOR. */ 22064 int n_elts = XVECLEN (vals, 0); 22065 for (i = 0; i < n_elts; ++i) 22066 { 22067 rtx x = XVECEXP (vals, 0, i); 22068 if (CONST_INT_P (x) || CONST_DOUBLE_P (x)) 22069 n_const++; 22070 } 22071 if (n_const == n_elts) 22072 const_vec = gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)); 22073 } 22074 else 22075 gcc_unreachable (); 22076 22077 if (const_vec != NULL_RTX 22078 && aarch64_simd_valid_immediate (const_vec, NULL)) 22079 /* Load using MOVI/MVNI. */ 22080 return const_vec; 22081 else if ((const_dup = aarch64_simd_dup_constant (vals)) != NULL_RTX) 22082 /* Loaded using DUP. */ 22083 return const_dup; 22084 else if (const_vec != NULL_RTX) 22085 /* Load from constant pool. We cannot take advantage of single-cycle 22086 LD1 because we need a PC-relative addressing mode. */ 22087 return const_vec; 22088 else 22089 /* A PARALLEL containing something not valid inside CONST_VECTOR. 22090 We cannot construct an initializer. */ 22091 return NULL_RTX; 22092 } 22093 22094 /* Expand a vector initialisation sequence, such that TARGET is 22095 initialised to contain VALS. */ 22096 22097 void 22098 aarch64_expand_vector_init (rtx target, rtx vals) 22099 { 22100 machine_mode mode = GET_MODE (target); 22101 scalar_mode inner_mode = GET_MODE_INNER (mode); 22102 /* The number of vector elements. */ 22103 int n_elts = XVECLEN (vals, 0); 22104 /* The number of vector elements which are not constant. */ 22105 int n_var = 0; 22106 rtx any_const = NULL_RTX; 22107 /* The first element of vals. */ 22108 rtx v0 = XVECEXP (vals, 0, 0); 22109 bool all_same = true; 22110 22111 /* This is a special vec_init<M><N> where N is not an element mode but a 22112 vector mode with half the elements of M. We expect to find two entries 22113 of mode N in VALS and we must put their concatentation into TARGET. */ 22114 if (XVECLEN (vals, 0) == 2 && VECTOR_MODE_P (GET_MODE (XVECEXP (vals, 0, 0)))) 22115 { 22116 machine_mode narrow_mode = GET_MODE (XVECEXP (vals, 0, 0)); 22117 gcc_assert (GET_MODE_INNER (narrow_mode) == inner_mode 22118 && known_eq (GET_MODE_SIZE (mode), 22119 2 * GET_MODE_SIZE (narrow_mode))); 22120 emit_insn (gen_aarch64_vec_concat (narrow_mode, target, 22121 XVECEXP (vals, 0, 0), 22122 XVECEXP (vals, 0, 1))); 22123 return; 22124 } 22125 22126 /* Count the number of variable elements to initialise. */ 22127 for (int i = 0; i < n_elts; ++i) 22128 { 22129 rtx x = XVECEXP (vals, 0, i); 22130 if (!(CONST_INT_P (x) || CONST_DOUBLE_P (x))) 22131 ++n_var; 22132 else 22133 any_const = x; 22134 22135 all_same &= rtx_equal_p (x, v0); 22136 } 22137 22138 /* No variable elements, hand off to aarch64_simd_make_constant which knows 22139 how best to handle this. */ 22140 if (n_var == 0) 22141 { 22142 rtx constant = aarch64_simd_make_constant (vals); 22143 if (constant != NULL_RTX) 22144 { 22145 emit_move_insn (target, constant); 22146 return; 22147 } 22148 } 22149 22150 /* Splat a single non-constant element if we can. */ 22151 if (all_same) 22152 { 22153 rtx x = copy_to_mode_reg (inner_mode, v0); 22154 aarch64_emit_move (target, gen_vec_duplicate (mode, x)); 22155 return; 22156 } 22157 22158 enum insn_code icode = optab_handler (vec_set_optab, mode); 22159 gcc_assert (icode != CODE_FOR_nothing); 22160 22161 /* If there are only variable elements, try to optimize 22162 the insertion using dup for the most common element 22163 followed by insertions. */ 22164 22165 /* The algorithm will fill matches[*][0] with the earliest matching element, 22166 and matches[X][1] with the count of duplicate elements (if X is the 22167 earliest element which has duplicates). */ 22168 22169 if (n_var == n_elts && n_elts <= 16) 22170 { 22171 int matches[16][2] = {0}; 22172 for (int i = 0; i < n_elts; i++) 22173 { 22174 for (int j = 0; j <= i; j++) 22175 { 22176 if (rtx_equal_p (XVECEXP (vals, 0, i), XVECEXP (vals, 0, j))) 22177 { 22178 matches[i][0] = j; 22179 matches[j][1]++; 22180 break; 22181 } 22182 } 22183 } 22184 int maxelement = 0; 22185 int maxv = 0; 22186 for (int i = 0; i < n_elts; i++) 22187 if (matches[i][1] > maxv) 22188 { 22189 maxelement = i; 22190 maxv = matches[i][1]; 22191 } 22192 22193 /* Create a duplicate of the most common element, unless all elements 22194 are equally useless to us, in which case just immediately set the 22195 vector register using the first element. */ 22196 22197 if (maxv == 1) 22198 { 22199 /* For vectors of two 64-bit elements, we can do even better. */ 22200 if (n_elts == 2 22201 && (inner_mode == E_DImode 22202 || inner_mode == E_DFmode)) 22203 22204 { 22205 rtx x0 = XVECEXP (vals, 0, 0); 22206 rtx x1 = XVECEXP (vals, 0, 1); 22207 /* Combine can pick up this case, but handling it directly 22208 here leaves clearer RTL. 22209 22210 This is load_pair_lanes<mode>, and also gives us a clean-up 22211 for store_pair_lanes<mode>. */ 22212 if (memory_operand (x0, inner_mode) 22213 && memory_operand (x1, inner_mode) 22214 && aarch64_mergeable_load_pair_p (mode, x0, x1)) 22215 { 22216 rtx t; 22217 if (inner_mode == DFmode) 22218 t = gen_load_pair_lanesdf (target, x0, x1); 22219 else 22220 t = gen_load_pair_lanesdi (target, x0, x1); 22221 emit_insn (t); 22222 return; 22223 } 22224 } 22225 /* The subreg-move sequence below will move into lane zero of the 22226 vector register. For big-endian we want that position to hold 22227 the last element of VALS. */ 22228 maxelement = BYTES_BIG_ENDIAN ? n_elts - 1 : 0; 22229 rtx x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, maxelement)); 22230 aarch64_emit_move (target, lowpart_subreg (mode, x, inner_mode)); 22231 } 22232 else 22233 { 22234 rtx x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, maxelement)); 22235 aarch64_emit_move (target, gen_vec_duplicate (mode, x)); 22236 } 22237 22238 /* Insert the rest. */ 22239 for (int i = 0; i < n_elts; i++) 22240 { 22241 rtx x = XVECEXP (vals, 0, i); 22242 if (matches[i][0] == maxelement) 22243 continue; 22244 x = copy_to_mode_reg (inner_mode, x); 22245 emit_insn (GEN_FCN (icode) (target, x, GEN_INT (i))); 22246 } 22247 return; 22248 } 22249 22250 /* Initialise a vector which is part-variable. We want to first try 22251 to build those lanes which are constant in the most efficient way we 22252 can. */ 22253 if (n_var != n_elts) 22254 { 22255 rtx copy = copy_rtx (vals); 22256 22257 /* Load constant part of vector. We really don't care what goes into the 22258 parts we will overwrite, but we're more likely to be able to load the 22259 constant efficiently if it has fewer, larger, repeating parts 22260 (see aarch64_simd_valid_immediate). */ 22261 for (int i = 0; i < n_elts; i++) 22262 { 22263 rtx x = XVECEXP (vals, 0, i); 22264 if (CONST_INT_P (x) || CONST_DOUBLE_P (x)) 22265 continue; 22266 rtx subst = any_const; 22267 for (int bit = n_elts / 2; bit > 0; bit /= 2) 22268 { 22269 /* Look in the copied vector, as more elements are const. */ 22270 rtx test = XVECEXP (copy, 0, i ^ bit); 22271 if (CONST_INT_P (test) || CONST_DOUBLE_P (test)) 22272 { 22273 subst = test; 22274 break; 22275 } 22276 } 22277 XVECEXP (copy, 0, i) = subst; 22278 } 22279 aarch64_expand_vector_init (target, copy); 22280 } 22281 22282 /* Insert the variable lanes directly. */ 22283 for (int i = 0; i < n_elts; i++) 22284 { 22285 rtx x = XVECEXP (vals, 0, i); 22286 if (CONST_INT_P (x) || CONST_DOUBLE_P (x)) 22287 continue; 22288 x = copy_to_mode_reg (inner_mode, x); 22289 emit_insn (GEN_FCN (icode) (target, x, GEN_INT (i))); 22290 } 22291 } 22292 22293 /* Emit RTL corresponding to: 22294 insr TARGET, ELEM. */ 22295 22296 static void 22297 emit_insr (rtx target, rtx elem) 22298 { 22299 machine_mode mode = GET_MODE (target); 22300 scalar_mode elem_mode = GET_MODE_INNER (mode); 22301 elem = force_reg (elem_mode, elem); 22302 22303 insn_code icode = optab_handler (vec_shl_insert_optab, mode); 22304 gcc_assert (icode != CODE_FOR_nothing); 22305 emit_insn (GEN_FCN (icode) (target, target, elem)); 22306 } 22307 22308 /* Subroutine of aarch64_sve_expand_vector_init for handling 22309 trailing constants. 22310 This function works as follows: 22311 (a) Create a new vector consisting of trailing constants. 22312 (b) Initialize TARGET with the constant vector using emit_move_insn. 22313 (c) Insert remaining elements in TARGET using insr. 22314 NELTS is the total number of elements in original vector while 22315 while NELTS_REQD is the number of elements that are actually 22316 significant. 22317 22318 ??? The heuristic used is to do above only if number of constants 22319 is at least half the total number of elements. May need fine tuning. */ 22320 22321 static bool 22322 aarch64_sve_expand_vector_init_handle_trailing_constants 22323 (rtx target, const rtx_vector_builder &builder, int nelts, int nelts_reqd) 22324 { 22325 machine_mode mode = GET_MODE (target); 22326 scalar_mode elem_mode = GET_MODE_INNER (mode); 22327 int n_trailing_constants = 0; 22328 22329 for (int i = nelts_reqd - 1; 22330 i >= 0 && valid_for_const_vector_p (elem_mode, builder.elt (i)); 22331 i--) 22332 n_trailing_constants++; 22333 22334 if (n_trailing_constants >= nelts_reqd / 2) 22335 { 22336 /* Try to use the natural pattern of BUILDER to extend the trailing 22337 constant elements to a full vector. Replace any variables in the 22338 extra elements with zeros. 22339 22340 ??? It would be better if the builders supported "don't care" 22341 elements, with the builder filling in whichever elements 22342 give the most compact encoding. */ 22343 rtx_vector_builder v (mode, nelts, 1); 22344 for (int i = 0; i < nelts; i++) 22345 { 22346 rtx x = builder.elt (i + nelts_reqd - n_trailing_constants); 22347 if (!valid_for_const_vector_p (elem_mode, x)) 22348 x = CONST0_RTX (elem_mode); 22349 v.quick_push (x); 22350 } 22351 rtx const_vec = v.build (); 22352 emit_move_insn (target, const_vec); 22353 22354 for (int i = nelts_reqd - n_trailing_constants - 1; i >= 0; i--) 22355 emit_insr (target, builder.elt (i)); 22356 22357 return true; 22358 } 22359 22360 return false; 22361 } 22362 22363 /* Subroutine of aarch64_sve_expand_vector_init. 22364 Works as follows: 22365 (a) Initialize TARGET by broadcasting element NELTS_REQD - 1 of BUILDER. 22366 (b) Skip trailing elements from BUILDER, which are the same as 22367 element NELTS_REQD - 1. 22368 (c) Insert earlier elements in reverse order in TARGET using insr. */ 22369 22370 static void 22371 aarch64_sve_expand_vector_init_insert_elems (rtx target, 22372 const rtx_vector_builder &builder, 22373 int nelts_reqd) 22374 { 22375 machine_mode mode = GET_MODE (target); 22376 scalar_mode elem_mode = GET_MODE_INNER (mode); 22377 22378 struct expand_operand ops[2]; 22379 enum insn_code icode = optab_handler (vec_duplicate_optab, mode); 22380 gcc_assert (icode != CODE_FOR_nothing); 22381 22382 create_output_operand (&ops[0], target, mode); 22383 create_input_operand (&ops[1], builder.elt (nelts_reqd - 1), elem_mode); 22384 expand_insn (icode, 2, ops); 22385 22386 int ndups = builder.count_dups (nelts_reqd - 1, -1, -1); 22387 for (int i = nelts_reqd - ndups - 1; i >= 0; i--) 22388 emit_insr (target, builder.elt (i)); 22389 } 22390 22391 /* Subroutine of aarch64_sve_expand_vector_init to handle case 22392 when all trailing elements of builder are same. 22393 This works as follows: 22394 (a) Use expand_insn interface to broadcast last vector element in TARGET. 22395 (b) Insert remaining elements in TARGET using insr. 22396 22397 ??? The heuristic used is to do above if number of same trailing elements 22398 is at least 3/4 of total number of elements, loosely based on 22399 heuristic from mostly_zeros_p. May need fine-tuning. */ 22400 22401 static bool 22402 aarch64_sve_expand_vector_init_handle_trailing_same_elem 22403 (rtx target, const rtx_vector_builder &builder, int nelts_reqd) 22404 { 22405 int ndups = builder.count_dups (nelts_reqd - 1, -1, -1); 22406 if (ndups >= (3 * nelts_reqd) / 4) 22407 { 22408 aarch64_sve_expand_vector_init_insert_elems (target, builder, 22409 nelts_reqd - ndups + 1); 22410 return true; 22411 } 22412 22413 return false; 22414 } 22415 22416 /* Initialize register TARGET from BUILDER. NELTS is the constant number 22417 of elements in BUILDER. 22418 22419 The function tries to initialize TARGET from BUILDER if it fits one 22420 of the special cases outlined below. 22421 22422 Failing that, the function divides BUILDER into two sub-vectors: 22423 v_even = even elements of BUILDER; 22424 v_odd = odd elements of BUILDER; 22425 22426 and recursively calls itself with v_even and v_odd. 22427 22428 if (recursive call succeeded for v_even or v_odd) 22429 TARGET = zip (v_even, v_odd) 22430 22431 The function returns true if it managed to build TARGET from BUILDER 22432 with one of the special cases, false otherwise. 22433 22434 Example: {a, 1, b, 2, c, 3, d, 4} 22435 22436 The vector gets divided into: 22437 v_even = {a, b, c, d} 22438 v_odd = {1, 2, 3, 4} 22439 22440 aarch64_sve_expand_vector_init(v_odd) hits case 1 and 22441 initialize tmp2 from constant vector v_odd using emit_move_insn. 22442 22443 aarch64_sve_expand_vector_init(v_even) fails since v_even contains 22444 4 elements, so we construct tmp1 from v_even using insr: 22445 tmp1 = dup(d) 22446 insr tmp1, c 22447 insr tmp1, b 22448 insr tmp1, a 22449 22450 And finally: 22451 TARGET = zip (tmp1, tmp2) 22452 which sets TARGET to {a, 1, b, 2, c, 3, d, 4}. */ 22453 22454 static bool 22455 aarch64_sve_expand_vector_init (rtx target, const rtx_vector_builder &builder, 22456 int nelts, int nelts_reqd) 22457 { 22458 machine_mode mode = GET_MODE (target); 22459 22460 /* Case 1: Vector contains trailing constants. */ 22461 22462 if (aarch64_sve_expand_vector_init_handle_trailing_constants 22463 (target, builder, nelts, nelts_reqd)) 22464 return true; 22465 22466 /* Case 2: Vector contains leading constants. */ 22467 22468 rtx_vector_builder rev_builder (mode, nelts_reqd, 1); 22469 for (int i = 0; i < nelts_reqd; i++) 22470 rev_builder.quick_push (builder.elt (nelts_reqd - i - 1)); 22471 rev_builder.finalize (); 22472 22473 if (aarch64_sve_expand_vector_init_handle_trailing_constants 22474 (target, rev_builder, nelts, nelts_reqd)) 22475 { 22476 emit_insn (gen_aarch64_sve_rev (mode, target, target)); 22477 return true; 22478 } 22479 22480 /* Case 3: Vector contains trailing same element. */ 22481 22482 if (aarch64_sve_expand_vector_init_handle_trailing_same_elem 22483 (target, builder, nelts_reqd)) 22484 return true; 22485 22486 /* Case 4: Vector contains leading same element. */ 22487 22488 if (aarch64_sve_expand_vector_init_handle_trailing_same_elem 22489 (target, rev_builder, nelts_reqd) && nelts_reqd == nelts) 22490 { 22491 emit_insn (gen_aarch64_sve_rev (mode, target, target)); 22492 return true; 22493 } 22494 22495 /* Avoid recursing below 4-elements. 22496 ??? The threshold 4 may need fine-tuning. */ 22497 22498 if (nelts_reqd <= 4) 22499 return false; 22500 22501 rtx_vector_builder v_even (mode, nelts, 1); 22502 rtx_vector_builder v_odd (mode, nelts, 1); 22503 22504 for (int i = 0; i < nelts * 2; i += 2) 22505 { 22506 v_even.quick_push (builder.elt (i)); 22507 v_odd.quick_push (builder.elt (i + 1)); 22508 } 22509 22510 v_even.finalize (); 22511 v_odd.finalize (); 22512 22513 rtx tmp1 = gen_reg_rtx (mode); 22514 bool did_even_p = aarch64_sve_expand_vector_init (tmp1, v_even, 22515 nelts, nelts_reqd / 2); 22516 22517 rtx tmp2 = gen_reg_rtx (mode); 22518 bool did_odd_p = aarch64_sve_expand_vector_init (tmp2, v_odd, 22519 nelts, nelts_reqd / 2); 22520 22521 if (!did_even_p && !did_odd_p) 22522 return false; 22523 22524 /* Initialize v_even and v_odd using INSR if it didn't match any of the 22525 special cases and zip v_even, v_odd. */ 22526 22527 if (!did_even_p) 22528 aarch64_sve_expand_vector_init_insert_elems (tmp1, v_even, nelts_reqd / 2); 22529 22530 if (!did_odd_p) 22531 aarch64_sve_expand_vector_init_insert_elems (tmp2, v_odd, nelts_reqd / 2); 22532 22533 rtvec v = gen_rtvec (2, tmp1, tmp2); 22534 emit_set_insn (target, gen_rtx_UNSPEC (mode, v, UNSPEC_ZIP1)); 22535 return true; 22536 } 22537 22538 /* Initialize register TARGET from the elements in PARALLEL rtx VALS. */ 22539 22540 void 22541 aarch64_sve_expand_vector_init (rtx target, rtx vals) 22542 { 22543 machine_mode mode = GET_MODE (target); 22544 int nelts = XVECLEN (vals, 0); 22545 22546 rtx_vector_builder v (mode, nelts, 1); 22547 for (int i = 0; i < nelts; i++) 22548 v.quick_push (XVECEXP (vals, 0, i)); 22549 v.finalize (); 22550 22551 /* If neither sub-vectors of v could be initialized specially, 22552 then use INSR to insert all elements from v into TARGET. 22553 ??? This might not be optimal for vectors with large 22554 initializers like 16-element or above. 22555 For nelts < 4, it probably isn't useful to handle specially. */ 22556 22557 if (nelts < 4 22558 || !aarch64_sve_expand_vector_init (target, v, nelts, nelts)) 22559 aarch64_sve_expand_vector_init_insert_elems (target, v, nelts); 22560 } 22561 22562 /* Check whether VALUE is a vector constant in which every element 22563 is either a power of 2 or a negated power of 2. If so, return 22564 a constant vector of log2s, and flip CODE between PLUS and MINUS 22565 if VALUE contains negated powers of 2. Return NULL_RTX otherwise. */ 22566 22567 static rtx 22568 aarch64_convert_mult_to_shift (rtx value, rtx_code &code) 22569 { 22570 if (!CONST_VECTOR_P (value)) 22571 return NULL_RTX; 22572 22573 rtx_vector_builder builder; 22574 if (!builder.new_unary_operation (GET_MODE (value), value, false)) 22575 return NULL_RTX; 22576 22577 scalar_mode int_mode = GET_MODE_INNER (GET_MODE (value)); 22578 /* 1 if the result of the multiplication must be negated, 22579 0 if it mustn't, or -1 if we don't yet care. */ 22580 int negate = -1; 22581 unsigned int encoded_nelts = const_vector_encoded_nelts (value); 22582 for (unsigned int i = 0; i < encoded_nelts; ++i) 22583 { 22584 rtx elt = CONST_VECTOR_ENCODED_ELT (value, i); 22585 if (!CONST_SCALAR_INT_P (elt)) 22586 return NULL_RTX; 22587 rtx_mode_t val (elt, int_mode); 22588 wide_int pow2 = wi::neg (val); 22589 if (val != pow2) 22590 { 22591 /* It matters whether we negate or not. Make that choice, 22592 and make sure that it's consistent with previous elements. */ 22593 if (negate == !wi::neg_p (val)) 22594 return NULL_RTX; 22595 negate = wi::neg_p (val); 22596 if (!negate) 22597 pow2 = val; 22598 } 22599 /* POW2 is now the value that we want to be a power of 2. */ 22600 int shift = wi::exact_log2 (pow2); 22601 if (shift < 0) 22602 return NULL_RTX; 22603 builder.quick_push (gen_int_mode (shift, int_mode)); 22604 } 22605 if (negate == -1) 22606 /* PLUS and MINUS are equivalent; canonicalize on PLUS. */ 22607 code = PLUS; 22608 else if (negate == 1) 22609 code = code == PLUS ? MINUS : PLUS; 22610 return builder.build (); 22611 } 22612 22613 /* Prepare for an integer SVE multiply-add or multiply-subtract pattern; 22614 CODE is PLUS for the former and MINUS for the latter. OPERANDS is the 22615 operands array, in the same order as for fma_optab. Return true if 22616 the function emitted all the necessary instructions, false if the caller 22617 should generate the pattern normally with the new OPERANDS array. */ 22618 22619 bool 22620 aarch64_prepare_sve_int_fma (rtx *operands, rtx_code code) 22621 { 22622 machine_mode mode = GET_MODE (operands[0]); 22623 if (rtx shifts = aarch64_convert_mult_to_shift (operands[2], code)) 22624 { 22625 rtx product = expand_binop (mode, vashl_optab, operands[1], shifts, 22626 NULL_RTX, true, OPTAB_DIRECT); 22627 force_expand_binop (mode, code == PLUS ? add_optab : sub_optab, 22628 operands[3], product, operands[0], true, 22629 OPTAB_DIRECT); 22630 return true; 22631 } 22632 operands[2] = force_reg (mode, operands[2]); 22633 return false; 22634 } 22635 22636 /* Likewise, but for a conditional pattern. */ 22637 22638 bool 22639 aarch64_prepare_sve_cond_int_fma (rtx *operands, rtx_code code) 22640 { 22641 machine_mode mode = GET_MODE (operands[0]); 22642 if (rtx shifts = aarch64_convert_mult_to_shift (operands[3], code)) 22643 { 22644 rtx product = expand_binop (mode, vashl_optab, operands[2], shifts, 22645 NULL_RTX, true, OPTAB_DIRECT); 22646 emit_insn (gen_cond (code, mode, operands[0], operands[1], 22647 operands[4], product, operands[5])); 22648 return true; 22649 } 22650 operands[3] = force_reg (mode, operands[3]); 22651 return false; 22652 } 22653 22654 static unsigned HOST_WIDE_INT 22655 aarch64_shift_truncation_mask (machine_mode mode) 22656 { 22657 if (!SHIFT_COUNT_TRUNCATED || aarch64_vector_data_mode_p (mode)) 22658 return 0; 22659 return GET_MODE_UNIT_BITSIZE (mode) - 1; 22660 } 22661 22662 /* Select a format to encode pointers in exception handling data. */ 22663 int 22664 aarch64_asm_preferred_eh_data_format (int code ATTRIBUTE_UNUSED, int global) 22665 { 22666 int type; 22667 switch (aarch64_cmodel) 22668 { 22669 case AARCH64_CMODEL_TINY: 22670 case AARCH64_CMODEL_TINY_PIC: 22671 case AARCH64_CMODEL_SMALL: 22672 case AARCH64_CMODEL_SMALL_PIC: 22673 case AARCH64_CMODEL_SMALL_SPIC: 22674 /* text+got+data < 4Gb. 4-byte signed relocs are sufficient 22675 for everything. */ 22676 type = DW_EH_PE_sdata4; 22677 break; 22678 default: 22679 /* No assumptions here. 8-byte relocs required. */ 22680 type = DW_EH_PE_sdata8; 22681 break; 22682 } 22683 return (global ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | type; 22684 } 22685 22686 /* Output .variant_pcs for aarch64_vector_pcs function symbols. */ 22687 22688 static void 22689 aarch64_asm_output_variant_pcs (FILE *stream, const tree decl, const char* name) 22690 { 22691 if (TREE_CODE (decl) == FUNCTION_DECL) 22692 { 22693 arm_pcs pcs = (arm_pcs) fndecl_abi (decl).id (); 22694 if (pcs == ARM_PCS_SIMD || pcs == ARM_PCS_SVE) 22695 { 22696 fprintf (stream, "\t.variant_pcs\t"); 22697 assemble_name (stream, name); 22698 fprintf (stream, "\n"); 22699 } 22700 } 22701 } 22702 22703 /* The last .arch and .tune assembly strings that we printed. */ 22704 static std::string aarch64_last_printed_arch_string; 22705 static std::string aarch64_last_printed_tune_string; 22706 22707 /* Implement ASM_DECLARE_FUNCTION_NAME. Output the ISA features used 22708 by the function fndecl. */ 22709 22710 void 22711 aarch64_declare_function_name (FILE *stream, const char* name, 22712 tree fndecl) 22713 { 22714 tree target_parts = DECL_FUNCTION_SPECIFIC_TARGET (fndecl); 22715 22716 struct cl_target_option *targ_options; 22717 if (target_parts) 22718 targ_options = TREE_TARGET_OPTION (target_parts); 22719 else 22720 targ_options = TREE_TARGET_OPTION (target_option_current_node); 22721 gcc_assert (targ_options); 22722 22723 const struct processor *this_arch 22724 = aarch64_get_arch (targ_options->x_explicit_arch); 22725 22726 uint64_t isa_flags = targ_options->x_aarch64_isa_flags; 22727 std::string extension 22728 = aarch64_get_extension_string_for_isa_flags (isa_flags, 22729 this_arch->flags); 22730 /* Only update the assembler .arch string if it is distinct from the last 22731 such string we printed. */ 22732 std::string to_print = this_arch->name + extension; 22733 if (to_print != aarch64_last_printed_arch_string) 22734 { 22735 asm_fprintf (asm_out_file, "\t.arch %s\n", to_print.c_str ()); 22736 aarch64_last_printed_arch_string = to_print; 22737 } 22738 22739 /* Print the cpu name we're tuning for in the comments, might be 22740 useful to readers of the generated asm. Do it only when it changes 22741 from function to function and verbose assembly is requested. */ 22742 const struct processor *this_tune 22743 = aarch64_get_tune_cpu (targ_options->x_explicit_tune_core); 22744 22745 if (flag_debug_asm && aarch64_last_printed_tune_string != this_tune->name) 22746 { 22747 asm_fprintf (asm_out_file, "\t" ASM_COMMENT_START ".tune %s\n", 22748 this_tune->name); 22749 aarch64_last_printed_tune_string = this_tune->name; 22750 } 22751 22752 aarch64_asm_output_variant_pcs (stream, fndecl, name); 22753 22754 /* Don't forget the type directive for ELF. */ 22755 ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "function"); 22756 ASM_OUTPUT_LABEL (stream, name); 22757 22758 cfun->machine->label_is_assembled = true; 22759 } 22760 22761 /* Implement PRINT_PATCHABLE_FUNCTION_ENTRY. */ 22762 22763 void 22764 aarch64_print_patchable_function_entry (FILE *file, 22765 unsigned HOST_WIDE_INT patch_area_size, 22766 bool record_p) 22767 { 22768 if (!cfun->machine->label_is_assembled) 22769 { 22770 /* Emit the patching area before the entry label, if any. */ 22771 default_print_patchable_function_entry (file, patch_area_size, 22772 record_p); 22773 return; 22774 } 22775 22776 rtx pa = gen_patchable_area (GEN_INT (patch_area_size), 22777 GEN_INT (record_p)); 22778 basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; 22779 22780 if (!aarch64_bti_enabled () 22781 || cgraph_node::get (cfun->decl)->only_called_directly_p ()) 22782 { 22783 /* Emit the patchable_area at the beginning of the function. */ 22784 rtx_insn *insn = emit_insn_before (pa, BB_HEAD (bb)); 22785 INSN_ADDRESSES_NEW (insn, -1); 22786 return; 22787 } 22788 22789 rtx_insn *insn = next_real_nondebug_insn (get_insns ()); 22790 if (!insn 22791 || !INSN_P (insn) 22792 || GET_CODE (PATTERN (insn)) != UNSPEC_VOLATILE 22793 || XINT (PATTERN (insn), 1) != UNSPECV_BTI_C) 22794 { 22795 /* Emit a BTI_C. */ 22796 insn = emit_insn_before (gen_bti_c (), BB_HEAD (bb)); 22797 } 22798 22799 /* Emit the patchable_area after BTI_C. */ 22800 insn = emit_insn_after (pa, insn); 22801 INSN_ADDRESSES_NEW (insn, -1); 22802 } 22803 22804 /* Output patchable area. */ 22805 22806 void 22807 aarch64_output_patchable_area (unsigned int patch_area_size, bool record_p) 22808 { 22809 default_print_patchable_function_entry (asm_out_file, patch_area_size, 22810 record_p); 22811 } 22812 22813 /* Implement ASM_OUTPUT_DEF_FROM_DECLS. Output .variant_pcs for aliases. */ 22814 22815 void 22816 aarch64_asm_output_alias (FILE *stream, const tree decl, const tree target) 22817 { 22818 const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); 22819 const char *value = IDENTIFIER_POINTER (target); 22820 aarch64_asm_output_variant_pcs (stream, decl, name); 22821 ASM_OUTPUT_DEF (stream, name, value); 22822 } 22823 22824 /* Implement ASM_OUTPUT_EXTERNAL. Output .variant_pcs for undefined 22825 function symbol references. */ 22826 22827 void 22828 aarch64_asm_output_external (FILE *stream, tree decl, const char* name) 22829 { 22830 default_elf_asm_output_external (stream, decl, name); 22831 aarch64_asm_output_variant_pcs (stream, decl, name); 22832 } 22833 22834 /* Triggered after a .cfi_startproc directive is emitted into the assembly file. 22835 Used to output the .cfi_b_key_frame directive when signing the current 22836 function with the B key. */ 22837 22838 void 22839 aarch64_post_cfi_startproc (FILE *f, tree ignored ATTRIBUTE_UNUSED) 22840 { 22841 if (cfun->machine->frame.laid_out && aarch64_return_address_signing_enabled () 22842 && aarch64_ra_sign_key == AARCH64_KEY_B) 22843 asm_fprintf (f, "\t.cfi_b_key_frame\n"); 22844 } 22845 22846 /* Implements TARGET_ASM_FILE_START. Output the assembly header. */ 22847 22848 static void 22849 aarch64_start_file (void) 22850 { 22851 struct cl_target_option *default_options 22852 = TREE_TARGET_OPTION (target_option_default_node); 22853 22854 const struct processor *default_arch 22855 = aarch64_get_arch (default_options->x_explicit_arch); 22856 uint64_t default_isa_flags = default_options->x_aarch64_isa_flags; 22857 std::string extension 22858 = aarch64_get_extension_string_for_isa_flags (default_isa_flags, 22859 default_arch->flags); 22860 22861 aarch64_last_printed_arch_string = default_arch->name + extension; 22862 aarch64_last_printed_tune_string = ""; 22863 asm_fprintf (asm_out_file, "\t.arch %s\n", 22864 aarch64_last_printed_arch_string.c_str ()); 22865 22866 default_file_start (); 22867 } 22868 22869 /* Emit load exclusive. */ 22870 22871 static void 22872 aarch64_emit_load_exclusive (machine_mode mode, rtx rval, 22873 rtx mem, rtx model_rtx) 22874 { 22875 if (mode == TImode) 22876 emit_insn (gen_aarch64_load_exclusive_pair (gen_lowpart (DImode, rval), 22877 gen_highpart (DImode, rval), 22878 mem, model_rtx)); 22879 else 22880 emit_insn (gen_aarch64_load_exclusive (mode, rval, mem, model_rtx)); 22881 } 22882 22883 /* Emit store exclusive. */ 22884 22885 static void 22886 aarch64_emit_store_exclusive (machine_mode mode, rtx bval, 22887 rtx mem, rtx rval, rtx model_rtx) 22888 { 22889 if (mode == TImode) 22890 emit_insn (gen_aarch64_store_exclusive_pair 22891 (bval, mem, operand_subword (rval, 0, 0, TImode), 22892 operand_subword (rval, 1, 0, TImode), model_rtx)); 22893 else 22894 emit_insn (gen_aarch64_store_exclusive (mode, bval, mem, rval, model_rtx)); 22895 } 22896 22897 /* Mark the previous jump instruction as unlikely. */ 22898 22899 static void 22900 aarch64_emit_unlikely_jump (rtx insn) 22901 { 22902 rtx_insn *jump = emit_jump_insn (insn); 22903 add_reg_br_prob_note (jump, profile_probability::very_unlikely ()); 22904 } 22905 22906 /* We store the names of the various atomic helpers in a 5x5 array. 22907 Return the libcall function given MODE, MODEL and NAMES. */ 22908 22909 rtx 22910 aarch64_atomic_ool_func(machine_mode mode, rtx model_rtx, 22911 const atomic_ool_names *names) 22912 { 22913 memmodel model = memmodel_from_int (INTVAL (model_rtx)); 22914 int mode_idx, model_idx; 22915 22916 switch (mode) 22917 { 22918 case E_QImode: 22919 mode_idx = 0; 22920 break; 22921 case E_HImode: 22922 mode_idx = 1; 22923 break; 22924 case E_SImode: 22925 mode_idx = 2; 22926 break; 22927 case E_DImode: 22928 mode_idx = 3; 22929 break; 22930 case E_TImode: 22931 mode_idx = 4; 22932 break; 22933 default: 22934 gcc_unreachable (); 22935 } 22936 22937 switch (model) 22938 { 22939 case MEMMODEL_RELAXED: 22940 model_idx = 0; 22941 break; 22942 case MEMMODEL_CONSUME: 22943 case MEMMODEL_ACQUIRE: 22944 model_idx = 1; 22945 break; 22946 case MEMMODEL_RELEASE: 22947 model_idx = 2; 22948 break; 22949 case MEMMODEL_ACQ_REL: 22950 case MEMMODEL_SEQ_CST: 22951 model_idx = 3; 22952 break; 22953 case MEMMODEL_SYNC_ACQUIRE: 22954 case MEMMODEL_SYNC_RELEASE: 22955 case MEMMODEL_SYNC_SEQ_CST: 22956 model_idx = 4; 22957 break; 22958 default: 22959 gcc_unreachable (); 22960 } 22961 22962 return init_one_libfunc_visibility (names->str[mode_idx][model_idx], 22963 VISIBILITY_HIDDEN); 22964 } 22965 22966 #define DEF0(B, N) \ 22967 { "__aarch64_" #B #N "_relax", \ 22968 "__aarch64_" #B #N "_acq", \ 22969 "__aarch64_" #B #N "_rel", \ 22970 "__aarch64_" #B #N "_acq_rel", \ 22971 "__aarch64_" #B #N "_sync" } 22972 22973 #define DEF4(B) DEF0(B, 1), DEF0(B, 2), DEF0(B, 4), DEF0(B, 8), \ 22974 { NULL, NULL, NULL, NULL } 22975 #define DEF5(B) DEF0(B, 1), DEF0(B, 2), DEF0(B, 4), DEF0(B, 8), DEF0(B, 16) 22976 22977 static const atomic_ool_names aarch64_ool_cas_names = { { DEF5(cas) } }; 22978 const atomic_ool_names aarch64_ool_swp_names = { { DEF4(swp) } }; 22979 const atomic_ool_names aarch64_ool_ldadd_names = { { DEF4(ldadd) } }; 22980 const atomic_ool_names aarch64_ool_ldset_names = { { DEF4(ldset) } }; 22981 const atomic_ool_names aarch64_ool_ldclr_names = { { DEF4(ldclr) } }; 22982 const atomic_ool_names aarch64_ool_ldeor_names = { { DEF4(ldeor) } }; 22983 22984 #undef DEF0 22985 #undef DEF4 22986 #undef DEF5 22987 22988 /* Expand a compare and swap pattern. */ 22989 22990 void 22991 aarch64_expand_compare_and_swap (rtx operands[]) 22992 { 22993 rtx bval, rval, mem, oldval, newval, is_weak, mod_s, mod_f, x, cc_reg; 22994 machine_mode mode, r_mode; 22995 22996 bval = operands[0]; 22997 rval = operands[1]; 22998 mem = operands[2]; 22999 oldval = operands[3]; 23000 newval = operands[4]; 23001 is_weak = operands[5]; 23002 mod_s = operands[6]; 23003 mod_f = operands[7]; 23004 mode = GET_MODE (mem); 23005 23006 /* Normally the succ memory model must be stronger than fail, but in the 23007 unlikely event of fail being ACQUIRE and succ being RELEASE we need to 23008 promote succ to ACQ_REL so that we don't lose the acquire semantics. */ 23009 if (is_mm_acquire (memmodel_from_int (INTVAL (mod_f))) 23010 && is_mm_release (memmodel_from_int (INTVAL (mod_s)))) 23011 mod_s = GEN_INT (MEMMODEL_ACQ_REL); 23012 23013 r_mode = mode; 23014 if (mode == QImode || mode == HImode) 23015 { 23016 r_mode = SImode; 23017 rval = gen_reg_rtx (r_mode); 23018 } 23019 23020 if (TARGET_LSE) 23021 { 23022 /* The CAS insn requires oldval and rval overlap, but we need to 23023 have a copy of oldval saved across the operation to tell if 23024 the operation is successful. */ 23025 if (reg_overlap_mentioned_p (rval, oldval)) 23026 rval = copy_to_mode_reg (r_mode, oldval); 23027 else 23028 emit_move_insn (rval, gen_lowpart (r_mode, oldval)); 23029 if (mode == TImode) 23030 newval = force_reg (mode, newval); 23031 23032 emit_insn (gen_aarch64_compare_and_swap_lse (mode, rval, mem, 23033 newval, mod_s)); 23034 cc_reg = aarch64_gen_compare_reg_maybe_ze (NE, rval, oldval, mode); 23035 } 23036 else if (TARGET_OUTLINE_ATOMICS) 23037 { 23038 /* Oldval must satisfy compare afterward. */ 23039 if (!aarch64_plus_operand (oldval, mode)) 23040 oldval = force_reg (mode, oldval); 23041 rtx func = aarch64_atomic_ool_func (mode, mod_s, &aarch64_ool_cas_names); 23042 rval = emit_library_call_value (func, NULL_RTX, LCT_NORMAL, r_mode, 23043 oldval, mode, newval, mode, 23044 XEXP (mem, 0), Pmode); 23045 cc_reg = aarch64_gen_compare_reg_maybe_ze (NE, rval, oldval, mode); 23046 } 23047 else 23048 { 23049 /* The oldval predicate varies by mode. Test it and force to reg. */ 23050 insn_code code = code_for_aarch64_compare_and_swap (mode); 23051 if (!insn_data[code].operand[2].predicate (oldval, mode)) 23052 oldval = force_reg (mode, oldval); 23053 23054 emit_insn (GEN_FCN (code) (rval, mem, oldval, newval, 23055 is_weak, mod_s, mod_f)); 23056 cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); 23057 } 23058 23059 if (r_mode != mode) 23060 rval = gen_lowpart (mode, rval); 23061 emit_move_insn (operands[1], rval); 23062 23063 x = gen_rtx_EQ (SImode, cc_reg, const0_rtx); 23064 emit_insn (gen_rtx_SET (bval, x)); 23065 } 23066 23067 /* Emit a barrier, that is appropriate for memory model MODEL, at the end of a 23068 sequence implementing an atomic operation. */ 23069 23070 static void 23071 aarch64_emit_post_barrier (enum memmodel model) 23072 { 23073 const enum memmodel base_model = memmodel_base (model); 23074 23075 if (is_mm_sync (model) 23076 && (base_model == MEMMODEL_ACQUIRE 23077 || base_model == MEMMODEL_ACQ_REL 23078 || base_model == MEMMODEL_SEQ_CST)) 23079 { 23080 emit_insn (gen_mem_thread_fence (GEN_INT (MEMMODEL_SEQ_CST))); 23081 } 23082 } 23083 23084 /* Split a compare and swap pattern. */ 23085 23086 void 23087 aarch64_split_compare_and_swap (rtx operands[]) 23088 { 23089 /* Split after prolog/epilog to avoid interactions with shrinkwrapping. */ 23090 gcc_assert (epilogue_completed); 23091 23092 rtx rval, mem, oldval, newval, scratch, x, model_rtx; 23093 machine_mode mode; 23094 bool is_weak; 23095 rtx_code_label *label1, *label2; 23096 enum memmodel model; 23097 23098 rval = operands[0]; 23099 mem = operands[1]; 23100 oldval = operands[2]; 23101 newval = operands[3]; 23102 is_weak = (operands[4] != const0_rtx); 23103 model_rtx = operands[5]; 23104 scratch = operands[7]; 23105 mode = GET_MODE (mem); 23106 model = memmodel_from_int (INTVAL (model_rtx)); 23107 23108 /* When OLDVAL is zero and we want the strong version we can emit a tighter 23109 loop: 23110 .label1: 23111 LD[A]XR rval, [mem] 23112 CBNZ rval, .label2 23113 ST[L]XR scratch, newval, [mem] 23114 CBNZ scratch, .label1 23115 .label2: 23116 CMP rval, 0. */ 23117 bool strong_zero_p = (!is_weak && !aarch64_track_speculation && 23118 oldval == const0_rtx && mode != TImode); 23119 23120 label1 = NULL; 23121 if (!is_weak) 23122 { 23123 label1 = gen_label_rtx (); 23124 emit_label (label1); 23125 } 23126 label2 = gen_label_rtx (); 23127 23128 /* The initial load can be relaxed for a __sync operation since a final 23129 barrier will be emitted to stop code hoisting. */ 23130 if (is_mm_sync (model)) 23131 aarch64_emit_load_exclusive (mode, rval, mem, GEN_INT (MEMMODEL_RELAXED)); 23132 else 23133 aarch64_emit_load_exclusive (mode, rval, mem, model_rtx); 23134 23135 if (strong_zero_p) 23136 x = gen_rtx_NE (VOIDmode, rval, const0_rtx); 23137 else 23138 { 23139 rtx cc_reg = aarch64_gen_compare_reg_maybe_ze (NE, rval, oldval, mode); 23140 x = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx); 23141 } 23142 x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, 23143 gen_rtx_LABEL_REF (Pmode, label2), pc_rtx); 23144 aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x)); 23145 23146 aarch64_emit_store_exclusive (mode, scratch, mem, newval, model_rtx); 23147 23148 if (!is_weak) 23149 { 23150 if (aarch64_track_speculation) 23151 { 23152 /* Emit an explicit compare instruction, so that we can correctly 23153 track the condition codes. */ 23154 rtx cc_reg = aarch64_gen_compare_reg (NE, scratch, const0_rtx); 23155 x = gen_rtx_NE (GET_MODE (cc_reg), cc_reg, const0_rtx); 23156 } 23157 else 23158 x = gen_rtx_NE (VOIDmode, scratch, const0_rtx); 23159 23160 x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, 23161 gen_rtx_LABEL_REF (Pmode, label1), pc_rtx); 23162 aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x)); 23163 } 23164 else 23165 aarch64_gen_compare_reg (NE, scratch, const0_rtx); 23166 23167 emit_label (label2); 23168 23169 /* If we used a CBNZ in the exchange loop emit an explicit compare with RVAL 23170 to set the condition flags. If this is not used it will be removed by 23171 later passes. */ 23172 if (strong_zero_p) 23173 aarch64_gen_compare_reg (NE, rval, const0_rtx); 23174 23175 /* Emit any final barrier needed for a __sync operation. */ 23176 if (is_mm_sync (model)) 23177 aarch64_emit_post_barrier (model); 23178 } 23179 23180 /* Split an atomic operation. */ 23181 23182 void 23183 aarch64_split_atomic_op (enum rtx_code code, rtx old_out, rtx new_out, rtx mem, 23184 rtx value, rtx model_rtx, rtx cond) 23185 { 23186 /* Split after prolog/epilog to avoid interactions with shrinkwrapping. */ 23187 gcc_assert (epilogue_completed); 23188 23189 machine_mode mode = GET_MODE (mem); 23190 machine_mode wmode = (mode == DImode ? DImode : SImode); 23191 const enum memmodel model = memmodel_from_int (INTVAL (model_rtx)); 23192 const bool is_sync = is_mm_sync (model); 23193 rtx_code_label *label; 23194 rtx x; 23195 23196 /* Split the atomic operation into a sequence. */ 23197 label = gen_label_rtx (); 23198 emit_label (label); 23199 23200 if (new_out) 23201 new_out = gen_lowpart (wmode, new_out); 23202 if (old_out) 23203 old_out = gen_lowpart (wmode, old_out); 23204 else 23205 old_out = new_out; 23206 value = simplify_gen_subreg (wmode, value, mode, 0); 23207 23208 /* The initial load can be relaxed for a __sync operation since a final 23209 barrier will be emitted to stop code hoisting. */ 23210 if (is_sync) 23211 aarch64_emit_load_exclusive (mode, old_out, mem, 23212 GEN_INT (MEMMODEL_RELAXED)); 23213 else 23214 aarch64_emit_load_exclusive (mode, old_out, mem, model_rtx); 23215 23216 switch (code) 23217 { 23218 case SET: 23219 new_out = value; 23220 break; 23221 23222 case NOT: 23223 x = gen_rtx_AND (wmode, old_out, value); 23224 emit_insn (gen_rtx_SET (new_out, x)); 23225 x = gen_rtx_NOT (wmode, new_out); 23226 emit_insn (gen_rtx_SET (new_out, x)); 23227 break; 23228 23229 case MINUS: 23230 if (CONST_INT_P (value)) 23231 { 23232 value = GEN_INT (-UINTVAL (value)); 23233 code = PLUS; 23234 } 23235 /* Fall through. */ 23236 23237 default: 23238 x = gen_rtx_fmt_ee (code, wmode, old_out, value); 23239 emit_insn (gen_rtx_SET (new_out, x)); 23240 break; 23241 } 23242 23243 aarch64_emit_store_exclusive (mode, cond, mem, 23244 gen_lowpart (mode, new_out), model_rtx); 23245 23246 if (aarch64_track_speculation) 23247 { 23248 /* Emit an explicit compare instruction, so that we can correctly 23249 track the condition codes. */ 23250 rtx cc_reg = aarch64_gen_compare_reg (NE, cond, const0_rtx); 23251 x = gen_rtx_NE (GET_MODE (cc_reg), cc_reg, const0_rtx); 23252 } 23253 else 23254 x = gen_rtx_NE (VOIDmode, cond, const0_rtx); 23255 23256 x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, 23257 gen_rtx_LABEL_REF (Pmode, label), pc_rtx); 23258 aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x)); 23259 23260 /* Emit any final barrier needed for a __sync operation. */ 23261 if (is_sync) 23262 aarch64_emit_post_barrier (model); 23263 } 23264 23265 static void 23266 aarch64_init_libfuncs (void) 23267 { 23268 /* Half-precision float operations. The compiler handles all operations 23269 with NULL libfuncs by converting to SFmode. */ 23270 23271 /* Conversions. */ 23272 set_conv_libfunc (trunc_optab, HFmode, SFmode, "__gnu_f2h_ieee"); 23273 set_conv_libfunc (sext_optab, SFmode, HFmode, "__gnu_h2f_ieee"); 23274 23275 /* Arithmetic. */ 23276 set_optab_libfunc (add_optab, HFmode, NULL); 23277 set_optab_libfunc (sdiv_optab, HFmode, NULL); 23278 set_optab_libfunc (smul_optab, HFmode, NULL); 23279 set_optab_libfunc (neg_optab, HFmode, NULL); 23280 set_optab_libfunc (sub_optab, HFmode, NULL); 23281 23282 /* Comparisons. */ 23283 set_optab_libfunc (eq_optab, HFmode, NULL); 23284 set_optab_libfunc (ne_optab, HFmode, NULL); 23285 set_optab_libfunc (lt_optab, HFmode, NULL); 23286 set_optab_libfunc (le_optab, HFmode, NULL); 23287 set_optab_libfunc (ge_optab, HFmode, NULL); 23288 set_optab_libfunc (gt_optab, HFmode, NULL); 23289 set_optab_libfunc (unord_optab, HFmode, NULL); 23290 } 23291 23292 /* Target hook for c_mode_for_suffix. */ 23293 static machine_mode 23294 aarch64_c_mode_for_suffix (char suffix) 23295 { 23296 if (suffix == 'q') 23297 return TFmode; 23298 23299 return VOIDmode; 23300 } 23301 23302 /* We can only represent floating point constants which will fit in 23303 "quarter-precision" values. These values are characterised by 23304 a sign bit, a 4-bit mantissa and a 3-bit exponent. And are given 23305 by: 23306 23307 (-1)^s * (n/16) * 2^r 23308 23309 Where: 23310 's' is the sign bit. 23311 'n' is an integer in the range 16 <= n <= 31. 23312 'r' is an integer in the range -3 <= r <= 4. */ 23313 23314 /* Return true iff X can be represented by a quarter-precision 23315 floating point immediate operand X. Note, we cannot represent 0.0. */ 23316 bool 23317 aarch64_float_const_representable_p (rtx x) 23318 { 23319 /* This represents our current view of how many bits 23320 make up the mantissa. */ 23321 int point_pos = 2 * HOST_BITS_PER_WIDE_INT - 1; 23322 int exponent; 23323 unsigned HOST_WIDE_INT mantissa, mask; 23324 REAL_VALUE_TYPE r, m; 23325 bool fail; 23326 23327 x = unwrap_const_vec_duplicate (x); 23328 if (!CONST_DOUBLE_P (x)) 23329 return false; 23330 23331 if (GET_MODE (x) == VOIDmode 23332 || (GET_MODE (x) == HFmode && !TARGET_FP_F16INST)) 23333 return false; 23334 23335 r = *CONST_DOUBLE_REAL_VALUE (x); 23336 23337 /* We cannot represent infinities, NaNs or +/-zero. We won't 23338 know if we have +zero until we analyse the mantissa, but we 23339 can reject the other invalid values. */ 23340 if (REAL_VALUE_ISINF (r) || REAL_VALUE_ISNAN (r) 23341 || REAL_VALUE_MINUS_ZERO (r)) 23342 return false; 23343 23344 /* Extract exponent. */ 23345 r = real_value_abs (&r); 23346 exponent = REAL_EXP (&r); 23347 23348 /* For the mantissa, we expand into two HOST_WIDE_INTS, apart from the 23349 highest (sign) bit, with a fixed binary point at bit point_pos. 23350 m1 holds the low part of the mantissa, m2 the high part. 23351 WARNING: If we ever have a representation using more than 2 * H_W_I - 1 23352 bits for the mantissa, this can fail (low bits will be lost). */ 23353 real_ldexp (&m, &r, point_pos - exponent); 23354 wide_int w = real_to_integer (&m, &fail, HOST_BITS_PER_WIDE_INT * 2); 23355 23356 /* If the low part of the mantissa has bits set we cannot represent 23357 the value. */ 23358 if (w.ulow () != 0) 23359 return false; 23360 /* We have rejected the lower HOST_WIDE_INT, so update our 23361 understanding of how many bits lie in the mantissa and 23362 look only at the high HOST_WIDE_INT. */ 23363 mantissa = w.elt (1); 23364 point_pos -= HOST_BITS_PER_WIDE_INT; 23365 23366 /* We can only represent values with a mantissa of the form 1.xxxx. */ 23367 mask = ((unsigned HOST_WIDE_INT)1 << (point_pos - 5)) - 1; 23368 if ((mantissa & mask) != 0) 23369 return false; 23370 23371 /* Having filtered unrepresentable values, we may now remove all 23372 but the highest 5 bits. */ 23373 mantissa >>= point_pos - 5; 23374 23375 /* We cannot represent the value 0.0, so reject it. This is handled 23376 elsewhere. */ 23377 if (mantissa == 0) 23378 return false; 23379 23380 /* Then, as bit 4 is always set, we can mask it off, leaving 23381 the mantissa in the range [0, 15]. */ 23382 mantissa &= ~(1 << 4); 23383 gcc_assert (mantissa <= 15); 23384 23385 /* GCC internally does not use IEEE754-like encoding (where normalized 23386 significands are in the range [1, 2). GCC uses [0.5, 1) (see real.cc). 23387 Our mantissa values are shifted 4 places to the left relative to 23388 normalized IEEE754 so we must modify the exponent returned by REAL_EXP 23389 by 5 places to correct for GCC's representation. */ 23390 exponent = 5 - exponent; 23391 23392 return (exponent >= 0 && exponent <= 7); 23393 } 23394 23395 /* Returns the string with the instruction for AdvSIMD MOVI, MVNI, ORR or BIC 23396 immediate with a CONST_VECTOR of MODE and WIDTH. WHICH selects whether to 23397 output MOVI/MVNI, ORR or BIC immediate. */ 23398 char* 23399 aarch64_output_simd_mov_immediate (rtx const_vector, unsigned width, 23400 enum simd_immediate_check which) 23401 { 23402 bool is_valid; 23403 static char templ[40]; 23404 const char *mnemonic; 23405 const char *shift_op; 23406 unsigned int lane_count = 0; 23407 char element_char; 23408 23409 struct simd_immediate_info info; 23410 23411 /* This will return true to show const_vector is legal for use as either 23412 a AdvSIMD MOVI instruction (or, implicitly, MVNI), ORR or BIC immediate. 23413 It will also update INFO to show how the immediate should be generated. 23414 WHICH selects whether to check for MOVI/MVNI, ORR or BIC. */ 23415 is_valid = aarch64_simd_valid_immediate (const_vector, &info, which); 23416 gcc_assert (is_valid); 23417 23418 element_char = sizetochar (GET_MODE_BITSIZE (info.elt_mode)); 23419 lane_count = width / GET_MODE_BITSIZE (info.elt_mode); 23420 23421 if (GET_MODE_CLASS (info.elt_mode) == MODE_FLOAT) 23422 { 23423 gcc_assert (info.insn == simd_immediate_info::MOV 23424 && info.u.mov.shift == 0); 23425 /* For FP zero change it to a CONST_INT 0 and use the integer SIMD 23426 move immediate path. */ 23427 if (aarch64_float_const_zero_rtx_p (info.u.mov.value)) 23428 info.u.mov.value = GEN_INT (0); 23429 else 23430 { 23431 const unsigned int buf_size = 20; 23432 char float_buf[buf_size] = {'\0'}; 23433 real_to_decimal_for_mode (float_buf, 23434 CONST_DOUBLE_REAL_VALUE (info.u.mov.value), 23435 buf_size, buf_size, 1, info.elt_mode); 23436 23437 if (lane_count == 1) 23438 snprintf (templ, sizeof (templ), "fmov\t%%d0, %s", float_buf); 23439 else 23440 snprintf (templ, sizeof (templ), "fmov\t%%0.%d%c, %s", 23441 lane_count, element_char, float_buf); 23442 return templ; 23443 } 23444 } 23445 23446 gcc_assert (CONST_INT_P (info.u.mov.value)); 23447 23448 if (which == AARCH64_CHECK_MOV) 23449 { 23450 mnemonic = info.insn == simd_immediate_info::MVN ? "mvni" : "movi"; 23451 shift_op = (info.u.mov.modifier == simd_immediate_info::MSL 23452 ? "msl" : "lsl"); 23453 if (lane_count == 1) 23454 snprintf (templ, sizeof (templ), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX, 23455 mnemonic, UINTVAL (info.u.mov.value)); 23456 else if (info.u.mov.shift) 23457 snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " 23458 HOST_WIDE_INT_PRINT_HEX ", %s %d", mnemonic, lane_count, 23459 element_char, UINTVAL (info.u.mov.value), shift_op, 23460 info.u.mov.shift); 23461 else 23462 snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " 23463 HOST_WIDE_INT_PRINT_HEX, mnemonic, lane_count, 23464 element_char, UINTVAL (info.u.mov.value)); 23465 } 23466 else 23467 { 23468 /* For AARCH64_CHECK_BIC and AARCH64_CHECK_ORR. */ 23469 mnemonic = info.insn == simd_immediate_info::MVN ? "bic" : "orr"; 23470 if (info.u.mov.shift) 23471 snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #" 23472 HOST_WIDE_INT_PRINT_DEC ", %s #%d", mnemonic, lane_count, 23473 element_char, UINTVAL (info.u.mov.value), "lsl", 23474 info.u.mov.shift); 23475 else 23476 snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #" 23477 HOST_WIDE_INT_PRINT_DEC, mnemonic, lane_count, 23478 element_char, UINTVAL (info.u.mov.value)); 23479 } 23480 return templ; 23481 } 23482 23483 char* 23484 aarch64_output_scalar_simd_mov_immediate (rtx immediate, scalar_int_mode mode) 23485 { 23486 23487 /* If a floating point number was passed and we desire to use it in an 23488 integer mode do the conversion to integer. */ 23489 if (CONST_DOUBLE_P (immediate) && GET_MODE_CLASS (mode) == MODE_INT) 23490 { 23491 unsigned HOST_WIDE_INT ival; 23492 if (!aarch64_reinterpret_float_as_int (immediate, &ival)) 23493 gcc_unreachable (); 23494 immediate = gen_int_mode (ival, mode); 23495 } 23496 23497 machine_mode vmode; 23498 /* use a 64 bit mode for everything except for DI/DF mode, where we use 23499 a 128 bit vector mode. */ 23500 int width = GET_MODE_BITSIZE (mode) == 64 ? 128 : 64; 23501 23502 vmode = aarch64_simd_container_mode (mode, width); 23503 rtx v_op = aarch64_simd_gen_const_vector_dup (vmode, INTVAL (immediate)); 23504 return aarch64_output_simd_mov_immediate (v_op, width); 23505 } 23506 23507 /* Return the output string to use for moving immediate CONST_VECTOR 23508 into an SVE register. */ 23509 23510 char * 23511 aarch64_output_sve_mov_immediate (rtx const_vector) 23512 { 23513 static char templ[40]; 23514 struct simd_immediate_info info; 23515 char element_char; 23516 23517 bool is_valid = aarch64_simd_valid_immediate (const_vector, &info); 23518 gcc_assert (is_valid); 23519 23520 element_char = sizetochar (GET_MODE_BITSIZE (info.elt_mode)); 23521 23522 machine_mode vec_mode = GET_MODE (const_vector); 23523 if (aarch64_sve_pred_mode_p (vec_mode)) 23524 { 23525 static char buf[sizeof ("ptrue\t%0.N, vlNNNNN")]; 23526 if (info.insn == simd_immediate_info::MOV) 23527 { 23528 gcc_assert (info.u.mov.value == const0_rtx); 23529 snprintf (buf, sizeof (buf), "pfalse\t%%0.b"); 23530 } 23531 else 23532 { 23533 gcc_assert (info.insn == simd_immediate_info::PTRUE); 23534 unsigned int total_bytes; 23535 if (info.u.pattern == AARCH64_SV_ALL 23536 && BYTES_PER_SVE_VECTOR.is_constant (&total_bytes)) 23537 snprintf (buf, sizeof (buf), "ptrue\t%%0.%c, vl%d", element_char, 23538 total_bytes / GET_MODE_SIZE (info.elt_mode)); 23539 else 23540 snprintf (buf, sizeof (buf), "ptrue\t%%0.%c, %s", element_char, 23541 svpattern_token (info.u.pattern)); 23542 } 23543 return buf; 23544 } 23545 23546 if (info.insn == simd_immediate_info::INDEX) 23547 { 23548 snprintf (templ, sizeof (templ), "index\t%%0.%c, #" 23549 HOST_WIDE_INT_PRINT_DEC ", #" HOST_WIDE_INT_PRINT_DEC, 23550 element_char, INTVAL (info.u.index.base), 23551 INTVAL (info.u.index.step)); 23552 return templ; 23553 } 23554 23555 if (GET_MODE_CLASS (info.elt_mode) == MODE_FLOAT) 23556 { 23557 if (aarch64_float_const_zero_rtx_p (info.u.mov.value)) 23558 info.u.mov.value = GEN_INT (0); 23559 else 23560 { 23561 const int buf_size = 20; 23562 char float_buf[buf_size] = {}; 23563 real_to_decimal_for_mode (float_buf, 23564 CONST_DOUBLE_REAL_VALUE (info.u.mov.value), 23565 buf_size, buf_size, 1, info.elt_mode); 23566 23567 snprintf (templ, sizeof (templ), "fmov\t%%0.%c, #%s", 23568 element_char, float_buf); 23569 return templ; 23570 } 23571 } 23572 23573 snprintf (templ, sizeof (templ), "mov\t%%0.%c, #" HOST_WIDE_INT_PRINT_DEC, 23574 element_char, INTVAL (info.u.mov.value)); 23575 return templ; 23576 } 23577 23578 /* Return the asm template for a PTRUES. CONST_UNSPEC is the 23579 aarch64_sve_ptrue_svpattern_immediate that describes the predicate 23580 pattern. */ 23581 23582 char * 23583 aarch64_output_sve_ptrues (rtx const_unspec) 23584 { 23585 static char templ[40]; 23586 23587 struct simd_immediate_info info; 23588 bool is_valid = aarch64_simd_valid_immediate (const_unspec, &info); 23589 gcc_assert (is_valid && info.insn == simd_immediate_info::PTRUE); 23590 23591 char element_char = sizetochar (GET_MODE_BITSIZE (info.elt_mode)); 23592 snprintf (templ, sizeof (templ), "ptrues\t%%0.%c, %s", element_char, 23593 svpattern_token (info.u.pattern)); 23594 return templ; 23595 } 23596 23597 /* Split operands into moves from op[1] + op[2] into op[0]. */ 23598 23599 void 23600 aarch64_split_combinev16qi (rtx operands[3]) 23601 { 23602 unsigned int dest = REGNO (operands[0]); 23603 unsigned int src1 = REGNO (operands[1]); 23604 unsigned int src2 = REGNO (operands[2]); 23605 machine_mode halfmode = GET_MODE (operands[1]); 23606 unsigned int halfregs = REG_NREGS (operands[1]); 23607 rtx destlo, desthi; 23608 23609 gcc_assert (halfmode == V16QImode); 23610 23611 if (src1 == dest && src2 == dest + halfregs) 23612 { 23613 /* No-op move. Can't split to nothing; emit something. */ 23614 emit_note (NOTE_INSN_DELETED); 23615 return; 23616 } 23617 23618 /* Preserve register attributes for variable tracking. */ 23619 destlo = gen_rtx_REG_offset (operands[0], halfmode, dest, 0); 23620 desthi = gen_rtx_REG_offset (operands[0], halfmode, dest + halfregs, 23621 GET_MODE_SIZE (halfmode)); 23622 23623 /* Special case of reversed high/low parts. */ 23624 if (reg_overlap_mentioned_p (operands[2], destlo) 23625 && reg_overlap_mentioned_p (operands[1], desthi)) 23626 { 23627 emit_insn (gen_xorv16qi3 (operands[1], operands[1], operands[2])); 23628 emit_insn (gen_xorv16qi3 (operands[2], operands[1], operands[2])); 23629 emit_insn (gen_xorv16qi3 (operands[1], operands[1], operands[2])); 23630 } 23631 else if (!reg_overlap_mentioned_p (operands[2], destlo)) 23632 { 23633 /* Try to avoid unnecessary moves if part of the result 23634 is in the right place already. */ 23635 if (src1 != dest) 23636 emit_move_insn (destlo, operands[1]); 23637 if (src2 != dest + halfregs) 23638 emit_move_insn (desthi, operands[2]); 23639 } 23640 else 23641 { 23642 if (src2 != dest + halfregs) 23643 emit_move_insn (desthi, operands[2]); 23644 if (src1 != dest) 23645 emit_move_insn (destlo, operands[1]); 23646 } 23647 } 23648 23649 /* vec_perm support. */ 23650 23651 struct expand_vec_perm_d 23652 { 23653 rtx target, op0, op1; 23654 vec_perm_indices perm; 23655 machine_mode vmode; 23656 unsigned int vec_flags; 23657 bool one_vector_p; 23658 bool testing_p; 23659 }; 23660 23661 static bool aarch64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d); 23662 23663 /* Generate a variable permutation. */ 23664 23665 static void 23666 aarch64_expand_vec_perm_1 (rtx target, rtx op0, rtx op1, rtx sel) 23667 { 23668 machine_mode vmode = GET_MODE (target); 23669 bool one_vector_p = rtx_equal_p (op0, op1); 23670 23671 gcc_checking_assert (vmode == V8QImode || vmode == V16QImode); 23672 gcc_checking_assert (GET_MODE (op0) == vmode); 23673 gcc_checking_assert (GET_MODE (op1) == vmode); 23674 gcc_checking_assert (GET_MODE (sel) == vmode); 23675 gcc_checking_assert (TARGET_SIMD); 23676 23677 if (one_vector_p) 23678 { 23679 if (vmode == V8QImode) 23680 { 23681 /* Expand the argument to a V16QI mode by duplicating it. */ 23682 rtx pair = gen_reg_rtx (V16QImode); 23683 emit_insn (gen_aarch64_combinev8qi (pair, op0, op0)); 23684 emit_insn (gen_aarch64_qtbl1v8qi (target, pair, sel)); 23685 } 23686 else 23687 { 23688 emit_insn (gen_aarch64_qtbl1v16qi (target, op0, sel)); 23689 } 23690 } 23691 else 23692 { 23693 rtx pair; 23694 23695 if (vmode == V8QImode) 23696 { 23697 pair = gen_reg_rtx (V16QImode); 23698 emit_insn (gen_aarch64_combinev8qi (pair, op0, op1)); 23699 emit_insn (gen_aarch64_qtbl1v8qi (target, pair, sel)); 23700 } 23701 else 23702 { 23703 pair = gen_reg_rtx (V2x16QImode); 23704 emit_insn (gen_aarch64_combinev16qi (pair, op0, op1)); 23705 emit_insn (gen_aarch64_qtbl2v16qi (target, pair, sel)); 23706 } 23707 } 23708 } 23709 23710 /* Expand a vec_perm with the operands given by TARGET, OP0, OP1 and SEL. 23711 NELT is the number of elements in the vector. */ 23712 23713 void 23714 aarch64_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel, 23715 unsigned int nelt) 23716 { 23717 machine_mode vmode = GET_MODE (target); 23718 bool one_vector_p = rtx_equal_p (op0, op1); 23719 rtx mask; 23720 23721 /* The TBL instruction does not use a modulo index, so we must take care 23722 of that ourselves. */ 23723 mask = aarch64_simd_gen_const_vector_dup (vmode, 23724 one_vector_p ? nelt - 1 : 2 * nelt - 1); 23725 sel = expand_simple_binop (vmode, AND, sel, mask, NULL, 0, OPTAB_LIB_WIDEN); 23726 23727 /* For big-endian, we also need to reverse the index within the vector 23728 (but not which vector). */ 23729 if (BYTES_BIG_ENDIAN) 23730 { 23731 /* If one_vector_p, mask is a vector of (nelt - 1)'s already. */ 23732 if (!one_vector_p) 23733 mask = aarch64_simd_gen_const_vector_dup (vmode, nelt - 1); 23734 sel = expand_simple_binop (vmode, XOR, sel, mask, 23735 NULL, 0, OPTAB_LIB_WIDEN); 23736 } 23737 aarch64_expand_vec_perm_1 (target, op0, op1, sel); 23738 } 23739 23740 /* Generate (set TARGET (unspec [OP0 OP1] CODE)). */ 23741 23742 static void 23743 emit_unspec2 (rtx target, int code, rtx op0, rtx op1) 23744 { 23745 emit_insn (gen_rtx_SET (target, 23746 gen_rtx_UNSPEC (GET_MODE (target), 23747 gen_rtvec (2, op0, op1), code))); 23748 } 23749 23750 /* Expand an SVE vec_perm with the given operands. */ 23751 23752 void 23753 aarch64_expand_sve_vec_perm (rtx target, rtx op0, rtx op1, rtx sel) 23754 { 23755 machine_mode data_mode = GET_MODE (target); 23756 machine_mode sel_mode = GET_MODE (sel); 23757 /* Enforced by the pattern condition. */ 23758 int nunits = GET_MODE_NUNITS (sel_mode).to_constant (); 23759 23760 /* Note: vec_perm indices are supposed to wrap when they go beyond the 23761 size of the two value vectors, i.e. the upper bits of the indices 23762 are effectively ignored. SVE TBL instead produces 0 for any 23763 out-of-range indices, so we need to modulo all the vec_perm indices 23764 to ensure they are all in range. */ 23765 rtx sel_reg = force_reg (sel_mode, sel); 23766 23767 /* Check if the sel only references the first values vector. */ 23768 if (CONST_VECTOR_P (sel) 23769 && aarch64_const_vec_all_in_range_p (sel, 0, nunits - 1)) 23770 { 23771 emit_unspec2 (target, UNSPEC_TBL, op0, sel_reg); 23772 return; 23773 } 23774 23775 /* Check if the two values vectors are the same. */ 23776 if (rtx_equal_p (op0, op1)) 23777 { 23778 rtx max_sel = aarch64_simd_gen_const_vector_dup (sel_mode, nunits - 1); 23779 rtx sel_mod = expand_simple_binop (sel_mode, AND, sel_reg, max_sel, 23780 NULL, 0, OPTAB_DIRECT); 23781 emit_unspec2 (target, UNSPEC_TBL, op0, sel_mod); 23782 return; 23783 } 23784 23785 /* Run TBL on for each value vector and combine the results. */ 23786 23787 rtx res0 = gen_reg_rtx (data_mode); 23788 rtx res1 = gen_reg_rtx (data_mode); 23789 rtx neg_num_elems = aarch64_simd_gen_const_vector_dup (sel_mode, -nunits); 23790 if (!CONST_VECTOR_P (sel) 23791 || !aarch64_const_vec_all_in_range_p (sel, 0, 2 * nunits - 1)) 23792 { 23793 rtx max_sel = aarch64_simd_gen_const_vector_dup (sel_mode, 23794 2 * nunits - 1); 23795 sel_reg = expand_simple_binop (sel_mode, AND, sel_reg, max_sel, 23796 NULL, 0, OPTAB_DIRECT); 23797 } 23798 emit_unspec2 (res0, UNSPEC_TBL, op0, sel_reg); 23799 rtx sel_sub = expand_simple_binop (sel_mode, PLUS, sel_reg, neg_num_elems, 23800 NULL, 0, OPTAB_DIRECT); 23801 emit_unspec2 (res1, UNSPEC_TBL, op1, sel_sub); 23802 if (GET_MODE_CLASS (data_mode) == MODE_VECTOR_INT) 23803 emit_insn (gen_rtx_SET (target, gen_rtx_IOR (data_mode, res0, res1))); 23804 else 23805 emit_unspec2 (target, UNSPEC_IORF, res0, res1); 23806 } 23807 23808 /* Recognize patterns suitable for the TRN instructions. */ 23809 static bool 23810 aarch64_evpc_trn (struct expand_vec_perm_d *d) 23811 { 23812 HOST_WIDE_INT odd; 23813 poly_uint64 nelt = d->perm.length (); 23814 rtx out, in0, in1, x; 23815 machine_mode vmode = d->vmode; 23816 23817 if (GET_MODE_UNIT_SIZE (vmode) > 8) 23818 return false; 23819 23820 /* Note that these are little-endian tests. 23821 We correct for big-endian later. */ 23822 if (!d->perm[0].is_constant (&odd) 23823 || (odd != 0 && odd != 1) 23824 || !d->perm.series_p (0, 2, odd, 2) 23825 || !d->perm.series_p (1, 2, nelt + odd, 2)) 23826 return false; 23827 23828 /* Success! */ 23829 if (d->testing_p) 23830 return true; 23831 23832 in0 = d->op0; 23833 in1 = d->op1; 23834 /* We don't need a big-endian lane correction for SVE; see the comment 23835 at the head of aarch64-sve.md for details. */ 23836 if (BYTES_BIG_ENDIAN && d->vec_flags == VEC_ADVSIMD) 23837 { 23838 x = in0, in0 = in1, in1 = x; 23839 odd = !odd; 23840 } 23841 out = d->target; 23842 23843 emit_set_insn (out, gen_rtx_UNSPEC (vmode, gen_rtvec (2, in0, in1), 23844 odd ? UNSPEC_TRN2 : UNSPEC_TRN1)); 23845 return true; 23846 } 23847 23848 /* Try to re-encode the PERM constant so it combines odd and even elements. 23849 This rewrites constants such as {0, 1, 4, 5}/V4SF to {0, 2}/V2DI. 23850 We retry with this new constant with the full suite of patterns. */ 23851 static bool 23852 aarch64_evpc_reencode (struct expand_vec_perm_d *d) 23853 { 23854 expand_vec_perm_d newd; 23855 unsigned HOST_WIDE_INT nelt; 23856 23857 if (d->vec_flags != VEC_ADVSIMD) 23858 return false; 23859 23860 /* Get the new mode. Always twice the size of the inner 23861 and half the elements. */ 23862 poly_uint64 vec_bits = GET_MODE_BITSIZE (d->vmode); 23863 unsigned int new_elt_bits = GET_MODE_UNIT_BITSIZE (d->vmode) * 2; 23864 auto new_elt_mode = int_mode_for_size (new_elt_bits, false).require (); 23865 machine_mode new_mode = aarch64_simd_container_mode (new_elt_mode, vec_bits); 23866 23867 if (new_mode == word_mode) 23868 return false; 23869 23870 /* to_constant is safe since this routine is specific to Advanced SIMD 23871 vectors. */ 23872 nelt = d->perm.length ().to_constant (); 23873 23874 vec_perm_builder newpermconst; 23875 newpermconst.new_vector (nelt / 2, nelt / 2, 1); 23876 23877 /* Convert the perm constant if we can. Require even, odd as the pairs. */ 23878 for (unsigned int i = 0; i < nelt; i += 2) 23879 { 23880 poly_int64 elt0 = d->perm[i]; 23881 poly_int64 elt1 = d->perm[i + 1]; 23882 poly_int64 newelt; 23883 if (!multiple_p (elt0, 2, &newelt) || maybe_ne (elt0 + 1, elt1)) 23884 return false; 23885 newpermconst.quick_push (newelt.to_constant ()); 23886 } 23887 newpermconst.finalize (); 23888 23889 newd.vmode = new_mode; 23890 newd.vec_flags = VEC_ADVSIMD; 23891 newd.target = d->target ? gen_lowpart (new_mode, d->target) : NULL; 23892 newd.op0 = d->op0 ? gen_lowpart (new_mode, d->op0) : NULL; 23893 newd.op1 = d->op1 ? gen_lowpart (new_mode, d->op1) : NULL; 23894 newd.testing_p = d->testing_p; 23895 newd.one_vector_p = d->one_vector_p; 23896 23897 newd.perm.new_vector (newpermconst, newd.one_vector_p ? 1 : 2, nelt / 2); 23898 return aarch64_expand_vec_perm_const_1 (&newd); 23899 } 23900 23901 /* Recognize patterns suitable for the UZP instructions. */ 23902 static bool 23903 aarch64_evpc_uzp (struct expand_vec_perm_d *d) 23904 { 23905 HOST_WIDE_INT odd; 23906 rtx out, in0, in1, x; 23907 machine_mode vmode = d->vmode; 23908 23909 if (GET_MODE_UNIT_SIZE (vmode) > 8) 23910 return false; 23911 23912 /* Note that these are little-endian tests. 23913 We correct for big-endian later. */ 23914 if (!d->perm[0].is_constant (&odd) 23915 || (odd != 0 && odd != 1) 23916 || !d->perm.series_p (0, 1, odd, 2)) 23917 return false; 23918 23919 /* Success! */ 23920 if (d->testing_p) 23921 return true; 23922 23923 in0 = d->op0; 23924 in1 = d->op1; 23925 /* We don't need a big-endian lane correction for SVE; see the comment 23926 at the head of aarch64-sve.md for details. */ 23927 if (BYTES_BIG_ENDIAN && d->vec_flags == VEC_ADVSIMD) 23928 { 23929 x = in0, in0 = in1, in1 = x; 23930 odd = !odd; 23931 } 23932 out = d->target; 23933 23934 emit_set_insn (out, gen_rtx_UNSPEC (vmode, gen_rtvec (2, in0, in1), 23935 odd ? UNSPEC_UZP2 : UNSPEC_UZP1)); 23936 return true; 23937 } 23938 23939 /* Recognize patterns suitable for the ZIP instructions. */ 23940 static bool 23941 aarch64_evpc_zip (struct expand_vec_perm_d *d) 23942 { 23943 unsigned int high; 23944 poly_uint64 nelt = d->perm.length (); 23945 rtx out, in0, in1, x; 23946 machine_mode vmode = d->vmode; 23947 23948 if (GET_MODE_UNIT_SIZE (vmode) > 8) 23949 return false; 23950 23951 /* Note that these are little-endian tests. 23952 We correct for big-endian later. */ 23953 poly_uint64 first = d->perm[0]; 23954 if ((maybe_ne (first, 0U) && maybe_ne (first * 2, nelt)) 23955 || !d->perm.series_p (0, 2, first, 1) 23956 || !d->perm.series_p (1, 2, first + nelt, 1)) 23957 return false; 23958 high = maybe_ne (first, 0U); 23959 23960 /* Success! */ 23961 if (d->testing_p) 23962 return true; 23963 23964 in0 = d->op0; 23965 in1 = d->op1; 23966 /* We don't need a big-endian lane correction for SVE; see the comment 23967 at the head of aarch64-sve.md for details. */ 23968 if (BYTES_BIG_ENDIAN && d->vec_flags == VEC_ADVSIMD) 23969 { 23970 x = in0, in0 = in1, in1 = x; 23971 high = !high; 23972 } 23973 out = d->target; 23974 23975 emit_set_insn (out, gen_rtx_UNSPEC (vmode, gen_rtvec (2, in0, in1), 23976 high ? UNSPEC_ZIP2 : UNSPEC_ZIP1)); 23977 return true; 23978 } 23979 23980 /* Recognize patterns for the EXT insn. */ 23981 23982 static bool 23983 aarch64_evpc_ext (struct expand_vec_perm_d *d) 23984 { 23985 HOST_WIDE_INT location; 23986 rtx offset; 23987 23988 /* The first element always refers to the first vector. 23989 Check if the extracted indices are increasing by one. */ 23990 if (d->vec_flags == VEC_SVE_PRED 23991 || !d->perm[0].is_constant (&location) 23992 || !d->perm.series_p (0, 1, location, 1)) 23993 return false; 23994 23995 /* Success! */ 23996 if (d->testing_p) 23997 return true; 23998 23999 /* The case where (location == 0) is a no-op for both big- and little-endian, 24000 and is removed by the mid-end at optimization levels -O1 and higher. 24001 24002 We don't need a big-endian lane correction for SVE; see the comment 24003 at the head of aarch64-sve.md for details. */ 24004 if (BYTES_BIG_ENDIAN && location != 0 && d->vec_flags == VEC_ADVSIMD) 24005 { 24006 /* After setup, we want the high elements of the first vector (stored 24007 at the LSB end of the register), and the low elements of the second 24008 vector (stored at the MSB end of the register). So swap. */ 24009 std::swap (d->op0, d->op1); 24010 /* location != 0 (above), so safe to assume (nelt - location) < nelt. 24011 to_constant () is safe since this is restricted to Advanced SIMD 24012 vectors. */ 24013 location = d->perm.length ().to_constant () - location; 24014 } 24015 24016 offset = GEN_INT (location); 24017 emit_set_insn (d->target, 24018 gen_rtx_UNSPEC (d->vmode, 24019 gen_rtvec (3, d->op0, d->op1, offset), 24020 UNSPEC_EXT)); 24021 return true; 24022 } 24023 24024 /* Recognize patterns for the REV{64,32,16} insns, which reverse elements 24025 within each 64-bit, 32-bit or 16-bit granule. */ 24026 24027 static bool 24028 aarch64_evpc_rev_local (struct expand_vec_perm_d *d) 24029 { 24030 HOST_WIDE_INT diff; 24031 unsigned int i, size, unspec; 24032 machine_mode pred_mode; 24033 24034 if (d->vec_flags == VEC_SVE_PRED 24035 || !d->one_vector_p 24036 || !d->perm[0].is_constant (&diff) 24037 || !diff) 24038 return false; 24039 24040 if (d->vec_flags & VEC_SVE_DATA) 24041 size = (diff + 1) * aarch64_sve_container_bits (d->vmode); 24042 else 24043 size = (diff + 1) * GET_MODE_UNIT_BITSIZE (d->vmode); 24044 if (size == 64) 24045 { 24046 unspec = UNSPEC_REV64; 24047 pred_mode = VNx2BImode; 24048 } 24049 else if (size == 32) 24050 { 24051 unspec = UNSPEC_REV32; 24052 pred_mode = VNx4BImode; 24053 } 24054 else if (size == 16) 24055 { 24056 unspec = UNSPEC_REV16; 24057 pred_mode = VNx8BImode; 24058 } 24059 else 24060 return false; 24061 24062 unsigned int step = diff + 1; 24063 for (i = 0; i < step; ++i) 24064 if (!d->perm.series_p (i, step, diff - i, step)) 24065 return false; 24066 24067 /* Success! */ 24068 if (d->testing_p) 24069 return true; 24070 24071 if (d->vec_flags & VEC_SVE_DATA) 24072 { 24073 rtx pred = aarch64_ptrue_reg (pred_mode); 24074 emit_insn (gen_aarch64_sve_revbhw (d->vmode, pred_mode, 24075 d->target, pred, d->op0)); 24076 return true; 24077 } 24078 rtx src = gen_rtx_UNSPEC (d->vmode, gen_rtvec (1, d->op0), unspec); 24079 emit_set_insn (d->target, src); 24080 return true; 24081 } 24082 24083 /* Recognize patterns for the REV insn, which reverses elements within 24084 a full vector. */ 24085 24086 static bool 24087 aarch64_evpc_rev_global (struct expand_vec_perm_d *d) 24088 { 24089 poly_uint64 nelt = d->perm.length (); 24090 24091 if (!d->one_vector_p || d->vec_flags == VEC_ADVSIMD) 24092 return false; 24093 24094 if (!d->perm.series_p (0, 1, nelt - 1, -1)) 24095 return false; 24096 24097 /* Success! */ 24098 if (d->testing_p) 24099 return true; 24100 24101 rtx src = gen_rtx_UNSPEC (d->vmode, gen_rtvec (1, d->op0), UNSPEC_REV); 24102 emit_set_insn (d->target, src); 24103 return true; 24104 } 24105 24106 static bool 24107 aarch64_evpc_dup (struct expand_vec_perm_d *d) 24108 { 24109 rtx out = d->target; 24110 rtx in0; 24111 HOST_WIDE_INT elt; 24112 machine_mode vmode = d->vmode; 24113 rtx lane; 24114 24115 if (d->vec_flags == VEC_SVE_PRED 24116 || d->perm.encoding ().encoded_nelts () != 1 24117 || !d->perm[0].is_constant (&elt)) 24118 return false; 24119 24120 if ((d->vec_flags & VEC_SVE_DATA) 24121 && elt * (aarch64_sve_container_bits (vmode) / 8) >= 64) 24122 return false; 24123 24124 /* Success! */ 24125 if (d->testing_p) 24126 return true; 24127 24128 /* The generic preparation in aarch64_expand_vec_perm_const_1 24129 swaps the operand order and the permute indices if it finds 24130 d->perm[0] to be in the second operand. Thus, we can always 24131 use d->op0 and need not do any extra arithmetic to get the 24132 correct lane number. */ 24133 in0 = d->op0; 24134 lane = GEN_INT (elt); /* The pattern corrects for big-endian. */ 24135 24136 rtx parallel = gen_rtx_PARALLEL (vmode, gen_rtvec (1, lane)); 24137 rtx select = gen_rtx_VEC_SELECT (GET_MODE_INNER (vmode), in0, parallel); 24138 emit_set_insn (out, gen_rtx_VEC_DUPLICATE (vmode, select)); 24139 return true; 24140 } 24141 24142 static bool 24143 aarch64_evpc_tbl (struct expand_vec_perm_d *d) 24144 { 24145 rtx rperm[MAX_COMPILE_TIME_VEC_BYTES], sel; 24146 machine_mode vmode = d->vmode; 24147 24148 /* Make sure that the indices are constant. */ 24149 unsigned int encoded_nelts = d->perm.encoding ().encoded_nelts (); 24150 for (unsigned int i = 0; i < encoded_nelts; ++i) 24151 if (!d->perm[i].is_constant ()) 24152 return false; 24153 24154 if (d->testing_p) 24155 return true; 24156 24157 /* Generic code will try constant permutation twice. Once with the 24158 original mode and again with the elements lowered to QImode. 24159 So wait and don't do the selector expansion ourselves. */ 24160 if (vmode != V8QImode && vmode != V16QImode) 24161 return false; 24162 24163 /* to_constant is safe since this routine is specific to Advanced SIMD 24164 vectors. */ 24165 unsigned int nelt = d->perm.length ().to_constant (); 24166 for (unsigned int i = 0; i < nelt; ++i) 24167 /* If big-endian and two vectors we end up with a weird mixed-endian 24168 mode on NEON. Reverse the index within each word but not the word 24169 itself. to_constant is safe because we checked is_constant above. */ 24170 rperm[i] = GEN_INT (BYTES_BIG_ENDIAN 24171 ? d->perm[i].to_constant () ^ (nelt - 1) 24172 : d->perm[i].to_constant ()); 24173 24174 sel = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, rperm)); 24175 sel = force_reg (vmode, sel); 24176 24177 aarch64_expand_vec_perm_1 (d->target, d->op0, d->op1, sel); 24178 return true; 24179 } 24180 24181 /* Try to implement D using an SVE TBL instruction. */ 24182 24183 static bool 24184 aarch64_evpc_sve_tbl (struct expand_vec_perm_d *d) 24185 { 24186 unsigned HOST_WIDE_INT nelt; 24187 24188 /* Permuting two variable-length vectors could overflow the 24189 index range. */ 24190 if (!d->one_vector_p && !d->perm.length ().is_constant (&nelt)) 24191 return false; 24192 24193 if (d->testing_p) 24194 return true; 24195 24196 machine_mode sel_mode = related_int_vector_mode (d->vmode).require (); 24197 rtx sel = vec_perm_indices_to_rtx (sel_mode, d->perm); 24198 if (d->one_vector_p) 24199 emit_unspec2 (d->target, UNSPEC_TBL, d->op0, force_reg (sel_mode, sel)); 24200 else 24201 aarch64_expand_sve_vec_perm (d->target, d->op0, d->op1, sel); 24202 return true; 24203 } 24204 24205 /* Try to implement D using SVE SEL instruction. */ 24206 24207 static bool 24208 aarch64_evpc_sel (struct expand_vec_perm_d *d) 24209 { 24210 machine_mode vmode = d->vmode; 24211 int unit_size = GET_MODE_UNIT_SIZE (vmode); 24212 24213 if (d->vec_flags != VEC_SVE_DATA 24214 || unit_size > 8) 24215 return false; 24216 24217 int n_patterns = d->perm.encoding ().npatterns (); 24218 poly_int64 vec_len = d->perm.length (); 24219 24220 for (int i = 0; i < n_patterns; ++i) 24221 if (!known_eq (d->perm[i], i) 24222 && !known_eq (d->perm[i], vec_len + i)) 24223 return false; 24224 24225 for (int i = n_patterns; i < n_patterns * 2; i++) 24226 if (!d->perm.series_p (i, n_patterns, i, n_patterns) 24227 && !d->perm.series_p (i, n_patterns, vec_len + i, n_patterns)) 24228 return false; 24229 24230 if (d->testing_p) 24231 return true; 24232 24233 machine_mode pred_mode = aarch64_sve_pred_mode (vmode); 24234 24235 /* Build a predicate that is true when op0 elements should be used. */ 24236 rtx_vector_builder builder (pred_mode, n_patterns, 2); 24237 for (int i = 0; i < n_patterns * 2; i++) 24238 { 24239 rtx elem = known_eq (d->perm[i], i) ? CONST1_RTX (BImode) 24240 : CONST0_RTX (BImode); 24241 builder.quick_push (elem); 24242 } 24243 24244 rtx const_vec = builder.build (); 24245 rtx pred = force_reg (pred_mode, const_vec); 24246 /* TARGET = PRED ? OP0 : OP1. */ 24247 emit_insn (gen_vcond_mask (vmode, vmode, d->target, d->op0, d->op1, pred)); 24248 return true; 24249 } 24250 24251 /* Recognize patterns suitable for the INS instructions. */ 24252 static bool 24253 aarch64_evpc_ins (struct expand_vec_perm_d *d) 24254 { 24255 machine_mode mode = d->vmode; 24256 unsigned HOST_WIDE_INT nelt; 24257 24258 if (d->vec_flags != VEC_ADVSIMD) 24259 return false; 24260 24261 /* to_constant is safe since this routine is specific to Advanced SIMD 24262 vectors. */ 24263 nelt = d->perm.length ().to_constant (); 24264 rtx insv = d->op0; 24265 24266 HOST_WIDE_INT idx = -1; 24267 24268 for (unsigned HOST_WIDE_INT i = 0; i < nelt; i++) 24269 { 24270 HOST_WIDE_INT elt; 24271 if (!d->perm[i].is_constant (&elt)) 24272 return false; 24273 if (elt == (HOST_WIDE_INT) i) 24274 continue; 24275 if (idx != -1) 24276 { 24277 idx = -1; 24278 break; 24279 } 24280 idx = i; 24281 } 24282 24283 if (idx == -1) 24284 { 24285 insv = d->op1; 24286 for (unsigned HOST_WIDE_INT i = 0; i < nelt; i++) 24287 { 24288 if (d->perm[i].to_constant () == (HOST_WIDE_INT) (i + nelt)) 24289 continue; 24290 if (idx != -1) 24291 return false; 24292 idx = i; 24293 } 24294 24295 if (idx == -1) 24296 return false; 24297 } 24298 24299 if (d->testing_p) 24300 return true; 24301 24302 gcc_assert (idx != -1); 24303 24304 unsigned extractindex = d->perm[idx].to_constant (); 24305 rtx extractv = d->op0; 24306 if (extractindex >= nelt) 24307 { 24308 extractv = d->op1; 24309 extractindex -= nelt; 24310 } 24311 gcc_assert (extractindex < nelt); 24312 24313 insn_code icode = code_for_aarch64_simd_vec_copy_lane (mode); 24314 expand_operand ops[5]; 24315 create_output_operand (&ops[0], d->target, mode); 24316 create_input_operand (&ops[1], insv, mode); 24317 create_integer_operand (&ops[2], 1 << idx); 24318 create_input_operand (&ops[3], extractv, mode); 24319 create_integer_operand (&ops[4], extractindex); 24320 expand_insn (icode, 5, ops); 24321 24322 return true; 24323 } 24324 24325 static bool 24326 aarch64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d) 24327 { 24328 /* The pattern matching functions above are written to look for a small 24329 number to begin the sequence (0, 1, N/2). If we begin with an index 24330 from the second operand, we can swap the operands. */ 24331 poly_int64 nelt = d->perm.length (); 24332 if (known_ge (d->perm[0], nelt)) 24333 { 24334 d->perm.rotate_inputs (1); 24335 std::swap (d->op0, d->op1); 24336 } 24337 24338 if ((d->vec_flags == VEC_ADVSIMD 24339 || d->vec_flags == VEC_SVE_DATA 24340 || d->vec_flags == (VEC_SVE_DATA | VEC_PARTIAL) 24341 || d->vec_flags == VEC_SVE_PRED) 24342 && known_gt (nelt, 1)) 24343 { 24344 if (aarch64_evpc_rev_local (d)) 24345 return true; 24346 else if (aarch64_evpc_rev_global (d)) 24347 return true; 24348 else if (aarch64_evpc_ext (d)) 24349 return true; 24350 else if (aarch64_evpc_dup (d)) 24351 return true; 24352 else if (aarch64_evpc_zip (d)) 24353 return true; 24354 else if (aarch64_evpc_uzp (d)) 24355 return true; 24356 else if (aarch64_evpc_trn (d)) 24357 return true; 24358 else if (aarch64_evpc_sel (d)) 24359 return true; 24360 else if (aarch64_evpc_ins (d)) 24361 return true; 24362 else if (aarch64_evpc_reencode (d)) 24363 return true; 24364 if (d->vec_flags == VEC_SVE_DATA) 24365 return aarch64_evpc_sve_tbl (d); 24366 else if (d->vec_flags == VEC_ADVSIMD) 24367 return aarch64_evpc_tbl (d); 24368 } 24369 return false; 24370 } 24371 24372 /* Implement TARGET_VECTORIZE_VEC_PERM_CONST. */ 24373 24374 static bool 24375 aarch64_vectorize_vec_perm_const (machine_mode vmode, rtx target, rtx op0, 24376 rtx op1, const vec_perm_indices &sel) 24377 { 24378 struct expand_vec_perm_d d; 24379 24380 /* Check whether the mask can be applied to a single vector. */ 24381 if (sel.ninputs () == 1 24382 || (op0 && rtx_equal_p (op0, op1))) 24383 d.one_vector_p = true; 24384 else if (sel.all_from_input_p (0)) 24385 { 24386 d.one_vector_p = true; 24387 op1 = op0; 24388 } 24389 else if (sel.all_from_input_p (1)) 24390 { 24391 d.one_vector_p = true; 24392 op0 = op1; 24393 } 24394 else 24395 d.one_vector_p = false; 24396 24397 d.perm.new_vector (sel.encoding (), d.one_vector_p ? 1 : 2, 24398 sel.nelts_per_input ()); 24399 d.vmode = vmode; 24400 d.vec_flags = aarch64_classify_vector_mode (d.vmode); 24401 d.target = target; 24402 d.op0 = op0 ? force_reg (vmode, op0) : NULL_RTX; 24403 if (op0 == op1) 24404 d.op1 = d.op0; 24405 else 24406 d.op1 = op1 ? force_reg (vmode, op1) : NULL_RTX; 24407 d.testing_p = !target; 24408 24409 if (!d.testing_p) 24410 return aarch64_expand_vec_perm_const_1 (&d); 24411 24412 rtx_insn *last = get_last_insn (); 24413 bool ret = aarch64_expand_vec_perm_const_1 (&d); 24414 gcc_assert (last == get_last_insn ()); 24415 24416 return ret; 24417 } 24418 24419 /* Generate a byte permute mask for a register of mode MODE, 24420 which has NUNITS units. */ 24421 24422 rtx 24423 aarch64_reverse_mask (machine_mode mode, unsigned int nunits) 24424 { 24425 /* We have to reverse each vector because we dont have 24426 a permuted load that can reverse-load according to ABI rules. */ 24427 rtx mask; 24428 rtvec v = rtvec_alloc (16); 24429 unsigned int i, j; 24430 unsigned int usize = GET_MODE_UNIT_SIZE (mode); 24431 24432 gcc_assert (BYTES_BIG_ENDIAN); 24433 gcc_assert (AARCH64_VALID_SIMD_QREG_MODE (mode)); 24434 24435 for (i = 0; i < nunits; i++) 24436 for (j = 0; j < usize; j++) 24437 RTVEC_ELT (v, i * usize + j) = GEN_INT ((i + 1) * usize - 1 - j); 24438 mask = gen_rtx_CONST_VECTOR (V16QImode, v); 24439 return force_reg (V16QImode, mask); 24440 } 24441 24442 /* Expand an SVE integer comparison using the SVE equivalent of: 24443 24444 (set TARGET (CODE OP0 OP1)). */ 24445 24446 void 24447 aarch64_expand_sve_vec_cmp_int (rtx target, rtx_code code, rtx op0, rtx op1) 24448 { 24449 machine_mode pred_mode = GET_MODE (target); 24450 machine_mode data_mode = GET_MODE (op0); 24451 rtx res = aarch64_sve_emit_int_cmp (target, pred_mode, code, data_mode, 24452 op0, op1); 24453 if (!rtx_equal_p (target, res)) 24454 emit_move_insn (target, res); 24455 } 24456 24457 /* Return the UNSPEC_COND_* code for comparison CODE. */ 24458 24459 static unsigned int 24460 aarch64_unspec_cond_code (rtx_code code) 24461 { 24462 switch (code) 24463 { 24464 case NE: 24465 return UNSPEC_COND_FCMNE; 24466 case EQ: 24467 return UNSPEC_COND_FCMEQ; 24468 case LT: 24469 return UNSPEC_COND_FCMLT; 24470 case GT: 24471 return UNSPEC_COND_FCMGT; 24472 case LE: 24473 return UNSPEC_COND_FCMLE; 24474 case GE: 24475 return UNSPEC_COND_FCMGE; 24476 case UNORDERED: 24477 return UNSPEC_COND_FCMUO; 24478 default: 24479 gcc_unreachable (); 24480 } 24481 } 24482 24483 /* Emit: 24484 24485 (set TARGET (unspec [PRED KNOWN_PTRUE_P OP0 OP1] UNSPEC_COND_<X>)) 24486 24487 where <X> is the operation associated with comparison CODE. 24488 KNOWN_PTRUE_P is true if PRED is known to be a PTRUE. */ 24489 24490 static void 24491 aarch64_emit_sve_fp_cond (rtx target, rtx_code code, rtx pred, 24492 bool known_ptrue_p, rtx op0, rtx op1) 24493 { 24494 rtx flag = gen_int_mode (known_ptrue_p, SImode); 24495 rtx unspec = gen_rtx_UNSPEC (GET_MODE (pred), 24496 gen_rtvec (4, pred, flag, op0, op1), 24497 aarch64_unspec_cond_code (code)); 24498 emit_set_insn (target, unspec); 24499 } 24500 24501 /* Emit the SVE equivalent of: 24502 24503 (set TMP1 (unspec [PRED KNOWN_PTRUE_P OP0 OP1] UNSPEC_COND_<X1>)) 24504 (set TMP2 (unspec [PRED KNOWN_PTRUE_P OP0 OP1] UNSPEC_COND_<X2>)) 24505 (set TARGET (ior:PRED_MODE TMP1 TMP2)) 24506 24507 where <Xi> is the operation associated with comparison CODEi. 24508 KNOWN_PTRUE_P is true if PRED is known to be a PTRUE. */ 24509 24510 static void 24511 aarch64_emit_sve_or_fp_conds (rtx target, rtx_code code1, rtx_code code2, 24512 rtx pred, bool known_ptrue_p, rtx op0, rtx op1) 24513 { 24514 machine_mode pred_mode = GET_MODE (pred); 24515 rtx tmp1 = gen_reg_rtx (pred_mode); 24516 aarch64_emit_sve_fp_cond (tmp1, code1, pred, known_ptrue_p, op0, op1); 24517 rtx tmp2 = gen_reg_rtx (pred_mode); 24518 aarch64_emit_sve_fp_cond (tmp2, code2, pred, known_ptrue_p, op0, op1); 24519 aarch64_emit_binop (target, ior_optab, tmp1, tmp2); 24520 } 24521 24522 /* Emit the SVE equivalent of: 24523 24524 (set TMP (unspec [PRED KNOWN_PTRUE_P OP0 OP1] UNSPEC_COND_<X>)) 24525 (set TARGET (not TMP)) 24526 24527 where <X> is the operation associated with comparison CODE. 24528 KNOWN_PTRUE_P is true if PRED is known to be a PTRUE. */ 24529 24530 static void 24531 aarch64_emit_sve_invert_fp_cond (rtx target, rtx_code code, rtx pred, 24532 bool known_ptrue_p, rtx op0, rtx op1) 24533 { 24534 machine_mode pred_mode = GET_MODE (pred); 24535 rtx tmp = gen_reg_rtx (pred_mode); 24536 aarch64_emit_sve_fp_cond (tmp, code, pred, known_ptrue_p, op0, op1); 24537 aarch64_emit_unop (target, one_cmpl_optab, tmp); 24538 } 24539 24540 /* Expand an SVE floating-point comparison using the SVE equivalent of: 24541 24542 (set TARGET (CODE OP0 OP1)) 24543 24544 If CAN_INVERT_P is true, the caller can also handle inverted results; 24545 return true if the result is in fact inverted. */ 24546 24547 bool 24548 aarch64_expand_sve_vec_cmp_float (rtx target, rtx_code code, 24549 rtx op0, rtx op1, bool can_invert_p) 24550 { 24551 machine_mode pred_mode = GET_MODE (target); 24552 machine_mode data_mode = GET_MODE (op0); 24553 24554 rtx ptrue = aarch64_ptrue_reg (pred_mode); 24555 switch (code) 24556 { 24557 case UNORDERED: 24558 /* UNORDERED has no immediate form. */ 24559 op1 = force_reg (data_mode, op1); 24560 /* fall through */ 24561 case LT: 24562 case LE: 24563 case GT: 24564 case GE: 24565 case EQ: 24566 case NE: 24567 { 24568 /* There is native support for the comparison. */ 24569 aarch64_emit_sve_fp_cond (target, code, ptrue, true, op0, op1); 24570 return false; 24571 } 24572 24573 case LTGT: 24574 /* This is a trapping operation (LT or GT). */ 24575 aarch64_emit_sve_or_fp_conds (target, LT, GT, ptrue, true, op0, op1); 24576 return false; 24577 24578 case UNEQ: 24579 if (!flag_trapping_math) 24580 { 24581 /* This would trap for signaling NaNs. */ 24582 op1 = force_reg (data_mode, op1); 24583 aarch64_emit_sve_or_fp_conds (target, UNORDERED, EQ, 24584 ptrue, true, op0, op1); 24585 return false; 24586 } 24587 /* fall through */ 24588 case UNLT: 24589 case UNLE: 24590 case UNGT: 24591 case UNGE: 24592 if (flag_trapping_math) 24593 { 24594 /* Work out which elements are ordered. */ 24595 rtx ordered = gen_reg_rtx (pred_mode); 24596 op1 = force_reg (data_mode, op1); 24597 aarch64_emit_sve_invert_fp_cond (ordered, UNORDERED, 24598 ptrue, true, op0, op1); 24599 24600 /* Test the opposite condition for the ordered elements, 24601 then invert the result. */ 24602 if (code == UNEQ) 24603 code = NE; 24604 else 24605 code = reverse_condition_maybe_unordered (code); 24606 if (can_invert_p) 24607 { 24608 aarch64_emit_sve_fp_cond (target, code, 24609 ordered, false, op0, op1); 24610 return true; 24611 } 24612 aarch64_emit_sve_invert_fp_cond (target, code, 24613 ordered, false, op0, op1); 24614 return false; 24615 } 24616 break; 24617 24618 case ORDERED: 24619 /* ORDERED has no immediate form. */ 24620 op1 = force_reg (data_mode, op1); 24621 break; 24622 24623 default: 24624 gcc_unreachable (); 24625 } 24626 24627 /* There is native support for the inverse comparison. */ 24628 code = reverse_condition_maybe_unordered (code); 24629 if (can_invert_p) 24630 { 24631 aarch64_emit_sve_fp_cond (target, code, ptrue, true, op0, op1); 24632 return true; 24633 } 24634 aarch64_emit_sve_invert_fp_cond (target, code, ptrue, true, op0, op1); 24635 return false; 24636 } 24637 24638 /* Expand an SVE vcond pattern with operands OPS. DATA_MODE is the mode 24639 of the data being selected and CMP_MODE is the mode of the values being 24640 compared. */ 24641 24642 void 24643 aarch64_expand_sve_vcond (machine_mode data_mode, machine_mode cmp_mode, 24644 rtx *ops) 24645 { 24646 machine_mode pred_mode = aarch64_get_mask_mode (cmp_mode).require (); 24647 rtx pred = gen_reg_rtx (pred_mode); 24648 if (FLOAT_MODE_P (cmp_mode)) 24649 { 24650 if (aarch64_expand_sve_vec_cmp_float (pred, GET_CODE (ops[3]), 24651 ops[4], ops[5], true)) 24652 std::swap (ops[1], ops[2]); 24653 } 24654 else 24655 aarch64_expand_sve_vec_cmp_int (pred, GET_CODE (ops[3]), ops[4], ops[5]); 24656 24657 if (!aarch64_sve_reg_or_dup_imm (ops[1], data_mode)) 24658 ops[1] = force_reg (data_mode, ops[1]); 24659 /* The "false" value can only be zero if the "true" value is a constant. */ 24660 if (register_operand (ops[1], data_mode) 24661 || !aarch64_simd_reg_or_zero (ops[2], data_mode)) 24662 ops[2] = force_reg (data_mode, ops[2]); 24663 24664 rtvec vec = gen_rtvec (3, pred, ops[1], ops[2]); 24665 emit_set_insn (ops[0], gen_rtx_UNSPEC (data_mode, vec, UNSPEC_SEL)); 24666 } 24667 24668 /* Implement TARGET_MODES_TIEABLE_P. In principle we should always return 24669 true. However due to issues with register allocation it is preferable 24670 to avoid tieing integer scalar and FP scalar modes. Executing integer 24671 operations in general registers is better than treating them as scalar 24672 vector operations. This reduces latency and avoids redundant int<->FP 24673 moves. So tie modes if they are either the same class, or vector modes 24674 with other vector modes, vector structs or any scalar mode. */ 24675 24676 static bool 24677 aarch64_modes_tieable_p (machine_mode mode1, machine_mode mode2) 24678 { 24679 if ((aarch64_advsimd_partial_struct_mode_p (mode1) 24680 != aarch64_advsimd_partial_struct_mode_p (mode2)) 24681 && maybe_gt (GET_MODE_SIZE (mode1), 8) 24682 && maybe_gt (GET_MODE_SIZE (mode2), 8)) 24683 return false; 24684 24685 if (GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2)) 24686 return true; 24687 24688 /* We specifically want to allow elements of "structure" modes to 24689 be tieable to the structure. This more general condition allows 24690 other rarer situations too. The reason we don't extend this to 24691 predicate modes is that there are no predicate structure modes 24692 nor any specific instructions for extracting part of a predicate 24693 register. */ 24694 if (aarch64_vector_data_mode_p (mode1) 24695 && aarch64_vector_data_mode_p (mode2)) 24696 return true; 24697 24698 /* Also allow any scalar modes with vectors. */ 24699 if (aarch64_vector_mode_supported_p (mode1) 24700 || aarch64_vector_mode_supported_p (mode2)) 24701 return true; 24702 24703 return false; 24704 } 24705 24706 /* Return a new RTX holding the result of moving POINTER forward by 24707 AMOUNT bytes. */ 24708 24709 static rtx 24710 aarch64_move_pointer (rtx pointer, poly_int64 amount) 24711 { 24712 rtx next = plus_constant (Pmode, XEXP (pointer, 0), amount); 24713 24714 return adjust_automodify_address (pointer, GET_MODE (pointer), 24715 next, amount); 24716 } 24717 24718 /* Return a new RTX holding the result of moving POINTER forward by the 24719 size of the mode it points to. */ 24720 24721 static rtx 24722 aarch64_progress_pointer (rtx pointer) 24723 { 24724 return aarch64_move_pointer (pointer, GET_MODE_SIZE (GET_MODE (pointer))); 24725 } 24726 24727 /* Copy one MODE sized block from SRC to DST, then progress SRC and DST by 24728 MODE bytes. */ 24729 24730 static void 24731 aarch64_copy_one_block_and_progress_pointers (rtx *src, rtx *dst, 24732 machine_mode mode) 24733 { 24734 /* Handle 256-bit memcpy separately. We do this by making 2 adjacent memory 24735 address copies using V4SImode so that we can use Q registers. */ 24736 if (known_eq (GET_MODE_BITSIZE (mode), 256)) 24737 { 24738 mode = V4SImode; 24739 rtx reg1 = gen_reg_rtx (mode); 24740 rtx reg2 = gen_reg_rtx (mode); 24741 /* "Cast" the pointers to the correct mode. */ 24742 *src = adjust_address (*src, mode, 0); 24743 *dst = adjust_address (*dst, mode, 0); 24744 /* Emit the memcpy. */ 24745 emit_insn (aarch64_gen_load_pair (mode, reg1, *src, reg2, 24746 aarch64_progress_pointer (*src))); 24747 emit_insn (aarch64_gen_store_pair (mode, *dst, reg1, 24748 aarch64_progress_pointer (*dst), reg2)); 24749 /* Move the pointers forward. */ 24750 *src = aarch64_move_pointer (*src, 32); 24751 *dst = aarch64_move_pointer (*dst, 32); 24752 return; 24753 } 24754 24755 rtx reg = gen_reg_rtx (mode); 24756 24757 /* "Cast" the pointers to the correct mode. */ 24758 *src = adjust_address (*src, mode, 0); 24759 *dst = adjust_address (*dst, mode, 0); 24760 /* Emit the memcpy. */ 24761 emit_move_insn (reg, *src); 24762 emit_move_insn (*dst, reg); 24763 /* Move the pointers forward. */ 24764 *src = aarch64_progress_pointer (*src); 24765 *dst = aarch64_progress_pointer (*dst); 24766 } 24767 24768 /* Expand a cpymem/movmem using the MOPS extension. OPERANDS are taken 24769 from the cpymem/movmem pattern. IS_MEMMOVE is true if this is a memmove 24770 rather than memcpy. Return true iff we succeeded. */ 24771 bool 24772 aarch64_expand_cpymem_mops (rtx *operands, bool is_memmove = false) 24773 { 24774 if (!TARGET_MOPS) 24775 return false; 24776 24777 /* All three registers are changed by the instruction, so each one 24778 must be a fresh pseudo. */ 24779 rtx dst_addr = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); 24780 rtx src_addr = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); 24781 rtx dst_mem = replace_equiv_address (operands[0], dst_addr); 24782 rtx src_mem = replace_equiv_address (operands[1], src_addr); 24783 rtx sz_reg = copy_to_mode_reg (DImode, operands[2]); 24784 if (is_memmove) 24785 emit_insn (gen_aarch64_movmemdi (dst_mem, src_mem, sz_reg)); 24786 else 24787 emit_insn (gen_aarch64_cpymemdi (dst_mem, src_mem, sz_reg)); 24788 return true; 24789 } 24790 24791 /* Expand cpymem, as if from a __builtin_memcpy. Return true if 24792 we succeed, otherwise return false, indicating that a libcall to 24793 memcpy should be emitted. */ 24794 24795 bool 24796 aarch64_expand_cpymem (rtx *operands) 24797 { 24798 int mode_bits; 24799 rtx dst = operands[0]; 24800 rtx src = operands[1]; 24801 unsigned align = UINTVAL (operands[3]); 24802 rtx base; 24803 machine_mode cur_mode = BLKmode; 24804 bool size_p = optimize_function_for_size_p (cfun); 24805 24806 /* Variable-sized or strict-align copies may use the MOPS expansion. */ 24807 if (!CONST_INT_P (operands[2]) || (STRICT_ALIGNMENT && align < 16)) 24808 return aarch64_expand_cpymem_mops (operands); 24809 24810 unsigned HOST_WIDE_INT size = UINTVAL (operands[2]); 24811 24812 /* Try to inline up to 256 bytes. */ 24813 unsigned max_copy_size = 256; 24814 unsigned mops_threshold = aarch64_mops_memcpy_size_threshold; 24815 24816 /* Large copies use MOPS when available or a library call. */ 24817 if (size > max_copy_size || (TARGET_MOPS && size > mops_threshold)) 24818 return aarch64_expand_cpymem_mops (operands); 24819 24820 int copy_bits = 256; 24821 24822 /* Default to 256-bit LDP/STP on large copies, however small copies, no SIMD 24823 support or slow 256-bit LDP/STP fall back to 128-bit chunks. */ 24824 if (size <= 24 24825 || !TARGET_SIMD 24826 || (aarch64_tune_params.extra_tuning_flags 24827 & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS)) 24828 copy_bits = 128; 24829 24830 /* Emit an inline load+store sequence and count the number of operations 24831 involved. We use a simple count of just the loads and stores emitted 24832 rather than rtx_insn count as all the pointer adjustments and reg copying 24833 in this function will get optimized away later in the pipeline. */ 24834 start_sequence (); 24835 unsigned nops = 0; 24836 24837 base = copy_to_mode_reg (Pmode, XEXP (dst, 0)); 24838 dst = adjust_automodify_address (dst, VOIDmode, base, 0); 24839 24840 base = copy_to_mode_reg (Pmode, XEXP (src, 0)); 24841 src = adjust_automodify_address (src, VOIDmode, base, 0); 24842 24843 /* Convert size to bits to make the rest of the code simpler. */ 24844 int n = size * BITS_PER_UNIT; 24845 24846 while (n > 0) 24847 { 24848 /* Find the largest mode in which to do the copy in without over reading 24849 or writing. */ 24850 opt_scalar_int_mode mode_iter; 24851 FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT) 24852 if (GET_MODE_BITSIZE (mode_iter.require ()) <= MIN (n, copy_bits)) 24853 cur_mode = mode_iter.require (); 24854 24855 gcc_assert (cur_mode != BLKmode); 24856 24857 mode_bits = GET_MODE_BITSIZE (cur_mode).to_constant (); 24858 24859 /* Prefer Q-register accesses for the last bytes. */ 24860 if (mode_bits == 128 && copy_bits == 256) 24861 cur_mode = V4SImode; 24862 24863 aarch64_copy_one_block_and_progress_pointers (&src, &dst, cur_mode); 24864 /* A single block copy is 1 load + 1 store. */ 24865 nops += 2; 24866 n -= mode_bits; 24867 24868 /* Emit trailing copies using overlapping unaligned accesses 24869 (when !STRICT_ALIGNMENT) - this is smaller and faster. */ 24870 if (n > 0 && n < copy_bits / 2 && !STRICT_ALIGNMENT) 24871 { 24872 machine_mode next_mode = smallest_mode_for_size (n, MODE_INT); 24873 int n_bits = GET_MODE_BITSIZE (next_mode).to_constant (); 24874 gcc_assert (n_bits <= mode_bits); 24875 src = aarch64_move_pointer (src, (n - n_bits) / BITS_PER_UNIT); 24876 dst = aarch64_move_pointer (dst, (n - n_bits) / BITS_PER_UNIT); 24877 n = n_bits; 24878 } 24879 } 24880 rtx_insn *seq = get_insns (); 24881 end_sequence (); 24882 /* MOPS sequence requires 3 instructions for the memory copying + 1 to move 24883 the constant size into a register. */ 24884 unsigned mops_cost = 3 + 1; 24885 24886 /* If MOPS is available at this point we don't consider the libcall as it's 24887 not a win even on code size. At this point only consider MOPS if 24888 optimizing for size. For speed optimizations we will have chosen between 24889 the two based on copy size already. */ 24890 if (TARGET_MOPS) 24891 { 24892 if (size_p && mops_cost < nops) 24893 return aarch64_expand_cpymem_mops (operands); 24894 emit_insn (seq); 24895 return true; 24896 } 24897 24898 /* A memcpy libcall in the worst case takes 3 instructions to prepare the 24899 arguments + 1 for the call. When MOPS is not available and we're 24900 optimizing for size a libcall may be preferable. */ 24901 unsigned libcall_cost = 4; 24902 if (size_p && libcall_cost < nops) 24903 return false; 24904 24905 emit_insn (seq); 24906 return true; 24907 } 24908 24909 /* Like aarch64_copy_one_block_and_progress_pointers, except for memset where 24910 SRC is a register we have created with the duplicated value to be set. */ 24911 static void 24912 aarch64_set_one_block_and_progress_pointer (rtx src, rtx *dst, 24913 machine_mode mode) 24914 { 24915 /* If we are copying 128bits or 256bits, we can do that straight from 24916 the SIMD register we prepared. */ 24917 if (known_eq (GET_MODE_BITSIZE (mode), 256)) 24918 { 24919 mode = GET_MODE (src); 24920 /* "Cast" the *dst to the correct mode. */ 24921 *dst = adjust_address (*dst, mode, 0); 24922 /* Emit the memset. */ 24923 emit_insn (aarch64_gen_store_pair (mode, *dst, src, 24924 aarch64_progress_pointer (*dst), src)); 24925 24926 /* Move the pointers forward. */ 24927 *dst = aarch64_move_pointer (*dst, 32); 24928 return; 24929 } 24930 if (known_eq (GET_MODE_BITSIZE (mode), 128)) 24931 { 24932 /* "Cast" the *dst to the correct mode. */ 24933 *dst = adjust_address (*dst, GET_MODE (src), 0); 24934 /* Emit the memset. */ 24935 emit_move_insn (*dst, src); 24936 /* Move the pointers forward. */ 24937 *dst = aarch64_move_pointer (*dst, 16); 24938 return; 24939 } 24940 /* For copying less, we have to extract the right amount from src. */ 24941 rtx reg = lowpart_subreg (mode, src, GET_MODE (src)); 24942 24943 /* "Cast" the *dst to the correct mode. */ 24944 *dst = adjust_address (*dst, mode, 0); 24945 /* Emit the memset. */ 24946 emit_move_insn (*dst, reg); 24947 /* Move the pointer forward. */ 24948 *dst = aarch64_progress_pointer (*dst); 24949 } 24950 24951 /* Expand a setmem using the MOPS instructions. OPERANDS are the same 24952 as for the setmem pattern. Return true iff we succeed. */ 24953 static bool 24954 aarch64_expand_setmem_mops (rtx *operands) 24955 { 24956 if (!TARGET_MOPS) 24957 return false; 24958 24959 /* The first two registers are changed by the instruction, so both 24960 of them must be a fresh pseudo. */ 24961 rtx dst_addr = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); 24962 rtx dst_mem = replace_equiv_address (operands[0], dst_addr); 24963 rtx sz_reg = copy_to_mode_reg (DImode, operands[1]); 24964 rtx val = operands[2]; 24965 if (val != CONST0_RTX (QImode)) 24966 val = force_reg (QImode, val); 24967 emit_insn (gen_aarch64_setmemdi (dst_mem, val, sz_reg)); 24968 return true; 24969 } 24970 24971 /* Expand setmem, as if from a __builtin_memset. Return true if 24972 we succeed, otherwise return false. */ 24973 24974 bool 24975 aarch64_expand_setmem (rtx *operands) 24976 { 24977 int n, mode_bits; 24978 unsigned HOST_WIDE_INT len; 24979 rtx dst = operands[0]; 24980 rtx val = operands[2], src; 24981 unsigned align = UINTVAL (operands[3]); 24982 rtx base; 24983 machine_mode cur_mode = BLKmode, next_mode; 24984 24985 /* Variable-sized or strict-align memset may use the MOPS expansion. */ 24986 if (!CONST_INT_P (operands[1]) || !TARGET_SIMD 24987 || (STRICT_ALIGNMENT && align < 16)) 24988 return aarch64_expand_setmem_mops (operands); 24989 24990 bool size_p = optimize_function_for_size_p (cfun); 24991 24992 /* Default the maximum to 256-bytes when considering only libcall vs 24993 SIMD broadcast sequence. */ 24994 unsigned max_set_size = 256; 24995 unsigned mops_threshold = aarch64_mops_memset_size_threshold; 24996 24997 len = UINTVAL (operands[1]); 24998 24999 /* Large memset uses MOPS when available or a library call. */ 25000 if (len > max_set_size || (TARGET_MOPS && len > mops_threshold)) 25001 return aarch64_expand_setmem_mops (operands); 25002 25003 int cst_val = !!(CONST_INT_P (val) && (INTVAL (val) != 0)); 25004 /* The MOPS sequence takes: 25005 3 instructions for the memory storing 25006 + 1 to move the constant size into a reg 25007 + 1 if VAL is a non-zero constant to move into a reg 25008 (zero constants can use XZR directly). */ 25009 unsigned mops_cost = 3 + 1 + cst_val; 25010 /* A libcall to memset in the worst case takes 3 instructions to prepare 25011 the arguments + 1 for the call. */ 25012 unsigned libcall_cost = 4; 25013 25014 /* Attempt a sequence with a vector broadcast followed by stores. 25015 Count the number of operations involved to see if it's worth it 25016 against the alternatives. A simple counter simd_ops on the 25017 algorithmically-relevant operations is used rather than an rtx_insn count 25018 as all the pointer adjusmtents and mode reinterprets will be optimized 25019 away later. */ 25020 start_sequence (); 25021 unsigned simd_ops = 0; 25022 25023 base = copy_to_mode_reg (Pmode, XEXP (dst, 0)); 25024 dst = adjust_automodify_address (dst, VOIDmode, base, 0); 25025 25026 /* Prepare the val using a DUP/MOVI v0.16B, val. */ 25027 src = expand_vector_broadcast (V16QImode, val); 25028 src = force_reg (V16QImode, src); 25029 simd_ops++; 25030 /* Convert len to bits to make the rest of the code simpler. */ 25031 n = len * BITS_PER_UNIT; 25032 25033 /* Maximum amount to copy in one go. We allow 256-bit chunks based on the 25034 AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS tuning parameter. */ 25035 const int copy_limit = (aarch64_tune_params.extra_tuning_flags 25036 & AARCH64_EXTRA_TUNE_NO_LDP_STP_QREGS) 25037 ? GET_MODE_BITSIZE (TImode) : 256; 25038 25039 while (n > 0) 25040 { 25041 /* Find the largest mode in which to do the copy without 25042 over writing. */ 25043 opt_scalar_int_mode mode_iter; 25044 FOR_EACH_MODE_IN_CLASS (mode_iter, MODE_INT) 25045 if (GET_MODE_BITSIZE (mode_iter.require ()) <= MIN (n, copy_limit)) 25046 cur_mode = mode_iter.require (); 25047 25048 gcc_assert (cur_mode != BLKmode); 25049 25050 mode_bits = GET_MODE_BITSIZE (cur_mode).to_constant (); 25051 aarch64_set_one_block_and_progress_pointer (src, &dst, cur_mode); 25052 simd_ops++; 25053 n -= mode_bits; 25054 25055 /* Emit trailing writes using overlapping unaligned accesses 25056 (when !STRICT_ALIGNMENT) - this is smaller and faster. */ 25057 if (n > 0 && n < copy_limit / 2 && !STRICT_ALIGNMENT) 25058 { 25059 next_mode = smallest_mode_for_size (n, MODE_INT); 25060 int n_bits = GET_MODE_BITSIZE (next_mode).to_constant (); 25061 gcc_assert (n_bits <= mode_bits); 25062 dst = aarch64_move_pointer (dst, (n - n_bits) / BITS_PER_UNIT); 25063 n = n_bits; 25064 } 25065 } 25066 rtx_insn *seq = get_insns (); 25067 end_sequence (); 25068 25069 if (size_p) 25070 { 25071 /* When optimizing for size we have 3 options: the SIMD broadcast sequence, 25072 call to memset or the MOPS expansion. */ 25073 if (TARGET_MOPS 25074 && mops_cost <= libcall_cost 25075 && mops_cost <= simd_ops) 25076 return aarch64_expand_setmem_mops (operands); 25077 /* If MOPS is not available or not shorter pick a libcall if the SIMD 25078 sequence is too long. */ 25079 else if (libcall_cost < simd_ops) 25080 return false; 25081 emit_insn (seq); 25082 return true; 25083 } 25084 25085 /* At this point the SIMD broadcast sequence is the best choice when 25086 optimizing for speed. */ 25087 emit_insn (seq); 25088 return true; 25089 } 25090 25091 25092 /* Split a DImode store of a CONST_INT SRC to MEM DST as two 25093 SImode stores. Handle the case when the constant has identical 25094 bottom and top halves. This is beneficial when the two stores can be 25095 merged into an STP and we avoid synthesising potentially expensive 25096 immediates twice. Return true if such a split is possible. */ 25097 25098 bool 25099 aarch64_split_dimode_const_store (rtx dst, rtx src) 25100 { 25101 rtx lo = gen_lowpart (SImode, src); 25102 rtx hi = gen_highpart_mode (SImode, DImode, src); 25103 25104 bool size_p = optimize_function_for_size_p (cfun); 25105 25106 if (!rtx_equal_p (lo, hi)) 25107 return false; 25108 25109 unsigned int orig_cost 25110 = aarch64_internal_mov_immediate (NULL_RTX, src, false, DImode); 25111 unsigned int lo_cost 25112 = aarch64_internal_mov_immediate (NULL_RTX, lo, false, SImode); 25113 25114 /* We want to transform: 25115 MOV x1, 49370 25116 MOVK x1, 0x140, lsl 16 25117 MOVK x1, 0xc0da, lsl 32 25118 MOVK x1, 0x140, lsl 48 25119 STR x1, [x0] 25120 into: 25121 MOV w1, 49370 25122 MOVK w1, 0x140, lsl 16 25123 STP w1, w1, [x0] 25124 So we want to perform this only when we save two instructions 25125 or more. When optimizing for size, however, accept any code size 25126 savings we can. */ 25127 if (size_p && orig_cost <= lo_cost) 25128 return false; 25129 25130 if (!size_p 25131 && (orig_cost <= lo_cost + 1)) 25132 return false; 25133 25134 rtx mem_lo = adjust_address (dst, SImode, 0); 25135 if (!aarch64_mem_pair_operand (mem_lo, SImode)) 25136 return false; 25137 25138 rtx tmp_reg = gen_reg_rtx (SImode); 25139 aarch64_expand_mov_immediate (tmp_reg, lo); 25140 rtx mem_hi = aarch64_move_pointer (mem_lo, GET_MODE_SIZE (SImode)); 25141 /* Don't emit an explicit store pair as this may not be always profitable. 25142 Let the sched-fusion logic decide whether to merge them. */ 25143 emit_move_insn (mem_lo, tmp_reg); 25144 emit_move_insn (mem_hi, tmp_reg); 25145 25146 return true; 25147 } 25148 25149 /* Generate RTL for a conditional branch with rtx comparison CODE in 25150 mode CC_MODE. The destination of the unlikely conditional branch 25151 is LABEL_REF. */ 25152 25153 void 25154 aarch64_gen_unlikely_cbranch (enum rtx_code code, machine_mode cc_mode, 25155 rtx label_ref) 25156 { 25157 rtx x; 25158 x = gen_rtx_fmt_ee (code, VOIDmode, 25159 gen_rtx_REG (cc_mode, CC_REGNUM), 25160 const0_rtx); 25161 25162 x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, 25163 gen_rtx_LABEL_REF (VOIDmode, label_ref), 25164 pc_rtx); 25165 aarch64_emit_unlikely_jump (gen_rtx_SET (pc_rtx, x)); 25166 } 25167 25168 /* Generate DImode scratch registers for 128-bit (TImode) addition. 25169 25170 OP1 represents the TImode destination operand 1 25171 OP2 represents the TImode destination operand 2 25172 LOW_DEST represents the low half (DImode) of TImode operand 0 25173 LOW_IN1 represents the low half (DImode) of TImode operand 1 25174 LOW_IN2 represents the low half (DImode) of TImode operand 2 25175 HIGH_DEST represents the high half (DImode) of TImode operand 0 25176 HIGH_IN1 represents the high half (DImode) of TImode operand 1 25177 HIGH_IN2 represents the high half (DImode) of TImode operand 2. */ 25178 25179 void 25180 aarch64_addti_scratch_regs (rtx op1, rtx op2, rtx *low_dest, 25181 rtx *low_in1, rtx *low_in2, 25182 rtx *high_dest, rtx *high_in1, 25183 rtx *high_in2) 25184 { 25185 *low_dest = gen_reg_rtx (DImode); 25186 *low_in1 = gen_lowpart (DImode, op1); 25187 *low_in2 = simplify_gen_subreg (DImode, op2, TImode, 25188 subreg_lowpart_offset (DImode, TImode)); 25189 *high_dest = gen_reg_rtx (DImode); 25190 *high_in1 = gen_highpart (DImode, op1); 25191 *high_in2 = simplify_gen_subreg (DImode, op2, TImode, 25192 subreg_highpart_offset (DImode, TImode)); 25193 } 25194 25195 /* Generate DImode scratch registers for 128-bit (TImode) subtraction. 25196 25197 This function differs from 'arch64_addti_scratch_regs' in that 25198 OP1 can be an immediate constant (zero). We must call 25199 subreg_highpart_offset with DImode and TImode arguments, otherwise 25200 VOIDmode will be used for the const_int which generates an internal 25201 error from subreg_size_highpart_offset which does not expect a size of zero. 25202 25203 OP1 represents the TImode destination operand 1 25204 OP2 represents the TImode destination operand 2 25205 LOW_DEST represents the low half (DImode) of TImode operand 0 25206 LOW_IN1 represents the low half (DImode) of TImode operand 1 25207 LOW_IN2 represents the low half (DImode) of TImode operand 2 25208 HIGH_DEST represents the high half (DImode) of TImode operand 0 25209 HIGH_IN1 represents the high half (DImode) of TImode operand 1 25210 HIGH_IN2 represents the high half (DImode) of TImode operand 2. */ 25211 25212 25213 void 25214 aarch64_subvti_scratch_regs (rtx op1, rtx op2, rtx *low_dest, 25215 rtx *low_in1, rtx *low_in2, 25216 rtx *high_dest, rtx *high_in1, 25217 rtx *high_in2) 25218 { 25219 *low_dest = gen_reg_rtx (DImode); 25220 *low_in1 = simplify_gen_subreg (DImode, op1, TImode, 25221 subreg_lowpart_offset (DImode, TImode)); 25222 25223 *low_in2 = simplify_gen_subreg (DImode, op2, TImode, 25224 subreg_lowpart_offset (DImode, TImode)); 25225 *high_dest = gen_reg_rtx (DImode); 25226 25227 *high_in1 = simplify_gen_subreg (DImode, op1, TImode, 25228 subreg_highpart_offset (DImode, TImode)); 25229 *high_in2 = simplify_gen_subreg (DImode, op2, TImode, 25230 subreg_highpart_offset (DImode, TImode)); 25231 } 25232 25233 /* Generate RTL for 128-bit (TImode) subtraction with overflow. 25234 25235 OP0 represents the TImode destination operand 0 25236 LOW_DEST represents the low half (DImode) of TImode operand 0 25237 LOW_IN1 represents the low half (DImode) of TImode operand 1 25238 LOW_IN2 represents the low half (DImode) of TImode operand 2 25239 HIGH_DEST represents the high half (DImode) of TImode operand 0 25240 HIGH_IN1 represents the high half (DImode) of TImode operand 1 25241 HIGH_IN2 represents the high half (DImode) of TImode operand 2 25242 UNSIGNED_P is true if the operation is being performed on unsigned 25243 values. */ 25244 void 25245 aarch64_expand_subvti (rtx op0, rtx low_dest, rtx low_in1, 25246 rtx low_in2, rtx high_dest, rtx high_in1, 25247 rtx high_in2, bool unsigned_p) 25248 { 25249 if (low_in2 == const0_rtx) 25250 { 25251 low_dest = low_in1; 25252 high_in2 = force_reg (DImode, high_in2); 25253 if (unsigned_p) 25254 emit_insn (gen_subdi3_compare1 (high_dest, high_in1, high_in2)); 25255 else 25256 emit_insn (gen_subvdi_insn (high_dest, high_in1, high_in2)); 25257 } 25258 else 25259 { 25260 if (aarch64_plus_immediate (low_in2, DImode)) 25261 emit_insn (gen_subdi3_compare1_imm (low_dest, low_in1, low_in2, 25262 GEN_INT (-UINTVAL (low_in2)))); 25263 else 25264 { 25265 low_in2 = force_reg (DImode, low_in2); 25266 emit_insn (gen_subdi3_compare1 (low_dest, low_in1, low_in2)); 25267 } 25268 high_in2 = force_reg (DImode, high_in2); 25269 25270 if (unsigned_p) 25271 emit_insn (gen_usubdi3_carryinC (high_dest, high_in1, high_in2)); 25272 else 25273 emit_insn (gen_subdi3_carryinV (high_dest, high_in1, high_in2)); 25274 } 25275 25276 emit_move_insn (gen_lowpart (DImode, op0), low_dest); 25277 emit_move_insn (gen_highpart (DImode, op0), high_dest); 25278 25279 } 25280 25281 /* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */ 25282 25283 static unsigned HOST_WIDE_INT 25284 aarch64_asan_shadow_offset (void) 25285 { 25286 if (TARGET_ILP32) 25287 return (HOST_WIDE_INT_1 << 29); 25288 else 25289 return (HOST_WIDE_INT_1 << 36); 25290 } 25291 25292 static rtx 25293 aarch64_gen_ccmp_first (rtx_insn **prep_seq, rtx_insn **gen_seq, 25294 int code, tree treeop0, tree treeop1) 25295 { 25296 machine_mode op_mode, cmp_mode, cc_mode = CCmode; 25297 rtx op0, op1; 25298 int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0)); 25299 insn_code icode; 25300 struct expand_operand ops[4]; 25301 25302 start_sequence (); 25303 expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); 25304 25305 op_mode = GET_MODE (op0); 25306 if (op_mode == VOIDmode) 25307 op_mode = GET_MODE (op1); 25308 25309 switch (op_mode) 25310 { 25311 case E_QImode: 25312 case E_HImode: 25313 case E_SImode: 25314 cmp_mode = SImode; 25315 icode = CODE_FOR_cmpsi; 25316 break; 25317 25318 case E_DImode: 25319 cmp_mode = DImode; 25320 icode = CODE_FOR_cmpdi; 25321 break; 25322 25323 case E_SFmode: 25324 cmp_mode = SFmode; 25325 cc_mode = aarch64_select_cc_mode ((rtx_code) code, op0, op1); 25326 icode = cc_mode == CCFPEmode ? CODE_FOR_fcmpesf : CODE_FOR_fcmpsf; 25327 break; 25328 25329 case E_DFmode: 25330 cmp_mode = DFmode; 25331 cc_mode = aarch64_select_cc_mode ((rtx_code) code, op0, op1); 25332 icode = cc_mode == CCFPEmode ? CODE_FOR_fcmpedf : CODE_FOR_fcmpdf; 25333 break; 25334 25335 default: 25336 end_sequence (); 25337 return NULL_RTX; 25338 } 25339 25340 op0 = prepare_operand (icode, op0, 0, op_mode, cmp_mode, unsignedp); 25341 op1 = prepare_operand (icode, op1, 1, op_mode, cmp_mode, unsignedp); 25342 if (!op0 || !op1) 25343 { 25344 end_sequence (); 25345 return NULL_RTX; 25346 } 25347 *prep_seq = get_insns (); 25348 end_sequence (); 25349 25350 create_fixed_operand (&ops[0], op0); 25351 create_fixed_operand (&ops[1], op1); 25352 25353 start_sequence (); 25354 if (!maybe_expand_insn (icode, 2, ops)) 25355 { 25356 end_sequence (); 25357 return NULL_RTX; 25358 } 25359 *gen_seq = get_insns (); 25360 end_sequence (); 25361 25362 return gen_rtx_fmt_ee ((rtx_code) code, cc_mode, 25363 gen_rtx_REG (cc_mode, CC_REGNUM), const0_rtx); 25364 } 25365 25366 static rtx 25367 aarch64_gen_ccmp_next (rtx_insn **prep_seq, rtx_insn **gen_seq, rtx prev, 25368 int cmp_code, tree treeop0, tree treeop1, int bit_code) 25369 { 25370 rtx op0, op1, target; 25371 machine_mode op_mode, cmp_mode, cc_mode = CCmode; 25372 int unsignedp = TYPE_UNSIGNED (TREE_TYPE (treeop0)); 25373 insn_code icode; 25374 struct expand_operand ops[6]; 25375 int aarch64_cond; 25376 25377 push_to_sequence (*prep_seq); 25378 expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); 25379 25380 op_mode = GET_MODE (op0); 25381 if (op_mode == VOIDmode) 25382 op_mode = GET_MODE (op1); 25383 25384 switch (op_mode) 25385 { 25386 case E_QImode: 25387 case E_HImode: 25388 case E_SImode: 25389 cmp_mode = SImode; 25390 break; 25391 25392 case E_DImode: 25393 cmp_mode = DImode; 25394 break; 25395 25396 case E_SFmode: 25397 cmp_mode = SFmode; 25398 cc_mode = aarch64_select_cc_mode ((rtx_code) cmp_code, op0, op1); 25399 break; 25400 25401 case E_DFmode: 25402 cmp_mode = DFmode; 25403 cc_mode = aarch64_select_cc_mode ((rtx_code) cmp_code, op0, op1); 25404 break; 25405 25406 default: 25407 end_sequence (); 25408 return NULL_RTX; 25409 } 25410 25411 icode = code_for_ccmp (cc_mode, cmp_mode); 25412 25413 op0 = prepare_operand (icode, op0, 2, op_mode, cmp_mode, unsignedp); 25414 op1 = prepare_operand (icode, op1, 3, op_mode, cmp_mode, unsignedp); 25415 if (!op0 || !op1) 25416 { 25417 end_sequence (); 25418 return NULL_RTX; 25419 } 25420 *prep_seq = get_insns (); 25421 end_sequence (); 25422 25423 target = gen_rtx_REG (cc_mode, CC_REGNUM); 25424 aarch64_cond = aarch64_get_condition_code_1 (cc_mode, (rtx_code) cmp_code); 25425 25426 if (bit_code != AND) 25427 { 25428 /* Treat the ccmp patterns as canonical and use them where possible, 25429 but fall back to ccmp_rev patterns if there's no other option. */ 25430 rtx_code prev_code = GET_CODE (prev); 25431 machine_mode prev_mode = GET_MODE (XEXP (prev, 0)); 25432 if ((prev_mode == CCFPmode || prev_mode == CCFPEmode) 25433 && !(prev_code == EQ 25434 || prev_code == NE 25435 || prev_code == ORDERED 25436 || prev_code == UNORDERED)) 25437 icode = code_for_ccmp_rev (cc_mode, cmp_mode); 25438 else 25439 { 25440 rtx_code code = reverse_condition (prev_code); 25441 prev = gen_rtx_fmt_ee (code, VOIDmode, XEXP (prev, 0), const0_rtx); 25442 } 25443 aarch64_cond = AARCH64_INVERSE_CONDITION_CODE (aarch64_cond); 25444 } 25445 25446 create_fixed_operand (&ops[0], XEXP (prev, 0)); 25447 create_fixed_operand (&ops[1], target); 25448 create_fixed_operand (&ops[2], op0); 25449 create_fixed_operand (&ops[3], op1); 25450 create_fixed_operand (&ops[4], prev); 25451 create_fixed_operand (&ops[5], GEN_INT (aarch64_cond)); 25452 25453 push_to_sequence (*gen_seq); 25454 if (!maybe_expand_insn (icode, 6, ops)) 25455 { 25456 end_sequence (); 25457 return NULL_RTX; 25458 } 25459 25460 *gen_seq = get_insns (); 25461 end_sequence (); 25462 25463 return gen_rtx_fmt_ee ((rtx_code) cmp_code, VOIDmode, target, const0_rtx); 25464 } 25465 25466 #undef TARGET_GEN_CCMP_FIRST 25467 #define TARGET_GEN_CCMP_FIRST aarch64_gen_ccmp_first 25468 25469 #undef TARGET_GEN_CCMP_NEXT 25470 #define TARGET_GEN_CCMP_NEXT aarch64_gen_ccmp_next 25471 25472 /* Implement TARGET_SCHED_MACRO_FUSION_P. Return true if target supports 25473 instruction fusion of some sort. */ 25474 25475 static bool 25476 aarch64_macro_fusion_p (void) 25477 { 25478 return aarch64_tune_params.fusible_ops != AARCH64_FUSE_NOTHING; 25479 } 25480 25481 25482 /* Implement TARGET_SCHED_MACRO_FUSION_PAIR_P. Return true if PREV and CURR 25483 should be kept together during scheduling. */ 25484 25485 static bool 25486 aarch_macro_fusion_pair_p (rtx_insn *prev, rtx_insn *curr) 25487 { 25488 rtx set_dest; 25489 rtx prev_set = single_set (prev); 25490 rtx curr_set = single_set (curr); 25491 /* prev and curr are simple SET insns i.e. no flag setting or branching. */ 25492 bool simple_sets_p = prev_set && curr_set && !any_condjump_p (curr); 25493 25494 if (!aarch64_macro_fusion_p ()) 25495 return false; 25496 25497 if (simple_sets_p && aarch64_fusion_enabled_p (AARCH64_FUSE_MOV_MOVK)) 25498 { 25499 /* We are trying to match: 25500 prev (mov) == (set (reg r0) (const_int imm16)) 25501 curr (movk) == (set (zero_extract (reg r0) 25502 (const_int 16) 25503 (const_int 16)) 25504 (const_int imm16_1)) */ 25505 25506 set_dest = SET_DEST (curr_set); 25507 25508 if (GET_CODE (set_dest) == ZERO_EXTRACT 25509 && CONST_INT_P (SET_SRC (curr_set)) 25510 && CONST_INT_P (SET_SRC (prev_set)) 25511 && CONST_INT_P (XEXP (set_dest, 2)) 25512 && INTVAL (XEXP (set_dest, 2)) == 16 25513 && REG_P (XEXP (set_dest, 0)) 25514 && REG_P (SET_DEST (prev_set)) 25515 && REGNO (XEXP (set_dest, 0)) == REGNO (SET_DEST (prev_set))) 25516 { 25517 return true; 25518 } 25519 } 25520 25521 if (simple_sets_p && aarch64_fusion_enabled_p (AARCH64_FUSE_ADRP_ADD)) 25522 { 25523 25524 /* We're trying to match: 25525 prev (adrp) == (set (reg r1) 25526 (high (symbol_ref ("SYM")))) 25527 curr (add) == (set (reg r0) 25528 (lo_sum (reg r1) 25529 (symbol_ref ("SYM")))) 25530 Note that r0 need not necessarily be the same as r1, especially 25531 during pre-regalloc scheduling. */ 25532 25533 if (satisfies_constraint_Ush (SET_SRC (prev_set)) 25534 && REG_P (SET_DEST (prev_set)) && REG_P (SET_DEST (curr_set))) 25535 { 25536 if (GET_CODE (SET_SRC (curr_set)) == LO_SUM 25537 && REG_P (XEXP (SET_SRC (curr_set), 0)) 25538 && REGNO (XEXP (SET_SRC (curr_set), 0)) 25539 == REGNO (SET_DEST (prev_set)) 25540 && rtx_equal_p (XEXP (SET_SRC (prev_set), 0), 25541 XEXP (SET_SRC (curr_set), 1))) 25542 return true; 25543 } 25544 } 25545 25546 if (simple_sets_p && aarch64_fusion_enabled_p (AARCH64_FUSE_MOVK_MOVK)) 25547 { 25548 25549 /* We're trying to match: 25550 prev (movk) == (set (zero_extract (reg r0) 25551 (const_int 16) 25552 (const_int 32)) 25553 (const_int imm16_1)) 25554 curr (movk) == (set (zero_extract (reg r0) 25555 (const_int 16) 25556 (const_int 48)) 25557 (const_int imm16_2)) */ 25558 25559 if (GET_CODE (SET_DEST (prev_set)) == ZERO_EXTRACT 25560 && GET_CODE (SET_DEST (curr_set)) == ZERO_EXTRACT 25561 && REG_P (XEXP (SET_DEST (prev_set), 0)) 25562 && REG_P (XEXP (SET_DEST (curr_set), 0)) 25563 && REGNO (XEXP (SET_DEST (prev_set), 0)) 25564 == REGNO (XEXP (SET_DEST (curr_set), 0)) 25565 && CONST_INT_P (XEXP (SET_DEST (prev_set), 2)) 25566 && CONST_INT_P (XEXP (SET_DEST (curr_set), 2)) 25567 && INTVAL (XEXP (SET_DEST (prev_set), 2)) == 32 25568 && INTVAL (XEXP (SET_DEST (curr_set), 2)) == 48 25569 && CONST_INT_P (SET_SRC (prev_set)) 25570 && CONST_INT_P (SET_SRC (curr_set))) 25571 return true; 25572 25573 } 25574 if (simple_sets_p && aarch64_fusion_enabled_p (AARCH64_FUSE_ADRP_LDR)) 25575 { 25576 /* We're trying to match: 25577 prev (adrp) == (set (reg r0) 25578 (high (symbol_ref ("SYM")))) 25579 curr (ldr) == (set (reg r1) 25580 (mem (lo_sum (reg r0) 25581 (symbol_ref ("SYM"))))) 25582 or 25583 curr (ldr) == (set (reg r1) 25584 (zero_extend (mem 25585 (lo_sum (reg r0) 25586 (symbol_ref ("SYM")))))) */ 25587 if (satisfies_constraint_Ush (SET_SRC (prev_set)) 25588 && REG_P (SET_DEST (prev_set)) && REG_P (SET_DEST (curr_set))) 25589 { 25590 rtx curr_src = SET_SRC (curr_set); 25591 25592 if (GET_CODE (curr_src) == ZERO_EXTEND) 25593 curr_src = XEXP (curr_src, 0); 25594 25595 if (MEM_P (curr_src) && GET_CODE (XEXP (curr_src, 0)) == LO_SUM 25596 && REG_P (XEXP (XEXP (curr_src, 0), 0)) 25597 && REGNO (XEXP (XEXP (curr_src, 0), 0)) 25598 == REGNO (SET_DEST (prev_set)) 25599 && rtx_equal_p (XEXP (XEXP (curr_src, 0), 1), 25600 XEXP (SET_SRC (prev_set), 0))) 25601 return true; 25602 } 25603 } 25604 25605 /* Fuse compare (CMP/CMN/TST/BICS) and conditional branch. */ 25606 if (aarch64_fusion_enabled_p (AARCH64_FUSE_CMP_BRANCH) 25607 && prev_set && curr_set && any_condjump_p (curr) 25608 && GET_CODE (SET_SRC (prev_set)) == COMPARE 25609 && SCALAR_INT_MODE_P (GET_MODE (XEXP (SET_SRC (prev_set), 0))) 25610 && reg_referenced_p (SET_DEST (prev_set), PATTERN (curr))) 25611 return true; 25612 25613 /* Fuse flag-setting ALU instructions and conditional branch. */ 25614 if (aarch64_fusion_enabled_p (AARCH64_FUSE_ALU_BRANCH) 25615 && any_condjump_p (curr)) 25616 { 25617 unsigned int condreg1, condreg2; 25618 rtx cc_reg_1; 25619 aarch64_fixed_condition_code_regs (&condreg1, &condreg2); 25620 cc_reg_1 = gen_rtx_REG (CCmode, condreg1); 25621 25622 if (reg_referenced_p (cc_reg_1, PATTERN (curr)) 25623 && prev 25624 && modified_in_p (cc_reg_1, prev)) 25625 { 25626 enum attr_type prev_type = get_attr_type (prev); 25627 25628 /* FIXME: this misses some which is considered simple arthematic 25629 instructions for ThunderX. Simple shifts are missed here. */ 25630 if (prev_type == TYPE_ALUS_SREG 25631 || prev_type == TYPE_ALUS_IMM 25632 || prev_type == TYPE_LOGICS_REG 25633 || prev_type == TYPE_LOGICS_IMM) 25634 return true; 25635 } 25636 } 25637 25638 /* Fuse ALU instructions and CBZ/CBNZ. */ 25639 if (prev_set 25640 && curr_set 25641 && aarch64_fusion_enabled_p (AARCH64_FUSE_ALU_CBZ) 25642 && any_condjump_p (curr)) 25643 { 25644 /* We're trying to match: 25645 prev (alu_insn) == (set (r0) plus ((r0) (r1/imm))) 25646 curr (cbz) == (set (pc) (if_then_else (eq/ne) (r0) 25647 (const_int 0)) 25648 (label_ref ("SYM")) 25649 (pc)) */ 25650 if (SET_DEST (curr_set) == (pc_rtx) 25651 && GET_CODE (SET_SRC (curr_set)) == IF_THEN_ELSE 25652 && REG_P (XEXP (XEXP (SET_SRC (curr_set), 0), 0)) 25653 && REG_P (SET_DEST (prev_set)) 25654 && REGNO (SET_DEST (prev_set)) 25655 == REGNO (XEXP (XEXP (SET_SRC (curr_set), 0), 0))) 25656 { 25657 /* Fuse ALU operations followed by conditional branch instruction. */ 25658 switch (get_attr_type (prev)) 25659 { 25660 case TYPE_ALU_IMM: 25661 case TYPE_ALU_SREG: 25662 case TYPE_ADC_REG: 25663 case TYPE_ADC_IMM: 25664 case TYPE_ADCS_REG: 25665 case TYPE_ADCS_IMM: 25666 case TYPE_LOGIC_REG: 25667 case TYPE_LOGIC_IMM: 25668 case TYPE_CSEL: 25669 case TYPE_ADR: 25670 case TYPE_MOV_IMM: 25671 case TYPE_SHIFT_REG: 25672 case TYPE_SHIFT_IMM: 25673 case TYPE_BFM: 25674 case TYPE_RBIT: 25675 case TYPE_REV: 25676 case TYPE_EXTEND: 25677 return true; 25678 25679 default:; 25680 } 25681 } 25682 } 25683 25684 /* Fuse A+B+1 and A-B-1 */ 25685 if (simple_sets_p 25686 && aarch64_fusion_enabled_p (AARCH64_FUSE_ADDSUB_2REG_CONST1)) 25687 { 25688 /* We're trying to match: 25689 prev == (set (r0) (plus (r0) (r1))) 25690 curr == (set (r0) (plus (r0) (const_int 1))) 25691 or: 25692 prev == (set (r0) (minus (r0) (r1))) 25693 curr == (set (r0) (plus (r0) (const_int -1))) */ 25694 25695 rtx prev_src = SET_SRC (prev_set); 25696 rtx curr_src = SET_SRC (curr_set); 25697 25698 int polarity = 1; 25699 if (GET_CODE (prev_src) == MINUS) 25700 polarity = -1; 25701 25702 if (GET_CODE (curr_src) == PLUS 25703 && (GET_CODE (prev_src) == PLUS || GET_CODE (prev_src) == MINUS) 25704 && CONST_INT_P (XEXP (curr_src, 1)) 25705 && INTVAL (XEXP (curr_src, 1)) == polarity 25706 && REG_P (XEXP (curr_src, 0)) 25707 && REG_P (SET_DEST (prev_set)) 25708 && REGNO (SET_DEST (prev_set)) == REGNO (XEXP (curr_src, 0))) 25709 return true; 25710 } 25711 25712 return false; 25713 } 25714 25715 /* Return true iff the instruction fusion described by OP is enabled. */ 25716 25717 bool 25718 aarch64_fusion_enabled_p (enum aarch64_fusion_pairs op) 25719 { 25720 return (aarch64_tune_params.fusible_ops & op) != 0; 25721 } 25722 25723 /* If MEM is in the form of [base+offset], extract the two parts 25724 of address and set to BASE and OFFSET, otherwise return false 25725 after clearing BASE and OFFSET. */ 25726 25727 bool 25728 extract_base_offset_in_addr (rtx mem, rtx *base, rtx *offset) 25729 { 25730 rtx addr; 25731 25732 gcc_assert (MEM_P (mem)); 25733 25734 addr = XEXP (mem, 0); 25735 25736 if (REG_P (addr)) 25737 { 25738 *base = addr; 25739 *offset = const0_rtx; 25740 return true; 25741 } 25742 25743 if (GET_CODE (addr) == PLUS 25744 && REG_P (XEXP (addr, 0)) && CONST_INT_P (XEXP (addr, 1))) 25745 { 25746 *base = XEXP (addr, 0); 25747 *offset = XEXP (addr, 1); 25748 return true; 25749 } 25750 25751 *base = NULL_RTX; 25752 *offset = NULL_RTX; 25753 25754 return false; 25755 } 25756 25757 /* Types for scheduling fusion. */ 25758 enum sched_fusion_type 25759 { 25760 SCHED_FUSION_NONE = 0, 25761 SCHED_FUSION_LD_SIGN_EXTEND, 25762 SCHED_FUSION_LD_ZERO_EXTEND, 25763 SCHED_FUSION_LD, 25764 SCHED_FUSION_ST, 25765 SCHED_FUSION_NUM 25766 }; 25767 25768 /* If INSN is a load or store of address in the form of [base+offset], 25769 extract the two parts and set to BASE and OFFSET. Return scheduling 25770 fusion type this INSN is. */ 25771 25772 static enum sched_fusion_type 25773 fusion_load_store (rtx_insn *insn, rtx *base, rtx *offset) 25774 { 25775 rtx x, dest, src; 25776 enum sched_fusion_type fusion = SCHED_FUSION_LD; 25777 25778 gcc_assert (INSN_P (insn)); 25779 x = PATTERN (insn); 25780 if (GET_CODE (x) != SET) 25781 return SCHED_FUSION_NONE; 25782 25783 src = SET_SRC (x); 25784 dest = SET_DEST (x); 25785 25786 machine_mode dest_mode = GET_MODE (dest); 25787 25788 if (!aarch64_mode_valid_for_sched_fusion_p (dest_mode)) 25789 return SCHED_FUSION_NONE; 25790 25791 if (GET_CODE (src) == SIGN_EXTEND) 25792 { 25793 fusion = SCHED_FUSION_LD_SIGN_EXTEND; 25794 src = XEXP (src, 0); 25795 if (!MEM_P (src) || GET_MODE (src) != SImode) 25796 return SCHED_FUSION_NONE; 25797 } 25798 else if (GET_CODE (src) == ZERO_EXTEND) 25799 { 25800 fusion = SCHED_FUSION_LD_ZERO_EXTEND; 25801 src = XEXP (src, 0); 25802 if (!MEM_P (src) || GET_MODE (src) != SImode) 25803 return SCHED_FUSION_NONE; 25804 } 25805 25806 if (MEM_P (src) && REG_P (dest)) 25807 extract_base_offset_in_addr (src, base, offset); 25808 else if (MEM_P (dest) && (REG_P (src) || src == const0_rtx)) 25809 { 25810 fusion = SCHED_FUSION_ST; 25811 extract_base_offset_in_addr (dest, base, offset); 25812 } 25813 else 25814 return SCHED_FUSION_NONE; 25815 25816 if (*base == NULL_RTX || *offset == NULL_RTX) 25817 fusion = SCHED_FUSION_NONE; 25818 25819 return fusion; 25820 } 25821 25822 /* Implement the TARGET_SCHED_FUSION_PRIORITY hook. 25823 25824 Currently we only support to fuse ldr or str instructions, so FUSION_PRI 25825 and PRI are only calculated for these instructions. For other instruction, 25826 FUSION_PRI and PRI are simply set to MAX_PRI - 1. In the future, other 25827 type instruction fusion can be added by returning different priorities. 25828 25829 It's important that irrelevant instructions get the largest FUSION_PRI. */ 25830 25831 static void 25832 aarch64_sched_fusion_priority (rtx_insn *insn, int max_pri, 25833 int *fusion_pri, int *pri) 25834 { 25835 int tmp, off_val; 25836 rtx base, offset; 25837 enum sched_fusion_type fusion; 25838 25839 gcc_assert (INSN_P (insn)); 25840 25841 tmp = max_pri - 1; 25842 fusion = fusion_load_store (insn, &base, &offset); 25843 if (fusion == SCHED_FUSION_NONE) 25844 { 25845 *pri = tmp; 25846 *fusion_pri = tmp; 25847 return; 25848 } 25849 25850 /* Set FUSION_PRI according to fusion type and base register. */ 25851 *fusion_pri = tmp - fusion * FIRST_PSEUDO_REGISTER - REGNO (base); 25852 25853 /* Calculate PRI. */ 25854 tmp /= 2; 25855 25856 /* INSN with smaller offset goes first. */ 25857 off_val = (int)(INTVAL (offset)); 25858 if (off_val >= 0) 25859 tmp -= (off_val & 0xfffff); 25860 else 25861 tmp += ((- off_val) & 0xfffff); 25862 25863 *pri = tmp; 25864 return; 25865 } 25866 25867 /* Implement the TARGET_SCHED_ADJUST_PRIORITY hook. 25868 Adjust priority of sha1h instructions so they are scheduled before 25869 other SHA1 instructions. */ 25870 25871 static int 25872 aarch64_sched_adjust_priority (rtx_insn *insn, int priority) 25873 { 25874 rtx x = PATTERN (insn); 25875 25876 if (GET_CODE (x) == SET) 25877 { 25878 x = SET_SRC (x); 25879 25880 if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_SHA1H) 25881 return priority + 10; 25882 } 25883 25884 return priority; 25885 } 25886 25887 /* If REVERSED is null, return true if memory reference *MEM2 comes 25888 immediately after memory reference *MEM1. Do not change the references 25889 in this case. 25890 25891 Otherwise, check if *MEM1 and *MEM2 are consecutive memory references and, 25892 if they are, try to make them use constant offsets from the same base 25893 register. Return true on success. When returning true, set *REVERSED 25894 to true if *MEM1 comes after *MEM2, false if *MEM1 comes before *MEM2. */ 25895 static bool 25896 aarch64_check_consecutive_mems (rtx *mem1, rtx *mem2, bool *reversed) 25897 { 25898 if (reversed) 25899 *reversed = false; 25900 25901 if (GET_RTX_CLASS (GET_CODE (XEXP (*mem1, 0))) == RTX_AUTOINC 25902 || GET_RTX_CLASS (GET_CODE (XEXP (*mem2, 0))) == RTX_AUTOINC) 25903 return false; 25904 25905 if (!MEM_SIZE_KNOWN_P (*mem1) || !MEM_SIZE_KNOWN_P (*mem2)) 25906 return false; 25907 25908 auto size1 = MEM_SIZE (*mem1); 25909 auto size2 = MEM_SIZE (*mem2); 25910 25911 rtx base1, base2, offset1, offset2; 25912 extract_base_offset_in_addr (*mem1, &base1, &offset1); 25913 extract_base_offset_in_addr (*mem2, &base2, &offset2); 25914 25915 /* Make sure at least one memory is in base+offset form. */ 25916 if (!(base1 && offset1) && !(base2 && offset2)) 25917 return false; 25918 25919 /* If both mems already use the same base register, just check the 25920 offsets. */ 25921 if (base1 && base2 && rtx_equal_p (base1, base2)) 25922 { 25923 if (!offset1 || !offset2) 25924 return false; 25925 25926 if (known_eq (UINTVAL (offset1) + size1, UINTVAL (offset2))) 25927 return true; 25928 25929 if (known_eq (UINTVAL (offset2) + size2, UINTVAL (offset1)) && reversed) 25930 { 25931 *reversed = true; 25932 return true; 25933 } 25934 25935 return false; 25936 } 25937 25938 /* Otherwise, check whether the MEM_EXPRs and MEM_OFFSETs together 25939 guarantee that the values are consecutive. */ 25940 if (MEM_EXPR (*mem1) 25941 && MEM_EXPR (*mem2) 25942 && MEM_OFFSET_KNOWN_P (*mem1) 25943 && MEM_OFFSET_KNOWN_P (*mem2)) 25944 { 25945 poly_int64 expr_offset1; 25946 poly_int64 expr_offset2; 25947 tree expr_base1 = get_addr_base_and_unit_offset (MEM_EXPR (*mem1), 25948 &expr_offset1); 25949 tree expr_base2 = get_addr_base_and_unit_offset (MEM_EXPR (*mem2), 25950 &expr_offset2); 25951 if (!expr_base1 25952 || !expr_base2 25953 || !DECL_P (expr_base1) 25954 || !operand_equal_p (expr_base1, expr_base2, OEP_ADDRESS_OF)) 25955 return false; 25956 25957 expr_offset1 += MEM_OFFSET (*mem1); 25958 expr_offset2 += MEM_OFFSET (*mem2); 25959 25960 if (known_eq (expr_offset1 + size1, expr_offset2)) 25961 ; 25962 else if (known_eq (expr_offset2 + size2, expr_offset1) && reversed) 25963 *reversed = true; 25964 else 25965 return false; 25966 25967 if (reversed) 25968 { 25969 if (base2) 25970 { 25971 rtx addr1 = plus_constant (Pmode, XEXP (*mem2, 0), 25972 expr_offset1 - expr_offset2); 25973 *mem1 = replace_equiv_address_nv (*mem1, addr1); 25974 } 25975 else 25976 { 25977 rtx addr2 = plus_constant (Pmode, XEXP (*mem1, 0), 25978 expr_offset2 - expr_offset1); 25979 *mem2 = replace_equiv_address_nv (*mem2, addr2); 25980 } 25981 } 25982 return true; 25983 } 25984 25985 return false; 25986 } 25987 25988 /* Return true if MEM1 and MEM2 can be combined into a single access 25989 of mode MODE, with the combined access having the same address as MEM1. */ 25990 25991 bool 25992 aarch64_mergeable_load_pair_p (machine_mode mode, rtx mem1, rtx mem2) 25993 { 25994 if (STRICT_ALIGNMENT && MEM_ALIGN (mem1) < GET_MODE_ALIGNMENT (mode)) 25995 return false; 25996 return aarch64_check_consecutive_mems (&mem1, &mem2, nullptr); 25997 } 25998 25999 /* Given OPERANDS of consecutive load/store, check if we can merge 26000 them into ldp/stp. LOAD is true if they are load instructions. 26001 MODE is the mode of memory operands. */ 26002 26003 bool 26004 aarch64_operands_ok_for_ldpstp (rtx *operands, bool load, 26005 machine_mode mode) 26006 { 26007 enum reg_class rclass_1, rclass_2; 26008 rtx mem_1, mem_2, reg_1, reg_2; 26009 26010 /* Allow the tuning structure to disable LDP instruction formation 26011 from combining instructions (e.g., in peephole2). */ 26012 if (load && (aarch64_tune_params.extra_tuning_flags 26013 & AARCH64_EXTRA_TUNE_NO_LDP_COMBINE)) 26014 return false; 26015 26016 if (load) 26017 { 26018 mem_1 = operands[1]; 26019 mem_2 = operands[3]; 26020 reg_1 = operands[0]; 26021 reg_2 = operands[2]; 26022 gcc_assert (REG_P (reg_1) && REG_P (reg_2)); 26023 if (REGNO (reg_1) == REGNO (reg_2)) 26024 return false; 26025 if (reg_overlap_mentioned_p (reg_1, mem_2)) 26026 return false; 26027 } 26028 else 26029 { 26030 mem_1 = operands[0]; 26031 mem_2 = operands[2]; 26032 reg_1 = operands[1]; 26033 reg_2 = operands[3]; 26034 } 26035 26036 /* The mems cannot be volatile. */ 26037 if (MEM_VOLATILE_P (mem_1) || MEM_VOLATILE_P (mem_2)) 26038 return false; 26039 26040 /* If we have SImode and slow unaligned ldp, 26041 check the alignment to be at least 8 byte. */ 26042 if (mode == SImode 26043 && (aarch64_tune_params.extra_tuning_flags 26044 & AARCH64_EXTRA_TUNE_SLOW_UNALIGNED_LDPW) 26045 && !optimize_size 26046 && MEM_ALIGN (mem_1) < 8 * BITS_PER_UNIT) 26047 return false; 26048 26049 /* Check if the addresses are in the form of [base+offset]. */ 26050 bool reversed = false; 26051 if (!aarch64_check_consecutive_mems (&mem_1, &mem_2, &reversed)) 26052 return false; 26053 26054 /* The operands must be of the same size. */ 26055 gcc_assert (known_eq (GET_MODE_SIZE (GET_MODE (mem_1)), 26056 GET_MODE_SIZE (GET_MODE (mem_2)))); 26057 26058 /* The lower memory access must be a mem-pair operand. */ 26059 rtx lower_mem = reversed ? mem_2 : mem_1; 26060 if (!aarch64_mem_pair_operand (lower_mem, GET_MODE (lower_mem))) 26061 return false; 26062 26063 if (REG_P (reg_1) && FP_REGNUM_P (REGNO (reg_1))) 26064 rclass_1 = FP_REGS; 26065 else 26066 rclass_1 = GENERAL_REGS; 26067 26068 if (REG_P (reg_2) && FP_REGNUM_P (REGNO (reg_2))) 26069 rclass_2 = FP_REGS; 26070 else 26071 rclass_2 = GENERAL_REGS; 26072 26073 /* Check if the registers are of same class. */ 26074 if (rclass_1 != rclass_2) 26075 return false; 26076 26077 return true; 26078 } 26079 26080 /* Given OPERANDS of consecutive load/store that can be merged, 26081 swap them if they are not in ascending order. */ 26082 void 26083 aarch64_swap_ldrstr_operands (rtx* operands, bool load) 26084 { 26085 int mem_op = load ? 1 : 0; 26086 bool reversed = false; 26087 if (!aarch64_check_consecutive_mems (operands + mem_op, 26088 operands + mem_op + 2, &reversed)) 26089 gcc_unreachable (); 26090 26091 if (reversed) 26092 { 26093 /* Irrespective of whether this is a load or a store, 26094 we do the same swap. */ 26095 std::swap (operands[0], operands[2]); 26096 std::swap (operands[1], operands[3]); 26097 } 26098 } 26099 26100 /* Taking X and Y to be HOST_WIDE_INT pointers, return the result of a 26101 comparison between the two. */ 26102 int 26103 aarch64_host_wide_int_compare (const void *x, const void *y) 26104 { 26105 return wi::cmps (* ((const HOST_WIDE_INT *) x), 26106 * ((const HOST_WIDE_INT *) y)); 26107 } 26108 26109 /* Taking X and Y to be pairs of RTX, one pointing to a MEM rtx and the 26110 other pointing to a REG rtx containing an offset, compare the offsets 26111 of the two pairs. 26112 26113 Return: 26114 26115 1 iff offset (X) > offset (Y) 26116 0 iff offset (X) == offset (Y) 26117 -1 iff offset (X) < offset (Y) */ 26118 int 26119 aarch64_ldrstr_offset_compare (const void *x, const void *y) 26120 { 26121 const rtx * operands_1 = (const rtx *) x; 26122 const rtx * operands_2 = (const rtx *) y; 26123 rtx mem_1, mem_2, base, offset_1, offset_2; 26124 26125 if (MEM_P (operands_1[0])) 26126 mem_1 = operands_1[0]; 26127 else 26128 mem_1 = operands_1[1]; 26129 26130 if (MEM_P (operands_2[0])) 26131 mem_2 = operands_2[0]; 26132 else 26133 mem_2 = operands_2[1]; 26134 26135 /* Extract the offsets. */ 26136 extract_base_offset_in_addr (mem_1, &base, &offset_1); 26137 extract_base_offset_in_addr (mem_2, &base, &offset_2); 26138 26139 gcc_assert (offset_1 != NULL_RTX && offset_2 != NULL_RTX); 26140 26141 return wi::cmps (INTVAL (offset_1), INTVAL (offset_2)); 26142 } 26143 26144 /* Given OPERANDS of consecutive load/store, check if we can merge 26145 them into ldp/stp by adjusting the offset. LOAD is true if they 26146 are load instructions. MODE is the mode of memory operands. 26147 26148 Given below consecutive stores: 26149 26150 str w1, [xb, 0x100] 26151 str w1, [xb, 0x104] 26152 str w1, [xb, 0x108] 26153 str w1, [xb, 0x10c] 26154 26155 Though the offsets are out of the range supported by stp, we can 26156 still pair them after adjusting the offset, like: 26157 26158 add scratch, xb, 0x100 26159 stp w1, w1, [scratch] 26160 stp w1, w1, [scratch, 0x8] 26161 26162 The peephole patterns detecting this opportunity should guarantee 26163 the scratch register is avaliable. */ 26164 26165 bool 26166 aarch64_operands_adjust_ok_for_ldpstp (rtx *operands, bool load, 26167 machine_mode mode) 26168 { 26169 const int num_insns = 4; 26170 enum reg_class rclass; 26171 HOST_WIDE_INT offvals[num_insns], msize; 26172 rtx mem[num_insns], reg[num_insns], base[num_insns], offset[num_insns]; 26173 26174 if (load) 26175 { 26176 for (int i = 0; i < num_insns; i++) 26177 { 26178 reg[i] = operands[2 * i]; 26179 mem[i] = operands[2 * i + 1]; 26180 26181 gcc_assert (REG_P (reg[i])); 26182 } 26183 26184 /* Do not attempt to merge the loads if the loads clobber each other. */ 26185 for (int i = 0; i < 8; i += 2) 26186 for (int j = i + 2; j < 8; j += 2) 26187 if (reg_overlap_mentioned_p (operands[i], operands[j])) 26188 return false; 26189 } 26190 else 26191 for (int i = 0; i < num_insns; i++) 26192 { 26193 mem[i] = operands[2 * i]; 26194 reg[i] = operands[2 * i + 1]; 26195 } 26196 26197 /* Skip if memory operand is by itself valid for ldp/stp. */ 26198 if (!MEM_P (mem[0]) || aarch64_mem_pair_operand (mem[0], mode)) 26199 return false; 26200 26201 for (int i = 0; i < num_insns; i++) 26202 { 26203 /* The mems cannot be volatile. */ 26204 if (MEM_VOLATILE_P (mem[i])) 26205 return false; 26206 26207 /* Check if the addresses are in the form of [base+offset]. */ 26208 extract_base_offset_in_addr (mem[i], base + i, offset + i); 26209 if (base[i] == NULL_RTX || offset[i] == NULL_RTX) 26210 return false; 26211 } 26212 26213 /* Check if the registers are of same class. */ 26214 rclass = REG_P (reg[0]) && FP_REGNUM_P (REGNO (reg[0])) 26215 ? FP_REGS : GENERAL_REGS; 26216 26217 for (int i = 1; i < num_insns; i++) 26218 if (REG_P (reg[i]) && FP_REGNUM_P (REGNO (reg[i]))) 26219 { 26220 if (rclass != FP_REGS) 26221 return false; 26222 } 26223 else 26224 { 26225 if (rclass != GENERAL_REGS) 26226 return false; 26227 } 26228 26229 /* Only the last register in the order in which they occur 26230 may be clobbered by the load. */ 26231 if (rclass == GENERAL_REGS && load) 26232 for (int i = 0; i < num_insns - 1; i++) 26233 if (reg_mentioned_p (reg[i], mem[i])) 26234 return false; 26235 26236 /* Check if the bases are same. */ 26237 for (int i = 0; i < num_insns - 1; i++) 26238 if (!rtx_equal_p (base[i], base[i + 1])) 26239 return false; 26240 26241 for (int i = 0; i < num_insns; i++) 26242 offvals[i] = INTVAL (offset[i]); 26243 26244 msize = GET_MODE_SIZE (mode).to_constant (); 26245 26246 /* Check if the offsets can be put in the right order to do a ldp/stp. */ 26247 qsort (offvals, num_insns, sizeof (HOST_WIDE_INT), 26248 aarch64_host_wide_int_compare); 26249 26250 if (!(offvals[1] == offvals[0] + msize 26251 && offvals[3] == offvals[2] + msize)) 26252 return false; 26253 26254 /* Check that offsets are within range of each other. The ldp/stp 26255 instructions have 7 bit immediate offsets, so use 0x80. */ 26256 if (offvals[2] - offvals[0] >= msize * 0x80) 26257 return false; 26258 26259 /* The offsets must be aligned with respect to each other. */ 26260 if (offvals[0] % msize != offvals[2] % msize) 26261 return false; 26262 26263 /* If we have SImode and slow unaligned ldp, 26264 check the alignment to be at least 8 byte. */ 26265 if (mode == SImode 26266 && (aarch64_tune_params.extra_tuning_flags 26267 & AARCH64_EXTRA_TUNE_SLOW_UNALIGNED_LDPW) 26268 && !optimize_size 26269 && MEM_ALIGN (mem[0]) < 8 * BITS_PER_UNIT) 26270 return false; 26271 26272 return true; 26273 } 26274 26275 /* Given OPERANDS of consecutive load/store, this function pairs them 26276 into LDP/STP after adjusting the offset. It depends on the fact 26277 that the operands can be sorted so the offsets are correct for STP. 26278 MODE is the mode of memory operands. CODE is the rtl operator 26279 which should be applied to all memory operands, it's SIGN_EXTEND, 26280 ZERO_EXTEND or UNKNOWN. */ 26281 26282 bool 26283 aarch64_gen_adjusted_ldpstp (rtx *operands, bool load, 26284 machine_mode mode, RTX_CODE code) 26285 { 26286 rtx base, offset_1, offset_3, t1, t2; 26287 rtx mem_1, mem_2, mem_3, mem_4; 26288 rtx temp_operands[8]; 26289 HOST_WIDE_INT off_val_1, off_val_3, base_off, new_off_1, new_off_3, 26290 stp_off_upper_limit, stp_off_lower_limit, msize; 26291 26292 /* We make changes on a copy as we may still bail out. */ 26293 for (int i = 0; i < 8; i ++) 26294 temp_operands[i] = operands[i]; 26295 26296 /* Sort the operands. Note for cases as below: 26297 [base + 0x310] = A 26298 [base + 0x320] = B 26299 [base + 0x330] = C 26300 [base + 0x320] = D 26301 We need stable sorting otherwise wrong data may be store to offset 0x320. 26302 Also note the dead store in above case should be optimized away, but no 26303 guarantees here. */ 26304 gcc_stablesort(temp_operands, 4, 2 * sizeof (rtx *), 26305 aarch64_ldrstr_offset_compare); 26306 26307 /* Copy the memory operands so that if we have to bail for some 26308 reason the original addresses are unchanged. */ 26309 if (load) 26310 { 26311 mem_1 = copy_rtx (temp_operands[1]); 26312 mem_2 = copy_rtx (temp_operands[3]); 26313 mem_3 = copy_rtx (temp_operands[5]); 26314 mem_4 = copy_rtx (temp_operands[7]); 26315 } 26316 else 26317 { 26318 mem_1 = copy_rtx (temp_operands[0]); 26319 mem_2 = copy_rtx (temp_operands[2]); 26320 mem_3 = copy_rtx (temp_operands[4]); 26321 mem_4 = copy_rtx (temp_operands[6]); 26322 gcc_assert (code == UNKNOWN); 26323 } 26324 26325 extract_base_offset_in_addr (mem_1, &base, &offset_1); 26326 extract_base_offset_in_addr (mem_3, &base, &offset_3); 26327 gcc_assert (base != NULL_RTX && offset_1 != NULL_RTX 26328 && offset_3 != NULL_RTX); 26329 26330 /* Adjust offset so it can fit in LDP/STP instruction. */ 26331 msize = GET_MODE_SIZE (mode).to_constant(); 26332 stp_off_upper_limit = msize * (0x40 - 1); 26333 stp_off_lower_limit = - msize * 0x40; 26334 26335 off_val_1 = INTVAL (offset_1); 26336 off_val_3 = INTVAL (offset_3); 26337 26338 /* The base offset is optimally half way between the two STP/LDP offsets. */ 26339 if (msize <= 4) 26340 base_off = (off_val_1 + off_val_3) / 2; 26341 else 26342 /* However, due to issues with negative LDP/STP offset generation for 26343 larger modes, for DF, DI and vector modes. we must not use negative 26344 addresses smaller than 9 signed unadjusted bits can store. This 26345 provides the most range in this case. */ 26346 base_off = off_val_1; 26347 26348 /* Adjust the base so that it is aligned with the addresses but still 26349 optimal. */ 26350 if (base_off % msize != off_val_1 % msize) 26351 /* Fix the offset, bearing in mind we want to make it bigger not 26352 smaller. */ 26353 base_off += (((base_off % msize) - (off_val_1 % msize)) + msize) % msize; 26354 else if (msize <= 4) 26355 /* The negative range of LDP/STP is one larger than the positive range. */ 26356 base_off += msize; 26357 26358 /* Check if base offset is too big or too small. We can attempt to resolve 26359 this issue by setting it to the maximum value and seeing if the offsets 26360 still fit. */ 26361 if (base_off >= 0x1000) 26362 { 26363 base_off = 0x1000 - 1; 26364 /* We must still make sure that the base offset is aligned with respect 26365 to the address. But it may not be made any bigger. */ 26366 base_off -= (((base_off % msize) - (off_val_1 % msize)) + msize) % msize; 26367 } 26368 26369 /* Likewise for the case where the base is too small. */ 26370 if (base_off <= -0x1000) 26371 { 26372 base_off = -0x1000 + 1; 26373 base_off += (((base_off % msize) - (off_val_1 % msize)) + msize) % msize; 26374 } 26375 26376 /* Offset of the first STP/LDP. */ 26377 new_off_1 = off_val_1 - base_off; 26378 26379 /* Offset of the second STP/LDP. */ 26380 new_off_3 = off_val_3 - base_off; 26381 26382 /* The offsets must be within the range of the LDP/STP instructions. */ 26383 if (new_off_1 > stp_off_upper_limit || new_off_1 < stp_off_lower_limit 26384 || new_off_3 > stp_off_upper_limit || new_off_3 < stp_off_lower_limit) 26385 return false; 26386 26387 replace_equiv_address_nv (mem_1, plus_constant (Pmode, operands[8], 26388 new_off_1), true); 26389 replace_equiv_address_nv (mem_2, plus_constant (Pmode, operands[8], 26390 new_off_1 + msize), true); 26391 replace_equiv_address_nv (mem_3, plus_constant (Pmode, operands[8], 26392 new_off_3), true); 26393 replace_equiv_address_nv (mem_4, plus_constant (Pmode, operands[8], 26394 new_off_3 + msize), true); 26395 26396 if (!aarch64_mem_pair_operand (mem_1, mode) 26397 || !aarch64_mem_pair_operand (mem_3, mode)) 26398 return false; 26399 26400 if (code == ZERO_EXTEND) 26401 { 26402 mem_1 = gen_rtx_ZERO_EXTEND (DImode, mem_1); 26403 mem_2 = gen_rtx_ZERO_EXTEND (DImode, mem_2); 26404 mem_3 = gen_rtx_ZERO_EXTEND (DImode, mem_3); 26405 mem_4 = gen_rtx_ZERO_EXTEND (DImode, mem_4); 26406 } 26407 else if (code == SIGN_EXTEND) 26408 { 26409 mem_1 = gen_rtx_SIGN_EXTEND (DImode, mem_1); 26410 mem_2 = gen_rtx_SIGN_EXTEND (DImode, mem_2); 26411 mem_3 = gen_rtx_SIGN_EXTEND (DImode, mem_3); 26412 mem_4 = gen_rtx_SIGN_EXTEND (DImode, mem_4); 26413 } 26414 26415 if (load) 26416 { 26417 operands[0] = temp_operands[0]; 26418 operands[1] = mem_1; 26419 operands[2] = temp_operands[2]; 26420 operands[3] = mem_2; 26421 operands[4] = temp_operands[4]; 26422 operands[5] = mem_3; 26423 operands[6] = temp_operands[6]; 26424 operands[7] = mem_4; 26425 } 26426 else 26427 { 26428 operands[0] = mem_1; 26429 operands[1] = temp_operands[1]; 26430 operands[2] = mem_2; 26431 operands[3] = temp_operands[3]; 26432 operands[4] = mem_3; 26433 operands[5] = temp_operands[5]; 26434 operands[6] = mem_4; 26435 operands[7] = temp_operands[7]; 26436 } 26437 26438 /* Emit adjusting instruction. */ 26439 emit_insn (gen_rtx_SET (operands[8], plus_constant (DImode, base, base_off))); 26440 /* Emit ldp/stp instructions. */ 26441 t1 = gen_rtx_SET (operands[0], operands[1]); 26442 t2 = gen_rtx_SET (operands[2], operands[3]); 26443 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2))); 26444 t1 = gen_rtx_SET (operands[4], operands[5]); 26445 t2 = gen_rtx_SET (operands[6], operands[7]); 26446 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2))); 26447 return true; 26448 } 26449 26450 /* Implement TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE. Assume for now that 26451 it isn't worth branching around empty masked ops (including masked 26452 stores). */ 26453 26454 static bool 26455 aarch64_empty_mask_is_expensive (unsigned) 26456 { 26457 return false; 26458 } 26459 26460 /* Return 1 if pseudo register should be created and used to hold 26461 GOT address for PIC code. */ 26462 26463 bool 26464 aarch64_use_pseudo_pic_reg (void) 26465 { 26466 return aarch64_cmodel == AARCH64_CMODEL_SMALL_SPIC; 26467 } 26468 26469 /* Implement TARGET_UNSPEC_MAY_TRAP_P. */ 26470 26471 static int 26472 aarch64_unspec_may_trap_p (const_rtx x, unsigned flags) 26473 { 26474 switch (XINT (x, 1)) 26475 { 26476 case UNSPEC_GOTSMALLPIC: 26477 case UNSPEC_GOTSMALLPIC28K: 26478 case UNSPEC_GOTTINYPIC: 26479 return 0; 26480 default: 26481 break; 26482 } 26483 26484 return default_unspec_may_trap_p (x, flags); 26485 } 26486 26487 26488 /* If X is a positive CONST_DOUBLE with a value that is a power of 2 26489 return the log2 of that value. Otherwise return -1. */ 26490 26491 int 26492 aarch64_fpconst_pow_of_2 (rtx x) 26493 { 26494 const REAL_VALUE_TYPE *r; 26495 26496 if (!CONST_DOUBLE_P (x)) 26497 return -1; 26498 26499 r = CONST_DOUBLE_REAL_VALUE (x); 26500 26501 if (REAL_VALUE_NEGATIVE (*r) 26502 || REAL_VALUE_ISNAN (*r) 26503 || REAL_VALUE_ISINF (*r) 26504 || !real_isinteger (r, DFmode)) 26505 return -1; 26506 26507 return exact_log2 (real_to_integer (r)); 26508 } 26509 26510 /* If X is a positive CONST_DOUBLE with a value that is the reciprocal of a 26511 power of 2 (i.e 1/2^n) return the number of float bits. e.g. for x==(1/2^n) 26512 return n. Otherwise return -1. */ 26513 26514 int 26515 aarch64_fpconst_pow2_recip (rtx x) 26516 { 26517 REAL_VALUE_TYPE r0; 26518 26519 if (!CONST_DOUBLE_P (x)) 26520 return -1; 26521 26522 r0 = *CONST_DOUBLE_REAL_VALUE (x); 26523 if (exact_real_inverse (DFmode, &r0) 26524 && !REAL_VALUE_NEGATIVE (r0)) 26525 { 26526 int ret = exact_log2 (real_to_integer (&r0)); 26527 if (ret >= 1 && ret <= 32) 26528 return ret; 26529 } 26530 return -1; 26531 } 26532 26533 /* If X is a vector of equal CONST_DOUBLE values and that value is 26534 Y, return the aarch64_fpconst_pow_of_2 of Y. Otherwise return -1. */ 26535 26536 int 26537 aarch64_vec_fpconst_pow_of_2 (rtx x) 26538 { 26539 int nelts; 26540 if (!CONST_VECTOR_P (x) 26541 || !CONST_VECTOR_NUNITS (x).is_constant (&nelts)) 26542 return -1; 26543 26544 if (GET_MODE_CLASS (GET_MODE (x)) != MODE_VECTOR_FLOAT) 26545 return -1; 26546 26547 int firstval = aarch64_fpconst_pow_of_2 (CONST_VECTOR_ELT (x, 0)); 26548 if (firstval <= 0) 26549 return -1; 26550 26551 for (int i = 1; i < nelts; i++) 26552 if (aarch64_fpconst_pow_of_2 (CONST_VECTOR_ELT (x, i)) != firstval) 26553 return -1; 26554 26555 return firstval; 26556 } 26557 26558 /* Implement TARGET_PROMOTED_TYPE to promote 16-bit floating point types 26559 to float. 26560 26561 __fp16 always promotes through this hook. 26562 _Float16 may promote if TARGET_FLT_EVAL_METHOD is 16, but we do that 26563 through the generic excess precision logic rather than here. */ 26564 26565 static tree 26566 aarch64_promoted_type (const_tree t) 26567 { 26568 if (SCALAR_FLOAT_TYPE_P (t) 26569 && TYPE_MAIN_VARIANT (t) == aarch64_fp16_type_node) 26570 return float_type_node; 26571 26572 return NULL_TREE; 26573 } 26574 26575 /* Implement the TARGET_OPTAB_SUPPORTED_P hook. */ 26576 26577 static bool 26578 aarch64_optab_supported_p (int op, machine_mode mode1, machine_mode, 26579 optimization_type opt_type) 26580 { 26581 switch (op) 26582 { 26583 case rsqrt_optab: 26584 return opt_type == OPTIMIZE_FOR_SPEED && use_rsqrt_p (mode1); 26585 26586 default: 26587 return true; 26588 } 26589 } 26590 26591 /* Implement the TARGET_DWARF_POLY_INDETERMINATE_VALUE hook. */ 26592 26593 static unsigned int 26594 aarch64_dwarf_poly_indeterminate_value (unsigned int i, unsigned int *factor, 26595 int *offset) 26596 { 26597 /* Polynomial invariant 1 == (VG / 2) - 1. */ 26598 gcc_assert (i == 1); 26599 *factor = 2; 26600 *offset = 1; 26601 return AARCH64_DWARF_VG; 26602 } 26603 26604 /* Implement TARGET_LIBGCC_FLOATING_POINT_MODE_SUPPORTED_P - return TRUE 26605 if MODE is HFmode, and punt to the generic implementation otherwise. */ 26606 26607 static bool 26608 aarch64_libgcc_floating_mode_supported_p (scalar_float_mode mode) 26609 { 26610 return (mode == HFmode 26611 ? true 26612 : default_libgcc_floating_mode_supported_p (mode)); 26613 } 26614 26615 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P - return TRUE 26616 if MODE is HFmode, and punt to the generic implementation otherwise. */ 26617 26618 static bool 26619 aarch64_scalar_mode_supported_p (scalar_mode mode) 26620 { 26621 return (mode == HFmode 26622 ? true 26623 : default_scalar_mode_supported_p (mode)); 26624 } 26625 26626 /* Set the value of FLT_EVAL_METHOD. 26627 ISO/IEC TS 18661-3 defines two values that we'd like to make use of: 26628 26629 0: evaluate all operations and constants, whose semantic type has at 26630 most the range and precision of type float, to the range and 26631 precision of float; evaluate all other operations and constants to 26632 the range and precision of the semantic type; 26633 26634 N, where _FloatN is a supported interchange floating type 26635 evaluate all operations and constants, whose semantic type has at 26636 most the range and precision of _FloatN type, to the range and 26637 precision of the _FloatN type; evaluate all other operations and 26638 constants to the range and precision of the semantic type; 26639 26640 If we have the ARMv8.2-A extensions then we support _Float16 in native 26641 precision, so we should set this to 16. Otherwise, we support the type, 26642 but want to evaluate expressions in float precision, so set this to 26643 0. */ 26644 26645 static enum flt_eval_method 26646 aarch64_excess_precision (enum excess_precision_type type) 26647 { 26648 switch (type) 26649 { 26650 case EXCESS_PRECISION_TYPE_FAST: 26651 case EXCESS_PRECISION_TYPE_STANDARD: 26652 /* We can calculate either in 16-bit range and precision or 26653 32-bit range and precision. Make that decision based on whether 26654 we have native support for the ARMv8.2-A 16-bit floating-point 26655 instructions or not. */ 26656 return (TARGET_FP_F16INST 26657 ? FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16 26658 : FLT_EVAL_METHOD_PROMOTE_TO_FLOAT); 26659 case EXCESS_PRECISION_TYPE_IMPLICIT: 26660 case EXCESS_PRECISION_TYPE_FLOAT16: 26661 return FLT_EVAL_METHOD_PROMOTE_TO_FLOAT16; 26662 default: 26663 gcc_unreachable (); 26664 } 26665 return FLT_EVAL_METHOD_UNPREDICTABLE; 26666 } 26667 26668 /* Implement TARGET_SCHED_CAN_SPECULATE_INSN. Return true if INSN can be 26669 scheduled for speculative execution. Reject the long-running division 26670 and square-root instructions. */ 26671 26672 static bool 26673 aarch64_sched_can_speculate_insn (rtx_insn *insn) 26674 { 26675 switch (get_attr_type (insn)) 26676 { 26677 case TYPE_SDIV: 26678 case TYPE_UDIV: 26679 case TYPE_FDIVS: 26680 case TYPE_FDIVD: 26681 case TYPE_FSQRTS: 26682 case TYPE_FSQRTD: 26683 case TYPE_NEON_FP_SQRT_S: 26684 case TYPE_NEON_FP_SQRT_D: 26685 case TYPE_NEON_FP_SQRT_S_Q: 26686 case TYPE_NEON_FP_SQRT_D_Q: 26687 case TYPE_NEON_FP_DIV_S: 26688 case TYPE_NEON_FP_DIV_D: 26689 case TYPE_NEON_FP_DIV_S_Q: 26690 case TYPE_NEON_FP_DIV_D_Q: 26691 return false; 26692 default: 26693 return true; 26694 } 26695 } 26696 26697 /* Implement TARGET_COMPUTE_PRESSURE_CLASSES. */ 26698 26699 static int 26700 aarch64_compute_pressure_classes (reg_class *classes) 26701 { 26702 int i = 0; 26703 classes[i++] = GENERAL_REGS; 26704 classes[i++] = FP_REGS; 26705 /* PR_REGS isn't a useful pressure class because many predicate pseudo 26706 registers need to go in PR_LO_REGS at some point during their 26707 lifetime. Splitting it into two halves has the effect of making 26708 all predicates count against PR_LO_REGS, so that we try whenever 26709 possible to restrict the number of live predicates to 8. This 26710 greatly reduces the amount of spilling in certain loops. */ 26711 classes[i++] = PR_LO_REGS; 26712 classes[i++] = PR_HI_REGS; 26713 return i; 26714 } 26715 26716 /* Implement TARGET_CAN_CHANGE_MODE_CLASS. */ 26717 26718 static bool 26719 aarch64_can_change_mode_class (machine_mode from, 26720 machine_mode to, reg_class_t) 26721 { 26722 unsigned int from_flags = aarch64_classify_vector_mode (from); 26723 unsigned int to_flags = aarch64_classify_vector_mode (to); 26724 26725 bool from_sve_p = (from_flags & VEC_ANY_SVE); 26726 bool to_sve_p = (to_flags & VEC_ANY_SVE); 26727 26728 bool from_partial_sve_p = from_sve_p && (from_flags & VEC_PARTIAL); 26729 bool to_partial_sve_p = to_sve_p && (to_flags & VEC_PARTIAL); 26730 26731 bool from_pred_p = (from_flags & VEC_SVE_PRED); 26732 bool to_pred_p = (to_flags & VEC_SVE_PRED); 26733 26734 bool from_full_advsimd_struct_p = (from_flags == (VEC_ADVSIMD | VEC_STRUCT)); 26735 bool to_partial_advsimd_struct_p = (to_flags == (VEC_ADVSIMD | VEC_STRUCT 26736 | VEC_PARTIAL)); 26737 26738 /* Don't allow changes between predicate modes and other modes. 26739 Only predicate registers can hold predicate modes and only 26740 non-predicate registers can hold non-predicate modes, so any 26741 attempt to mix them would require a round trip through memory. */ 26742 if (from_pred_p != to_pred_p) 26743 return false; 26744 26745 /* Don't allow changes between partial SVE modes and other modes. 26746 The contents of partial SVE modes are distributed evenly across 26747 the register, whereas GCC expects them to be clustered together. */ 26748 if (from_partial_sve_p != to_partial_sve_p) 26749 return false; 26750 26751 /* Similarly reject changes between partial SVE modes that have 26752 different patterns of significant and insignificant bits. */ 26753 if (from_partial_sve_p 26754 && (aarch64_sve_container_bits (from) != aarch64_sve_container_bits (to) 26755 || GET_MODE_UNIT_SIZE (from) != GET_MODE_UNIT_SIZE (to))) 26756 return false; 26757 26758 /* Don't allow changes between partial and full Advanced SIMD structure 26759 modes. */ 26760 if (from_full_advsimd_struct_p && to_partial_advsimd_struct_p) 26761 return false; 26762 26763 if (maybe_ne (BITS_PER_SVE_VECTOR, 128u)) 26764 { 26765 /* Don't allow changes between SVE modes and other modes that might 26766 be bigger than 128 bits. In particular, OImode, CImode and XImode 26767 divide into 128-bit quantities while SVE modes divide into 26768 BITS_PER_SVE_VECTOR quantities. */ 26769 if (from_sve_p && !to_sve_p && maybe_gt (GET_MODE_BITSIZE (to), 128)) 26770 return false; 26771 if (to_sve_p && !from_sve_p && maybe_gt (GET_MODE_BITSIZE (from), 128)) 26772 return false; 26773 } 26774 26775 if (BYTES_BIG_ENDIAN) 26776 { 26777 /* Don't allow changes between SVE data modes and non-SVE modes. 26778 See the comment at the head of aarch64-sve.md for details. */ 26779 if (from_sve_p != to_sve_p) 26780 return false; 26781 26782 /* Don't allow changes in element size: lane 0 of the new vector 26783 would not then be lane 0 of the old vector. See the comment 26784 above aarch64_maybe_expand_sve_subreg_move for a more detailed 26785 description. 26786 26787 In the worst case, this forces a register to be spilled in 26788 one mode and reloaded in the other, which handles the 26789 endianness correctly. */ 26790 if (from_sve_p && GET_MODE_UNIT_SIZE (from) != GET_MODE_UNIT_SIZE (to)) 26791 return false; 26792 } 26793 return true; 26794 } 26795 26796 /* Implement TARGET_EARLY_REMAT_MODES. */ 26797 26798 static void 26799 aarch64_select_early_remat_modes (sbitmap modes) 26800 { 26801 /* SVE values are not normally live across a call, so it should be 26802 worth doing early rematerialization even in VL-specific mode. */ 26803 for (int i = 0; i < NUM_MACHINE_MODES; ++i) 26804 if (aarch64_sve_mode_p ((machine_mode) i)) 26805 bitmap_set_bit (modes, i); 26806 } 26807 26808 /* Override the default target speculation_safe_value. */ 26809 static rtx 26810 aarch64_speculation_safe_value (machine_mode mode, 26811 rtx result, rtx val, rtx failval) 26812 { 26813 /* Maybe we should warn if falling back to hard barriers. They are 26814 likely to be noticably more expensive than the alternative below. */ 26815 if (!aarch64_track_speculation) 26816 return default_speculation_safe_value (mode, result, val, failval); 26817 26818 if (!REG_P (val)) 26819 val = copy_to_mode_reg (mode, val); 26820 26821 if (!aarch64_reg_or_zero (failval, mode)) 26822 failval = copy_to_mode_reg (mode, failval); 26823 26824 emit_insn (gen_despeculate_copy (mode, result, val, failval)); 26825 return result; 26826 } 26827 26828 /* Implement TARGET_ESTIMATED_POLY_VALUE. 26829 Look into the tuning structure for an estimate. 26830 KIND specifies the type of requested estimate: min, max or likely. 26831 For cores with a known SVE width all three estimates are the same. 26832 For generic SVE tuning we want to distinguish the maximum estimate from 26833 the minimum and likely ones. 26834 The likely estimate is the same as the minimum in that case to give a 26835 conservative behavior of auto-vectorizing with SVE when it is a win 26836 even for 128-bit SVE. 26837 When SVE width information is available VAL.coeffs[1] is multiplied by 26838 the number of VQ chunks over the initial Advanced SIMD 128 bits. */ 26839 26840 static HOST_WIDE_INT 26841 aarch64_estimated_poly_value (poly_int64 val, 26842 poly_value_estimate_kind kind 26843 = POLY_VALUE_LIKELY) 26844 { 26845 unsigned int width_source = aarch64_tune_params.sve_width; 26846 26847 /* If there is no core-specific information then the minimum and likely 26848 values are based on 128-bit vectors and the maximum is based on 26849 the architectural maximum of 2048 bits. */ 26850 if (width_source == SVE_SCALABLE) 26851 switch (kind) 26852 { 26853 case POLY_VALUE_MIN: 26854 case POLY_VALUE_LIKELY: 26855 return val.coeffs[0]; 26856 case POLY_VALUE_MAX: 26857 return val.coeffs[0] + val.coeffs[1] * 15; 26858 } 26859 26860 /* Allow sve_width to be a bitmask of different VL, treating the lowest 26861 as likely. This could be made more general if future -mtune options 26862 need it to be. */ 26863 if (kind == POLY_VALUE_MAX) 26864 width_source = 1 << floor_log2 (width_source); 26865 else 26866 width_source = least_bit_hwi (width_source); 26867 26868 /* If the core provides width information, use that. */ 26869 HOST_WIDE_INT over_128 = width_source - 128; 26870 return val.coeffs[0] + val.coeffs[1] * over_128 / 128; 26871 } 26872 26873 26874 /* Return true for types that could be supported as SIMD return or 26875 argument types. */ 26876 26877 static bool 26878 supported_simd_type (tree t) 26879 { 26880 if (SCALAR_FLOAT_TYPE_P (t) || INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t)) 26881 { 26882 HOST_WIDE_INT s = tree_to_shwi (TYPE_SIZE_UNIT (t)); 26883 return s == 1 || s == 2 || s == 4 || s == 8; 26884 } 26885 return false; 26886 } 26887 26888 /* Return true for types that currently are supported as SIMD return 26889 or argument types. */ 26890 26891 static bool 26892 currently_supported_simd_type (tree t, tree b) 26893 { 26894 if (COMPLEX_FLOAT_TYPE_P (t)) 26895 return false; 26896 26897 if (TYPE_SIZE (t) != TYPE_SIZE (b)) 26898 return false; 26899 26900 return supported_simd_type (t); 26901 } 26902 26903 /* Implement TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN. */ 26904 26905 static int 26906 aarch64_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node, 26907 struct cgraph_simd_clone *clonei, 26908 tree base_type, int num) 26909 { 26910 tree t, ret_type; 26911 unsigned int elt_bits, count = 0; 26912 unsigned HOST_WIDE_INT const_simdlen; 26913 poly_uint64 vec_bits; 26914 26915 if (!TARGET_SIMD) 26916 return 0; 26917 26918 /* For now, SVE simdclones won't produce illegal simdlen, So only check 26919 const simdlens here. */ 26920 if (maybe_ne (clonei->simdlen, 0U) 26921 && clonei->simdlen.is_constant (&const_simdlen) 26922 && (const_simdlen < 2 26923 || const_simdlen > 1024 26924 || (const_simdlen & (const_simdlen - 1)) != 0)) 26925 { 26926 warning_at (DECL_SOURCE_LOCATION (node->decl), 0, 26927 "unsupported simdlen %wd", const_simdlen); 26928 return 0; 26929 } 26930 26931 ret_type = TREE_TYPE (TREE_TYPE (node->decl)); 26932 if (TREE_CODE (ret_type) != VOID_TYPE 26933 && !currently_supported_simd_type (ret_type, base_type)) 26934 { 26935 if (TYPE_SIZE (ret_type) != TYPE_SIZE (base_type)) 26936 warning_at (DECL_SOURCE_LOCATION (node->decl), 0, 26937 "GCC does not currently support mixed size types " 26938 "for %<simd%> functions"); 26939 else if (supported_simd_type (ret_type)) 26940 warning_at (DECL_SOURCE_LOCATION (node->decl), 0, 26941 "GCC does not currently support return type %qT " 26942 "for %<simd%> functions", ret_type); 26943 else 26944 warning_at (DECL_SOURCE_LOCATION (node->decl), 0, 26945 "unsupported return type %qT for %<simd%> functions", 26946 ret_type); 26947 return 0; 26948 } 26949 26950 int i; 26951 tree type_arg_types = TYPE_ARG_TYPES (TREE_TYPE (node->decl)); 26952 bool decl_arg_p = (node->definition || type_arg_types == NULL_TREE); 26953 26954 for (t = (decl_arg_p ? DECL_ARGUMENTS (node->decl) : type_arg_types), i = 0; 26955 t && t != void_list_node; t = TREE_CHAIN (t), i++) 26956 { 26957 tree arg_type = decl_arg_p ? TREE_TYPE (t) : TREE_VALUE (t); 26958 26959 if (clonei->args[i].arg_type != SIMD_CLONE_ARG_TYPE_UNIFORM 26960 && !currently_supported_simd_type (arg_type, base_type)) 26961 { 26962 if (TYPE_SIZE (arg_type) != TYPE_SIZE (base_type)) 26963 warning_at (DECL_SOURCE_LOCATION (node->decl), 0, 26964 "GCC does not currently support mixed size types " 26965 "for %<simd%> functions"); 26966 else 26967 warning_at (DECL_SOURCE_LOCATION (node->decl), 0, 26968 "GCC does not currently support argument type %qT " 26969 "for %<simd%> functions", arg_type); 26970 return 0; 26971 } 26972 } 26973 26974 clonei->vecsize_mangle = 'n'; 26975 clonei->mask_mode = VOIDmode; 26976 elt_bits = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (base_type)); 26977 if (known_eq (clonei->simdlen, 0U)) 26978 { 26979 /* We don't support simdlen == 1. */ 26980 if (known_eq (elt_bits, 64)) 26981 { 26982 count = 1; 26983 vec_bits = 128; 26984 } 26985 else 26986 { 26987 count = 2; 26988 vec_bits = (num == 0 ? 64 : 128); 26989 } 26990 clonei->simdlen = exact_div (vec_bits, elt_bits); 26991 } 26992 else 26993 { 26994 count = 1; 26995 vec_bits = clonei->simdlen * elt_bits; 26996 /* For now, SVE simdclones won't produce illegal simdlen, So only check 26997 const simdlens here. */ 26998 if (clonei->simdlen.is_constant (&const_simdlen) 26999 && maybe_ne (vec_bits, 64U) && maybe_ne (vec_bits, 128U)) 27000 { 27001 warning_at (DECL_SOURCE_LOCATION (node->decl), 0, 27002 "GCC does not currently support simdlen %wd for type %qT", 27003 const_simdlen, base_type); 27004 return 0; 27005 } 27006 } 27007 27008 clonei->vecsize_int = vec_bits; 27009 clonei->vecsize_float = vec_bits; 27010 return count; 27011 } 27012 27013 /* Implement TARGET_SIMD_CLONE_ADJUST. */ 27014 27015 static void 27016 aarch64_simd_clone_adjust (struct cgraph_node *node) 27017 { 27018 /* Add aarch64_vector_pcs target attribute to SIMD clones so they 27019 use the correct ABI. */ 27020 27021 tree t = TREE_TYPE (node->decl); 27022 TYPE_ATTRIBUTES (t) = make_attribute ("aarch64_vector_pcs", "default", 27023 TYPE_ATTRIBUTES (t)); 27024 } 27025 27026 /* Implement TARGET_SIMD_CLONE_USABLE. */ 27027 27028 static int 27029 aarch64_simd_clone_usable (struct cgraph_node *node) 27030 { 27031 switch (node->simdclone->vecsize_mangle) 27032 { 27033 case 'n': 27034 if (!TARGET_SIMD) 27035 return -1; 27036 return 0; 27037 default: 27038 gcc_unreachable (); 27039 } 27040 } 27041 27042 /* Implement TARGET_COMP_TYPE_ATTRIBUTES */ 27043 27044 static int 27045 aarch64_comp_type_attributes (const_tree type1, const_tree type2) 27046 { 27047 auto check_attr = [&](const char *name) { 27048 tree attr1 = lookup_attribute (name, TYPE_ATTRIBUTES (type1)); 27049 tree attr2 = lookup_attribute (name, TYPE_ATTRIBUTES (type2)); 27050 if (!attr1 && !attr2) 27051 return true; 27052 27053 return attr1 && attr2 && attribute_value_equal (attr1, attr2); 27054 }; 27055 27056 if (!check_attr ("aarch64_vector_pcs")) 27057 return 0; 27058 if (!check_attr ("Advanced SIMD type")) 27059 return 0; 27060 if (!check_attr ("SVE type")) 27061 return 0; 27062 if (!check_attr ("SVE sizeless type")) 27063 return 0; 27064 return 1; 27065 } 27066 27067 /* Implement TARGET_GET_MULTILIB_ABI_NAME */ 27068 27069 static const char * 27070 aarch64_get_multilib_abi_name (void) 27071 { 27072 if (TARGET_BIG_END) 27073 return TARGET_ILP32 ? "aarch64_be_ilp32" : "aarch64_be"; 27074 return TARGET_ILP32 ? "aarch64_ilp32" : "aarch64"; 27075 } 27076 27077 /* Implement TARGET_STACK_PROTECT_GUARD. In case of a 27078 global variable based guard use the default else 27079 return a null tree. */ 27080 static tree 27081 aarch64_stack_protect_guard (void) 27082 { 27083 if (aarch64_stack_protector_guard == SSP_GLOBAL) 27084 return default_stack_protect_guard (); 27085 27086 return NULL_TREE; 27087 } 27088 27089 /* Return the diagnostic message string if conversion from FROMTYPE to 27090 TOTYPE is not allowed, NULL otherwise. */ 27091 27092 static const char * 27093 aarch64_invalid_conversion (const_tree fromtype, const_tree totype) 27094 { 27095 if (element_mode (fromtype) != element_mode (totype)) 27096 { 27097 /* Do no allow conversions to/from BFmode scalar types. */ 27098 if (TYPE_MODE (fromtype) == BFmode) 27099 return N_("invalid conversion from type %<bfloat16_t%>"); 27100 if (TYPE_MODE (totype) == BFmode) 27101 return N_("invalid conversion to type %<bfloat16_t%>"); 27102 } 27103 27104 /* Conversion allowed. */ 27105 return NULL; 27106 } 27107 27108 /* Return the diagnostic message string if the unary operation OP is 27109 not permitted on TYPE, NULL otherwise. */ 27110 27111 static const char * 27112 aarch64_invalid_unary_op (int op, const_tree type) 27113 { 27114 /* Reject all single-operand operations on BFmode except for &. */ 27115 if (element_mode (type) == BFmode && op != ADDR_EXPR) 27116 return N_("operation not permitted on type %<bfloat16_t%>"); 27117 27118 /* Operation allowed. */ 27119 return NULL; 27120 } 27121 27122 /* Return the diagnostic message string if the binary operation OP is 27123 not permitted on TYPE1 and TYPE2, NULL otherwise. */ 27124 27125 static const char * 27126 aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1, 27127 const_tree type2) 27128 { 27129 /* Reject all 2-operand operations on BFmode. */ 27130 if (element_mode (type1) == BFmode 27131 || element_mode (type2) == BFmode) 27132 return N_("operation not permitted on type %<bfloat16_t%>"); 27133 27134 if (VECTOR_TYPE_P (type1) 27135 && VECTOR_TYPE_P (type2) 27136 && !TYPE_INDIVISIBLE_P (type1) 27137 && !TYPE_INDIVISIBLE_P (type2) 27138 && (aarch64_sve::builtin_type_p (type1) 27139 != aarch64_sve::builtin_type_p (type2))) 27140 return N_("cannot combine GNU and SVE vectors in a binary operation"); 27141 27142 /* Operation allowed. */ 27143 return NULL; 27144 } 27145 27146 /* Implement TARGET_MEMTAG_CAN_TAG_ADDRESSES. Here we tell the rest of the 27147 compiler that we automatically ignore the top byte of our pointers, which 27148 allows using -fsanitize=hwaddress. */ 27149 bool 27150 aarch64_can_tag_addresses () 27151 { 27152 return !TARGET_ILP32; 27153 } 27154 27155 /* Implement TARGET_ASM_FILE_END for AArch64. This adds the AArch64 GNU NOTE 27156 section at the end if needed. */ 27157 #define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 27158 #define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0) 27159 #define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1U << 1) 27160 void 27161 aarch64_file_end_indicate_exec_stack () 27162 { 27163 file_end_indicate_exec_stack (); 27164 27165 unsigned feature_1_and = 0; 27166 if (aarch64_bti_enabled ()) 27167 feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI; 27168 27169 if (aarch64_ra_sign_scope != AARCH64_FUNCTION_NONE) 27170 feature_1_and |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC; 27171 27172 if (feature_1_and) 27173 { 27174 /* Generate .note.gnu.property section. */ 27175 switch_to_section (get_section (".note.gnu.property", 27176 SECTION_NOTYPE, NULL)); 27177 27178 /* PT_NOTE header: namesz, descsz, type. 27179 namesz = 4 ("GNU\0") 27180 descsz = 16 (Size of the program property array) 27181 [(12 + padding) * Number of array elements] 27182 type = 5 (NT_GNU_PROPERTY_TYPE_0). */ 27183 assemble_align (POINTER_SIZE); 27184 assemble_integer (GEN_INT (4), 4, 32, 1); 27185 assemble_integer (GEN_INT (ROUND_UP (12, POINTER_BYTES)), 4, 32, 1); 27186 assemble_integer (GEN_INT (5), 4, 32, 1); 27187 27188 /* PT_NOTE name. */ 27189 assemble_string ("GNU", 4); 27190 27191 /* PT_NOTE contents for NT_GNU_PROPERTY_TYPE_0: 27192 type = GNU_PROPERTY_AARCH64_FEATURE_1_AND 27193 datasz = 4 27194 data = feature_1_and. */ 27195 assemble_integer (GEN_INT (GNU_PROPERTY_AARCH64_FEATURE_1_AND), 4, 32, 1); 27196 assemble_integer (GEN_INT (4), 4, 32, 1); 27197 assemble_integer (GEN_INT (feature_1_and), 4, 32, 1); 27198 27199 /* Pad the size of the note to the required alignment. */ 27200 assemble_align (POINTER_SIZE); 27201 } 27202 } 27203 #undef GNU_PROPERTY_AARCH64_FEATURE_1_PAC 27204 #undef GNU_PROPERTY_AARCH64_FEATURE_1_BTI 27205 #undef GNU_PROPERTY_AARCH64_FEATURE_1_AND 27206 27207 /* Helper function for straight line speculation. 27208 Return what barrier should be emitted for straight line speculation 27209 mitigation. 27210 When not mitigating against straight line speculation this function returns 27211 an empty string. 27212 When mitigating against straight line speculation, use: 27213 * SB when the v8.5-A SB extension is enabled. 27214 * DSB+ISB otherwise. */ 27215 const char * 27216 aarch64_sls_barrier (int mitigation_required) 27217 { 27218 return mitigation_required 27219 ? (TARGET_SB ? "sb" : "dsb\tsy\n\tisb") 27220 : ""; 27221 } 27222 27223 static GTY (()) tree aarch64_sls_shared_thunks[30]; 27224 static GTY (()) bool aarch64_sls_shared_thunks_needed = false; 27225 const char *indirect_symbol_names[30] = { 27226 "__call_indirect_x0", 27227 "__call_indirect_x1", 27228 "__call_indirect_x2", 27229 "__call_indirect_x3", 27230 "__call_indirect_x4", 27231 "__call_indirect_x5", 27232 "__call_indirect_x6", 27233 "__call_indirect_x7", 27234 "__call_indirect_x8", 27235 "__call_indirect_x9", 27236 "__call_indirect_x10", 27237 "__call_indirect_x11", 27238 "__call_indirect_x12", 27239 "__call_indirect_x13", 27240 "__call_indirect_x14", 27241 "__call_indirect_x15", 27242 "", /* "__call_indirect_x16", */ 27243 "", /* "__call_indirect_x17", */ 27244 "__call_indirect_x18", 27245 "__call_indirect_x19", 27246 "__call_indirect_x20", 27247 "__call_indirect_x21", 27248 "__call_indirect_x22", 27249 "__call_indirect_x23", 27250 "__call_indirect_x24", 27251 "__call_indirect_x25", 27252 "__call_indirect_x26", 27253 "__call_indirect_x27", 27254 "__call_indirect_x28", 27255 "__call_indirect_x29", 27256 }; 27257 27258 /* Function to create a BLR thunk. This thunk is used to mitigate straight 27259 line speculation. Instead of a simple BLR that can be speculated past, 27260 we emit a BL to this thunk, and this thunk contains a BR to the relevant 27261 register. These thunks have the relevant speculation barries put after 27262 their indirect branch so that speculation is blocked. 27263 27264 We use such a thunk so the speculation barriers are kept off the 27265 architecturally executed path in order to reduce the performance overhead. 27266 27267 When optimizing for size we use stubs shared by the linked object. 27268 When optimizing for performance we emit stubs for each function in the hope 27269 that the branch predictor can better train on jumps specific for a given 27270 function. */ 27271 rtx 27272 aarch64_sls_create_blr_label (int regnum) 27273 { 27274 gcc_assert (STUB_REGNUM_P (regnum)); 27275 if (optimize_function_for_size_p (cfun)) 27276 { 27277 /* For the thunks shared between different functions in this compilation 27278 unit we use a named symbol -- this is just for users to more easily 27279 understand the generated assembly. */ 27280 aarch64_sls_shared_thunks_needed = true; 27281 const char *thunk_name = indirect_symbol_names[regnum]; 27282 if (aarch64_sls_shared_thunks[regnum] == NULL) 27283 { 27284 /* Build a decl representing this function stub and record it for 27285 later. We build a decl here so we can use the GCC machinery for 27286 handling sections automatically (through `get_named_section` and 27287 `make_decl_one_only`). That saves us a lot of trouble handling 27288 the specifics of different output file formats. */ 27289 tree decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, 27290 get_identifier (thunk_name), 27291 build_function_type_list (void_type_node, 27292 NULL_TREE)); 27293 DECL_RESULT (decl) = build_decl (BUILTINS_LOCATION, RESULT_DECL, 27294 NULL_TREE, void_type_node); 27295 TREE_PUBLIC (decl) = 1; 27296 TREE_STATIC (decl) = 1; 27297 DECL_IGNORED_P (decl) = 1; 27298 DECL_ARTIFICIAL (decl) = 1; 27299 make_decl_one_only (decl, DECL_ASSEMBLER_NAME (decl)); 27300 resolve_unique_section (decl, 0, false); 27301 aarch64_sls_shared_thunks[regnum] = decl; 27302 } 27303 27304 return gen_rtx_SYMBOL_REF (Pmode, thunk_name); 27305 } 27306 27307 if (cfun->machine->call_via[regnum] == NULL) 27308 cfun->machine->call_via[regnum] 27309 = gen_rtx_LABEL_REF (Pmode, gen_label_rtx ()); 27310 return cfun->machine->call_via[regnum]; 27311 } 27312 27313 /* Helper function for aarch64_sls_emit_blr_function_thunks and 27314 aarch64_sls_emit_shared_blr_thunks below. */ 27315 static void 27316 aarch64_sls_emit_function_stub (FILE *out_file, int regnum) 27317 { 27318 /* Save in x16 and branch to that function so this transformation does 27319 not prevent jumping to `BTI c` instructions. */ 27320 asm_fprintf (out_file, "\tmov\tx16, x%d\n", regnum); 27321 asm_fprintf (out_file, "\tbr\tx16\n"); 27322 } 27323 27324 /* Emit all BLR stubs for this particular function. 27325 Here we emit all the BLR stubs needed for the current function. Since we 27326 emit these stubs in a consecutive block we know there will be no speculation 27327 gadgets between each stub, and hence we only emit a speculation barrier at 27328 the end of the stub sequences. 27329 27330 This is called in the TARGET_ASM_FUNCTION_EPILOGUE hook. */ 27331 void 27332 aarch64_sls_emit_blr_function_thunks (FILE *out_file) 27333 { 27334 if (! aarch64_harden_sls_blr_p ()) 27335 return; 27336 27337 bool any_functions_emitted = false; 27338 /* We must save and restore the current function section since this assembly 27339 is emitted at the end of the function. This means it can be emitted *just 27340 after* the cold section of a function. That cold part would be emitted in 27341 a different section. That switch would trigger a `.cfi_endproc` directive 27342 to be emitted in the original section and a `.cfi_startproc` directive to 27343 be emitted in the new section. Switching to the original section without 27344 restoring would mean that the `.cfi_endproc` emitted as a function ends 27345 would happen in a different section -- leaving an unmatched 27346 `.cfi_startproc` in the cold text section and an unmatched `.cfi_endproc` 27347 in the standard text section. */ 27348 section *save_text_section = in_section; 27349 switch_to_section (function_section (current_function_decl)); 27350 for (int regnum = 0; regnum < 30; ++regnum) 27351 { 27352 rtx specu_label = cfun->machine->call_via[regnum]; 27353 if (specu_label == NULL) 27354 continue; 27355 27356 targetm.asm_out.print_operand (out_file, specu_label, 0); 27357 asm_fprintf (out_file, ":\n"); 27358 aarch64_sls_emit_function_stub (out_file, regnum); 27359 any_functions_emitted = true; 27360 } 27361 if (any_functions_emitted) 27362 /* Can use the SB if needs be here, since this stub will only be used 27363 by the current function, and hence for the current target. */ 27364 asm_fprintf (out_file, "\t%s\n", aarch64_sls_barrier (true)); 27365 switch_to_section (save_text_section); 27366 } 27367 27368 /* Emit shared BLR stubs for the current compilation unit. 27369 Over the course of compiling this unit we may have converted some BLR 27370 instructions to a BL to a shared stub function. This is where we emit those 27371 stub functions. 27372 This function is for the stubs shared between different functions in this 27373 compilation unit. We share when optimizing for size instead of speed. 27374 27375 This function is called through the TARGET_ASM_FILE_END hook. */ 27376 void 27377 aarch64_sls_emit_shared_blr_thunks (FILE *out_file) 27378 { 27379 if (! aarch64_sls_shared_thunks_needed) 27380 return; 27381 27382 for (int regnum = 0; regnum < 30; ++regnum) 27383 { 27384 tree decl = aarch64_sls_shared_thunks[regnum]; 27385 if (!decl) 27386 continue; 27387 27388 const char *name = indirect_symbol_names[regnum]; 27389 switch_to_section (get_named_section (decl, NULL, 0)); 27390 ASM_OUTPUT_ALIGN (out_file, 2); 27391 targetm.asm_out.globalize_label (out_file, name); 27392 /* Only emits if the compiler is configured for an assembler that can 27393 handle visibility directives. */ 27394 targetm.asm_out.assemble_visibility (decl, VISIBILITY_HIDDEN); 27395 ASM_OUTPUT_TYPE_DIRECTIVE (out_file, name, "function"); 27396 ASM_OUTPUT_LABEL (out_file, name); 27397 aarch64_sls_emit_function_stub (out_file, regnum); 27398 /* Use the most conservative target to ensure it can always be used by any 27399 function in the translation unit. */ 27400 asm_fprintf (out_file, "\tdsb\tsy\n\tisb\n"); 27401 ASM_DECLARE_FUNCTION_SIZE (out_file, name, decl); 27402 } 27403 } 27404 27405 /* Implement TARGET_ASM_FILE_END. */ 27406 void 27407 aarch64_asm_file_end () 27408 { 27409 aarch64_sls_emit_shared_blr_thunks (asm_out_file); 27410 /* Since this function will be called for the ASM_FILE_END hook, we ensure 27411 that what would be called otherwise (e.g. `file_end_indicate_exec_stack` 27412 for FreeBSD) still gets called. */ 27413 #ifdef TARGET_ASM_FILE_END 27414 TARGET_ASM_FILE_END (); 27415 #endif 27416 } 27417 27418 const char * 27419 aarch64_indirect_call_asm (rtx addr) 27420 { 27421 gcc_assert (REG_P (addr)); 27422 if (aarch64_harden_sls_blr_p ()) 27423 { 27424 rtx stub_label = aarch64_sls_create_blr_label (REGNO (addr)); 27425 output_asm_insn ("bl\t%0", &stub_label); 27426 } 27427 else 27428 output_asm_insn ("blr\t%0", &addr); 27429 return ""; 27430 } 27431 27432 /* Target-specific selftests. */ 27433 27434 #if CHECKING_P 27435 27436 namespace selftest { 27437 27438 /* Selftest for the RTL loader. 27439 Verify that the RTL loader copes with a dump from 27440 print_rtx_function. This is essentially just a test that class 27441 function_reader can handle a real dump, but it also verifies 27442 that lookup_reg_by_dump_name correctly handles hard regs. 27443 The presence of hard reg names in the dump means that the test is 27444 target-specific, hence it is in this file. */ 27445 27446 static void 27447 aarch64_test_loading_full_dump () 27448 { 27449 rtl_dump_test t (SELFTEST_LOCATION, locate_file ("aarch64/times-two.rtl")); 27450 27451 ASSERT_STREQ ("times_two", IDENTIFIER_POINTER (DECL_NAME (cfun->decl))); 27452 27453 rtx_insn *insn_1 = get_insn_by_uid (1); 27454 ASSERT_EQ (NOTE, GET_CODE (insn_1)); 27455 27456 rtx_insn *insn_15 = get_insn_by_uid (15); 27457 ASSERT_EQ (INSN, GET_CODE (insn_15)); 27458 ASSERT_EQ (USE, GET_CODE (PATTERN (insn_15))); 27459 27460 /* Verify crtl->return_rtx. */ 27461 ASSERT_EQ (REG, GET_CODE (crtl->return_rtx)); 27462 ASSERT_EQ (0, REGNO (crtl->return_rtx)); 27463 ASSERT_EQ (SImode, GET_MODE (crtl->return_rtx)); 27464 } 27465 27466 /* Test the fractional_cost class. */ 27467 27468 static void 27469 aarch64_test_fractional_cost () 27470 { 27471 using cf = fractional_cost; 27472 27473 ASSERT_EQ (cf (0, 20), 0); 27474 27475 ASSERT_EQ (cf (4, 2), 2); 27476 ASSERT_EQ (3, cf (9, 3)); 27477 27478 ASSERT_NE (cf (5, 2), 2); 27479 ASSERT_NE (3, cf (8, 3)); 27480 27481 ASSERT_EQ (cf (7, 11) + cf (15, 11), 2); 27482 ASSERT_EQ (cf (2, 3) + cf (3, 5), cf (19, 15)); 27483 ASSERT_EQ (cf (2, 3) + cf (1, 6) + cf (1, 6), 1); 27484 27485 ASSERT_EQ (cf (14, 15) - cf (4, 15), cf (2, 3)); 27486 ASSERT_EQ (cf (1, 4) - cf (1, 2), 0); 27487 ASSERT_EQ (cf (3, 5) - cf (1, 10), cf (1, 2)); 27488 ASSERT_EQ (cf (11, 3) - 3, cf (2, 3)); 27489 ASSERT_EQ (3 - cf (7, 3), cf (2, 3)); 27490 ASSERT_EQ (3 - cf (10, 3), 0); 27491 27492 ASSERT_EQ (cf (2, 3) * 5, cf (10, 3)); 27493 ASSERT_EQ (14 * cf (11, 21), cf (22, 3)); 27494 27495 ASSERT_TRUE (cf (4, 15) < cf (5, 15)); 27496 ASSERT_FALSE (cf (5, 15) < cf (5, 15)); 27497 ASSERT_FALSE (cf (6, 15) < cf (5, 15)); 27498 ASSERT_TRUE (cf (1, 3) < cf (2, 5)); 27499 ASSERT_TRUE (cf (1, 12) < cf (1, 6)); 27500 ASSERT_FALSE (cf (5, 3) < cf (5, 3)); 27501 ASSERT_TRUE (cf (239, 240) < 1); 27502 ASSERT_FALSE (cf (240, 240) < 1); 27503 ASSERT_FALSE (cf (241, 240) < 1); 27504 ASSERT_FALSE (2 < cf (207, 104)); 27505 ASSERT_FALSE (2 < cf (208, 104)); 27506 ASSERT_TRUE (2 < cf (209, 104)); 27507 27508 ASSERT_TRUE (cf (4, 15) < cf (5, 15)); 27509 ASSERT_FALSE (cf (5, 15) < cf (5, 15)); 27510 ASSERT_FALSE (cf (6, 15) < cf (5, 15)); 27511 ASSERT_TRUE (cf (1, 3) < cf (2, 5)); 27512 ASSERT_TRUE (cf (1, 12) < cf (1, 6)); 27513 ASSERT_FALSE (cf (5, 3) < cf (5, 3)); 27514 ASSERT_TRUE (cf (239, 240) < 1); 27515 ASSERT_FALSE (cf (240, 240) < 1); 27516 ASSERT_FALSE (cf (241, 240) < 1); 27517 ASSERT_FALSE (2 < cf (207, 104)); 27518 ASSERT_FALSE (2 < cf (208, 104)); 27519 ASSERT_TRUE (2 < cf (209, 104)); 27520 27521 ASSERT_FALSE (cf (4, 15) >= cf (5, 15)); 27522 ASSERT_TRUE (cf (5, 15) >= cf (5, 15)); 27523 ASSERT_TRUE (cf (6, 15) >= cf (5, 15)); 27524 ASSERT_FALSE (cf (1, 3) >= cf (2, 5)); 27525 ASSERT_FALSE (cf (1, 12) >= cf (1, 6)); 27526 ASSERT_TRUE (cf (5, 3) >= cf (5, 3)); 27527 ASSERT_FALSE (cf (239, 240) >= 1); 27528 ASSERT_TRUE (cf (240, 240) >= 1); 27529 ASSERT_TRUE (cf (241, 240) >= 1); 27530 ASSERT_TRUE (2 >= cf (207, 104)); 27531 ASSERT_TRUE (2 >= cf (208, 104)); 27532 ASSERT_FALSE (2 >= cf (209, 104)); 27533 27534 ASSERT_FALSE (cf (4, 15) > cf (5, 15)); 27535 ASSERT_FALSE (cf (5, 15) > cf (5, 15)); 27536 ASSERT_TRUE (cf (6, 15) > cf (5, 15)); 27537 ASSERT_FALSE (cf (1, 3) > cf (2, 5)); 27538 ASSERT_FALSE (cf (1, 12) > cf (1, 6)); 27539 ASSERT_FALSE (cf (5, 3) > cf (5, 3)); 27540 ASSERT_FALSE (cf (239, 240) > 1); 27541 ASSERT_FALSE (cf (240, 240) > 1); 27542 ASSERT_TRUE (cf (241, 240) > 1); 27543 ASSERT_TRUE (2 > cf (207, 104)); 27544 ASSERT_FALSE (2 > cf (208, 104)); 27545 ASSERT_FALSE (2 > cf (209, 104)); 27546 27547 ASSERT_EQ (cf (1, 2).ceil (), 1); 27548 ASSERT_EQ (cf (11, 7).ceil (), 2); 27549 ASSERT_EQ (cf (20, 1).ceil (), 20); 27550 ASSERT_EQ ((cf (0xfffffffd) + 1).ceil (), 0xfffffffe); 27551 ASSERT_EQ ((cf (0xfffffffd) + 2).ceil (), 0xffffffff); 27552 ASSERT_EQ ((cf (0xfffffffd) + 3).ceil (), 0xffffffff); 27553 ASSERT_EQ ((cf (0x7fffffff) * 2).ceil (), 0xfffffffe); 27554 ASSERT_EQ ((cf (0x80000000) * 2).ceil (), 0xffffffff); 27555 27556 ASSERT_EQ (cf (1, 2).as_double (), 0.5); 27557 } 27558 27559 /* Test SVE arithmetic folding. */ 27560 27561 static void 27562 aarch64_test_sve_folding () 27563 { 27564 tree res = fold_unary (BIT_NOT_EXPR, ssizetype, 27565 ssize_int (poly_int64 (1, 1))); 27566 ASSERT_TRUE (operand_equal_p (res, ssize_int (poly_int64 (-2, -1)))); 27567 } 27568 27569 /* Run all target-specific selftests. */ 27570 27571 static void 27572 aarch64_run_selftests (void) 27573 { 27574 aarch64_test_loading_full_dump (); 27575 aarch64_test_fractional_cost (); 27576 aarch64_test_sve_folding (); 27577 } 27578 27579 } // namespace selftest 27580 27581 #endif /* #if CHECKING_P */ 27582 27583 #undef TARGET_STACK_PROTECT_GUARD 27584 #define TARGET_STACK_PROTECT_GUARD aarch64_stack_protect_guard 27585 27586 #undef TARGET_ADDRESS_COST 27587 #define TARGET_ADDRESS_COST aarch64_address_cost 27588 27589 /* This hook will determines whether unnamed bitfields affect the alignment 27590 of the containing structure. The hook returns true if the structure 27591 should inherit the alignment requirements of an unnamed bitfield's 27592 type. */ 27593 #undef TARGET_ALIGN_ANON_BITFIELD 27594 #define TARGET_ALIGN_ANON_BITFIELD hook_bool_void_true 27595 27596 #undef TARGET_ASM_ALIGNED_DI_OP 27597 #define TARGET_ASM_ALIGNED_DI_OP "\t.xword\t" 27598 27599 #undef TARGET_ASM_ALIGNED_HI_OP 27600 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" 27601 27602 #undef TARGET_ASM_ALIGNED_SI_OP 27603 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" 27604 27605 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK 27606 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \ 27607 hook_bool_const_tree_hwi_hwi_const_tree_true 27608 27609 #undef TARGET_ASM_FILE_START 27610 #define TARGET_ASM_FILE_START aarch64_start_file 27611 27612 #undef TARGET_ASM_OUTPUT_MI_THUNK 27613 #define TARGET_ASM_OUTPUT_MI_THUNK aarch64_output_mi_thunk 27614 27615 #undef TARGET_ASM_SELECT_RTX_SECTION 27616 #define TARGET_ASM_SELECT_RTX_SECTION aarch64_select_rtx_section 27617 27618 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE 27619 #define TARGET_ASM_TRAMPOLINE_TEMPLATE aarch64_asm_trampoline_template 27620 27621 #undef TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY 27622 #define TARGET_ASM_PRINT_PATCHABLE_FUNCTION_ENTRY aarch64_print_patchable_function_entry 27623 27624 #undef TARGET_BUILD_BUILTIN_VA_LIST 27625 #define TARGET_BUILD_BUILTIN_VA_LIST aarch64_build_builtin_va_list 27626 27627 #undef TARGET_CALLEE_COPIES 27628 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_false 27629 27630 #undef TARGET_CAN_ELIMINATE 27631 #define TARGET_CAN_ELIMINATE aarch64_can_eliminate 27632 27633 #undef TARGET_CAN_INLINE_P 27634 #define TARGET_CAN_INLINE_P aarch64_can_inline_p 27635 27636 #undef TARGET_CANNOT_FORCE_CONST_MEM 27637 #define TARGET_CANNOT_FORCE_CONST_MEM aarch64_cannot_force_const_mem 27638 27639 #undef TARGET_CASE_VALUES_THRESHOLD 27640 #define TARGET_CASE_VALUES_THRESHOLD aarch64_case_values_threshold 27641 27642 #undef TARGET_CONDITIONAL_REGISTER_USAGE 27643 #define TARGET_CONDITIONAL_REGISTER_USAGE aarch64_conditional_register_usage 27644 27645 #undef TARGET_MEMBER_TYPE_FORCES_BLK 27646 #define TARGET_MEMBER_TYPE_FORCES_BLK aarch64_member_type_forces_blk 27647 27648 /* Only the least significant bit is used for initialization guard 27649 variables. */ 27650 #undef TARGET_CXX_GUARD_MASK_BIT 27651 #define TARGET_CXX_GUARD_MASK_BIT hook_bool_void_true 27652 27653 #undef TARGET_C_MODE_FOR_SUFFIX 27654 #define TARGET_C_MODE_FOR_SUFFIX aarch64_c_mode_for_suffix 27655 27656 #ifdef TARGET_BIG_ENDIAN_DEFAULT 27657 #undef TARGET_DEFAULT_TARGET_FLAGS 27658 #define TARGET_DEFAULT_TARGET_FLAGS (MASK_BIG_END) 27659 #endif 27660 27661 #undef TARGET_CLASS_MAX_NREGS 27662 #define TARGET_CLASS_MAX_NREGS aarch64_class_max_nregs 27663 27664 #undef TARGET_BUILTIN_DECL 27665 #define TARGET_BUILTIN_DECL aarch64_builtin_decl 27666 27667 #undef TARGET_BUILTIN_RECIPROCAL 27668 #define TARGET_BUILTIN_RECIPROCAL aarch64_builtin_reciprocal 27669 27670 #undef TARGET_C_EXCESS_PRECISION 27671 #define TARGET_C_EXCESS_PRECISION aarch64_excess_precision 27672 27673 #undef TARGET_EXPAND_BUILTIN 27674 #define TARGET_EXPAND_BUILTIN aarch64_expand_builtin 27675 27676 #undef TARGET_EXPAND_BUILTIN_VA_START 27677 #define TARGET_EXPAND_BUILTIN_VA_START aarch64_expand_builtin_va_start 27678 27679 #undef TARGET_FOLD_BUILTIN 27680 #define TARGET_FOLD_BUILTIN aarch64_fold_builtin 27681 27682 #undef TARGET_FUNCTION_ARG 27683 #define TARGET_FUNCTION_ARG aarch64_function_arg 27684 27685 #undef TARGET_FUNCTION_ARG_ADVANCE 27686 #define TARGET_FUNCTION_ARG_ADVANCE aarch64_function_arg_advance 27687 27688 #undef TARGET_FUNCTION_ARG_BOUNDARY 27689 #define TARGET_FUNCTION_ARG_BOUNDARY aarch64_function_arg_boundary 27690 27691 #undef TARGET_FUNCTION_ARG_PADDING 27692 #define TARGET_FUNCTION_ARG_PADDING aarch64_function_arg_padding 27693 27694 #undef TARGET_GET_RAW_RESULT_MODE 27695 #define TARGET_GET_RAW_RESULT_MODE aarch64_get_reg_raw_mode 27696 #undef TARGET_GET_RAW_ARG_MODE 27697 #define TARGET_GET_RAW_ARG_MODE aarch64_get_reg_raw_mode 27698 27699 #undef TARGET_FUNCTION_OK_FOR_SIBCALL 27700 #define TARGET_FUNCTION_OK_FOR_SIBCALL aarch64_function_ok_for_sibcall 27701 27702 #undef TARGET_FUNCTION_VALUE 27703 #define TARGET_FUNCTION_VALUE aarch64_function_value 27704 27705 #undef TARGET_FUNCTION_VALUE_REGNO_P 27706 #define TARGET_FUNCTION_VALUE_REGNO_P aarch64_function_value_regno_p 27707 27708 #undef TARGET_GIMPLE_FOLD_BUILTIN 27709 #define TARGET_GIMPLE_FOLD_BUILTIN aarch64_gimple_fold_builtin 27710 27711 #undef TARGET_GIMPLIFY_VA_ARG_EXPR 27712 #define TARGET_GIMPLIFY_VA_ARG_EXPR aarch64_gimplify_va_arg_expr 27713 27714 #undef TARGET_INIT_BUILTINS 27715 #define TARGET_INIT_BUILTINS aarch64_init_builtins 27716 27717 #undef TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS 27718 #define TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS \ 27719 aarch64_ira_change_pseudo_allocno_class 27720 27721 #undef TARGET_LEGITIMATE_ADDRESS_P 27722 #define TARGET_LEGITIMATE_ADDRESS_P aarch64_legitimate_address_hook_p 27723 27724 #undef TARGET_LEGITIMATE_CONSTANT_P 27725 #define TARGET_LEGITIMATE_CONSTANT_P aarch64_legitimate_constant_p 27726 27727 #undef TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT 27728 #define TARGET_LEGITIMIZE_ADDRESS_DISPLACEMENT \ 27729 aarch64_legitimize_address_displacement 27730 27731 #undef TARGET_LIBGCC_CMP_RETURN_MODE 27732 #define TARGET_LIBGCC_CMP_RETURN_MODE aarch64_libgcc_cmp_return_mode 27733 27734 #undef TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P 27735 #define TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P \ 27736 aarch64_libgcc_floating_mode_supported_p 27737 27738 #undef TARGET_MANGLE_TYPE 27739 #define TARGET_MANGLE_TYPE aarch64_mangle_type 27740 27741 #undef TARGET_INVALID_CONVERSION 27742 #define TARGET_INVALID_CONVERSION aarch64_invalid_conversion 27743 27744 #undef TARGET_INVALID_UNARY_OP 27745 #define TARGET_INVALID_UNARY_OP aarch64_invalid_unary_op 27746 27747 #undef TARGET_INVALID_BINARY_OP 27748 #define TARGET_INVALID_BINARY_OP aarch64_invalid_binary_op 27749 27750 #undef TARGET_VERIFY_TYPE_CONTEXT 27751 #define TARGET_VERIFY_TYPE_CONTEXT aarch64_verify_type_context 27752 27753 #undef TARGET_MEMORY_MOVE_COST 27754 #define TARGET_MEMORY_MOVE_COST aarch64_memory_move_cost 27755 27756 #undef TARGET_MIN_DIVISIONS_FOR_RECIP_MUL 27757 #define TARGET_MIN_DIVISIONS_FOR_RECIP_MUL aarch64_min_divisions_for_recip_mul 27758 27759 #undef TARGET_MUST_PASS_IN_STACK 27760 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size 27761 27762 /* This target hook should return true if accesses to volatile bitfields 27763 should use the narrowest mode possible. It should return false if these 27764 accesses should use the bitfield container type. */ 27765 #undef TARGET_NARROW_VOLATILE_BITFIELD 27766 #define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false 27767 27768 #undef TARGET_OPTION_OVERRIDE 27769 #define TARGET_OPTION_OVERRIDE aarch64_override_options 27770 27771 #undef TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE 27772 #define TARGET_OVERRIDE_OPTIONS_AFTER_CHANGE \ 27773 aarch64_override_options_after_change 27774 27775 #undef TARGET_OFFLOAD_OPTIONS 27776 #define TARGET_OFFLOAD_OPTIONS aarch64_offload_options 27777 27778 #undef TARGET_OPTION_SAVE 27779 #define TARGET_OPTION_SAVE aarch64_option_save 27780 27781 #undef TARGET_OPTION_RESTORE 27782 #define TARGET_OPTION_RESTORE aarch64_option_restore 27783 27784 #undef TARGET_OPTION_PRINT 27785 #define TARGET_OPTION_PRINT aarch64_option_print 27786 27787 #undef TARGET_OPTION_VALID_ATTRIBUTE_P 27788 #define TARGET_OPTION_VALID_ATTRIBUTE_P aarch64_option_valid_attribute_p 27789 27790 #undef TARGET_SET_CURRENT_FUNCTION 27791 #define TARGET_SET_CURRENT_FUNCTION aarch64_set_current_function 27792 27793 #undef TARGET_PASS_BY_REFERENCE 27794 #define TARGET_PASS_BY_REFERENCE aarch64_pass_by_reference 27795 27796 #undef TARGET_PREFERRED_RELOAD_CLASS 27797 #define TARGET_PREFERRED_RELOAD_CLASS aarch64_preferred_reload_class 27798 27799 #undef TARGET_SCHED_REASSOCIATION_WIDTH 27800 #define TARGET_SCHED_REASSOCIATION_WIDTH aarch64_reassociation_width 27801 27802 #undef TARGET_PROMOTED_TYPE 27803 #define TARGET_PROMOTED_TYPE aarch64_promoted_type 27804 27805 #undef TARGET_SECONDARY_RELOAD 27806 #define TARGET_SECONDARY_RELOAD aarch64_secondary_reload 27807 27808 #undef TARGET_SHIFT_TRUNCATION_MASK 27809 #define TARGET_SHIFT_TRUNCATION_MASK aarch64_shift_truncation_mask 27810 27811 #undef TARGET_SETUP_INCOMING_VARARGS 27812 #define TARGET_SETUP_INCOMING_VARARGS aarch64_setup_incoming_varargs 27813 27814 #undef TARGET_STRUCT_VALUE_RTX 27815 #define TARGET_STRUCT_VALUE_RTX aarch64_struct_value_rtx 27816 27817 #undef TARGET_REGISTER_MOVE_COST 27818 #define TARGET_REGISTER_MOVE_COST aarch64_register_move_cost 27819 27820 #undef TARGET_RETURN_IN_MEMORY 27821 #define TARGET_RETURN_IN_MEMORY aarch64_return_in_memory 27822 27823 #undef TARGET_RETURN_IN_MSB 27824 #define TARGET_RETURN_IN_MSB aarch64_return_in_msb 27825 27826 #undef TARGET_RTX_COSTS 27827 #define TARGET_RTX_COSTS aarch64_rtx_costs_wrapper 27828 27829 #undef TARGET_SCALAR_MODE_SUPPORTED_P 27830 #define TARGET_SCALAR_MODE_SUPPORTED_P aarch64_scalar_mode_supported_p 27831 27832 #undef TARGET_SCHED_ISSUE_RATE 27833 #define TARGET_SCHED_ISSUE_RATE aarch64_sched_issue_rate 27834 27835 #undef TARGET_SCHED_VARIABLE_ISSUE 27836 #define TARGET_SCHED_VARIABLE_ISSUE aarch64_sched_variable_issue 27837 27838 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD 27839 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \ 27840 aarch64_sched_first_cycle_multipass_dfa_lookahead 27841 27842 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD 27843 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD \ 27844 aarch64_first_cycle_multipass_dfa_lookahead_guard 27845 27846 #undef TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS 27847 #define TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS \ 27848 aarch64_get_separate_components 27849 27850 #undef TARGET_SHRINK_WRAP_COMPONENTS_FOR_BB 27851 #define TARGET_SHRINK_WRAP_COMPONENTS_FOR_BB \ 27852 aarch64_components_for_bb 27853 27854 #undef TARGET_SHRINK_WRAP_DISQUALIFY_COMPONENTS 27855 #define TARGET_SHRINK_WRAP_DISQUALIFY_COMPONENTS \ 27856 aarch64_disqualify_components 27857 27858 #undef TARGET_SHRINK_WRAP_EMIT_PROLOGUE_COMPONENTS 27859 #define TARGET_SHRINK_WRAP_EMIT_PROLOGUE_COMPONENTS \ 27860 aarch64_emit_prologue_components 27861 27862 #undef TARGET_SHRINK_WRAP_EMIT_EPILOGUE_COMPONENTS 27863 #define TARGET_SHRINK_WRAP_EMIT_EPILOGUE_COMPONENTS \ 27864 aarch64_emit_epilogue_components 27865 27866 #undef TARGET_SHRINK_WRAP_SET_HANDLED_COMPONENTS 27867 #define TARGET_SHRINK_WRAP_SET_HANDLED_COMPONENTS \ 27868 aarch64_set_handled_components 27869 27870 #undef TARGET_TRAMPOLINE_INIT 27871 #define TARGET_TRAMPOLINE_INIT aarch64_trampoline_init 27872 27873 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P 27874 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P aarch64_use_blocks_for_constant_p 27875 27876 #undef TARGET_VECTOR_MODE_SUPPORTED_P 27877 #define TARGET_VECTOR_MODE_SUPPORTED_P aarch64_vector_mode_supported_p 27878 27879 #undef TARGET_COMPATIBLE_VECTOR_TYPES_P 27880 #define TARGET_COMPATIBLE_VECTOR_TYPES_P aarch64_compatible_vector_types_p 27881 27882 #undef TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT 27883 #define TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT \ 27884 aarch64_builtin_support_vector_misalignment 27885 27886 #undef TARGET_ARRAY_MODE 27887 #define TARGET_ARRAY_MODE aarch64_array_mode 27888 27889 #undef TARGET_ARRAY_MODE_SUPPORTED_P 27890 #define TARGET_ARRAY_MODE_SUPPORTED_P aarch64_array_mode_supported_p 27891 27892 #undef TARGET_VECTORIZE_CREATE_COSTS 27893 #define TARGET_VECTORIZE_CREATE_COSTS aarch64_vectorize_create_costs 27894 27895 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST 27896 #define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST \ 27897 aarch64_builtin_vectorization_cost 27898 27899 #undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE 27900 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE aarch64_preferred_simd_mode 27901 27902 #undef TARGET_VECTORIZE_BUILTINS 27903 #define TARGET_VECTORIZE_BUILTINS 27904 27905 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION 27906 #define TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION \ 27907 aarch64_builtin_vectorized_function 27908 27909 #undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES 27910 #define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES \ 27911 aarch64_autovectorize_vector_modes 27912 27913 #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV 27914 #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV \ 27915 aarch64_atomic_assign_expand_fenv 27916 27917 /* Section anchor support. */ 27918 27919 #undef TARGET_MIN_ANCHOR_OFFSET 27920 #define TARGET_MIN_ANCHOR_OFFSET -256 27921 27922 /* Limit the maximum anchor offset to 4k-1, since that's the limit for a 27923 byte offset; we can do much more for larger data types, but have no way 27924 to determine the size of the access. We assume accesses are aligned. */ 27925 #undef TARGET_MAX_ANCHOR_OFFSET 27926 #define TARGET_MAX_ANCHOR_OFFSET 4095 27927 27928 #undef TARGET_VECTOR_ALIGNMENT 27929 #define TARGET_VECTOR_ALIGNMENT aarch64_simd_vector_alignment 27930 27931 #undef TARGET_VECTORIZE_PREFERRED_VECTOR_ALIGNMENT 27932 #define TARGET_VECTORIZE_PREFERRED_VECTOR_ALIGNMENT \ 27933 aarch64_vectorize_preferred_vector_alignment 27934 #undef TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE 27935 #define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE \ 27936 aarch64_simd_vector_alignment_reachable 27937 27938 /* vec_perm support. */ 27939 27940 #undef TARGET_VECTORIZE_VEC_PERM_CONST 27941 #define TARGET_VECTORIZE_VEC_PERM_CONST \ 27942 aarch64_vectorize_vec_perm_const 27943 27944 #undef TARGET_VECTORIZE_RELATED_MODE 27945 #define TARGET_VECTORIZE_RELATED_MODE aarch64_vectorize_related_mode 27946 #undef TARGET_VECTORIZE_GET_MASK_MODE 27947 #define TARGET_VECTORIZE_GET_MASK_MODE aarch64_get_mask_mode 27948 #undef TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE 27949 #define TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE \ 27950 aarch64_empty_mask_is_expensive 27951 #undef TARGET_PREFERRED_ELSE_VALUE 27952 #define TARGET_PREFERRED_ELSE_VALUE \ 27953 aarch64_preferred_else_value 27954 27955 #undef TARGET_INIT_LIBFUNCS 27956 #define TARGET_INIT_LIBFUNCS aarch64_init_libfuncs 27957 27958 #undef TARGET_FIXED_CONDITION_CODE_REGS 27959 #define TARGET_FIXED_CONDITION_CODE_REGS aarch64_fixed_condition_code_regs 27960 27961 #undef TARGET_FLAGS_REGNUM 27962 #define TARGET_FLAGS_REGNUM CC_REGNUM 27963 27964 #undef TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS 27965 #define TARGET_CALL_FUSAGE_CONTAINS_NON_CALLEE_CLOBBERS true 27966 27967 #undef TARGET_ASAN_SHADOW_OFFSET 27968 #define TARGET_ASAN_SHADOW_OFFSET aarch64_asan_shadow_offset 27969 27970 #undef TARGET_LEGITIMIZE_ADDRESS 27971 #define TARGET_LEGITIMIZE_ADDRESS aarch64_legitimize_address 27972 27973 #undef TARGET_SCHED_CAN_SPECULATE_INSN 27974 #define TARGET_SCHED_CAN_SPECULATE_INSN aarch64_sched_can_speculate_insn 27975 27976 #undef TARGET_CAN_USE_DOLOOP_P 27977 #define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost 27978 27979 #undef TARGET_SCHED_ADJUST_PRIORITY 27980 #define TARGET_SCHED_ADJUST_PRIORITY aarch64_sched_adjust_priority 27981 27982 #undef TARGET_SCHED_MACRO_FUSION_P 27983 #define TARGET_SCHED_MACRO_FUSION_P aarch64_macro_fusion_p 27984 27985 #undef TARGET_SCHED_MACRO_FUSION_PAIR_P 27986 #define TARGET_SCHED_MACRO_FUSION_PAIR_P aarch_macro_fusion_pair_p 27987 27988 #undef TARGET_SCHED_FUSION_PRIORITY 27989 #define TARGET_SCHED_FUSION_PRIORITY aarch64_sched_fusion_priority 27990 27991 #undef TARGET_UNSPEC_MAY_TRAP_P 27992 #define TARGET_UNSPEC_MAY_TRAP_P aarch64_unspec_may_trap_p 27993 27994 #undef TARGET_USE_PSEUDO_PIC_REG 27995 #define TARGET_USE_PSEUDO_PIC_REG aarch64_use_pseudo_pic_reg 27996 27997 #undef TARGET_PRINT_OPERAND 27998 #define TARGET_PRINT_OPERAND aarch64_print_operand 27999 28000 #undef TARGET_PRINT_OPERAND_ADDRESS 28001 #define TARGET_PRINT_OPERAND_ADDRESS aarch64_print_operand_address 28002 28003 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA 28004 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA aarch64_output_addr_const_extra 28005 28006 #undef TARGET_OPTAB_SUPPORTED_P 28007 #define TARGET_OPTAB_SUPPORTED_P aarch64_optab_supported_p 28008 28009 #undef TARGET_OMIT_STRUCT_RETURN_REG 28010 #define TARGET_OMIT_STRUCT_RETURN_REG true 28011 28012 #undef TARGET_DWARF_POLY_INDETERMINATE_VALUE 28013 #define TARGET_DWARF_POLY_INDETERMINATE_VALUE \ 28014 aarch64_dwarf_poly_indeterminate_value 28015 28016 /* The architecture reserves bits 0 and 1 so use bit 2 for descriptors. */ 28017 #undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS 28018 #define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 4 28019 28020 #undef TARGET_HARD_REGNO_NREGS 28021 #define TARGET_HARD_REGNO_NREGS aarch64_hard_regno_nregs 28022 #undef TARGET_HARD_REGNO_MODE_OK 28023 #define TARGET_HARD_REGNO_MODE_OK aarch64_hard_regno_mode_ok 28024 28025 #undef TARGET_MODES_TIEABLE_P 28026 #define TARGET_MODES_TIEABLE_P aarch64_modes_tieable_p 28027 28028 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED 28029 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \ 28030 aarch64_hard_regno_call_part_clobbered 28031 28032 #undef TARGET_INSN_CALLEE_ABI 28033 #define TARGET_INSN_CALLEE_ABI aarch64_insn_callee_abi 28034 28035 #undef TARGET_CONSTANT_ALIGNMENT 28036 #define TARGET_CONSTANT_ALIGNMENT aarch64_constant_alignment 28037 28038 #undef TARGET_STACK_CLASH_PROTECTION_ALLOCA_PROBE_RANGE 28039 #define TARGET_STACK_CLASH_PROTECTION_ALLOCA_PROBE_RANGE \ 28040 aarch64_stack_clash_protection_alloca_probe_range 28041 28042 #undef TARGET_COMPUTE_PRESSURE_CLASSES 28043 #define TARGET_COMPUTE_PRESSURE_CLASSES aarch64_compute_pressure_classes 28044 28045 #undef TARGET_CAN_CHANGE_MODE_CLASS 28046 #define TARGET_CAN_CHANGE_MODE_CLASS aarch64_can_change_mode_class 28047 28048 #undef TARGET_SELECT_EARLY_REMAT_MODES 28049 #define TARGET_SELECT_EARLY_REMAT_MODES aarch64_select_early_remat_modes 28050 28051 #undef TARGET_SPECULATION_SAFE_VALUE 28052 #define TARGET_SPECULATION_SAFE_VALUE aarch64_speculation_safe_value 28053 28054 #undef TARGET_ESTIMATED_POLY_VALUE 28055 #define TARGET_ESTIMATED_POLY_VALUE aarch64_estimated_poly_value 28056 28057 #undef TARGET_ATTRIBUTE_TABLE 28058 #define TARGET_ATTRIBUTE_TABLE aarch64_attribute_table 28059 28060 #undef TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN 28061 #define TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN \ 28062 aarch64_simd_clone_compute_vecsize_and_simdlen 28063 28064 #undef TARGET_SIMD_CLONE_ADJUST 28065 #define TARGET_SIMD_CLONE_ADJUST aarch64_simd_clone_adjust 28066 28067 #undef TARGET_SIMD_CLONE_USABLE 28068 #define TARGET_SIMD_CLONE_USABLE aarch64_simd_clone_usable 28069 28070 #undef TARGET_COMP_TYPE_ATTRIBUTES 28071 #define TARGET_COMP_TYPE_ATTRIBUTES aarch64_comp_type_attributes 28072 28073 #undef TARGET_GET_MULTILIB_ABI_NAME 28074 #define TARGET_GET_MULTILIB_ABI_NAME aarch64_get_multilib_abi_name 28075 28076 #undef TARGET_FNTYPE_ABI 28077 #define TARGET_FNTYPE_ABI aarch64_fntype_abi 28078 28079 #undef TARGET_MEMTAG_CAN_TAG_ADDRESSES 28080 #define TARGET_MEMTAG_CAN_TAG_ADDRESSES aarch64_can_tag_addresses 28081 28082 #if CHECKING_P 28083 #undef TARGET_RUN_TARGET_SELFTESTS 28084 #define TARGET_RUN_TARGET_SELFTESTS selftest::aarch64_run_selftests 28085 #endif /* #if CHECKING_P */ 28086 28087 #undef TARGET_ASM_POST_CFI_STARTPROC 28088 #define TARGET_ASM_POST_CFI_STARTPROC aarch64_post_cfi_startproc 28089 28090 #undef TARGET_STRICT_ARGUMENT_NAMING 28091 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true 28092 28093 #undef TARGET_MD_ASM_ADJUST 28094 #define TARGET_MD_ASM_ADJUST arm_md_asm_adjust 28095 28096 #undef TARGET_ASM_FILE_END 28097 #define TARGET_ASM_FILE_END aarch64_asm_file_end 28098 28099 #undef TARGET_ASM_FUNCTION_EPILOGUE 28100 #define TARGET_ASM_FUNCTION_EPILOGUE aarch64_sls_emit_blr_function_thunks 28101 28102 #undef TARGET_HAVE_SHADOW_CALL_STACK 28103 #define TARGET_HAVE_SHADOW_CALL_STACK true 28104 28105 struct gcc_target targetm = TARGET_INITIALIZER; 28106 28107 #include "gt-aarch64.h" 28108