diff options
author | mkuvyrkov <mkuvyrkov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-02 16:02:09 +0000 |
---|---|---|
committer | mkuvyrkov <mkuvyrkov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-02 16:02:09 +0000 |
commit | 44ad1e5665214c8974e03fc04229fb954ba4ff74 (patch) | |
tree | 577fec572602f5e9c38ef19c8798360503bcb808 /gcc | |
parent | 636b26c10c00e9dc4c4311b21c9776ddfda81732 (diff) | |
download | gcc-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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 40 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 18 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 255 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 27 | ||||
-rw-r--r-- | gcc/doc/tm.texi.in | 27 | ||||
-rw-r--r-- | gcc/haifa-sched.c | 65 | ||||
-rw-r--r-- | gcc/sched-int.h | 2 | ||||
-rw-r--r-- | gcc/sel-sched.c | 3 | ||||
-rw-r--r-- | gcc/target.def | 78 |
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 |