Mercurial > hg > CbC > CbC_gcc
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 |