comparison gcc/config/mips/mips.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
comparison
equal deleted inserted replaced
111:04ced10e8804 131:84e7813d76e9
1 /* Subroutines used for MIPS code generation. 1 /* Subroutines used for MIPS code generation.
2 Copyright (C) 1989-2017 Free Software Foundation, Inc. 2 Copyright (C) 1989-2018 Free Software Foundation, Inc.
3 Contributed by A. Lichnewsky, lich@inria.inria.fr. 3 Contributed by A. Lichnewsky, lich@inria.inria.fr.
4 Changes by Michael Meissner, meissner@osf.org. 4 Changes by Michael Meissner, meissner@osf.org.
5 64-bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and 5 64-bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
6 Brendan Eich, brendan@microunity.com. 6 Brendan Eich, brendan@microunity.com.
7 7
18 GNU General Public License for more details. 18 GNU General Public License for more details.
19 19
20 You should have received a copy of the GNU General Public License 20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING3. If not see 21 along with GCC; see the file COPYING3. If not see
22 <http://www.gnu.org/licenses/>. */ 22 <http://www.gnu.org/licenses/>. */
23
24 #define IN_TARGET_CODE 1
23 25
24 #include "config.h" 26 #include "config.h"
25 #include "system.h" 27 #include "system.h"
26 #include "coretypes.h" 28 #include "coretypes.h"
27 #include "backend.h" 29 #include "backend.h"
194 ADDRESS_LO_SUM, 196 ADDRESS_LO_SUM,
195 ADDRESS_CONST_INT, 197 ADDRESS_CONST_INT,
196 ADDRESS_SYMBOLIC 198 ADDRESS_SYMBOLIC
197 }; 199 };
198 200
201 /* Classifies an unconditional branch of interest for the P6600. */
202
203 enum mips_ucbranch_type
204 {
205 /* May not even be a branch. */
206 UC_UNDEFINED,
207 UC_BALC,
208 UC_OTHER
209 };
210
199 /* Macros to create an enumeration identifier for a function prototype. */ 211 /* Macros to create an enumeration identifier for a function prototype. */
200 #define MIPS_FTYPE_NAME1(A, B) MIPS_##A##_FTYPE_##B 212 #define MIPS_FTYPE_NAME1(A, B) MIPS_##A##_FTYPE_##B
201 #define MIPS_FTYPE_NAME2(A, B, C) MIPS_##A##_FTYPE_##B##_##C 213 #define MIPS_FTYPE_NAME2(A, B, C) MIPS_##A##_FTYPE_##B##_##C
202 #define MIPS_FTYPE_NAME3(A, B, C, D) MIPS_##A##_FTYPE_##B##_##C##_##D 214 #define MIPS_FTYPE_NAME3(A, B, C, D) MIPS_##A##_FTYPE_##B##_##C##_##D
203 #define MIPS_FTYPE_NAME4(A, B, C, D, E) MIPS_##A##_FTYPE_##B##_##C##_##D##_##E 215 #define MIPS_FTYPE_NAME4(A, B, C, D, E) MIPS_##A##_FTYPE_##B##_##C##_##D##_##E
487 499
488 /* The ambient values of other global variables. */ 500 /* The ambient values of other global variables. */
489 static int mips_base_schedule_insns; /* flag_schedule_insns */ 501 static int mips_base_schedule_insns; /* flag_schedule_insns */
490 static int mips_base_reorder_blocks_and_partition; /* flag_reorder... */ 502 static int mips_base_reorder_blocks_and_partition; /* flag_reorder... */
491 static int mips_base_move_loop_invariants; /* flag_move_loop_invariants */ 503 static int mips_base_move_loop_invariants; /* flag_move_loop_invariants */
492 static int mips_base_align_loops; /* align_loops */ 504 static const char *mips_base_align_loops; /* align_loops */
493 static int mips_base_align_jumps; /* align_jumps */ 505 static const char *mips_base_align_jumps; /* align_jumps */
494 static int mips_base_align_functions; /* align_functions */ 506 static const char *mips_base_align_functions; /* align_functions */
495 507
496 /* Index [M][R] is true if register R is allowed to hold a value of mode M. */ 508 /* Index [M][R] is true if register R is allowed to hold a value of mode M. */
497 static bool mips_hard_regno_mode_ok_p[MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER]; 509 static bool mips_hard_regno_mode_ok_p[MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
498 510
499 /* Index C is true if character C is a valid PRINT_OPERAND punctation 511 /* Index C is true if character C is a valid PRINT_OPERAND punctation
593 static tree mips_handle_use_shadow_register_set_attr (tree *, tree, tree, int, 605 static tree mips_handle_use_shadow_register_set_attr (tree *, tree, tree, int,
594 bool *); 606 bool *);
595 607
596 /* The value of TARGET_ATTRIBUTE_TABLE. */ 608 /* The value of TARGET_ATTRIBUTE_TABLE. */
597 static const struct attribute_spec mips_attribute_table[] = { 609 static const struct attribute_spec mips_attribute_table[] = {
598 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, 610 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
599 om_diagnostic } */ 611 affects_type_identity, handler, exclude } */
600 { "long_call", 0, 0, false, true, true, NULL, false }, 612 { "long_call", 0, 0, false, true, true, false, NULL, NULL },
601 { "short_call", 0, 0, false, true, true, NULL, false }, 613 { "short_call", 0, 0, false, true, true, false, NULL, NULL },
602 { "far", 0, 0, false, true, true, NULL, false }, 614 { "far", 0, 0, false, true, true, false, NULL, NULL },
603 { "near", 0, 0, false, true, true, NULL, false }, 615 { "near", 0, 0, false, true, true, false, NULL, NULL },
604 /* We would really like to treat "mips16" and "nomips16" as type 616 /* We would really like to treat "mips16" and "nomips16" as type
605 attributes, but GCC doesn't provide the hooks we need to support 617 attributes, but GCC doesn't provide the hooks we need to support
606 the right conversion rules. As declaration attributes, they affect 618 the right conversion rules. As declaration attributes, they affect
607 code generation but don't carry other semantics. */ 619 code generation but don't carry other semantics. */
608 { "mips16", 0, 0, true, false, false, NULL, false }, 620 { "mips16", 0, 0, true, false, false, false, NULL, NULL },
609 { "nomips16", 0, 0, true, false, false, NULL, false }, 621 { "nomips16", 0, 0, true, false, false, false, NULL, NULL },
610 { "micromips", 0, 0, true, false, false, NULL, false }, 622 { "micromips", 0, 0, true, false, false, false, NULL, NULL },
611 { "nomicromips", 0, 0, true, false, false, NULL, false }, 623 { "nomicromips", 0, 0, true, false, false, false, NULL, NULL },
612 { "nocompression", 0, 0, true, false, false, NULL, false }, 624 { "nocompression", 0, 0, true, false, false, false, NULL, NULL },
613 /* Allow functions to be specified as interrupt handlers */ 625 /* Allow functions to be specified as interrupt handlers */
614 { "interrupt", 0, 1, false, true, true, mips_handle_interrupt_attr, 626 { "interrupt", 0, 1, false, true, true, false, mips_handle_interrupt_attr,
615 false }, 627 NULL },
616 { "use_shadow_register_set", 0, 1, false, true, true, 628 { "use_shadow_register_set", 0, 1, false, true, true, false,
617 mips_handle_use_shadow_register_set_attr, false }, 629 mips_handle_use_shadow_register_set_attr, NULL },
618 { "keep_interrupts_masked", 0, 0, false, true, true, NULL, false }, 630 { "keep_interrupts_masked", 0, 0, false, true, true, false, NULL, NULL },
619 { "use_debug_exception_return", 0, 0, false, true, true, NULL, false }, 631 { "use_debug_exception_return", 0, 0, false, true, true, false, NULL, NULL },
620 { NULL, 0, 0, false, false, false, NULL, false } 632 { NULL, 0, 0, false, false, false, false, NULL, NULL }
621 }; 633 };
622 634
623 /* A table describing all the processors GCC knows about; see 635 /* A table describing all the processors GCC knows about; see
624 mips-cpus.def for details. */ 636 mips-cpus.def for details. */
625 static const struct mips_cpu_info mips_cpu_info_table[] = { 637 static const struct mips_cpu_info mips_cpu_info_table[] = {
1123 COSTS_N_INSNS (5), /* int_mult_di */ 1135 COSTS_N_INSNS (5), /* int_mult_di */
1124 COSTS_N_INSNS (36), /* int_div_si */ 1136 COSTS_N_INSNS (36), /* int_div_si */
1125 COSTS_N_INSNS (36), /* int_div_di */ 1137 COSTS_N_INSNS (36), /* int_div_di */
1126 2, /* branch_cost */ 1138 2, /* branch_cost */
1127 4 /* memory_latency */ 1139 4 /* memory_latency */
1140 },
1141 { /* P6600 */
1142 COSTS_N_INSNS (4), /* fp_add */
1143 COSTS_N_INSNS (5), /* fp_mult_sf */
1144 COSTS_N_INSNS (5), /* fp_mult_df */
1145 COSTS_N_INSNS (17), /* fp_div_sf */
1146 COSTS_N_INSNS (17), /* fp_div_df */
1147 COSTS_N_INSNS (5), /* int_mult_si */
1148 COSTS_N_INSNS (5), /* int_mult_di */
1149 COSTS_N_INSNS (8), /* int_div_si */
1150 COSTS_N_INSNS (8), /* int_div_di */
1151 2, /* branch_cost */
1152 4 /* memory_latency */
1128 } 1153 }
1129 }; 1154 };
1130 1155
1131 static rtx mips_find_pic_call_symbol (rtx_insn *, rtx, bool); 1156 static rtx mips_find_pic_call_symbol (rtx_insn *, rtx, bool);
1132 static int mips_register_move_cost (machine_mode, reg_class_t, 1157 static int mips_register_move_cost (machine_mode, reg_class_t,
1133 reg_class_t); 1158 reg_class_t);
1134 static unsigned int mips_function_arg_boundary (machine_mode, const_tree); 1159 static unsigned int mips_function_arg_boundary (machine_mode, const_tree);
1135 static machine_mode mips_get_reg_raw_mode (int regno);
1136 static rtx mips_gen_const_int_vector_shuffle (machine_mode, int); 1160 static rtx mips_gen_const_int_vector_shuffle (machine_mode, int);
1137 1161
1138 /* This hash table keeps track of implicit "mips16" and "nomips16" attributes 1162 /* This hash table keeps track of implicit "mips16" and "nomips16" attributes
1139 for -mflip_mips16. It maps decl names onto a boolean mode setting. */ 1163 for -mflip_mips16. It maps decl names onto a boolean mode setting. */
1140 static GTY (()) hash_map<nofree_string_hash, bool> *mflip_mips16_htab; 1164 static GTY (()) hash_map<nofree_string_hash, bool> *mflip_mips16_htab;
6109 return alignment; 6133 return alignment;
6110 } 6134 }
6111 6135
6112 /* Implement TARGET_GET_RAW_RESULT_MODE and TARGET_GET_RAW_ARG_MODE. */ 6136 /* Implement TARGET_GET_RAW_RESULT_MODE and TARGET_GET_RAW_ARG_MODE. */
6113 6137
6114 static machine_mode 6138 static fixed_size_mode
6115 mips_get_reg_raw_mode (int regno) 6139 mips_get_reg_raw_mode (int regno)
6116 { 6140 {
6117 if (TARGET_FLOATXX && FP_REG_P (regno)) 6141 if (TARGET_FLOATXX && FP_REG_P (regno))
6118 return DFmode; 6142 return DFmode;
6119 return default_get_reg_raw_mode (regno); 6143 return default_get_reg_raw_mode (regno);
13398 return word_mode; 13422 return word_mode;
13399 } 13423 }
13400 13424
13401 /* Implement TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES. */ 13425 /* Implement TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES. */
13402 13426
13403 static unsigned int 13427 static void
13404 mips_autovectorize_vector_sizes (void) 13428 mips_autovectorize_vector_sizes (vector_sizes *sizes)
13405 { 13429 {
13406 return ISA_HAS_MSA ? 16 : 0; 13430 if (ISA_HAS_MSA)
13431 sizes->safe_push (16);
13407 } 13432 }
13408 13433
13409 /* Implement TARGET_INIT_LIBFUNCS. */ 13434 /* Implement TARGET_INIT_LIBFUNCS. */
13410 13435
13411 static void 13436 static void
14588 14613
14589 case PROCESSOR_LOONGSON_2E: 14614 case PROCESSOR_LOONGSON_2E:
14590 case PROCESSOR_LOONGSON_2F: 14615 case PROCESSOR_LOONGSON_2F:
14591 case PROCESSOR_LOONGSON_3A: 14616 case PROCESSOR_LOONGSON_3A:
14592 case PROCESSOR_P5600: 14617 case PROCESSOR_P5600:
14618 case PROCESSOR_P6600:
14593 return 4; 14619 return 4;
14594 14620
14595 case PROCESSOR_XLP: 14621 case PROCESSOR_XLP:
14596 return (reload_completed ? 4 : 3); 14622 return (reload_completed ? 4 : 3);
14597 14623
14723 return 4; 14749 return 4;
14724 14750
14725 if (TUNE_OCTEON) 14751 if (TUNE_OCTEON)
14726 return 2; 14752 return 2;
14727 14753
14728 if (TUNE_P5600 || TUNE_I6400) 14754 if (TUNE_P5600 || TUNE_P6600 || TUNE_I6400)
14729 return 4; 14755 return 4;
14730 14756
14731 return 0; 14757 return 0;
14732 } 14758 }
14733 14759
17610 a link-time-constant address. */ 17636 a link-time-constant address. */
17611 17637
17612 static bool 17638 static bool
17613 r10k_safe_mem_expr_p (tree expr, unsigned HOST_WIDE_INT offset) 17639 r10k_safe_mem_expr_p (tree expr, unsigned HOST_WIDE_INT offset)
17614 { 17640 {
17615 HOST_WIDE_INT bitoffset, bitsize; 17641 poly_int64 bitoffset, bitsize;
17616 tree inner, var_offset; 17642 tree inner, var_offset;
17617 machine_mode mode; 17643 machine_mode mode;
17618 int unsigned_p, reverse_p, volatile_p; 17644 int unsigned_p, reverse_p, volatile_p;
17619 17645
17620 inner = get_inner_reference (expr, &bitsize, &bitoffset, &var_offset, &mode, 17646 inner = get_inner_reference (expr, &bitsize, &bitoffset, &var_offset, &mode,
17795 We therefore insert the barrier at the beginning 17821 We therefore insert the barrier at the beginning
17796 of the region. */ 17822 of the region. */
17797 if (r10k_needs_protection_p (insn)) 17823 if (r10k_needs_protection_p (insn))
17798 { 17824 {
17799 emit_insn_before (gen_r10k_cache_barrier (), 17825 emit_insn_before (gen_r10k_cache_barrier (),
17800 unprotected_region); 17826 as_a <rtx_insn *> (unprotected_region));
17801 unprotected_region = NULL_RTX; 17827 unprotected_region = NULL_RTX;
17802 } 17828 }
17803 } 17829 }
17804 } 17830 }
17805 17831
18511 last2 = last; 18537 last2 = last;
18512 last = insn; 18538 last = insn;
18513 } 18539 }
18514 18540
18515 /* See whether INSN is an aligned label. */ 18541 /* See whether INSN is an aligned label. */
18516 if (LABEL_P (insn) && label_to_alignment (insn) >= 3) 18542 if (LABEL_P (insn) && label_to_alignment (insn).levels[0].log >= 3)
18517 aligned_p = true; 18543 aligned_p = true;
18518 } 18544 }
18519 dfa_finish (); 18545 dfa_finish ();
18520 } 18546 }
18521 18547
18641 SYMBOL_CONTEXT_LEA, &type) 18667 SYMBOL_CONTEXT_LEA, &type)
18642 && type == SYMBOL_GOTOFF_PAGE) 18668 && type == SYMBOL_GOTOFF_PAGE)
18643 return !mips_lo_sum_offset_lookup (htab, XVECEXP (x, 0, 1), NO_INSERT); 18669 return !mips_lo_sum_offset_lookup (htab, XVECEXP (x, 0, 1), NO_INSERT);
18644 } 18670 }
18645 return false; 18671 return false;
18672 }
18673
18674 /* Subroutine of mips_avoid_hazard. We classify unconditional branches
18675 of interest for the P6600 for performance reasons. We're interested
18676 in differentiating BALC from JIC, JIALC and BC. */
18677
18678 static enum mips_ucbranch_type
18679 mips_classify_branch_p6600 (rtx_insn *insn)
18680 {
18681 /* We ignore sequences here as they represent a filled delay slot. */
18682 if (!insn
18683 || !USEFUL_INSN_P (insn)
18684 || GET_CODE (PATTERN (insn)) == SEQUENCE)
18685 return UC_UNDEFINED;
18686
18687 if (get_attr_jal (insn) == JAL_INDIRECT /* JIC and JIALC. */
18688 || get_attr_type (insn) == TYPE_JUMP) /* BC. */
18689 return UC_OTHER;
18690
18691 if (CALL_P (insn) && get_attr_jal (insn) == JAL_DIRECT)
18692 return UC_BALC;
18693
18694 return UC_UNDEFINED;
18646 } 18695 }
18647 18696
18648 /* Subroutine of mips_reorg_process_insns. If there is a hazard between 18697 /* Subroutine of mips_reorg_process_insns. If there is a hazard between
18649 INSN and a previous instruction, avoid it by inserting nops after 18698 INSN and a previous instruction, avoid it by inserting nops after
18650 instruction AFTER. 18699 instruction AFTER.
18695 else if (*fs_delay && get_attr_can_delay (insn) == CAN_DELAY_NO 18744 else if (*fs_delay && get_attr_can_delay (insn) == CAN_DELAY_NO
18696 && GET_CODE (PATTERN (after)) != SEQUENCE 18745 && GET_CODE (PATTERN (after)) != SEQUENCE
18697 && GET_CODE (pattern) != ASM_INPUT 18746 && GET_CODE (pattern) != ASM_INPUT
18698 && asm_noperands (pattern) < 0) 18747 && asm_noperands (pattern) < 0)
18699 nops = 1; 18748 nops = 1;
18749 /* The P6600's branch predictor can handle static sequences of back-to-back
18750 branches in the following cases:
18751
18752 (1) BALC followed by any conditional compact branch
18753 (2) BALC followed by BALC
18754
18755 Any other combinations of compact branches will incur performance
18756 penalty. Inserting a no-op only costs space as the dispatch unit will
18757 disregard the nop. */
18758 else if (TUNE_P6600 && TARGET_CB_MAYBE && !optimize_size
18759 && ((mips_classify_branch_p6600 (after) == UC_BALC
18760 && mips_classify_branch_p6600 (insn) == UC_OTHER)
18761 || (mips_classify_branch_p6600 (insn) == UC_BALC
18762 && mips_classify_branch_p6600 (after) == UC_OTHER)))
18763 nops = 1;
18700 else 18764 else
18701 nops = 0; 18765 nops = 0;
18702 18766
18703 /* Insert the nops between this instruction and the previous one. 18767 /* Insert the nops between this instruction and the previous one.
18704 Each new nop takes us further from the last hilo hazard. */ 18768 Each new nop takes us further from the last hilo hazard. */
18705 *hilo_delay += nops; 18769 *hilo_delay += nops;
18770
18771 /* Move to the next real instruction if we are inserting a NOP and this
18772 instruction is a call with debug information. The reason being that
18773 we can't separate the call from the debug info. */
18774 rtx_insn *real_after = after;
18775 if (real_after && nops && CALL_P (real_after))
18776 while (real_after
18777 && (NOTE_P (NEXT_INSN (real_after))
18778 || BARRIER_P (NEXT_INSN (real_after))))
18779 real_after = NEXT_INSN (real_after);
18780
18706 while (nops-- > 0) 18781 while (nops-- > 0)
18707 emit_insn_after (gen_hazard_nop (), after); 18782 emit_insn_after (gen_hazard_nop (), real_after);
18708 18783
18709 /* Set up the state for the next instruction. */ 18784 /* Set up the state for the next instruction. */
18710 *hilo_delay += ninsns; 18785 *hilo_delay += ninsns;
18711 *delayed_reg = 0; 18786 *delayed_reg = 0;
18712 *fs_delay = false; 18787 *fs_delay = false;
18713 if (INSN_CODE (insn) >= 0) 18788 if (INSN_CODE (insn) >= 0)
18714 switch (get_attr_hazard (insn)) 18789 switch (get_attr_hazard (insn))
18715 { 18790 {
18716 case HAZARD_NONE: 18791 case HAZARD_NONE:
18792 /* For the P6600, flag some unconditional branches as having a
18793 pseudo-forbidden slot. This will cause additional nop insertion
18794 or SEQUENCE breaking as required. This is for performance
18795 reasons not correctness. */
18796 if (TUNE_P6600
18797 && !optimize_size
18798 && TARGET_CB_MAYBE
18799 && mips_classify_branch_p6600 (insn) == UC_OTHER)
18800 *fs_delay = true;
18717 break; 18801 break;
18718 18802
18719 case HAZARD_FORBIDDEN_SLOT: 18803 case HAZARD_FORBIDDEN_SLOT:
18720 if (TARGET_CB_MAYBE) 18804 if (TARGET_CB_MAYBE)
18721 *fs_delay = true; 18805 *fs_delay = true;
18951 &delayed_reg, lo_reg, &fs_delay); 19035 &delayed_reg, lo_reg, &fs_delay);
18952 /* When a compact branch introduces a forbidden slot hazard 19036 /* When a compact branch introduces a forbidden slot hazard
18953 and the next useful instruction is a SEQUENCE of a jump 19037 and the next useful instruction is a SEQUENCE of a jump
18954 and a non-nop instruction in the delay slot, remove the 19038 and a non-nop instruction in the delay slot, remove the
18955 sequence and replace it with the delay slot instruction 19039 sequence and replace it with the delay slot instruction
18956 then the jump to clear the forbidden slot hazard. */ 19040 then the jump to clear the forbidden slot hazard.
18957 19041
18958 if (fs_delay) 19042 For the P6600, this optimisation solves the performance
19043 penalty associated with BALC followed by a delay slot
19044 branch. We do not set fs_delay as we do not want
19045 the full logic of a forbidden slot; the penalty exists
19046 only against branches not the full class of forbidden
19047 slot instructions. */
19048
19049 if (fs_delay || (TUNE_P6600
19050 && TARGET_CB_MAYBE
19051 && mips_classify_branch_p6600 (insn)
19052 == UC_BALC))
18959 { 19053 {
18960 /* Search onwards from the current position looking for 19054 /* Search onwards from the current position looking for
18961 a SEQUENCE. We are looking for pipeline hazards here 19055 a SEQUENCE. We are looking for pipeline hazards here
18962 and do not need to worry about labels or barriers as 19056 and do not need to worry about labels or barriers as
18963 the optimization only undoes delay slot filling which 19057 the optimization only undoes delay slot filling which
19421 /* Restore base settings of various flags. */ 19515 /* Restore base settings of various flags. */
19422 target_flags = mips_base_target_flags; 19516 target_flags = mips_base_target_flags;
19423 flag_schedule_insns = mips_base_schedule_insns; 19517 flag_schedule_insns = mips_base_schedule_insns;
19424 flag_reorder_blocks_and_partition = mips_base_reorder_blocks_and_partition; 19518 flag_reorder_blocks_and_partition = mips_base_reorder_blocks_and_partition;
19425 flag_move_loop_invariants = mips_base_move_loop_invariants; 19519 flag_move_loop_invariants = mips_base_move_loop_invariants;
19426 align_loops = mips_base_align_loops; 19520 str_align_loops = mips_base_align_loops;
19427 align_jumps = mips_base_align_jumps; 19521 str_align_jumps = mips_base_align_jumps;
19428 align_functions = mips_base_align_functions; 19522 str_align_functions = mips_base_align_functions;
19429 target_flags &= ~(MASK_MIPS16 | MASK_MICROMIPS); 19523 target_flags &= ~(MASK_MIPS16 | MASK_MICROMIPS);
19430 target_flags |= compression_mode; 19524 target_flags |= compression_mode;
19431 19525
19432 if (compression_mode & MASK_MIPS16) 19526 if (compression_mode & MASK_MIPS16)
19433 { 19527 {
19493 target_flags &= ~MASK_BRANCHLIKELY; 19587 target_flags &= ~MASK_BRANCHLIKELY;
19494 19588
19495 /* Provide default values for align_* for 64-bit targets. */ 19589 /* Provide default values for align_* for 64-bit targets. */
19496 if (TARGET_64BIT) 19590 if (TARGET_64BIT)
19497 { 19591 {
19498 if (align_loops == 0) 19592 if (flag_align_loops && !str_align_loops)
19499 align_loops = 8; 19593 str_align_loops = "8";
19500 if (align_jumps == 0) 19594 if (flag_align_jumps && !str_align_jumps)
19501 align_jumps = 8; 19595 str_align_jumps = "8";
19502 if (align_functions == 0) 19596 if (flag_align_functions && !str_align_functions)
19503 align_functions = 8; 19597 str_align_functions = "8";
19504 } 19598 }
19505 19599
19506 targetm.min_anchor_offset = -32768; 19600 targetm.min_anchor_offset = -32768;
19507 targetm.max_anchor_offset = 32767; 19601 targetm.max_anchor_offset = 32767;
19508 19602
20182 /* Save base state of options. */ 20276 /* Save base state of options. */
20183 mips_base_target_flags = target_flags; 20277 mips_base_target_flags = target_flags;
20184 mips_base_schedule_insns = flag_schedule_insns; 20278 mips_base_schedule_insns = flag_schedule_insns;
20185 mips_base_reorder_blocks_and_partition = flag_reorder_blocks_and_partition; 20279 mips_base_reorder_blocks_and_partition = flag_reorder_blocks_and_partition;
20186 mips_base_move_loop_invariants = flag_move_loop_invariants; 20280 mips_base_move_loop_invariants = flag_move_loop_invariants;
20187 mips_base_align_loops = align_loops; 20281 mips_base_align_loops = str_align_loops;
20188 mips_base_align_jumps = align_jumps; 20282 mips_base_align_jumps = str_align_jumps;
20189 mips_base_align_functions = align_functions; 20283 mips_base_align_functions = str_align_functions;
20190 20284
20191 /* Now select the ISA mode. 20285 /* Now select the ISA mode.
20192 20286
20193 Do all CPP-sensitive stuff in uncompressed mode; we'll switch modes 20287 Do all CPP-sensitive stuff in uncompressed mode; we'll switch modes
20194 later if required. */ 20288 later if required. */
20422 { 20516 {
20423 if (INSN_P (insn) 20517 if (INSN_P (insn)
20424 && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE 20518 && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
20425 && XINT (PATTERN (insn), 1) == UNSPEC_CONSTTABLE) 20519 && XINT (PATTERN (insn), 1) == UNSPEC_CONSTTABLE)
20426 mips_set_text_contents_type (asm_out_file, "__pool_", 20520 mips_set_text_contents_type (asm_out_file, "__pool_",
20427 XINT (XVECEXP (PATTERN (insn), 0, 0), 0), 20521 INTVAL (XVECEXP (PATTERN (insn), 0, 0)),
20428 FALSE); 20522 FALSE);
20429 20523
20430 if (mips_need_noat_wrapper_p (insn, opvec, noperands)) 20524 if (mips_need_noat_wrapper_p (insn, opvec, noperands))
20431 mips_push_asm_switch (&mips_noat); 20525 mips_push_asm_switch (&mips_noat);
20432 } 20526 }
20446 20540
20447 if (INSN_P (insn) 20541 if (INSN_P (insn)
20448 && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE 20542 && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
20449 && XINT (PATTERN (insn), 1) == UNSPEC_CONSTTABLE_END) 20543 && XINT (PATTERN (insn), 1) == UNSPEC_CONSTTABLE_END)
20450 mips_set_text_contents_type (asm_out_file, "__pend_", 20544 mips_set_text_contents_type (asm_out_file, "__pend_",
20451 XINT (XVECEXP (PATTERN (insn), 0, 0), 0), 20545 INTVAL (XVECEXP (PATTERN (insn), 0, 0)),
20452 TRUE); 20546 TRUE);
20453 } 20547 }
20454 20548
20455 /* Return the function that is used to expand the <u>mulsidi3 pattern. 20549 /* Return the function that is used to expand the <u>mulsidi3 pattern.
20456 EXT_CODE is the code of the extension used. Return NULL if widening 20550 EXT_CODE is the code of the extension used. Return NULL if widening
21376 if (mips_expand_msa_shuffle (d)) 21470 if (mips_expand_msa_shuffle (d))
21377 return true; 21471 return true;
21378 return false; 21472 return false;
21379 } 21473 }
21380 21474
21381 /* Expand a vec_perm_const pattern. */ 21475 /* Implement TARGET_VECTORIZE_VEC_PERM_CONST. */
21382 21476
21383 bool 21477 static bool
21384 mips_expand_vec_perm_const (rtx operands[4]) 21478 mips_vectorize_vec_perm_const (machine_mode vmode, rtx target, rtx op0,
21479 rtx op1, const vec_perm_indices &sel)
21385 { 21480 {
21386 struct expand_vec_perm_d d; 21481 struct expand_vec_perm_d d;
21387 int i, nelt, which; 21482 int i, nelt, which;
21388 unsigned char orig_perm[MAX_VECT_LEN]; 21483 unsigned char orig_perm[MAX_VECT_LEN];
21389 rtx sel;
21390 bool ok; 21484 bool ok;
21391 21485
21392 d.target = operands[0]; 21486 d.target = target;
21393 d.op0 = operands[1]; 21487 d.op0 = op0;
21394 d.op1 = operands[2]; 21488 d.op1 = op1;
21395 sel = operands[3]; 21489
21396 21490 d.vmode = vmode;
21397 d.vmode = GET_MODE (d.target); 21491 gcc_assert (VECTOR_MODE_P (vmode));
21398 gcc_assert (VECTOR_MODE_P (d.vmode)); 21492 d.nelt = nelt = GET_MODE_NUNITS (vmode);
21399 d.nelt = nelt = GET_MODE_NUNITS (d.vmode); 21493 d.testing_p = !target;
21400 d.testing_p = false;
21401 21494
21402 /* This is overly conservative, but ensures we don't get an 21495 /* This is overly conservative, but ensures we don't get an
21403 uninitialized warning on ORIG_PERM. */ 21496 uninitialized warning on ORIG_PERM. */
21404 memset (orig_perm, 0, MAX_VECT_LEN); 21497 memset (orig_perm, 0, MAX_VECT_LEN);
21405 for (i = which = 0; i < nelt; ++i) 21498 for (i = which = 0; i < nelt; ++i)
21406 { 21499 {
21407 rtx e = XVECEXP (sel, 0, i); 21500 int ei = sel[i] & (2 * nelt - 1);
21408 int ei = INTVAL (e) & (2 * nelt - 1);
21409 which |= (ei < nelt ? 1 : 2); 21501 which |= (ei < nelt ? 1 : 2);
21410 orig_perm[i] = ei; 21502 orig_perm[i] = ei;
21411 } 21503 }
21412 memcpy (d.perm, orig_perm, MAX_VECT_LEN); 21504 memcpy (d.perm, orig_perm, MAX_VECT_LEN);
21413 21505
21416 default: 21508 default:
21417 gcc_unreachable(); 21509 gcc_unreachable();
21418 21510
21419 case 3: 21511 case 3:
21420 d.one_vector_p = false; 21512 d.one_vector_p = false;
21421 if (!rtx_equal_p (d.op0, d.op1)) 21513 if (d.testing_p || !rtx_equal_p (d.op0, d.op1))
21422 break; 21514 break;
21423 /* FALLTHRU */ 21515 /* FALLTHRU */
21424 21516
21425 case 2: 21517 case 2:
21426 for (i = 0; i < nelt; ++i) 21518 for (i = 0; i < nelt; ++i)
21431 21523
21432 case 1: 21524 case 1:
21433 d.op1 = d.op0; 21525 d.op1 = d.op0;
21434 d.one_vector_p = true; 21526 d.one_vector_p = true;
21435 break; 21527 break;
21528 }
21529
21530 if (d.testing_p)
21531 {
21532 d.target = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 1);
21533 d.op1 = d.op0 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 2);
21534 if (!d.one_vector_p)
21535 d.op1 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 3);
21536
21537 start_sequence ();
21538 ok = mips_expand_vec_perm_const_1 (&d);
21539 end_sequence ();
21540 return ok;
21436 } 21541 }
21437 21542
21438 ok = mips_expand_vec_perm_const_1 (&d); 21543 ok = mips_expand_vec_perm_const_1 (&d);
21439 21544
21440 /* If we were given a two-vector permutation which just happened to 21545 /* If we were given a two-vector permutation which just happened to
21444 support in mips_expand_vec_perm_const_1 to guess the adjustment 21549 support in mips_expand_vec_perm_const_1 to guess the adjustment
21445 that should be made for a single operand. Just try again with 21550 that should be made for a single operand. Just try again with
21446 the original permutation. */ 21551 the original permutation. */
21447 if (!ok && which == 3) 21552 if (!ok && which == 3)
21448 { 21553 {
21449 d.op0 = operands[1]; 21554 d.op0 = op0;
21450 d.op1 = operands[2]; 21555 d.op1 = op1;
21451 d.one_vector_p = false; 21556 d.one_vector_p = false;
21452 memcpy (d.perm, orig_perm, MAX_VECT_LEN); 21557 memcpy (d.perm, orig_perm, MAX_VECT_LEN);
21453 ok = mips_expand_vec_perm_const_1 (&d); 21558 ok = mips_expand_vec_perm_const_1 (&d);
21454 } 21559 }
21455 21560
21463 machine_mode mode) 21568 machine_mode mode)
21464 { 21569 {
21465 if (MSA_SUPPORTED_MODE_P (mode)) 21570 if (MSA_SUPPORTED_MODE_P (mode))
21466 return 2; 21571 return 2;
21467 return 1; 21572 return 1;
21468 }
21469
21470 /* Implement TARGET_VECTORIZE_VEC_PERM_CONST_OK. */
21471
21472 static bool
21473 mips_vectorize_vec_perm_const_ok (machine_mode vmode, vec_perm_indices sel)
21474 {
21475 struct expand_vec_perm_d d;
21476 unsigned int i, nelt, which;
21477 bool ret;
21478
21479 d.vmode = vmode;
21480 d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
21481 d.testing_p = true;
21482
21483 /* Categorize the set of elements in the selector. */
21484 for (i = which = 0; i < nelt; ++i)
21485 {
21486 unsigned char e = sel[i];
21487 d.perm[i] = e;
21488 gcc_assert (e < 2 * nelt);
21489 which |= (e < nelt ? 1 : 2);
21490 }
21491
21492 /* For all elements from second vector, fold the elements to first. */
21493 if (which == 2)
21494 for (i = 0; i < nelt; ++i)
21495 d.perm[i] -= nelt;
21496
21497 /* Check whether the mask can be applied to the vector type. */
21498 d.one_vector_p = (which != 3);
21499
21500 d.target = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 1);
21501 d.op1 = d.op0 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 2);
21502 if (!d.one_vector_p)
21503 d.op1 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 3);
21504
21505 start_sequence ();
21506 ret = mips_expand_vec_perm_const_1 (&d);
21507 end_sequence ();
21508
21509 return ret;
21510 } 21573 }
21511 21574
21512 /* Expand an integral vector unpack operation. */ 21575 /* Expand an integral vector unpack operation. */
21513 21576
21514 void 21577 void
21679 /* Return a const_int vector of VAL with mode MODE. */ 21742 /* Return a const_int vector of VAL with mode MODE. */
21680 21743
21681 rtx 21744 rtx
21682 mips_gen_const_int_vector (machine_mode mode, HOST_WIDE_INT val) 21745 mips_gen_const_int_vector (machine_mode mode, HOST_WIDE_INT val)
21683 { 21746 {
21684 int nunits = GET_MODE_NUNITS (mode); 21747 rtx c = gen_int_mode (val, GET_MODE_INNER (mode));
21685 rtvec v = rtvec_alloc (nunits); 21748 return gen_const_vec_duplicate (mode, c);
21686 int i;
21687
21688 for (i = 0; i < nunits; i++)
21689 RTVEC_ELT (v, i) = gen_int_mode (val, GET_MODE_INNER (mode));
21690
21691 return gen_rtx_CONST_VECTOR (mode, v);
21692 } 21749 }
21693 21750
21694 /* Return a vector of repeated 4-element sets generated from 21751 /* Return a vector of repeated 4-element sets generated from
21695 immediate VAL in mode MODE. */ 21752 immediate VAL in mode MODE. */
21696 21753
21841 gcc_unreachable (); 21898 gcc_unreachable ();
21842 } 21899 }
21843 } 21900 }
21844 else 21901 else
21845 { 21902 {
21846 rtvec vec = shallow_copy_rtvec (XVEC (vals, 0)); 21903 emit_move_insn (target, CONST0_RTX (vmode));
21847
21848 for (i = 0; i < nelt; ++i)
21849 RTVEC_ELT (vec, i) = CONST0_RTX (imode);
21850
21851 emit_move_insn (target, gen_rtx_CONST_VECTOR (vmode, vec));
21852 21904
21853 for (i = 0; i < nelt; ++i) 21905 for (i = 0; i < nelt; ++i)
21854 { 21906 {
21855 rtx temp = gen_reg_rtx (imode); 21907 rtx temp = gen_reg_rtx (imode);
21856 emit_move_insn (temp, XVECEXP (vals, 0, i)); 21908 emit_move_insn (temp, XVECEXP (vals, 0, i));
22330 } 22382 }
22331 22383
22332 /* Implement TARGET_TRULY_NOOP_TRUNCATION. */ 22384 /* Implement TARGET_TRULY_NOOP_TRUNCATION. */
22333 22385
22334 static bool 22386 static bool
22335 mips_truly_noop_truncation (unsigned int outprec, unsigned int inprec) 22387 mips_truly_noop_truncation (poly_uint64 outprec, poly_uint64 inprec)
22336 { 22388 {
22337 return !TARGET_64BIT || inprec <= 32 || outprec > 32; 22389 return !TARGET_64BIT || inprec <= 32 || outprec > 32;
22338 } 22390 }
22339 22391
22340 /* Implement TARGET_CONSTANT_ALIGNMENT. */ 22392 /* Implement TARGET_CONSTANT_ALIGNMENT. */
22343 mips_constant_alignment (const_tree exp, HOST_WIDE_INT align) 22395 mips_constant_alignment (const_tree exp, HOST_WIDE_INT align)
22344 { 22396 {
22345 if (TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR) 22397 if (TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR)
22346 return MAX (align, BITS_PER_WORD); 22398 return MAX (align, BITS_PER_WORD);
22347 return align; 22399 return align;
22400 }
22401
22402 /* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */
22403
22404 static unsigned HOST_WIDE_INT
22405 mips_asan_shadow_offset (void)
22406 {
22407 return 0x0aaa0000;
22348 } 22408 }
22349 22409
22350 /* Implement TARGET_STARTING_FRAME_OFFSET. See mips_compute_frame_info 22410 /* Implement TARGET_STARTING_FRAME_OFFSET. See mips_compute_frame_info
22351 for details about the frame layout. */ 22411 for details about the frame layout. */
22352 22412
22599 #define TARGET_SHIFT_TRUNCATION_MASK mips_shift_truncation_mask 22659 #define TARGET_SHIFT_TRUNCATION_MASK mips_shift_truncation_mask
22600 22660
22601 #undef TARGET_PREPARE_PCH_SAVE 22661 #undef TARGET_PREPARE_PCH_SAVE
22602 #define TARGET_PREPARE_PCH_SAVE mips_prepare_pch_save 22662 #define TARGET_PREPARE_PCH_SAVE mips_prepare_pch_save
22603 22663
22604 #undef TARGET_VECTORIZE_VEC_PERM_CONST_OK 22664 #undef TARGET_VECTORIZE_VEC_PERM_CONST
22605 #define TARGET_VECTORIZE_VEC_PERM_CONST_OK mips_vectorize_vec_perm_const_ok 22665 #define TARGET_VECTORIZE_VEC_PERM_CONST mips_vectorize_vec_perm_const
22606 22666
22607 #undef TARGET_SCHED_REASSOCIATION_WIDTH 22667 #undef TARGET_SCHED_REASSOCIATION_WIDTH
22608 #define TARGET_SCHED_REASSOCIATION_WIDTH mips_sched_reassociation_width 22668 #define TARGET_SCHED_REASSOCIATION_WIDTH mips_sched_reassociation_width
22609 22669
22610 #undef TARGET_CASE_VALUES_THRESHOLD 22670 #undef TARGET_CASE_VALUES_THRESHOLD
22656 #define TARGET_TRULY_NOOP_TRUNCATION mips_truly_noop_truncation 22716 #define TARGET_TRULY_NOOP_TRUNCATION mips_truly_noop_truncation
22657 22717
22658 #undef TARGET_CONSTANT_ALIGNMENT 22718 #undef TARGET_CONSTANT_ALIGNMENT
22659 #define TARGET_CONSTANT_ALIGNMENT mips_constant_alignment 22719 #define TARGET_CONSTANT_ALIGNMENT mips_constant_alignment
22660 22720
22721 #undef TARGET_ASAN_SHADOW_OFFSET
22722 #define TARGET_ASAN_SHADOW_OFFSET mips_asan_shadow_offset
22723
22661 #undef TARGET_STARTING_FRAME_OFFSET 22724 #undef TARGET_STARTING_FRAME_OFFSET
22662 #define TARGET_STARTING_FRAME_OFFSET mips_starting_frame_offset 22725 #define TARGET_STARTING_FRAME_OFFSET mips_starting_frame_offset
22663 22726
22664 struct gcc_target targetm = TARGET_INITIALIZER; 22727 struct gcc_target targetm = TARGET_INITIALIZER;
22665 22728