summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog28
-rw-r--r--gcc/config/sh/sh.c410
-rw-r--r--gcc/config/sh/sh.h6
-rw-r--r--gcc/doc/tm.texi13
-rw-r--r--gcc/flow.c5
-rw-r--r--gcc/haifa-sched.c6
-rw-r--r--gcc/target-def.h4
-rw-r--r--gcc/target.h6
8 files changed, 476 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index afbb5256a81..99cbcb3f71c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,31 @@
+2003-02-24 Sanjiv Kumar Gupta <sanjivg@noida.hcltech.com>
+
+ * target-def.h (TARGET_SCHED_INIT_GLOBAL,
+ TARGET_SCHED_FINISH_GLOBAL): New macros.
+
+ * target.h (md_init_global, md_finish_global): Function
+ declarations corresponding to new target macros.
+
+ * haifa-sched.c (sched_init, sched_finish): Allow target to
+ call the new schedular hooks.
+
+ * flow.c (recompute_reg_usage): Add PROP_DEATH_NOTES flag in
+ call to update_life_info.
+
+ * config/sh/sh.h (OVERRIDE_OPTIONS): Re-enable
+ flag_schedule_insns for SH4.
+
+ * config/sh/sh.c (sh_md_init_global, sh_md_finish_global,
+ find_set_regmode_weight, find_insn_regmode_weight,
+ find_regmode_weight), sh_md_init, sh_dfa_new_cycle,
+ sh_variable_issue, high_pressure, ready_reorder,
+ rank_for_reorder, swap_reorder, sh_reorder, sh_reorder2): New
+ functions used to throttle the insn movement in first
+ scheduling pass for SH.
+
+ * gcc/doc/tm.texi: Document TARGET_SCHED_INIT_GLOBAL and
+ TARGET_SCHED_FINISH_GLOBAL.
+
2004-02-24 Alexandre Oliva <aoliva@redhat.com>
Implement FR-V FDPIC ABI support for frv-uclinux and frv-linux.
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 1acdeadfd6a..dbb463d9915 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -49,6 +49,7 @@ Boston, MA 02111-1307, USA. */
#include "ra.h"
#include "cfglayout.h"
#include "intl.h"
+#include "sched-int.h"
#include "ggc.h"
int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
@@ -101,6 +102,21 @@ int current_function_anonymous_args;
/* Which cpu are we scheduling for. */
enum processor_type sh_cpu;
+/* Definitions used in ready queue reordering for first scheduling pass. */
+
+/* Reg weights arrays for modes SFmode and SImode, indexed by insn LUID. */
+static short *regmode_weight[2];
+
+/* Total SFmode and SImode weights of scheduled insns. */
+static int curr_regmode_pressure[2];
+
+/* If true, skip cycles for Q -> R movement. */
+static int skip_cycles = 0;
+
+/* Cached value of can_issue_more. This is cached in sh_variable_issue hook
+ and returned from sh_reorder2. */
+static short cached_can_issue_more;
+
/* Saved operands from the last compare to use when we generate an scc
or bcc insn. */
@@ -211,6 +227,21 @@ static void sh_insert_attributes (tree, tree *);
static int sh_adjust_cost (rtx, rtx, rtx, int);
static int sh_use_dfa_interface (void);
static int sh_issue_rate (void);
+static int sh_dfa_new_cycle (FILE *, int, rtx, int, int, int *sort_p);
+static short find_set_regmode_weight (rtx, enum machine_mode);
+static short find_insn_regmode_weight (rtx, enum machine_mode);
+static void find_regmode_weight (int, enum machine_mode);
+static void sh_md_init_global (FILE *, int, int);
+static void sh_md_finish_global (FILE *, int);
+static int rank_for_reorder (const void *, const void *);
+static void swap_reorder (rtx *, int);
+static void ready_reorder (rtx *, int);
+static short high_pressure (enum machine_mode);
+static int sh_reorder (FILE *, int, rtx *, int *, int);
+static int sh_reorder2 (FILE *, int, rtx *, int *, int);
+static void sh_md_init (FILE *, int, int);
+static int sh_variable_issue (FILE *, int, rtx, int);
+
static bool sh_function_ok_for_sibcall (tree, tree);
static bool sh_cannot_modify_jumps_p (void);
@@ -293,6 +324,62 @@ static tree sh_build_builtin_va_list (void);
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE sh_issue_rate
+/* The next 5 hooks have been implemented for reenabling sched1. With the
+ help of these macros we are limiting the movement of insns in sched1 to
+ reduce the register pressure. The overall idea is to keep count of SImode
+ and SFmode regs required by already scheduled insns. When these counts
+ cross some threshold values; give priority to insns that free registers.
+ The insn that frees registers is most likely to be the insn with lowest
+ LUID (original insn order); but such an insn might be there in the stalled
+ queue (Q) instead of the ready queue (R). To solve this, we skip cycles
+ upto a max of 8 cycles so that such insns may move from Q -> R.
+
+ The description of the hooks are as below:
+
+ TARGET_SCHED_INIT_GLOBAL: Added a new target hook in the generic
+ scheduler; it is called inside the sched_init function just after
+ find_insn_reg_weights function call. It is used to calculate the SImode
+ and SFmode weights of insns of basic blocks; much similiar to what
+ find_insn_reg_weights does.
+ TARGET_SCHED_FINISH_GLOBAL: Corresponding cleanup hook.
+
+ TARGET_SCHED_DFA_NEW_CYCLE: Skip cycles if high register pressure is
+ indicated by TARGET_SCHED_REORDER2; doing this may move insns from
+ (Q)->(R).
+
+ TARGET_SCHED_REORDER: If the register pressure for SImode or SFmode is
+ high; reorder the ready queue so that the insn with lowest LUID will be
+ issued next.
+
+ TARGET_SCHED_REORDER2: If the register pressure is high, indicate to
+ TARGET_SCHED_DFA_NEW_CYCLE to skip cycles.
+
+ TARGET_SCHED_VARIABLE_ISSUE: Cache the value of can_issue_more so that it
+ can be returned from TARGET_SCHED_REORDER2.
+
+ TARGET_SCHED_INIT: Reset the register pressure counting variables. */
+
+#undef TARGET_SCHED_DFA_NEW_CYCLE
+#define TARGET_SCHED_DFA_NEW_CYCLE sh_dfa_new_cycle
+
+#undef TARGET_SCHED_INIT_GLOBAL
+#define TARGET_SCHED_INIT_GLOBAL sh_md_init_global
+
+#undef TARGET_SCHED_FINISH_GLOBAL
+#define TARGET_SCHED_FINISH_GLOBAL sh_md_finish_global
+
+#undef TARGET_SCHED_VARIABLE_ISSUE
+#define TARGET_SCHED_VARIABLE_ISSUE sh_variable_issue
+
+#undef TARGET_SCHED_REORDER
+#define TARGET_SCHED_REORDER sh_reorder
+
+#undef TARGET_SCHED_REORDER2
+#define TARGET_SCHED_REORDER2 sh_reorder2
+
+#undef TARGET_SCHED_INIT
+#define TARGET_SCHED_INIT sh_md_init
+
#undef TARGET_CANNOT_MODIFY_JUMPS_P
#define TARGET_CANNOT_MODIFY_JUMPS_P sh_cannot_modify_jumps_p
#undef TARGET_BRANCH_TARGET_REGISTER_CLASS
@@ -354,6 +441,12 @@ static tree sh_build_builtin_va_list (void);
#undef TARGET_PCH_VALID_P
#define TARGET_PCH_VALID_P sh_pch_valid_p
+/* Return regmode weight for insn. */
+#define INSN_REGMODE_WEIGHT(INSN, MODE) regmode_weight[((MODE) == SImode) ? 0 : 1][INSN_UID (INSN)]
+
+/* Return current register pressure for regmode. */
+#define CURR_REGMODE_PRESSURE(MODE) curr_regmode_pressure[((MODE) == SImode) ? 0 : 1]
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Print the operand address in x to the stream. */
@@ -8264,6 +8357,323 @@ sh_issue_rate(void)
return 1;
}
+/* Functions for ready queue reordering for sched1. */
+
+/* Get weight for mode for a set x. */
+static short
+find_set_regmode_weight (x, mode)
+ rtx x;
+ enum machine_mode mode;
+{
+ if (GET_CODE (x) == CLOBBER && register_operand (SET_DEST (x), mode))
+ return 1;
+ if (GET_CODE (x) == SET && register_operand (SET_DEST (x), mode))
+ {
+ if (GET_CODE (SET_DEST (x)) == REG)
+ {
+ if (!reg_mentioned_p (SET_DEST (x), SET_SRC (x)))
+ return 1;
+ else
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/* Get regmode weight for insn. */
+static short
+find_insn_regmode_weight (insn, mode)
+ rtx insn;
+ enum machine_mode mode;
+{
+ short reg_weight = 0;
+ rtx x;
+
+ /* Increment weight for each register born here. */
+ x = PATTERN (insn);
+ reg_weight += find_set_regmode_weight (x, mode);
+ if (GET_CODE (x) == PARALLEL)
+ {
+ int j;
+ for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
+ {
+ x = XVECEXP (PATTERN (insn), 0, j);
+ reg_weight += find_set_regmode_weight (x, mode);
+ }
+ }
+ /* Decrement weight for each register that dies here. */
+ for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
+ {
+ if (REG_NOTE_KIND (x) == REG_DEAD || REG_NOTE_KIND (x) == REG_UNUSED)
+ {
+ rtx note = XEXP (x, 0);
+ if (GET_CODE (note) == REG && GET_MODE (note) == mode)
+ reg_weight--;
+ }
+ }
+ return reg_weight;
+}
+
+/* Calculate regmode weights for all insns of a basic block. */
+static void
+find_regmode_weight (b, mode)
+ int b;
+ enum machine_mode mode;
+{
+ rtx insn, next_tail, head, tail;
+
+ get_block_head_tail (b, &head, &tail);
+ next_tail = NEXT_INSN (tail);
+
+ for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
+ {
+ /* Handle register life information. */
+ if (!INSN_P (insn))
+ continue;
+
+ if (mode == SFmode)
+ INSN_REGMODE_WEIGHT (insn, mode) =
+ find_insn_regmode_weight (insn, mode) + 2 * find_insn_regmode_weight (insn, DFmode);
+ else if (mode == SImode)
+ INSN_REGMODE_WEIGHT (insn, mode) =
+ find_insn_regmode_weight (insn, mode) + 2 * find_insn_regmode_weight (insn, DImode);
+ }
+}
+
+/* Comparison function for ready queue sorting. */
+static int
+rank_for_reorder (x, y)
+ const void *x;
+ const void *y;
+{
+ rtx tmp = *(const rtx *) y;
+ rtx tmp2 = *(const rtx *) x;
+
+ /* The insn in a schedule group should be issued the first. */
+ if (SCHED_GROUP_P (tmp) != SCHED_GROUP_P (tmp2))
+ return SCHED_GROUP_P (tmp2) ? 1 : -1;
+
+ /* If insns are equally good, sort by INSN_LUID (original insn order), This
+ minimizes instruction movement, thus minimizing sched's effect on
+ register pressure. */
+ return INSN_LUID (tmp) - INSN_LUID (tmp2);
+}
+
+/* Resort the array A in which only element at index N may be out of order. */
+static void
+swap_reorder (a, n)
+ rtx *a;
+ int n;
+{
+ rtx insn = a[n - 1];
+ int i = n - 2;
+
+ while (i >= 0 && rank_for_reorder (a + i, &insn) >= 0)
+ {
+ a[i + 1] = a[i];
+ i -= 1;
+ }
+ a[i + 1] = insn;
+}
+
+#define SCHED_REORDER(READY, N_READY) \
+do { if ((N_READY) == 2) \
+ swap_reorder (READY, N_READY); \
+ else if ((N_READY) > 2) \
+ qsort (READY, N_READY, sizeof (rtx), rank_for_reorder); } \
+while (0)
+
+/* Sort the ready list READY by ascending priority, using the SCHED_REORDER
+ macro. */
+static void
+ready_reorder (ready, nready)
+ rtx *ready;
+ int nready;
+{
+ SCHED_REORDER (ready, nready);
+}
+
+/* Calculate regmode weights for all insns of all basic block. */
+static void
+sh_md_init_global (dump, verbose, old_max_uid)
+ FILE *dump ATTRIBUTE_UNUSED;
+ int verbose ATTRIBUTE_UNUSED;
+ int old_max_uid;
+{
+ basic_block b;
+
+ regmode_weight[0] = (short *) xcalloc (old_max_uid, sizeof (short));
+ regmode_weight[1] = (short *) xcalloc (old_max_uid, sizeof (short));
+
+ FOR_EACH_BB_REVERSE (b)
+ {
+ find_regmode_weight (b->index, SImode);
+ find_regmode_weight (b->index, SFmode);
+ }
+
+ CURR_REGMODE_PRESSURE (SImode) = 0;
+ CURR_REGMODE_PRESSURE (SFmode) = 0;
+
+}
+
+/* Cleanup. */
+static void
+sh_md_finish_global (dump, verbose)
+ FILE *dump ATTRIBUTE_UNUSED;
+ int verbose ATTRIBUTE_UNUSED;
+{
+ if (regmode_weight[0])
+ {
+ free (regmode_weight[0]);
+ regmode_weight[0] = NULL;
+ }
+ if (regmode_weight[1])
+ {
+ free (regmode_weight[1]);
+ regmode_weight[1] = NULL;
+ }
+}
+
+/* Cache the can_issue_more so that we can return it from reorder2. Also,
+ keep count of register pressures on SImode and SFmode. */
+static int
+sh_variable_issue (dump, sched_verbose, insn, can_issue_more)
+ FILE *dump ATTRIBUTE_UNUSED;
+ int sched_verbose ATTRIBUTE_UNUSED;
+ rtx insn;
+ int can_issue_more;
+{
+ if (GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER)
+ cached_can_issue_more = can_issue_more - 1;
+ else
+ cached_can_issue_more = can_issue_more;
+
+ if (reload_completed)
+ return cached_can_issue_more;
+
+ CURR_REGMODE_PRESSURE (SImode) += INSN_REGMODE_WEIGHT (insn, SImode);
+ CURR_REGMODE_PRESSURE (SFmode) += INSN_REGMODE_WEIGHT (insn, SFmode);
+
+ return cached_can_issue_more;
+}
+
+static void
+sh_md_init (dump, verbose, veclen)
+ FILE *dump ATTRIBUTE_UNUSED;
+ int verbose ATTRIBUTE_UNUSED;
+ int veclen ATTRIBUTE_UNUSED;
+{
+ CURR_REGMODE_PRESSURE (SImode) = 0;
+ CURR_REGMODE_PRESSURE (SFmode) = 0;
+}
+
+/* Some magic numbers. */
+/* Pressure on register r0 can lead to spill failures. so avoid sched1 for
+ functions that already have high pressure on r0. */
+#define R0_MAX_LIFE_REGIONS 2
+#define R0_MAX_LIVE_LENGTH 12
+/* Register Pressure threshols for SImode and SFmode registers. */
+#define SIMODE_MAX_WEIGHT 5
+#define SFMODE_MAX_WEIGHT 10
+
+/* Return true if the pressure is high for MODE. */
+static short
+high_pressure (mode)
+ enum machine_mode mode;
+{
+ /* Pressure on register r0 can lead to spill failures. so avoid sched1 for
+ functions that already have high pressure on r0. */
+ if ((REG_N_SETS (0) - REG_N_DEATHS (0)) >= R0_MAX_LIFE_REGIONS
+ && REG_LIVE_LENGTH (0) >= R0_MAX_LIVE_LENGTH)
+ return 1;
+
+ if (mode == SFmode)
+ return (CURR_REGMODE_PRESSURE (SFmode) > SFMODE_MAX_WEIGHT);
+ else
+ return (CURR_REGMODE_PRESSURE (SImode) > SIMODE_MAX_WEIGHT);
+}
+
+/* Reorder ready queue if register pressure is high. */
+static int
+sh_reorder (dump, sched_verbose, ready, n_readyp, clock_var)
+ FILE *dump ATTRIBUTE_UNUSED;
+ int sched_verbose ATTRIBUTE_UNUSED;
+ rtx *ready;
+ int *n_readyp;
+ int clock_var ATTRIBUTE_UNUSED;
+{
+ if (reload_completed)
+ return sh_issue_rate ();
+
+ if (high_pressure (SFmode) || high_pressure (SImode))
+ {
+ ready_reorder (ready, *n_readyp);
+ }
+
+ return sh_issue_rate ();
+}
+
+/* Skip cycles if the current register pressure is high. */
+static int
+sh_reorder2 (dump, sched_verbose, ready, n_readyp, clock_var)
+ FILE *dump ATTRIBUTE_UNUSED;
+ int sched_verbose ATTRIBUTE_UNUSED;
+ rtx *ready ATTRIBUTE_UNUSED;
+ int *n_readyp ATTRIBUTE_UNUSED;
+ int clock_var ATTRIBUTE_UNUSED;
+{
+ if (reload_completed)
+ return cached_can_issue_more;
+
+ if (high_pressure(SFmode) || high_pressure (SImode))
+ skip_cycles = 1;
+
+ return cached_can_issue_more;
+}
+
+/* Skip cycles without sorting the ready queue. This will move insn from
+ Q->R. If this is the last cycle we are skipping; allow sorting of ready
+ queue by sh_reorder. */
+
+/* Generally, skipping these many cycles are sufficient for all insns to move
+ from Q -> R. */
+#define MAX_SKIPS 8
+
+static int
+sh_dfa_new_cycle (sched_dump, sched_verbose, insn, last_clock_var,
+ clock_var, sort_p)
+ FILE *sched_dump ATTRIBUTE_UNUSED;
+ int sched_verbose ATTRIBUTE_UNUSED;
+ rtx insn ATTRIBUTE_UNUSED;
+ int last_clock_var;
+ int clock_var;
+ int *sort_p;
+{
+ if (reload_completed)
+ return 0;
+
+ if (skip_cycles)
+ {
+ if ((clock_var - last_clock_var) < MAX_SKIPS)
+ {
+ *sort_p = 0;
+ return 1;
+ }
+ /* If this is the last cycle we are skipping, allow reordering of R. */
+ if ((clock_var - last_clock_var) == MAX_SKIPS)
+ {
+ *sort_p = 1;
+ return 1;
+ }
+ }
+
+ skip_cycles = 0;
+
+ return 0;
+}
+
/* SHmedia requires registers for branches, so we can't generate new
branches past reload. */
static bool
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 8580cb6d201..6bdfefe7932 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -516,7 +516,11 @@ do { \
/* Never run scheduling before reload, since that can \
break global alloc, and generates slower code anyway due \
to the pressure on R0. */ \
- flag_schedule_insns = 0; \
+ /* Enable sched1 for SH4; ready queue will be reordered by \
+ the target hooks when pressure is high. We can not do this for \
+ SH3 and lower as they give spill failures for R0. */ \
+ if (!TARGET_HARD_SH4) \
+ flag_schedule_insns = 0; \
} \
\
if (align_loops == 0) \
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index e618c8eff81..1ffa5ee413b 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -5571,6 +5571,19 @@ to. @var{verbose} is the verbose level provided by
@option{-fsched-verbose-@var{n}}.
@end deftypefn
+@deftypefn {Target Hook} void TARGET_SCHED_INIT_GLOBAL (FILE *@var{file}, int @var{verbose}, int @var{old_max_uid})
+This hook is executed by the scheduler after function level initializations.
+@var{file} is either a null pointer, or a stdio stream to write any debug output to.
+@var{verbose} is the verbose level provided by @option{-fsched-verbose-@var{n}}.
+@var{old_max_uid} is the maximum insn uid when scheduling begins.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_FINISH_GLOBAL (FILE *@var{file}, int @var{verbose})
+This is the cleanup hook corresponding to TARGET_SCHED_INIT_GLOBAL.
+@var{file} is either a null pointer, or a stdio stream to write any debug output to.
+@var{verbose} is the verbose level provided by @option{-fsched-verbose-@var{n}}.
+@end deftypefn
+
@deftypefn {Target Hook} int TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE (void)
This hook is called many times during insn scheduling. If the hook
returns nonzero, the automaton based pipeline description is used for
diff --git a/gcc/flow.c b/gcc/flow.c
index 56a0bfa1db5..736e5e61bcb 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -4260,7 +4260,10 @@ void
recompute_reg_usage (rtx f ATTRIBUTE_UNUSED, int loop_step ATTRIBUTE_UNUSED)
{
allocate_reg_life_data ();
- update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO);
+ /* distribute_notes in combiner fails to convert some of the REG_UNUSED notes
+ to REG_DEAD notes. This causes CHECK_DEAD_NOTES in sched1 to abort. To
+ solve this update the DEATH_NOTES here. */
+ update_life_info (NULL, UPDATE_LIFE_LOCAL, PROP_REG_INFO | PROP_DEATH_NOTES);
}
/* Optionally removes all the REG_DEAD and REG_UNUSED notes from a set of
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 5cfce5936cb..496ea2caa2a 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -2856,6 +2856,9 @@ sched_init (FILE *dump_file)
removing death notes. */
FOR_EACH_BB_REVERSE (b)
find_insn_reg_weight (b->index);
+
+ if (targetm.sched.md_init_global)
+ (*targetm.sched.md_init_global) (sched_dump, sched_verbose, old_max_uid);
}
/* Free global data used during insn scheduling. */
@@ -2875,5 +2878,8 @@ sched_finish (void)
end_alias_analysis ();
if (write_symbols != NO_DEBUG)
free (line_note_head);
+
+ if (targetm.sched.md_finish_global)
+ (*targetm.sched.md_finish_global) (sched_dump, sched_verbose);
}
#endif /* INSN_SCHEDULING */
diff --git a/gcc/target-def.h b/gcc/target-def.h
index ef4c777378c..0b35bc1855a 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -217,6 +217,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TARGET_SCHED_VARIABLE_ISSUE 0
#define TARGET_SCHED_INIT 0
#define TARGET_SCHED_FINISH 0
+#define TARGET_SCHED_INIT_GLOBAL 0
+#define TARGET_SCHED_FINISH_GLOBAL 0
#define TARGET_SCHED_REORDER 0
#define TARGET_SCHED_REORDER2 0
#define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK 0
@@ -239,6 +241,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_SCHED_VARIABLE_ISSUE, \
TARGET_SCHED_INIT, \
TARGET_SCHED_FINISH, \
+ TARGET_SCHED_INIT_GLOBAL, \
+ TARGET_SCHED_FINISH_GLOBAL, \
TARGET_SCHED_REORDER, \
TARGET_SCHED_REORDER2, \
TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK, \
diff --git a/gcc/target.h b/gcc/target.h
index ed96b02efe4..67cf25da0f6 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -183,6 +183,12 @@ struct gcc_target
/* Finalize machine-dependent scheduling code. */
void (* md_finish) (FILE *, int);
+ /* Initialize machine-dependent function while scheduling code. */
+ void (* md_init_global) (FILE *, int, int);
+
+ /* Finalize machine-dependent function wide scheduling code. */
+ void (* md_finish_global) (FILE *, int);
+
/* Reorder insns in a machine-dependent fashion, in two different
places. Default does nothing. */
int (* reorder) (FILE *, int, rtx *, int *, int);