summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormkuvyrkov <mkuvyrkov@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-02 16:02:09 +0000
committermkuvyrkov <mkuvyrkov@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-02 16:02:09 +0000
commit44ad1e5665214c8974e03fc04229fb954ba4ff74 (patch)
tree577fec572602f5e9c38ef19c8798360503bcb808
parent636b26c10c00e9dc4c4311b21c9776ddfda81732 (diff)
downloadgcc-44ad1e5665214c8974e03fc04229fb954ba4ff74.tar.gz
Model decoder of Core 2/i7 for multipass scheduling.
* config/i386/i386-protos.h (struct ix86_first_cycle_multipass_data_): New type to hold target-specific data for multipass scheduling. (TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T): Define. * config/i386/i386.c (ia32_multipass_dfa_lookahead): Update for Core 2/i7. (core2i7_secondary_decoder_max_insn_size,) (core2i7_secondary_ifetch_block_size, core2i7_ifetch_block_max_insns): New static variables. ([const_]ix86_first_cycle_multipass_data_t): New typedefs. ([_]ix86_first_cycle_multipass_data): New static variable. (core2i7_first_cycle_multipass_init, core2i7_dfa_poast_advance_cycle): Implement targetm.sched hooks. (core2i7_first_cycle_multipass_filter_ready_try): New static subroutine of ... (core2i7_first_cycle_multipass_{begin, issue, backtrack, end, fini}): Implement new targetm.sched hooks. (ix86_sched_init_global, TARGET_SCHED_INIT_GLOBAL): Define targetm.sched hook to install multipass scheduling hooks on demand. * doc/tm.texi.in: Document new targetm.sched hooks. * doc/tm.texi: Regenerate. * haifa-sched.c (TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T): Define. (first_cycle_multipass_data_t): New typedef. (struct choice_entry: target_data): New field. (max_issue): Add first_cycle_insn_p parameter. Call new target hooks to allow target model restrictions not represented in DFA. (choose_ready, schedule_block): Update. (sched_extend_ready_list, sched_finish_ready_list): Call new target hooks to initialize target-specific data for multipass scheduling. * sched-int.h (max_issue): Update declaration. * sel-sched.c (choose_best_insn): Update. * target.def (first_cycle_multipass_{begin, issue, backtrack},) (first_cycle_multipass_{init, fini}): Define and document new targetm.sched hooks. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166196 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog40
-rw-r--r--gcc/config/i386/i386-protos.h18
-rw-r--r--gcc/config/i386/i386.c255
-rw-r--r--gcc/doc/tm.texi27
-rw-r--r--gcc/doc/tm.texi.in27
-rw-r--r--gcc/haifa-sched.c65
-rw-r--r--gcc/sched-int.h2
-rw-r--r--gcc/sel-sched.c3
-rw-r--r--gcc/target.def78
9 files changed, 501 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b5d15ce51b6..7f58b923164 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,43 @@
+2010-11-02 Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ Model decoder of Core 2/i7 for multipass scheduling.
+
+ * config/i386/i386-protos.h (struct ix86_first_cycle_multipass_data_):
+ New type to hold target-specific data for multipass scheduling.
+ (TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T): Define.
+ * config/i386/i386.c (ia32_multipass_dfa_lookahead): Update for
+ Core 2/i7.
+ (core2i7_secondary_decoder_max_insn_size,)
+ (core2i7_secondary_ifetch_block_size, core2i7_ifetch_block_max_insns):
+ New static variables.
+ ([const_]ix86_first_cycle_multipass_data_t): New typedefs.
+ ([_]ix86_first_cycle_multipass_data): New static variable.
+ (core2i7_first_cycle_multipass_init, core2i7_dfa_poast_advance_cycle):
+ Implement targetm.sched hooks.
+ (core2i7_first_cycle_multipass_filter_ready_try): New static subroutine
+ of ...
+ (core2i7_first_cycle_multipass_{begin, issue, backtrack, end, fini}):
+ Implement new targetm.sched hooks.
+ (ix86_sched_init_global, TARGET_SCHED_INIT_GLOBAL): Define
+ targetm.sched hook to install multipass scheduling hooks on demand.
+
+ * doc/tm.texi.in: Document new targetm.sched hooks.
+ * doc/tm.texi: Regenerate.
+
+ * haifa-sched.c (TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T): Define.
+ (first_cycle_multipass_data_t): New typedef.
+ (struct choice_entry: target_data): New field.
+ (max_issue): Add first_cycle_insn_p parameter. Call new target hooks
+ to allow target model restrictions not represented in DFA.
+ (choose_ready, schedule_block): Update.
+ (sched_extend_ready_list, sched_finish_ready_list): Call new target
+ hooks to initialize target-specific data for multipass scheduling.
+ * sched-int.h (max_issue): Update declaration.
+ * sel-sched.c (choose_best_insn): Update.
+ * target.def (first_cycle_multipass_{begin, issue, backtrack},)
+ (first_cycle_multipass_{init, fini}): Define and document new
+ targetm.sched hooks.
+
2010-11-02 Richard Guenther <rguenther@suse.de>
PR tree-optimization/46184
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index f6f9071395f..13b1394b425 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -271,3 +271,21 @@ extern enum attr_cpu ix86_schedule;
#endif
extern const char * ix86_output_call_insn (rtx insn, rtx call_op, int addr_op);
+
+#ifdef RTX_CODE
+/* Target data for multipass lookahead scheduling.
+ Currently used for Core 2/i7 tuning. */
+struct ix86_first_cycle_multipass_data_
+{
+ /* The length (in bytes) of ifetch block in this solution. */
+ int ifetch_block_len;
+ /* Number of instructions in ifetch block in this solution. */
+ int ifetch_block_n_insns;
+ /* Bitmap to remember changes to ready_try for backtracking. */
+ sbitmap ready_try_change;
+ /* Size of the bitmap. */
+ int ready_try_change_size;
+};
+# define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T \
+ struct ix86_first_cycle_multipass_data_
+#endif /* RTX_CODE */
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index eb3e623925d..bda8ed3f9cd 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -22273,12 +22273,265 @@ ia32_multipass_dfa_lookahead (void)
case PROCESSOR_K6:
return 1;
+ case PROCESSOR_CORE2:
+ case PROCESSOR_COREI7_32:
+ case PROCESSOR_COREI7_64:
+ /* Generally, we want haifa-sched:max_issue() to look ahead as far
+ as many instructions can be executed on a cycle, i.e.,
+ issue_rate. I wonder why tuning for many CPUs does not do this. */
+ return ix86_issue_rate ();
+
default:
return 0;
}
}
+
+/* Model decoder of Core 2/i7.
+ Below hooks for multipass scheduling (see haifa-sched.c:max_issue)
+ track the instruction fetch block boundaries and make sure that long
+ (9+ bytes) instructions are assigned to D0. */
+
+/* Maximum length of an insn that can be handled by
+ a secondary decoder unit. '8' for Core 2/i7. */
+static int core2i7_secondary_decoder_max_insn_size;
+
+/* Ifetch block size, i.e., number of bytes decoder reads per cycle.
+ '16' for Core 2/i7. */
+static int core2i7_ifetch_block_size;
+
+/* Maximum number of instructions decoder can handle per cycle.
+ '6' for Core 2/i7. */
+static int core2i7_ifetch_block_max_insns;
+
+typedef struct ix86_first_cycle_multipass_data_ *
+ ix86_first_cycle_multipass_data_t;
+typedef const struct ix86_first_cycle_multipass_data_ *
+ const_ix86_first_cycle_multipass_data_t;
+
+/* A variable to store target state across calls to max_issue within
+ one cycle. */
+static struct ix86_first_cycle_multipass_data_ _ix86_first_cycle_multipass_data,
+ *ix86_first_cycle_multipass_data = &_ix86_first_cycle_multipass_data;
+
+/* Initialize DATA. */
+static void
+core2i7_first_cycle_multipass_init (void *_data)
+{
+ ix86_first_cycle_multipass_data_t data
+ = (ix86_first_cycle_multipass_data_t) _data;
+
+ data->ifetch_block_len = 0;
+ data->ifetch_block_n_insns = 0;
+ data->ready_try_change = NULL;
+ data->ready_try_change_size = 0;
+}
+
+/* Advancing the cycle; reset ifetch block counts. */
+static void
+core2i7_dfa_post_advance_cycle (void)
+{
+ ix86_first_cycle_multipass_data_t data = ix86_first_cycle_multipass_data;
+
+ gcc_assert (data->ifetch_block_n_insns <= core2i7_ifetch_block_max_insns);
+
+ data->ifetch_block_len = 0;
+ data->ifetch_block_n_insns = 0;
+}
+
+static int min_insn_size (rtx);
+
+/* Filter out insns from ready_try that the core will not be able to issue
+ on current cycle due to decoder. */
+static void
+core2i7_first_cycle_multipass_filter_ready_try
+(const_ix86_first_cycle_multipass_data_t data,
+ char *ready_try, int n_ready, bool first_cycle_insn_p)
+{
+ while (n_ready--)
+ {
+ rtx insn;
+ int insn_size;
+
+ if (ready_try[n_ready])
+ continue;
+
+ insn = get_ready_element (n_ready);
+ insn_size = min_insn_size (insn);
+
+ if (/* If this is a too long an insn for a secondary decoder ... */
+ (!first_cycle_insn_p
+ && insn_size > core2i7_secondary_decoder_max_insn_size)
+ /* ... or it would not fit into the ifetch block ... */
+ || data->ifetch_block_len + insn_size > core2i7_ifetch_block_size
+ /* ... or the decoder is full already ... */
+ || data->ifetch_block_n_insns + 1 > core2i7_ifetch_block_max_insns)
+ /* ... mask the insn out. */
+ {
+ ready_try[n_ready] = 1;
+
+ if (data->ready_try_change)
+ SET_BIT (data->ready_try_change, n_ready);
+ }
+ }
+}
+
+/* Prepare for a new round of multipass lookahead scheduling. */
+static void
+core2i7_first_cycle_multipass_begin (void *_data, char *ready_try, int n_ready,
+ bool first_cycle_insn_p)
+{
+ ix86_first_cycle_multipass_data_t data
+ = (ix86_first_cycle_multipass_data_t) _data;
+ const_ix86_first_cycle_multipass_data_t prev_data
+ = ix86_first_cycle_multipass_data;
+
+ /* Restore the state from the end of the previous round. */
+ data->ifetch_block_len = prev_data->ifetch_block_len;
+ data->ifetch_block_n_insns = prev_data->ifetch_block_n_insns;
+
+ /* Filter instructions that cannot be issued on current cycle due to
+ decoder restrictions. */
+ core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready,
+ first_cycle_insn_p);
+}
+
+/* INSN is being issued in current solution. Account for its impact on
+ the decoder model. */
+static void
+core2i7_first_cycle_multipass_issue (void *_data, char *ready_try, int n_ready,
+ rtx insn, const void *_prev_data)
+{
+ ix86_first_cycle_multipass_data_t data
+ = (ix86_first_cycle_multipass_data_t) _data;
+ const_ix86_first_cycle_multipass_data_t prev_data
+ = (const_ix86_first_cycle_multipass_data_t) _prev_data;
+
+ int insn_size = min_insn_size (insn);
+
+ data->ifetch_block_len = prev_data->ifetch_block_len + insn_size;
+ data->ifetch_block_n_insns = prev_data->ifetch_block_n_insns + 1;
+ gcc_assert (data->ifetch_block_len <= core2i7_ifetch_block_size
+ && data->ifetch_block_n_insns <= core2i7_ifetch_block_max_insns);
+
+ /* Allocate or resize the bitmap for storing INSN's effect on ready_try. */
+ if (!data->ready_try_change)
+ {
+ data->ready_try_change = sbitmap_alloc (n_ready);
+ data->ready_try_change_size = n_ready;
+ }
+ else if (data->ready_try_change_size < n_ready)
+ {
+ data->ready_try_change = sbitmap_resize (data->ready_try_change,
+ n_ready, 0);
+ data->ready_try_change_size = n_ready;
+ }
+ sbitmap_zero (data->ready_try_change);
+
+ /* Filter out insns from ready_try that the core will not be able to issue
+ on current cycle due to decoder. */
+ core2i7_first_cycle_multipass_filter_ready_try (data, ready_try, n_ready,
+ false);
+}
+
+/* Revert the effect on ready_try. */
+static void
+core2i7_first_cycle_multipass_backtrack (const void *_data,
+ char *ready_try,
+ int n_ready ATTRIBUTE_UNUSED)
+{
+ const_ix86_first_cycle_multipass_data_t data
+ = (const_ix86_first_cycle_multipass_data_t) _data;
+ unsigned int i = 0;
+ sbitmap_iterator sbi;
+
+ gcc_assert (sbitmap_last_set_bit (data->ready_try_change) < n_ready);
+ EXECUTE_IF_SET_IN_SBITMAP (data->ready_try_change, 0, i, sbi)
+ {
+ ready_try[i] = 0;
+ }
+}
+
+/* Save the result of multipass lookahead scheduling for the next round. */
+static void
+core2i7_first_cycle_multipass_end (const void *_data)
+{
+ const_ix86_first_cycle_multipass_data_t data
+ = (const_ix86_first_cycle_multipass_data_t) _data;
+ ix86_first_cycle_multipass_data_t next_data
+ = ix86_first_cycle_multipass_data;
+
+ if (data != NULL)
+ {
+ next_data->ifetch_block_len = data->ifetch_block_len;
+ next_data->ifetch_block_n_insns = data->ifetch_block_n_insns;
+ }
+}
+
+/* Deallocate target data. */
+static void
+core2i7_first_cycle_multipass_fini (void *_data)
+{
+ ix86_first_cycle_multipass_data_t data
+ = (ix86_first_cycle_multipass_data_t) _data;
+
+ if (data->ready_try_change)
+ {
+ sbitmap_free (data->ready_try_change);
+ data->ready_try_change = NULL;
+ data->ready_try_change_size = 0;
+ }
+}
+
+/* Prepare for scheduling pass. */
+static void
+ix86_sched_init_global (FILE *dump ATTRIBUTE_UNUSED,
+ int verbose ATTRIBUTE_UNUSED,
+ int max_uid ATTRIBUTE_UNUSED)
+{
+ /* Install scheduling hooks for current CPU. Some of these hooks are used
+ in time-critical parts of the scheduler, so we only set them up when
+ they are actually used. */
+ switch (ix86_tune)
+ {
+ case PROCESSOR_CORE2:
+ case PROCESSOR_COREI7_32:
+ case PROCESSOR_COREI7_64:
+ targetm.sched.dfa_post_advance_cycle
+ = core2i7_dfa_post_advance_cycle;
+ targetm.sched.first_cycle_multipass_init
+ = core2i7_first_cycle_multipass_init;
+ targetm.sched.first_cycle_multipass_begin
+ = core2i7_first_cycle_multipass_begin;
+ targetm.sched.first_cycle_multipass_issue
+ = core2i7_first_cycle_multipass_issue;
+ targetm.sched.first_cycle_multipass_backtrack
+ = core2i7_first_cycle_multipass_backtrack;
+ targetm.sched.first_cycle_multipass_end
+ = core2i7_first_cycle_multipass_end;
+ targetm.sched.first_cycle_multipass_fini
+ = core2i7_first_cycle_multipass_fini;
+
+ /* Set decoder parameters. */
+ core2i7_secondary_decoder_max_insn_size = 8;
+ core2i7_ifetch_block_size = 16;
+ core2i7_ifetch_block_max_insns = 6;
+ break;
+
+ default:
+ targetm.sched.dfa_post_advance_cycle = NULL;
+ targetm.sched.first_cycle_multipass_init = NULL;
+ targetm.sched.first_cycle_multipass_begin = NULL;
+ targetm.sched.first_cycle_multipass_issue = NULL;
+ targetm.sched.first_cycle_multipass_backtrack = NULL;
+ targetm.sched.first_cycle_multipass_end = NULL;
+ targetm.sched.first_cycle_multipass_fini = NULL;
+ break;
+ }
+}
+
+
/* Compute the alignment given to a constant that is being placed in memory.
EXP is the constant and ALIGN is the alignment that the object would
ordinarily have.
@@ -34030,6 +34283,8 @@ ix86_autovectorize_vector_sizes (void)
#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA i386_asm_output_addr_const_extra
+#undef TARGET_SCHED_INIT_GLOBAL
+#define TARGET_SCHED_INIT_GLOBAL ix86_sched_init_global
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST ix86_adjust_cost
#undef TARGET_SCHED_ISSUE_RATE
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 9126d437ace..7ce1c50f434 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -6654,6 +6654,33 @@ be issued.
The default is that any ready insns can be chosen to be issued.
@end deftypefn
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BEGIN (void *@var{data}, char *@var{ready_try}, int @var{n_ready}, bool @var{first_cycle_insn_p})
+This hook prepares the target backend for a new round of multipass
+scheduling.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_ISSUE (void *@var{data}, char *@var{ready_try}, int @var{n_ready}, rtx @var{insn}, const void *@var{prev_data})
+This hook is called when multipass scheduling evaluates instruction INSN.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BACKTRACK (const void *@var{data}, char *@var{ready_try}, int @var{n_ready})
+This is called when multipass scheduling backtracks from evaluation of
+an instruction.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_END (const void *@var{data})
+This hook notifies the target about the result of the concluded current
+round of multipass scheduling.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_INIT (void *@var{data})
+This hook initilizes target-specific data used in multipass scheduling.
+@end deftypefn
+
+@deftypefn {Target Hook} void TARGET_SCHED_FIRST_CYCLE_MULTIPASS_FINI (void *@var{data})
+This hook finilizes target-specific data used in multipass scheduling.
+@end deftypefn
+
@deftypefn {Target Hook} int TARGET_SCHED_DFA_NEW_CYCLE (FILE *@var{dump}, int @var{verbose}, rtx @var{insn}, int @var{last_clock}, int @var{clock}, int *@var{sort_p})
This hook is called by the insn scheduler before issuing @var{insn}
on cycle @var{clock}. If the hook returns nonzero,
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 2c36a765906..23b38d3337f 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -6642,6 +6642,33 @@ be issued.
The default is that any ready insns can be chosen to be issued.
@end deftypefn
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BEGIN
+This hook prepares the target backend for a new round of multipass
+scheduling.
+@end deftypefn
+
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_ISSUE
+This hook is called when multipass scheduling evaluates instruction INSN.
+@end deftypefn
+
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_BACKTRACK
+This is called when multipass scheduling backtracks from evaluation of
+an instruction.
+@end deftypefn
+
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_END
+This hook notifies the target about the result of the concluded current
+round of multipass scheduling.
+@end deftypefn
+
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_INIT
+This hook initilizes target-specific data used in multipass scheduling.
+@end deftypefn
+
+@hook TARGET_SCHED_FIRST_CYCLE_MULTIPASS_FINI
+This hook finilizes target-specific data used in multipass scheduling.
+@end deftypefn
+
@hook TARGET_SCHED_DFA_NEW_CYCLE
This hook is called by the insn scheduler before issuing @var{insn}
on cycle @var{clock}. If the hook returns nonzero,
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 8fb988e2a62..434b760d07d 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -540,8 +540,6 @@ static void debug_ready_list (struct ready_list *);
static rtx ready_remove (struct ready_list *, int);
static void ready_remove_insn (rtx);
-static int choose_ready (struct ready_list *, rtx *);
-
static void fix_inter_tick (rtx, rtx);
static int fix_tick_ready (rtx);
static void change_queue_index (rtx, int);
@@ -2390,6 +2388,12 @@ insn_finishes_cycle_p (rtx insn)
return false;
}
+/* Define type for target data used in multipass scheduling. */
+#ifndef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T
+# define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T int
+#endif
+typedef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T first_cycle_multipass_data_t;
+
/* The following structure describe an entry of the stack of choices. */
struct choice_entry
{
@@ -2401,6 +2405,8 @@ struct choice_entry
int n;
/* State after issuing the insn. */
state_t state;
+ /* Target-specific data. */
+ first_cycle_multipass_data_t target_data;
};
/* The following array is used to implement a stack of choices used in
@@ -2451,7 +2457,7 @@ static int cached_issue_rate = 0;
CLOBBERs, etc must be filtered elsewhere. */
int
max_issue (struct ready_list *ready, int privileged_n, state_t state,
- int *index)
+ bool first_cycle_insn_p, int *index)
{
int n, i, all, n_ready, best, delay, tries_num;
int more_issue;
@@ -2484,6 +2490,10 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
memcpy (top->state, state, dfa_state_size);
top->rest = dfa_lookahead;
top->n = 0;
+ if (targetm.sched.first_cycle_multipass_begin)
+ targetm.sched.first_cycle_multipass_begin (&top->target_data,
+ ready_try, n_ready,
+ first_cycle_insn_p);
/* Count the number of the insns to search among. */
for (all = i = 0; i < n_ready; i++)
@@ -2542,6 +2552,11 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
/* Backtrack. */
ready_try [i] = 0;
+
+ if (targetm.sched.first_cycle_multipass_backtrack)
+ targetm.sched.first_cycle_multipass_backtrack (&top->target_data,
+ ready_try, n_ready);
+
top--;
memcpy (state, top->state, dfa_state_size);
}
@@ -2573,8 +2588,15 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
top->index = i;
top->n = n;
memcpy (top->state, state, dfa_state_size);
-
ready_try [i] = 1;
+
+ if (targetm.sched.first_cycle_multipass_issue)
+ targetm.sched.first_cycle_multipass_issue (&top->target_data,
+ ready_try, n_ready,
+ insn,
+ &((top - 1)
+ ->target_data));
+
i = -1;
}
}
@@ -2583,6 +2605,11 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
i++;
}
+ if (targetm.sched.first_cycle_multipass_end)
+ targetm.sched.first_cycle_multipass_end (best != 0
+ ? &choice_stack[1].target_data
+ : NULL);
+
/* Restore the original state of the DFA. */
memcpy (state, choice_stack->state, dfa_state_size);
@@ -2597,7 +2624,8 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
0 if INSN_PTR is set to point to the desirable insn,
1 if choose_ready () should be restarted without advancing the cycle. */
static int
-choose_ready (struct ready_list *ready, rtx *insn_ptr)
+choose_ready (struct ready_list *ready, bool first_cycle_insn_p,
+ rtx *insn_ptr)
{
int lookahead;
@@ -2726,7 +2754,7 @@ choose_ready (struct ready_list *ready, rtx *insn_ptr)
(insn)));
}
- if (max_issue (ready, 1, curr_state, &index) == 0)
+ if (max_issue (ready, 1, curr_state, first_cycle_insn_p, &index) == 0)
{
*insn_ptr = ready_remove_first (ready);
if (sched_verbose >= 4)
@@ -2754,7 +2782,8 @@ choose_ready (struct ready_list *ready, rtx *insn_ptr)
void
schedule_block (basic_block *target_bb)
{
- int i, first_cycle_insn_p;
+ int i;
+ bool first_cycle_insn_p;
int can_issue_more;
state_t temp_state = NULL; /* It is used for multipass scheduling. */
int sort_p, advance, start_clock_var;
@@ -2960,7 +2989,7 @@ schedule_block (basic_block *target_bb)
else
can_issue_more = issue_rate;
- first_cycle_insn_p = 1;
+ first_cycle_insn_p = true;
cycle_issued_insns = 0;
for (;;)
{
@@ -3003,7 +3032,7 @@ schedule_block (basic_block *target_bb)
int res;
insn = NULL_RTX;
- res = choose_ready (&ready, &insn);
+ res = choose_ready (&ready, first_cycle_insn_p, &insn);
if (res < 0)
/* Finish cycle. */
@@ -3156,7 +3185,7 @@ schedule_block (basic_block *target_bb)
if (advance != 0)
break;
- first_cycle_insn_p = 0;
+ first_cycle_insn_p = false;
/* Sort the ready list based on priority. This must be
redone here, as schedule_insn may have readied additional
@@ -3952,7 +3981,13 @@ sched_extend_ready_list (int new_sched_ready_n_insns)
new_sched_ready_n_insns + 1);
for (; i <= new_sched_ready_n_insns; i++)
- choice_stack[i].state = xmalloc (dfa_state_size);
+ {
+ choice_stack[i].state = xmalloc (dfa_state_size);
+
+ if (targetm.sched.first_cycle_multipass_init)
+ targetm.sched.first_cycle_multipass_init (&(choice_stack[i]
+ .target_data));
+ }
sched_ready_n_insns = new_sched_ready_n_insns;
}
@@ -3971,7 +4006,13 @@ sched_finish_ready_list (void)
ready_try = NULL;
for (i = 0; i <= sched_ready_n_insns; i++)
- free (choice_stack [i].state);
+ {
+ if (targetm.sched.first_cycle_multipass_fini)
+ targetm.sched.first_cycle_multipass_fini (&(choice_stack[i]
+ .target_data));
+
+ free (choice_stack [i].state);
+ }
free (choice_stack);
choice_stack = NULL;
diff --git a/gcc/sched-int.h b/gcc/sched-int.h
index bea5aab5800..68cfa23ee06 100644
--- a/gcc/sched-int.h
+++ b/gcc/sched-int.h
@@ -195,7 +195,7 @@ struct ready_list
extern char *ready_try;
extern struct ready_list ready;
-extern int max_issue (struct ready_list *, int, state_t, int *);
+extern int max_issue (struct ready_list *, int, state_t, bool, int *);
extern void ebb_compute_jump_reg_dependencies (rtx, regset, regset, regset);
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index ce014ed7f55..70e831d7cee 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -4320,8 +4320,9 @@ choose_best_insn (fence_t fence, int privileged_n, int *index)
if (dfa_lookahead > 0)
{
cycle_issued_insns = FENCE_ISSUED_INSNS (fence);
+ /* TODO: pass equivalent of first_cycle_insn_p to max_issue (). */
can_issue = max_issue (&ready, privileged_n,
- FENCE_STATE (fence), index);
+ FENCE_STATE (fence), true, index);
if (sched_verbose >= 2)
sel_print ("max_issue: we can issue %d insns, already did %d insns\n",
can_issue, FENCE_ISSUED_INSNS (fence));
diff --git a/gcc/target.def b/gcc/target.def
index 98cea58c40d..37ba3bc620e 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -650,6 +650,84 @@ DEFHOOK
"",
int, (rtx insn), NULL)
+/* This hook prepares the target for a new round of multipass
+ scheduling.
+ DATA is a pointer to target-specific data used for multipass scheduling.
+ READY_TRY and N_READY represent the current state of search in the
+ optimization space. The target can filter out instructions that
+ should not be tried during current round by setting corresponding
+ elements in READY_TRY to non-zero.
+ FIRST_CYCLE_INSN_P is true if this is the first round of multipass
+ scheduling on current cycle. */
+DEFHOOK
+(first_cycle_multipass_begin,
+ "",
+ void, (void *data, char *ready_try, int n_ready, bool first_cycle_insn_p),
+ NULL)
+
+/* This hook is called when multipass scheduling evaluates instruction INSN.
+ DATA is a pointer to target-specific data that can be used to record effects
+ of INSN on CPU that are not described in DFA.
+ READY_TRY and N_READY represent the current state of search in the
+ optimization space. The target can filter out instructions that
+ should not be tried after issueing INSN by setting corresponding
+ elements in READY_TRY to non-zero.
+ INSN is the instruction being evaluated.
+ PREV_DATA is a pointer to target-specific data corresponding
+ to a state before issueing INSN. */
+DEFHOOK
+(first_cycle_multipass_issue,
+ "",
+ void, (void *data, char *ready_try, int n_ready, rtx insn,
+ const void *prev_data), NULL)
+
+/* This hook is called when multipass scheduling backtracks from evaluation of
+ instruction corresponding to DATA.
+ DATA is a pointer to target-specific data that stores the effects
+ of instruction from which the algorithm backtracks on CPU that are not
+ described in DFA.
+ READY_TRY and N_READY represent the current state of search in the
+ optimization space. The target can filter out instructions that
+ should not be tried after issueing INSN by setting corresponding
+ elements in READY_TRY to non-zero. */
+DEFHOOK
+(first_cycle_multipass_backtrack,
+ "",
+ void, (const void *data, char *ready_try, int n_ready), NULL)
+
+/* This hook notifies the target about the result of the concluded current
+ round of multipass scheduling.
+ DATA is a pointer.
+ If DATA is non-NULL it points to target-specific data used for multipass
+ scheduling which corresponds to instruction at the start of the chain of
+ the winning solution. DATA is NULL when multipass scheduling cannot find
+ a good enough solution on current cycle and decides to retry later,
+ usually after advancing the cycle count. */
+DEFHOOK
+(first_cycle_multipass_end,
+ "",
+ void, (const void *data), NULL)
+
+/* This hook is called to initialize target-specific data for multipass
+ scheduling after it has been allocated.
+ DATA is a pointer to target-specific data that stores the effects
+ of instruction from which the algorithm backtracks on CPU that are not
+ described in DFA. */
+DEFHOOK
+(first_cycle_multipass_init,
+ "",
+ void, (void *data), NULL)
+
+/* This hook is called to finalize target-specific data for multipass
+ scheduling before it is deallocated.
+ DATA is a pointer to target-specific data that stores the effects
+ of instruction from which the algorithm backtracks on CPU that are not
+ described in DFA. */
+DEFHOOK
+(first_cycle_multipass_fini,
+ "",
+ void, (void *data), NULL)
+
/* The following member value is pointer to a function called by
the insn scheduler before issuing insn passed as the third
parameter on given cycle. If the hook returns nonzero, the