From 39ba1719f70b31b0793b23d1d43e56d55181c44e Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sun, 25 Apr 2004 08:28:32 +0000 Subject: [PATCH] mips-protos.h (mips_linked_macc_p): Declare. * config/mips/mips-protos.h (mips_linked_macc_p): Declare. * config/mips/mips.h (TUNE_MACC_CHAINS): New macro. * config/mips/mips.c (TARGET_SCHED_REORDER): Define. (TARGET_SCHED_VARIABLE_ISSUE): Define. (mips_adjust_cost): Move later in file, next to other sched hooks. (mips_macc_chains_last_hilo): New variable. (mips_linked_madd_p, mips_macc_chains_record, mips_macc_chains_reorder) (mips_promote_ready, mips_sched_reorder, mips_variable_issue): New. * config/mips/mips.md (may_clobber_hilo): New attribute. From-SVN: r81157 --- gcc/ChangeLog | 12 ++++ gcc/config/mips/mips-protos.h | 1 + gcc/config/mips/mips.c | 159 ++++++++++++++++++++++++++++++++++++++---- gcc/config/mips/mips.h | 33 +++++++++ gcc/config/mips/mips.md | 7 ++ 5 files changed, 197 insertions(+), 15 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8c70524..b5f9080 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2004-04-25 Richard Sandiford + + * config/mips/mips-protos.h (mips_linked_macc_p): Declare. + * config/mips/mips.h (TUNE_MACC_CHAINS): New macro. + * config/mips/mips.c (TARGET_SCHED_REORDER): Define. + (TARGET_SCHED_VARIABLE_ISSUE): Define. + (mips_adjust_cost): Move later in file, next to other sched hooks. + (mips_macc_chains_last_hilo): New variable. + (mips_linked_madd_p, mips_macc_chains_record, mips_macc_chains_reorder) + (mips_promote_ready, mips_sched_reorder, mips_variable_issue): New. + * config/mips/mips.md (may_clobber_hilo): New attribute. + 2004-04-24 Roger Sayle Bruce Korb diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 761cf47..f3b7bdbed 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -201,6 +201,7 @@ extern const char *mips_output_conditional_branch (rtx, rtx *, int, int, int, int); extern const char *mips_output_division (const char *, rtx *); extern unsigned int mips_hard_regno_nregs (int, enum machine_mode); +extern bool mips_linked_madd_p (rtx, rtx); extern const char *mips_emit_prefetch (rtx *); extern void irix_asm_output_align (FILE *, unsigned); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 9720c7d..bbb664e 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -226,9 +226,14 @@ static bool mips_strict_matching_cpu_name_p (const char *, const char *); static bool mips_matching_cpu_name_p (const char *, const char *); static const struct mips_cpu_info *mips_parse_cpu (const char *, const char *); static const struct mips_cpu_info *mips_cpu_info_from_isa (int); -static int mips_adjust_cost (rtx, rtx, rtx, int); static bool mips_return_in_memory (tree, tree); static bool mips_strict_argument_naming (CUMULATIVE_ARGS *); +static void mips_macc_chains_record (rtx); +static void mips_macc_chains_reorder (rtx *, int); +static void mips_promote_ready (rtx *, int, int); +static int mips_sched_reorder (FILE *, int, rtx *, int *, int); +static int mips_variable_issue (FILE *, int, rtx, int); +static int mips_adjust_cost (rtx, rtx, rtx, int); static int mips_issue_rate (void); static int mips_use_dfa_pipeline_interface (void); static int mips_multipass_dfa_lookahead (void); @@ -670,6 +675,10 @@ const struct mips_cpu_info mips_cpu_info_table[] = { #undef TARGET_ASM_SELECT_RTX_SECTION #define TARGET_ASM_SELECT_RTX_SECTION mips_select_rtx_section +#undef TARGET_SCHED_REORDER +#define TARGET_SCHED_REORDER mips_sched_reorder +#undef TARGET_SCHED_VARIABLE_ISSUE +#define TARGET_SCHED_VARIABLE_ISSUE mips_variable_issue #undef TARGET_SCHED_ADJUST_COST #define TARGET_SCHED_ADJUST_COST mips_adjust_cost #undef TARGET_SCHED_ISSUE_RATE @@ -9152,20 +9161,6 @@ mips_cpu_info_from_isa (int isa) return 0; } -/* Adjust the cost of INSN based on the relationship between INSN that - is dependent on DEP_INSN through the dependence LINK. The default - is to make no adjustment to COST. - - On the MIPS, ignore the cost of anti- and output-dependencies. */ -static int -mips_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link, - rtx dep ATTRIBUTE_UNUSED, int cost) -{ - if (REG_NOTE_KIND (link) != 0) - return 0; /* Anti or output dependence. */ - return cost; -} - /* Implement HARD_REGNO_NREGS. The size of FP registers are controlled by UNITS_PER_FPREG. All other registers are word sized. */ @@ -9200,6 +9195,140 @@ mips_strict_argument_naming (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED) return !TARGET_OLDABI; } +/* Return true if INSN is a multiply-add or multiply-subtract + instruction and PREV assigns to the accumulator operand. */ + +bool +mips_linked_madd_p (rtx prev, rtx insn) +{ + rtx x; + + x = single_set (insn); + if (x == 0) + return false; + + x = SET_SRC (x); + + if (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 0)) == MULT + && reg_set_p (XEXP (x, 1), prev)) + return true; + + if (GET_CODE (x) == MINUS + && GET_CODE (XEXP (x, 1)) == MULT + && reg_set_p (XEXP (x, 0), prev)) + return true; + + return false; +} + +/* Used by TUNE_MACC_CHAINS to record the last scheduled instruction + that may clobber hi or lo. */ + +static rtx mips_macc_chains_last_hilo; + +/* A TUNE_MACC_CHAINS helper function. Record that instruction INSN has + been scheduled, updating mips_macc_chains_last_hilo appropriately. */ + +static void +mips_macc_chains_record (rtx insn) +{ + if (get_attr_may_clobber_hilo (insn)) + mips_macc_chains_last_hilo = insn; +} + +/* A TUNE_MACC_CHAINS helper function. Search ready queue READY, which + has NREADY elements, looking for a multiply-add or multiply-subtract + instruction that is cumulative with mips_macc_chains_last_hilo. + If there is one, promote it ahead of anything else that might + clobber hi or lo. */ + +static void +mips_macc_chains_reorder (rtx *ready, int nready) +{ + int i, j; + + if (mips_macc_chains_last_hilo != 0) + for (i = nready - 1; i >= 0; i--) + if (mips_linked_madd_p (mips_macc_chains_last_hilo, ready[i])) + { + for (j = nready - 1; j > i; j--) + if (recog_memoized (ready[j]) >= 0 + && get_attr_may_clobber_hilo (ready[j])) + { + mips_promote_ready (ready, i, j); + break; + } + break; + } +} + +/* Remove the instruction at index LOWER from ready queue READY and + reinsert it in front of the instruction at index HIGHER. LOWER must + be <= HIGHER. */ + +static void +mips_promote_ready (rtx *ready, int lower, int higher) +{ + rtx new_head; + int i; + + new_head = ready[lower]; + for (i = lower; i < higher; i++) + ready[i] = ready[i + 1]; + ready[i] = new_head; +} + +/* Implement TARGET_SCHED_REORDER. */ + +static int +mips_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED, + rtx *ready, int *nreadyp, int cycle) +{ + if (!reload_completed && TUNE_MACC_CHAINS) + { + if (cycle == 0) + mips_macc_chains_last_hilo = 0; + if (*nreadyp > 0) + mips_macc_chains_reorder (ready, *nreadyp); + } + return mips_issue_rate (); +} + +/* Implement TARGET_SCHED_VARIABLE_ISSUE. */ + +static int +mips_variable_issue (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED, + rtx insn, int more) +{ + switch (GET_CODE (PATTERN (insn))) + { + case USE: + case CLOBBER: + /* Don't count USEs and CLOBBERs against the issue rate. */ + break; + + default: + more--; + if (!reload_completed && TUNE_MACC_CHAINS) + mips_macc_chains_record (insn); + break; + } + return more; +} + +/* Implement TARGET_SCHED_ADJUST_COST. We assume that anti and output + dependencies have no cost. */ + +static int +mips_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link, + rtx dep ATTRIBUTE_UNUSED, int cost) +{ + if (REG_NOTE_KIND (link) != 0) + return 0; + return cost; +} + /* Return the number of instructions that can be issued per cycle. */ static int diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 73fbe71..e678ba9 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -340,6 +340,39 @@ extern const struct mips_cpu_info *mips_tune_info; #define TUNE_MIPS9000 (mips_tune == PROCESSOR_R9000) #define TUNE_SB1 (mips_tune == PROCESSOR_SB1) +/* True if the pre-reload scheduler should try to create chains of + multiply-add or multiply-subtract instructions. For example, + suppose we have: + + t1 = a * b + t2 = t1 + c * d + t3 = c * d + t4 = t3 - c * d + + t1 will have a higher priority and t2 and t3 will have a higher + priority than t4. However, before reload, there is no dependence + between t1 and t3, and they can often have similar priorities. + The scheduler will then tend to prefer: + + t1 = a * b + t3 = e * f + t2 = t1 + c * d + t4 = t3 - g * h + + which stops us from making full use of macc/madd-style instructions. + This sort of situation occurs frequently in Fourier transforms and + in unrolled loops. + + To counter this, the TUNE_MACC_CHAINS code will reorder the ready + queue so that chained multiply-add and multiply-subtract instructions + appear ahead of any other instruction that is likely to clobber lo. + In the example above, if t2 and t3 become ready at the same time, + the code ensures that t2 is scheduled first. + + Multiply-accumulate instructions are a bigger win for some targets + than others, so this macro is defined on an opt-in basis. */ +#define TUNE_MACC_CHAINS TUNE_MIPS5500 + #define TARGET_OLDABI (mips_abi == ABI_32 || mips_abi == ABI_O64) #define TARGET_NEWABI (mips_abi == ABI_N32 || mips_abi == ABI_64) diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 7f36d63..d5071dd 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -277,6 +277,13 @@ (const_string "yes") (const_string "no")))) +;; True if an instruction might assign to hi or lo when reloaded. +;; This is used by the TUNE_MACC_CHAINS code. +(define_attr "may_clobber_hilo" "no,yes" + (if_then_else (eq_attr "type" "imul,imadd,idiv,mthilo") + (const_string "yes") + (const_string "no"))) + ;; Describe a user's asm statement. (define_asm_attributes [(set_attr "type" "multi")]) -- 2.7.4