Hi Matthew, As already discussed, the link to the P6600 doesn't appear to be referenced on mips.com but reachable when searching for 'p6600':
https://www.mips.com/downloads/p6600-multiprocessing-programmers-guide/ I'm resubmitting the whole patch again with updated ChangeLog. > > > > +/* Classifies an unconditional branch of interest for the P6600. */ > > + > > +enum mips_ucbranch_type { > > Newline for brace. Done. > > +/* Subroutine of mips_avoid_hazard. We classify unconditional > > branches > > + of interest for the P6600 for performance reasons. We're > > interested > > + in differentiating BALC from JIC, JIALC and BC. */ > > + > > +static enum mips_ucbranch_type > > +mips_classify_branch_p6600 (rtx_insn *insn) { > > + if (!(insn > > + && USEFUL_INSN_P (insn) > > + && GET_CODE (PATTERN (insn)) != SEQUENCE)) > > + return UC_UNDEFINED; > > Let's switch this around to the following with a comment to say ignore > sequences because they represent a filled delay slot branch (which > presumably is not affected by the uArch issue). > > if (insn > || !USEFUL_INSN_P (insn) > || GET_CODE (PATTERN (insn)) == SEQUENCE)) > return UC_UNDEFINED; Switched around and added a comment. > > > + > > + if (get_attr_jal (insn) == JAL_INDIRECT /* JIC and JIALC. */ > > + || get_attr_type (insn) == TYPE_JUMP) /* BC as it is a loose > > jump. */ > > + return UC_OTHER; > > I don't recall what a loose jump was supposed to refer to, presumably > 'direct jump'. Left it just as 'BC'. > > > /* Subroutine of mips_reorg_process_insns. If there is a hazard > > between > > INSN and a previous instruction, avoid it by inserting nops after > > instruction AFTER. > > @@ -18699,14 +18744,36 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn > > *insn, int *hilo_delay, > > && GET_CODE (pattern) != ASM_INPUT > > && asm_noperands (pattern) < 0) > > nops = 1; > > + /* The P6600's branch predictor does not handle certain static > > + sequences of back-to-back jumps well. Inserting a no-op only > > + costs space as the dispatch unit will disregard the nop. > > + Here we handle the cases of back to back unconditional branches > > + that are inefficent. */ > > + else if (TUNE_P6600 && TARGET_CB_MAYBE && !optimize_size > > + && ((mips_classify_branch_p6600 (after) == UC_BALC > > + && mips_classify_branch_p6600 (insn) == UC_OTHER) > > + || (mips_classify_branch_p6600 (insn) == UC_BALC > > + && (mips_classify_branch_p6600 (after) == UC_OTHER)))) > > Unnecessary braces on the last clause here. Removed the braces and change the comment. > > > + nops = 1; > > This appears to show that a BALC with a compact branch (other than BALC) > is the problem case either before or after the BALC. This is what we need > to see in a public document. Or at least (re)confirmed as the issue. > > > else > > nops = 0; > > > > /* Insert the nops between this instruction and the previous one. > > Each new nop takes us further from the last hilo hazard. */ > > *hilo_delay += nops; > > + > > + /* If we're tuning for the P6600, we come across an annoying GCC > > + assumption that debug information always follows a call. Move > > + past any debug information in that case. */ > > + rtx_insn *real_after = after; > > + if (real_after && nops && CALL_P (real_after)) > > + while (TUNE_P6600 && real_after > > + && (NOTE_P (NEXT_INSN (real_after)) > > + || BARRIER_P (NEXT_INSN (real_after)))) > > + real_after = NEXT_INSN (real_after); > > + > > This looks OK but it seems unnecessary to limit to the P6600. It is just > that we have not had hazards on branches before now. Removed the restriction. > > > while (nops-- > 0) > > - emit_insn_after (gen_hazard_nop (), after); > > + emit_insn_after (gen_hazard_nop (), real_after); > > > > /* Set up the state for the next instruction. */ > > *hilo_delay += ninsns; > > @@ -18716,6 +18783,14 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn > > *insn, int *hilo_delay, > > switch (get_attr_hazard (insn)) > > { > > case HAZARD_NONE: > > + /* For the P6600, flag some unconditional branches as having a > > + pseudo-forbidden slot. This will cause additional nop > > insertion > > + or SEQUENCE breaking as required. */ > > + if (TUNE_P6600 > > + && !optimize_size > > + && TARGET_CB_MAYBE > > + && mips_classify_branch_p6600 (insn) == UC_OTHER) > > + *fs_delay = true; > > This appears to be saying that all unconditional branches (except > BALC) will introduce a performance penalty if followed by any other non- > delay/non-forbidden slot instruction. Added a comment that this is for performance reasons. > > > break; > > > > case HAZARD_FORBIDDEN_SLOT: > > @@ -18957,7 +19032,10 @@ mips_reorg_process_insns (void) > > sequence and replace it with the delay slot instruction > > then the jump to clear the forbidden slot hazard. */ > > > > - if (fs_delay) > > + if (fs_delay || (TUNE_P6600 > > + && TARGET_CB_MAYBE > > + && mips_classify_branch_p6600 (insn) > > + == UC_BALC)) > > This seems to be accounting for a BALC followed by delay slot branch but > more of a hint than a guarantee as it is going to convert the delay slot > branch to a compact branch which presumably is 'better' > for the P6600. I left it as it is i.e. without additional comments. > > The implied rules from the patch seem to be: > > BALC -> JIC/JIALC/BC == BAD - insert NOP to fix > JIC/JIALC/BC -> BALC == BAD - insert NOP to fix > JIC/JIALC/BC -> non-DS-INSN == BAD - treat as forbidden slot > BALC -> BALC == OK > BALC -> Delay slot branch == BAD - undo delay slot to fix > BALC -> Conditional compact branch == OK And that would be the expected behaviour. I added a comment in mips_avoid_hazard() to list the cases that would be handled by the branch predictor. > > > { > > /* Search onwards from the current position looking for > > a SEQUENCE. We are looking for pipeline hazards > here > > diff --git a/gcc/config/mips/p6600.md b/gcc/config/mips/p6600.md new > > file mode 100644 index 0000000..17144a1 > > --- /dev/null > > +++ b/gcc/config/mips/p6600.md > > @@ -0,0 +1,342 @@ > > +;; DFA-based pipeline description for P6600. > > +;; > > +;; Copyright (C) 2007-2015 Free Software Foundation, Inc. > > Copyright year should just be 2018 for first submission of a new file. > > The scheduler references to fminmax and fclass types that do not yet exist > in trunk. As for frint. Removed. > > This patch is dependent on public information becoming available about the > uArch branch prediction rules that are implemented in this patch so that > the logic can be correctly maintained in the future. Regards, Robert gcc/ChangeLog: 2018-06-12 Matthew Fortune <matthew.fort...@mips.com> Prachi Godbole <prachi.godb...@imgtec.com> * config/mips/mips-cpus.def: Define P6600. * config/mips/mips-tables.opt: Regenerate. * config/mips/mips.c (mips_ucbranch_type): New enum. (mips_rtx_cost_data): Add support for P6600. (mips_issue_rate): Likewise. (mips_multipass_dfa_lookahead): Likewise. (mips_avoid_hazard): Likewise. (mips_reorg_process_insns): Likewise. (mips_classify_branch_p6600): New function. * config/mips/mips.h (TUNE_P6600): New define. (MIPS_ISA_LEVEL_SPEC): Infer mips64r6 from p6600. (ENABLE_LD_ST_PAIRS): Enable load/store bonding for p6600. * config/mips/mips.md: Include p6600.md. (processor): Add p6600. * config/mips/p6600.md: New file. * doc/invoke.texi: Add p6600 to supported architectures. --- gcc/config/mips/mips-cpus.def | 1 + gcc/config/mips/mips-tables.opt | 3 + gcc/config/mips/mips.c | 91 ++++++++- gcc/config/mips/mips.h | 6 +- gcc/config/mips/mips.md | 2 + gcc/config/mips/p6600.md | 342 ++++++++++++++++++++++++++++++++ gcc/doc/invoke.texi | 2 +- 7 files changed, 441 insertions(+), 6 deletions(-) create mode 100644 gcc/config/mips/p6600.md diff --git a/gcc/config/mips/mips-cpus.def b/gcc/config/mips/mips-cpus.def index 7314335f147..6a545634417 100644 --- a/gcc/config/mips/mips-cpus.def +++ b/gcc/config/mips/mips-cpus.def @@ -172,3 +172,4 @@ MIPS_CPU ("xlp", PROCESSOR_XLP, 65, PTF_AVOID_BRANCHLIKELY_SPEED) /* MIPS64 Release 6 processors. */ MIPS_CPU ("i6400", PROCESSOR_I6400, 69, 0) MIPS_CPU ("i6500", PROCESSOR_I6400, 69, 0) +MIPS_CPU ("p6600", PROCESSOR_P6600, 69, 0) diff --git a/gcc/config/mips/mips-tables.opt b/gcc/config/mips/mips-tables.opt index d8e50b298b5..11be4639fc3 100644 --- a/gcc/config/mips/mips-tables.opt +++ b/gcc/config/mips/mips-tables.opt @@ -699,3 +699,6 @@ Enum(mips_arch_opt_value) String(i6400) Value(102) Canonical EnumValue Enum(mips_arch_opt_value) String(i6500) Value(103) Canonical +EnumValue +Enum(mips_arch_opt_value) String(p6600) Value(104) Canonical + diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index bfe64bb060c..ae3c8d9604b 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -198,6 +198,16 @@ enum mips_address_type { ADDRESS_SYMBOLIC }; +/* Classifies an unconditional branch of interest for the P6600. */ + +enum mips_ucbranch_type +{ + /* May not even be a branch. */ + UC_UNDEFINED, + UC_BALC, + UC_OTHER +}; + /* Macros to create an enumeration identifier for a function prototype. */ #define MIPS_FTYPE_NAME1(A, B) MIPS_##A##_FTYPE_##B #define MIPS_FTYPE_NAME2(A, B, C) MIPS_##A##_FTYPE_##B##_##C @@ -1127,6 +1137,19 @@ static const struct mips_rtx_cost_data COSTS_N_INSNS (36), /* int_div_di */ 2, /* branch_cost */ 4 /* memory_latency */ + }, + { /* P6600 */ + COSTS_N_INSNS (4), /* fp_add */ + COSTS_N_INSNS (5), /* fp_mult_sf */ + COSTS_N_INSNS (5), /* fp_mult_df */ + COSTS_N_INSNS (17), /* fp_div_sf */ + COSTS_N_INSNS (17), /* fp_div_df */ + COSTS_N_INSNS (5), /* int_mult_si */ + COSTS_N_INSNS (5), /* int_mult_di */ + COSTS_N_INSNS (8), /* int_div_si */ + COSTS_N_INSNS (8), /* int_div_di */ + 2, /* branch_cost */ + 4 /* memory_latency */ } }; @@ -14592,6 +14615,7 @@ mips_issue_rate (void) case PROCESSOR_LOONGSON_2F: case PROCESSOR_LOONGSON_3A: case PROCESSOR_P5600: + case PROCESSOR_P6600: return 4; case PROCESSOR_XLP: @@ -14727,7 +14751,7 @@ mips_multipass_dfa_lookahead (void) if (TUNE_OCTEON) return 2; - if (TUNE_P5600 || TUNE_I6400) + if (TUNE_P5600 || TUNE_P6600 || TUNE_I6400) return 4; return 0; @@ -18647,6 +18671,29 @@ mips_orphaned_high_part_p (mips_offset_table *htab, rtx_insn *insn) return false; } +/* Subroutine of mips_avoid_hazard. We classify unconditional branches + of interest for the P6600 for performance reasons. We're interested + in differentiating BALC from JIC, JIALC and BC. */ + +static enum mips_ucbranch_type +mips_classify_branch_p6600 (rtx_insn *insn) +{ + /* We ignore sequences here as they represent a filled delay slot. */ + if (!insn + || !USEFUL_INSN_P (insn) + || GET_CODE (PATTERN (insn)) == SEQUENCE) + return UC_UNDEFINED; + + if (get_attr_jal (insn) == JAL_INDIRECT /* JIC and JIALC. */ + || get_attr_type (insn) == TYPE_JUMP) /* BC. */ + return UC_OTHER; + + if (CALL_P (insn) && get_attr_jal (insn) == JAL_DIRECT) + return UC_BALC; + + return UC_UNDEFINED; +} + /* Subroutine of mips_reorg_process_insns. If there is a hazard between INSN and a previous instruction, avoid it by inserting nops after instruction AFTER. @@ -18699,14 +18746,40 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay, && GET_CODE (pattern) != ASM_INPUT && asm_noperands (pattern) < 0) nops = 1; + /* The P6600's branch predictor can handle static sequences of back-to-back + branches in the following cases: + + (1) BALC followed by any conditional compact branch + (2) BALC followed by BALC + + Any other combinations of compact branches will incur performance + penalty. Inserting a no-op only costs space as the dispatch unit will + disregard the nop. */ + else if (TUNE_P6600 && TARGET_CB_MAYBE && !optimize_size + && ((mips_classify_branch_p6600 (after) == UC_BALC + && mips_classify_branch_p6600 (insn) == UC_OTHER) + || (mips_classify_branch_p6600 (insn) == UC_BALC + && mips_classify_branch_p6600 (after) == UC_OTHER))) + nops = 1; else nops = 0; /* Insert the nops between this instruction and the previous one. Each new nop takes us further from the last hilo hazard. */ *hilo_delay += nops; + + /* Move to the next real instruction if we are inserting a NOP and this + instruction is a call with debug information. The reason being that + we can't separate the call from the debug info. */ + rtx_insn *real_after = after; + if (real_after && nops && CALL_P (real_after)) + while (real_after + && (NOTE_P (NEXT_INSN (real_after)) + || BARRIER_P (NEXT_INSN (real_after)))) + real_after = NEXT_INSN (real_after); + while (nops-- > 0) - emit_insn_after (gen_hazard_nop (), after); + emit_insn_after (gen_hazard_nop (), real_after); /* Set up the state for the next instruction. */ *hilo_delay += ninsns; @@ -18716,6 +18789,15 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay, switch (get_attr_hazard (insn)) { case HAZARD_NONE: + /* For the P6600, flag some unconditional branches as having a + pseudo-forbidden slot. This will cause additional nop insertion + or SEQUENCE breaking as required. This is for performance + reasons not correctness. */ + if (TUNE_P6600 + && !optimize_size + && TARGET_CB_MAYBE + && mips_classify_branch_p6600 (insn) == UC_OTHER) + *fs_delay = true; break; case HAZARD_FORBIDDEN_SLOT: @@ -18957,7 +19039,10 @@ mips_reorg_process_insns (void) sequence and replace it with the delay slot instruction then the jump to clear the forbidden slot hazard. */ - if (fs_delay) + if (fs_delay || (TUNE_P6600 + && TARGET_CB_MAYBE + && mips_classify_branch_p6600 (insn) + == UC_BALC)) { /* Search onwards from the current position looking for a SEQUENCE. We are looking for pipeline hazards here diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 705434eca39..61c5ae24617 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -317,6 +317,7 @@ struct mips_cpu_info { || mips_tune == PROCESSOR_SB1A) #define TUNE_P5600 (mips_tune == PROCESSOR_P5600) #define TUNE_I6400 (mips_tune == PROCESSOR_I6400) +#define TUNE_P6600 (mips_tune == PROCESSOR_P6600) /* Whether vector modes and intrinsics for ST Microelectronics Loongson-2E/2F processors should be enabled. In o32 pairs of @@ -782,7 +783,7 @@ struct mips_cpu_info { %{march=mips64r2|march=loongson3a|march=octeon|march=xlp: -mips64r2} \ %{march=mips64r3: -mips64r3} \ %{march=mips64r5: -mips64r5} \ - %{march=mips64r6|march=i6400|march=i6500: -mips64r6}}" + %{march=mips64r6|march=i6400|march=i6500|march=p6600: -mips64r6}}" /* A spec that injects the default multilib ISA if no architecture is specified. */ @@ -3403,5 +3404,6 @@ struct GTY(()) machine_function { performance can be degraded for those targets. Hence, do not bond for micromips or fix_24k. */ #define ENABLE_LD_ST_PAIRS \ - (TARGET_LOAD_STORE_PAIRS && (TUNE_P5600 || TUNE_I6400) \ + (TARGET_LOAD_STORE_PAIRS \ + && (TUNE_P5600 || TUNE_I6400 || TUNE_P6600) \ && !TARGET_MICROMIPS && !TARGET_FIX_24K) diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 061e57db533..ea5a23be1f7 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -69,6 +69,7 @@ (define_enum "processor" [ p5600 m5100 i6400 + p6600 ]) (define_c_enum "unspec" [ @@ -1152,6 +1153,7 @@ (define_insn_reservation "ghost" 0 (include "i6400.md") (include "p5600.md") (include "m5100.md") +(include "p6600.md") (include "4k.md") (include "5k.md") (include "20kc.md") diff --git a/gcc/config/mips/p6600.md b/gcc/config/mips/p6600.md new file mode 100644 index 00000000000..211bdd77143 --- /dev/null +++ b/gcc/config/mips/p6600.md @@ -0,0 +1,342 @@ +;; DFA-based pipeline description for P6600. +;; +;; Copyright (C) 2018 Free Software Foundation, Inc. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. + +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +(define_automaton "p6600_agen_alq_pipe, p6600_mdu_pipe, p6600_fpu_pipe") + +;; The address generation queue (AGQ) has AL2, CTISTD and LDSTA pipes +(define_cpu_unit "p6600_agq, p6600_al2, p6600_ctistd, p6600_lsu" + "p6600_agen_alq_pipe") + +(define_cpu_unit "p6600_gpmul, p6600_gpdiv" "p6600_mdu_pipe") + +;; The arithmetic-logic-unit queue (ALQ) has ALU pipe +(define_cpu_unit "p6600_alq, p6600_alu" "p6600_agen_alq_pipe") + +;; The floating-point-unit queue (FPQ) has short and long pipes +(define_cpu_unit "p6600_fpu_short, p6600_fpu_long" "p6600_fpu_pipe") + +;; Short FPU pipeline. +(define_cpu_unit "p6600_fpu_intadd, p6600_fpu_cmp, p6600_fpu_float, + p6600_fpu_logic_a, p6600_fpu_logic_b, p6600_fpu_div, + p6600_fpu_store" "p6600_fpu_pipe") + +;; Long FPU pipeline. +(define_cpu_unit "p6600_fpu_logic, p6600_fpu_float_a, p6600_fpu_float_b, + p6600_fpu_float_c, p6600_fpu_float_d" "p6600_fpu_pipe") +(define_cpu_unit "p6600_fpu_mult, p6600_fpu_fdiv, p6600_fpu_apu" "p6600_fpu_pipe") + +(define_reservation "p6600_agq_al2" "p6600_agq, p6600_al2") +(define_reservation "p6600_agq_ctistd" "p6600_agq, p6600_ctistd") +(define_reservation "p6600_agq_lsu" "p6600_agq, p6600_lsu") +(define_reservation "p6600_alq_alu" "p6600_alq, p6600_alu") + +;; +;; FPU-MSA pipe +;; + +;; Arithmetic +;; add, hadd, sub, hsub, average, min, max, compare +(define_insn_reservation "p6600_msa_short_int_add" 2 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_int_arith")) + "p6600_fpu_short, p6600_fpu_intadd") + +;; Bitwise Instructions +;; and, or, xor, bit-clear, leading-bits-count, shift, shuffle +(define_insn_reservation "p6600_msa_short_logic" 2 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_shift,simd_bit,simd_splat,simd_fill,simd_shf, + simd_permute,simd_logic")) + "p6600_fpu_short, p6600_fpu_logic_a") + +;; move.v +(define_insn_reservation "p6600_msa_short_logic_move_v" 2 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_move")) + "p6600_fpu_short, p6600_fpu_logic_a") + +;; Float compare +(define_insn_reservation "p6600_msa_short_cmp" 2 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_fcmp")) + "p6600_fpu_short, p6600_fpu_cmp") + +;; Float exp2, min, max +(define_insn_reservation "p6600_msa_short_float2" 2 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_fexp2,simd_fminmax")) + "p6600_fpu_short, p6600_fpu_float") + +;; Vector sat +(define_insn_reservation "p6600_msa_short_logic3" 3 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_sat,simd_pcnt")) + "p6600_fpu_short, p6600_fpu_logic_a, p6600_fpu_logic_b") + +;; Vector copy, bz, bnz +(define_insn_reservation "p6600_msa_short_store4" 4 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_copy,simd_branch,simd_cmsa")) + "p6600_fpu_short, p6600_fpu_store") + +;; Vector load +(define_insn_reservation "p6600_msa_load" 8 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_load")) + "p6600_agq_lsu") + +;; Vector store +(define_insn_reservation "p6600_msa_short_store" 1 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_store")) + "p6600_agq_lsu") + +;; binsl, binsr, insert, vshf, sld +(define_insn_reservation "p6600_msa_long_logic" 2 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_bitins,simd_bitmov,simd_insert,simd_sld")) + "p6600_fpu_long, p6600_fpu_logic") + +;; Float fclass, flog2 +(define_insn_reservation "p6600_msa_long_float2" 2 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_fclass,simd_flog2")) + "p6600_fpu_long, p6600_fpu_float_a") + +;; fadd, fsub +(define_insn_reservation "p6600_msa_long_float4" 4 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_fadd,simd_fcvt")) + "p6600_fpu_long, p6600_fpu_float_a, p6600_fpu_float_b") + +;; fmul +(define_insn_reservation "p6600_msa_long_float5" 5 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_fmul")) + "p6600_fpu_long, p6600_fpu_float_a, p6600_fpu_float_b, p6600_fpu_float_c") + +;; fmadd, fmsub +(define_insn_reservation "p6600_msa_long_float8" 8 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_fmadd")) + "p6600_fpu_long, p6600_fpu_float_a, + p6600_fpu_float_b, p6600_fpu_float_c, p6600_fpu_float_d") + +;; Vector mul, dotp, madd, msub +(define_insn_reservation "p6600_msa_long_mult" 5 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_mul")) + "p6600_fpu_long, p6600_fpu_mult") + +;; fdiv, fmod (semi-pipelined) +(define_insn_reservation "p6600_msa_long_fdiv" 10 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_fdiv")) + "p6600_fpu_long, nothing, nothing, p6600_fpu_fdiv*8") + +;; div, mod (non-pipelined) +(define_insn_reservation "p6600_msa_long_div" 10 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "simd_div")) + "p6600_fpu_long, p6600_fpu_div*9, p6600_fpu_div + p6600_fpu_logic_a") + +;; +;; FPU pipe +;; + +;; fadd, fsub +(define_insn_reservation "p6600_fpu_fadd" 4 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "fadd")) + "p6600_fpu_long, p6600_fpu_apu") + +;; fabs, fneg, fcmp +(define_insn_reservation "p6600_fpu_fabs" 2 + (and (eq_attr "cpu" "p6600") + (ior (eq_attr "type" "fabs,fneg,fcmp,fmove") + (and (eq_attr "type" "condmove") + (eq_attr "mode" "SF,DF")))) + "p6600_fpu_short, p6600_fpu_apu") + +;; fload +(define_insn_reservation "p6600_fpu_fload" 8 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "fpload,fpidxload")) + "p6600_agq_lsu") + +;; fstore +(define_insn_reservation "p6600_fpu_fstore" 1 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "fpstore,fpidxstore")) + "p6600_agq_lsu") + +;; fmadd +(define_insn_reservation "p6600_fpu_fmadd" 8 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "fmadd")) + "p6600_fpu_long, p6600_fpu_apu") + +;; fmul +(define_insn_reservation "p6600_fpu_fmul" 5 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "fmul")) + "p6600_fpu_long, p6600_fpu_apu") + +;; fdiv, fsqrt +(define_insn_reservation "p6600_fpu_div" 17 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt")) + "p6600_fpu_long, p6600_fpu_apu*17") + +;; fcvt +(define_insn_reservation "p6600_fpu_fcvt" 4 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "fcvt")) + "p6600_fpu_long, p6600_fpu_apu") + +;; mtc +(define_insn_reservation "p6600_fpu_fmtc" 7 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "mtc")) + "p6600_agq_lsu") + +;; mfc +(define_insn_reservation "p6600_fpu_fmfc" 7 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "mfc")) + "p6600_agq_lsu") + +;; +;; Integer pipe +;; + +;; and +(define_insn_reservation "p6600_int_and" 1 + (and (eq_attr "cpu" "p6600") + (eq_attr "move_type" "logical")) + "p6600_alq_alu") + +;; lui +(define_insn_reservation "p6600_int_lui" 1 + (and (eq_attr "cpu" "p6600") + (eq_attr "move_type" "const")) + "p6600_alq_alu") + +;; Load lb, lbu, lh, lhu, lq, lw, lw_i2f, lwxs +(define_insn_reservation "p6600_int_load" 4 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "load")) + "p6600_agq_lsu") + +;; store +(define_insn_reservation "p6600_int_store" 3 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "store")) + "p6600_agq_lsu") + +;; andi, sll, srl, seb, seh +(define_insn_reservation "p6600_int_arith_1" 1 + (and (eq_attr "cpu" "p6600") + (eq_attr "move_type" "andi,sll0,signext")) + "p6600_alq_alu | p6600_agq_al2") + +;; addi, addiu, ori, xori, add, addu +(define_insn_reservation "p6600_int_arith_2" 1 + (and (eq_attr "cpu" "p6600") + (eq_attr "alu_type" "add,or,xor")) + "p6600_alq_alu | p6600_agq_al2") + +;; nor, sub +(define_insn_reservation "p6600_int_arith_3" 1 + (and (eq_attr "cpu" "p6600") + (eq_attr "alu_type" "and,not,nor,sub")) + "p6600_alq_alu") + +;; srl, sra, rotr, slt, sllv, srlv +(define_insn_reservation "p6600_int_arith_4" 1 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "shift,slt,move")) + "p6600_alq_alu | p6600_agq_al2") + +;; nop +(define_insn_reservation "p6600_int_nop" 0 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "nop")) + "p6600_alq_alu | p6600_agq_al2") + +;; clo, clz +(define_insn_reservation "p6600_int_countbits" 2 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "clz")) + "p6600_agq_al2") + +;; Conditional moves +(define_insn_reservation "p6600_int_condmove" 2 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "condmove")) + "p6600_agq_al2") + +;; mfhi/lo +(define_insn_reservation "p6600_dsp_mfhilo" 5 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "mfhi,mflo")) + "p6600_agq_lsu") + +;; mthi/lo +(define_insn_reservation "p6600_dsp_mthilo" 5 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "mthi,mtlo")) + "p6600_agq_lsu") + +;; mul, mulu, muh, muhu +(define_insn_reservation "p6600_dsp_mult" 4 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "imul3,imul,imul3nc")) + "p6600_gpmul") + +;; branch and jump +(define_insn_reservation "p6600_int_branch" 1 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "branch,jump")) + "p6600_agq_ctistd") + +;; prefetch +(define_insn_reservation "p6600_int_prefetch" 0 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "prefetch,prefetchx")) + "p6600_agq_lsu") + +;; divide +(define_insn_reservation "p6600_int_div" 8 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "idiv,idiv3")) + "p6600_gpdiv*5") + +;; arith +(define_insn_reservation "p6600_int_arith_5" 2 + (and (eq_attr "cpu" "p6600") + (eq_attr "type" "arith")) + "p6600_agq_al2") + +;; call +(define_insn_reservation "p6600_int_call" 2 + (and (eq_attr "cpu" "p6600") + (eq_attr "jal" "indirect,direct")) + "p6600_agq_ctistd") diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index b06ea6e7368..d933a168be5 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -20107,7 +20107,7 @@ The processor names are: @samp{m5100}, @samp{m5101}, @samp{octeon}, @samp{octeon+}, @samp{octeon2}, @samp{octeon3}, @samp{orion}, -@samp{p5600}, +@samp{p5600}, @samp{p6600}, @samp{r2000}, @samp{r3000}, @samp{r3900}, @samp{r4000}, @samp{r4400}, @samp{r4600}, @samp{r4650}, @samp{r4700}, @samp{r6000}, @samp{r8000}, @samp{rm7000}, @samp{rm9000}, -- 2.17.1