Dispatch scheduling for AMD Bulldozer processors.
2010-09-09 Reza Yazdani <reza.yazdani@amd.com> * config/i386/i386.c: Include sched-int.h. (TARGET_SCHED_DISPATCH): Defined. (TARGET_SCHED_DISPATCH_DO): Defined. (DISPATCH_WINDOW_SIZE): Defined. (MAX_DISPATCH_WINDOWS): Defined. (MAX_INSN): Defined. (MAX_IMM): Defined. (MAX_IMM_SIZE): Defined. (MAX_IMM_32): Defined. (MAX_IMM_64): Defined. (MAX_LOAD): Defined. (MAX_STORE): Defined. (BIG): Defined. (dispatch_group): New. (num_allowable_groups): New. (group_name): New. (sched_insn_info_s): New. (dispatch_windows_s): New. (imm_info_s): New. (dispatch_window_list): New. (dispatch_window_list1): New. (get_mem_group): New. (is_cmp): New. (dispatch_violation): New. (is_branch): New. (is_prefetch): New. (init_window): New. (allocate_window): New. (init_dispatch_sched): New. (is_end_basic_block): New. (process_end_window): New. (allocate_next_window): New. (find_constant_1): New. (find_constant): New. (get_num_immediates): New. (has_immediate): New. (get_insn_path): New. (get_insn_group): New. (count_num_restricted): New. (fits_dispatch_window): New. (add_insn_window): New. (add_to_dispatch_window): New. (debug_dispatch_window_file): New. (debug_dispatch_window): New. (debug_insn_dispatch_info_file): New. (debug_ready_dispatch): New. (do_dispatch): New. (has_dispatch): New. * config/i386/i386.h (debug_ready_dispatch): Declared. (debug_dispatch_window): Declared. * config/i386/i386.opt (mdispatch-scheduler): New flag. * doc/tm.texi.in (TARGET_SCHED_DISPATCH): New. (TARGET_SCHED_DISPATCH_DO): New. * doc/tm.texi: Regererated. * haifa-sched.c (choose_ready): Call targetm.sched.dispatch and ready_remove_first_dispatch (schedule_block): Call targetm.sched.dispatch and targetm.sched.dispatch_do. (sched_init): Call targetm.sched.dispatch and targetm.sched.dispatch_do. (ready_remove_first_dispatch): New. (number_in_ready): New. (get_ready_element): New. * hooks.c (hook_bool_rtx_int_false): New. (hook_void_rtx_int): New. * hooks.h (hook_bool_rtx_int_false): Declared. (hook_void_rtx_int): Declared. * sched-int.h (IS_DISPATCH_ON): Defined. (IS_CMP): Defined. (DISPATCH_VIOLATION): Defined. (FITS_DISPATCH_WINDOW): Defined. (DISPATCH_INIT): Defined. (ADD_TO_DISPATCH_WINDOW): Defined. (get_ready_element): Declared. (number_in_ready): Declared. * target.def (dispatch): Defined. (dispatch_do): Defined. From-SVN: r164133
This commit is contained in:
parent
be1c764ef4
commit
7942e47efd
|
@ -1,3 +1,83 @@
|
|||
2010-09-09 Reza Yazdani <reza.yazdani@amd.com>
|
||||
|
||||
* config/i386/i386.c: Include sched-int.h.
|
||||
(TARGET_SCHED_DISPATCH): Defined.
|
||||
(TARGET_SCHED_DISPATCH_DO): Defined.
|
||||
(DISPATCH_WINDOW_SIZE): Defined.
|
||||
(MAX_DISPATCH_WINDOWS): Defined.
|
||||
(MAX_INSN): Defined.
|
||||
(MAX_IMM): Defined.
|
||||
(MAX_IMM_SIZE): Defined.
|
||||
(MAX_IMM_32): Defined.
|
||||
(MAX_IMM_64): Defined.
|
||||
(MAX_LOAD): Defined.
|
||||
(MAX_STORE): Defined.
|
||||
(BIG): Defined.
|
||||
(dispatch_group): New.
|
||||
(num_allowable_groups): New.
|
||||
(group_name): New.
|
||||
(sched_insn_info_s): New.
|
||||
(dispatch_windows_s): New.
|
||||
(imm_info_s): New.
|
||||
(dispatch_window_list): New.
|
||||
(dispatch_window_list1): New.
|
||||
(get_mem_group): New.
|
||||
(is_cmp): New.
|
||||
(dispatch_violation): New.
|
||||
(is_branch): New.
|
||||
(is_prefetch): New.
|
||||
(init_window): New.
|
||||
(allocate_window): New.
|
||||
(init_dispatch_sched): New.
|
||||
(is_end_basic_block): New.
|
||||
(process_end_window): New.
|
||||
(allocate_next_window): New.
|
||||
(find_constant_1): New.
|
||||
(find_constant): New.
|
||||
(get_num_immediates): New.
|
||||
(has_immediate): New.
|
||||
(get_insn_path): New.
|
||||
(get_insn_group): New.
|
||||
(count_num_restricted): New.
|
||||
(fits_dispatch_window): New.
|
||||
(add_insn_window): New.
|
||||
(add_to_dispatch_window): New.
|
||||
(debug_dispatch_window_file): New.
|
||||
(debug_dispatch_window): New.
|
||||
(debug_insn_dispatch_info_file): New.
|
||||
(debug_ready_dispatch): New.
|
||||
(do_dispatch): New.
|
||||
(has_dispatch): New.
|
||||
* config/i386/i386.h (debug_ready_dispatch): Declared.
|
||||
(debug_dispatch_window): Declared.
|
||||
* config/i386/i386.opt (mdispatch-scheduler): New flag.
|
||||
* doc/tm.texi.in (TARGET_SCHED_DISPATCH): New.
|
||||
(TARGET_SCHED_DISPATCH_DO): New.
|
||||
* doc/tm.texi: Regererated.
|
||||
* haifa-sched.c (choose_ready): Call targetm.sched.dispatch and
|
||||
ready_remove_first_dispatch
|
||||
(schedule_block): Call targetm.sched.dispatch and
|
||||
targetm.sched.dispatch_do.
|
||||
(sched_init): Call targetm.sched.dispatch and
|
||||
targetm.sched.dispatch_do.
|
||||
(ready_remove_first_dispatch): New.
|
||||
(number_in_ready): New.
|
||||
(get_ready_element): New.
|
||||
* hooks.c (hook_bool_rtx_int_false): New.
|
||||
(hook_void_rtx_int): New.
|
||||
* hooks.h (hook_bool_rtx_int_false): Declared.
|
||||
(hook_void_rtx_int): Declared.
|
||||
* sched-int.h (IS_DISPATCH_ON): Defined.
|
||||
(IS_CMP): Defined.
|
||||
(DISPATCH_VIOLATION): Defined.
|
||||
(FITS_DISPATCH_WINDOW): Defined.
|
||||
(DISPATCH_INIT): Defined.
|
||||
(ADD_TO_DISPATCH_WINDOW): Defined.
|
||||
(get_ready_element): Declared.
|
||||
(number_in_ready): Declared.
|
||||
* target.def (dispatch): Defined.
|
||||
(dispatch_do): Defined.
|
||||
|
||||
2010-09-09 Vladimir Makarov <vmakarov@redhat.com>
|
||||
|
||||
PR middle-end/45312
|
||||
|
|
|
@ -55,7 +55,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "cselib.h"
|
||||
#include "debug.h"
|
||||
#include "dwarf2out.h"
|
||||
|
||||
#include "sched-int.h"
|
||||
static rtx legitimize_dllimport_symbol (rtx, bool);
|
||||
|
||||
#ifndef CHECK_STACK_LIMIT
|
||||
|
@ -31534,6 +31534,806 @@ ix86_enum_va_list (int idx, const char **pname, tree *ptree)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#undef TARGET_SCHED_DISPATCH
|
||||
#define TARGET_SCHED_DISPATCH has_dispatch
|
||||
#undef TARGET_SCHED_DISPATCH_DO
|
||||
#define TARGET_SCHED_DISPATCH_DO do_dispatch
|
||||
|
||||
/* The size of the dispatch window is the total number of bytes of
|
||||
object code allowed in a window. */
|
||||
#define DISPATCH_WINDOW_SIZE 16
|
||||
|
||||
/* Number of dispatch windows considered for scheduling. */
|
||||
#define MAX_DISPATCH_WINDOWS 3
|
||||
|
||||
/* Maximum number of instructions in a window. */
|
||||
#define MAX_INSN 4
|
||||
|
||||
/* Maximum number of immediate operands in a window. */
|
||||
#define MAX_IMM 4
|
||||
|
||||
/* Maximum number of immediate bits allowed in a window. */
|
||||
#define MAX_IMM_SIZE 128
|
||||
|
||||
/* Maximum number of 32 bit immediates allowed in a window. */
|
||||
#define MAX_IMM_32 4
|
||||
|
||||
/* Maximum number of 64 bit immediates allowed in a window. */
|
||||
#define MAX_IMM_64 2
|
||||
|
||||
/* Maximum total of loads or prefetches allowed in a window. */
|
||||
#define MAX_LOAD 2
|
||||
|
||||
/* Maximum total of stores allowed in a window. */
|
||||
#define MAX_STORE 1
|
||||
|
||||
#undef BIG
|
||||
#define BIG 100
|
||||
|
||||
|
||||
/* Dispatch groups. Istructions that affect the mix in a dispatch window. */
|
||||
enum dispatch_group {
|
||||
disp_no_group = 0,
|
||||
disp_load,
|
||||
disp_store,
|
||||
disp_load_store,
|
||||
disp_prefetch,
|
||||
disp_imm,
|
||||
disp_imm_32,
|
||||
disp_imm_64,
|
||||
disp_branch,
|
||||
disp_cmp,
|
||||
disp_jcc,
|
||||
disp_last
|
||||
};
|
||||
|
||||
/* Number of allowable groups in a dispatch window. It is an array
|
||||
indexed by dispatch_group enum. 100 is used as a big number,
|
||||
because the number of these kind of operations does not have any
|
||||
effect in dispatch window, but we need them for other reasons in
|
||||
the table. */
|
||||
static unsigned int num_allowable_groups[disp_last] = {
|
||||
0, 2, 1, 1, 2, 4, 4, 2, 1, BIG, BIG
|
||||
};
|
||||
|
||||
char group_name[disp_last + 1][16] = {
|
||||
"disp_no_group", "disp_load", "disp_store", "disp_load_store",
|
||||
"disp_prefetch", "disp_imm", "disp_imm_32", "disp_imm_64",
|
||||
"disp_branch", "disp_cmp", "disp_jcc", "disp_last"
|
||||
};
|
||||
|
||||
/* Instruction path. */
|
||||
enum insn_path {
|
||||
no_path = 0,
|
||||
path_single, /* Single micro op. */
|
||||
path_double, /* Double micro op. */
|
||||
path_multi, /* Instructions with more than 2 micro op.. */
|
||||
last_path
|
||||
};
|
||||
|
||||
/* sched_insn_info defines a window to the instructions scheduled in
|
||||
the basic block. It contains a pointer to the insn_info table and
|
||||
the instruction scheduled.
|
||||
|
||||
Windows are allocated for each basic block and are linked
|
||||
together. */
|
||||
typedef struct sched_insn_info_s {
|
||||
rtx insn;
|
||||
enum dispatch_group group;
|
||||
enum insn_path path;
|
||||
int byte_len;
|
||||
int imm_bytes;
|
||||
} sched_insn_info;
|
||||
|
||||
/* Linked list of dispatch windows. This is a two way list of
|
||||
dispatch windows of a basic block. It contains information about
|
||||
the number of uops in the window and the total number of
|
||||
instructions and of bytes in the object code for this dispatch
|
||||
window. */
|
||||
typedef struct dispatch_windows_s {
|
||||
int num_insn; /* Number of insn in the window. */
|
||||
int num_uops; /* Number of uops in the window. */
|
||||
int window_size; /* Number of bytes in the window. */
|
||||
int window_num; /* Window number between 0 or 1. */
|
||||
int num_imm; /* Number of immediates in an insn. */
|
||||
int num_imm_32; /* Number of 32 bit immediates in an insn. */
|
||||
int num_imm_64; /* Number of 64 bit immediates in an insn. */
|
||||
int imm_size; /* Total immediates in the window. */
|
||||
int num_loads; /* Total memory loads in the window. */
|
||||
int num_stores; /* Total memory stores in the window. */
|
||||
int violation; /* Violation exists in window. */
|
||||
sched_insn_info *window; /* Pointer to the window. */
|
||||
struct dispatch_windows_s *next;
|
||||
struct dispatch_windows_s *prev;
|
||||
} dispatch_windows;
|
||||
|
||||
/* Immediate valuse used in an insn. */
|
||||
typedef struct imm_info_s
|
||||
{
|
||||
int imm;
|
||||
int imm32;
|
||||
int imm64;
|
||||
} imm_info;
|
||||
|
||||
static dispatch_windows *dispatch_window_list;
|
||||
static dispatch_windows *dispatch_window_list1;
|
||||
|
||||
/* Get dispatch group of insn. */
|
||||
|
||||
static enum dispatch_group
|
||||
get_mem_group (rtx insn)
|
||||
{
|
||||
enum attr_memory memory;
|
||||
|
||||
if (INSN_CODE (insn) < 0)
|
||||
return disp_no_group;
|
||||
memory = get_attr_memory (insn);
|
||||
if (memory == MEMORY_STORE)
|
||||
return disp_store;
|
||||
|
||||
if (memory == MEMORY_LOAD)
|
||||
return disp_load;
|
||||
|
||||
if (memory == MEMORY_BOTH)
|
||||
return disp_load_store;
|
||||
|
||||
return disp_no_group;
|
||||
}
|
||||
|
||||
/* Return true if insn is a compare instruction. */
|
||||
|
||||
static bool
|
||||
is_cmp (rtx insn)
|
||||
{
|
||||
enum attr_type type;
|
||||
|
||||
type = get_attr_type (insn);
|
||||
return (type == TYPE_TEST
|
||||
|| type == TYPE_ICMP
|
||||
|| type == TYPE_FCMP
|
||||
|| GET_CODE (PATTERN (insn)) == COMPARE);
|
||||
}
|
||||
|
||||
/* Return true if a dispatch violation encountered. */
|
||||
|
||||
static bool
|
||||
dispatch_violation (void)
|
||||
{
|
||||
if (dispatch_window_list->next)
|
||||
return dispatch_window_list->next->violation;
|
||||
return dispatch_window_list->violation;
|
||||
}
|
||||
|
||||
/* Return true if insn is a branch instruction. */
|
||||
|
||||
static bool
|
||||
is_branch (rtx insn)
|
||||
{
|
||||
return (CALL_P (insn) || JUMP_P (insn));
|
||||
}
|
||||
|
||||
/* Return true if insn is a prefetch instruction. */
|
||||
|
||||
static bool
|
||||
is_prefetch (rtx insn)
|
||||
{
|
||||
return NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == PREFETCH;
|
||||
}
|
||||
|
||||
/* This function initializes a dispatch window and the list container holding a
|
||||
pointer to the window. */
|
||||
|
||||
static void
|
||||
init_window (int window_num)
|
||||
{
|
||||
int i;
|
||||
dispatch_windows *new_list;
|
||||
|
||||
if (window_num == 0)
|
||||
new_list = dispatch_window_list;
|
||||
else
|
||||
new_list = dispatch_window_list1;
|
||||
|
||||
new_list->num_insn = 0;
|
||||
new_list->num_uops = 0;
|
||||
new_list->window_size = 0;
|
||||
new_list->next = NULL;
|
||||
new_list->prev = NULL;
|
||||
new_list->window_num = window_num;
|
||||
new_list->num_imm = 0;
|
||||
new_list->num_imm_32 = 0;
|
||||
new_list->num_imm_64 = 0;
|
||||
new_list->imm_size = 0;
|
||||
new_list->num_loads = 0;
|
||||
new_list->num_stores = 0;
|
||||
new_list->violation = false;
|
||||
|
||||
for (i = 0; i < MAX_INSN; i++)
|
||||
{
|
||||
new_list->window[i].insn = NULL;
|
||||
new_list->window[i].group = disp_no_group;
|
||||
new_list->window[i].path = no_path;
|
||||
new_list->window[i].byte_len = 0;
|
||||
new_list->window[i].imm_bytes = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* This function allocates and initializes a dispatch window and the
|
||||
list container holding a pointer to the window. */
|
||||
|
||||
static dispatch_windows *
|
||||
allocate_window (void)
|
||||
{
|
||||
dispatch_windows *new_list = XNEW (struct dispatch_windows_s);
|
||||
new_list->window = XNEWVEC (struct sched_insn_info_s, MAX_INSN + 1);
|
||||
|
||||
return new_list;
|
||||
}
|
||||
|
||||
/* This routine initializes the dispatch scheduling information. It
|
||||
initiates building dispatch scheduler tables and constructs the
|
||||
first dispatch window. */
|
||||
|
||||
static void
|
||||
init_dispatch_sched (void)
|
||||
{
|
||||
/* Allocate a dispatch list and a window. */
|
||||
dispatch_window_list = allocate_window ();
|
||||
dispatch_window_list1 = allocate_window ();
|
||||
init_window (0);
|
||||
init_window (1);
|
||||
}
|
||||
|
||||
/* This function returns true if a branch is detected. End of a basic block
|
||||
does not have to be a branch, but here we assume only branches end a
|
||||
window. */
|
||||
|
||||
static bool
|
||||
is_end_basic_block (enum dispatch_group group)
|
||||
{
|
||||
return group == disp_branch;
|
||||
}
|
||||
|
||||
/* This function is called when the end of a window processing is reached. */
|
||||
|
||||
static void
|
||||
process_end_window (void)
|
||||
{
|
||||
gcc_assert (dispatch_window_list->num_insn <= MAX_INSN);
|
||||
if (dispatch_window_list->next)
|
||||
{
|
||||
gcc_assert (dispatch_window_list1->num_insn <= MAX_INSN);
|
||||
gcc_assert (dispatch_window_list->window_size
|
||||
+ dispatch_window_list1->window_size <= 48);
|
||||
init_window (1);
|
||||
}
|
||||
init_window (0);
|
||||
}
|
||||
|
||||
/* Allocates a new dispatch window and adds it to WINDOW_LIST.
|
||||
WINDOW_NUM is either 0 or 1. A maximum of two windows are generated
|
||||
for 48 bytes of instructions. Note that these windows are not dispatch
|
||||
windows that their sizes are DISPATCH_WINDOW_SIZE. */
|
||||
|
||||
static dispatch_windows *
|
||||
allocate_next_window (int window_num)
|
||||
{
|
||||
if (window_num == 0)
|
||||
{
|
||||
if (dispatch_window_list->next)
|
||||
init_window (1);
|
||||
init_window (0);
|
||||
return dispatch_window_list;
|
||||
}
|
||||
|
||||
dispatch_window_list->next = dispatch_window_list1;
|
||||
dispatch_window_list1->prev = dispatch_window_list;
|
||||
|
||||
return dispatch_window_list1;
|
||||
}
|
||||
|
||||
/* Increment the number of immediate operands of an instruction. */
|
||||
|
||||
static int
|
||||
find_constant_1 (rtx *in_rtx, imm_info *imm_values)
|
||||
{
|
||||
if (*in_rtx == 0)
|
||||
return 0;
|
||||
|
||||
switch ( GET_CODE (*in_rtx))
|
||||
{
|
||||
case CONST:
|
||||
case SYMBOL_REF:
|
||||
case CONST_INT:
|
||||
(imm_values->imm)++;
|
||||
if (x86_64_immediate_operand (*in_rtx, SImode))
|
||||
(imm_values->imm32)++;
|
||||
else
|
||||
(imm_values->imm64)++;
|
||||
break;
|
||||
|
||||
case CONST_DOUBLE:
|
||||
(imm_values->imm)++;
|
||||
(imm_values->imm64)++;
|
||||
break;
|
||||
|
||||
case CODE_LABEL:
|
||||
if (LABEL_KIND (*in_rtx) == LABEL_NORMAL)
|
||||
{
|
||||
(imm_values->imm)++;
|
||||
(imm_values->imm32)++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute number of immediate operands of an instruction. */
|
||||
|
||||
static void
|
||||
find_constant (rtx in_rtx, imm_info *imm_values)
|
||||
{
|
||||
for_each_rtx (INSN_P (in_rtx) ? &PATTERN (in_rtx) : &in_rtx,
|
||||
(rtx_function) find_constant_1, (void *) imm_values);
|
||||
}
|
||||
|
||||
/* Return total size of immediate operands of an instruction along with number
|
||||
of corresponding immediate-operands. It initializes its parameters to zero
|
||||
befor calling FIND_CONSTANT.
|
||||
INSN is the input instruction. IMM is the total of immediates.
|
||||
IMM32 is the number of 32 bit immediates. IMM64 is the number of 64
|
||||
bit immediates. */
|
||||
|
||||
static int
|
||||
get_num_immediates (rtx insn, int *imm, int *imm32, int *imm64)
|
||||
{
|
||||
imm_info imm_values = {0, 0, 0};
|
||||
|
||||
find_constant (insn, &imm_values);
|
||||
*imm = imm_values.imm;
|
||||
*imm32 = imm_values.imm32;
|
||||
*imm64 = imm_values.imm64;
|
||||
return imm_values.imm32 * 4 + imm_values.imm64 * 8;
|
||||
}
|
||||
|
||||
/* This function indicates if an operand of an instruction is an
|
||||
immediate. */
|
||||
|
||||
static bool
|
||||
has_immediate (rtx insn)
|
||||
{
|
||||
int num_imm_operand;
|
||||
int num_imm32_operand;
|
||||
int num_imm64_operand;
|
||||
|
||||
if (insn)
|
||||
return get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
|
||||
&num_imm64_operand);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Return single or double path for instructions. */
|
||||
|
||||
static enum insn_path
|
||||
get_insn_path (rtx insn)
|
||||
{
|
||||
enum attr_amdfam10_decode path = get_attr_amdfam10_decode (insn);
|
||||
|
||||
if ((int)path == 0)
|
||||
return path_single;
|
||||
|
||||
if ((int)path == 1)
|
||||
return path_double;
|
||||
|
||||
return path_multi;
|
||||
}
|
||||
|
||||
/* Return insn dispatch group. */
|
||||
|
||||
static enum dispatch_group
|
||||
get_insn_group (rtx insn)
|
||||
{
|
||||
enum dispatch_group group = get_mem_group (insn);
|
||||
if (group)
|
||||
return group;
|
||||
|
||||
if (is_branch (insn))
|
||||
return disp_branch;
|
||||
|
||||
if (is_cmp (insn))
|
||||
return disp_cmp;
|
||||
|
||||
if (has_immediate (insn))
|
||||
return disp_imm;
|
||||
|
||||
if (is_prefetch (insn))
|
||||
return disp_prefetch;
|
||||
|
||||
return disp_no_group;
|
||||
}
|
||||
|
||||
/* Count number of GROUP restricted instructions in a dispatch
|
||||
window WINDOW_LIST. */
|
||||
|
||||
static int
|
||||
count_num_restricted (rtx insn, dispatch_windows *window_list)
|
||||
{
|
||||
enum dispatch_group group = get_insn_group (insn);
|
||||
int imm_size;
|
||||
int num_imm_operand;
|
||||
int num_imm32_operand;
|
||||
int num_imm64_operand;
|
||||
|
||||
if (group == disp_no_group)
|
||||
return 0;
|
||||
|
||||
if (group == disp_imm)
|
||||
{
|
||||
imm_size = get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
|
||||
&num_imm64_operand);
|
||||
if (window_list->imm_size + imm_size > MAX_IMM_SIZE
|
||||
|| num_imm_operand + window_list->num_imm > MAX_IMM
|
||||
|| (num_imm32_operand > 0
|
||||
&& (window_list->num_imm_32 + num_imm32_operand > MAX_IMM_32
|
||||
|| window_list->num_imm_64 * 2 + num_imm32_operand > MAX_IMM_32))
|
||||
|| (num_imm64_operand > 0
|
||||
&& (window_list->num_imm_64 + num_imm64_operand > MAX_IMM_64
|
||||
|| window_list->num_imm_32 + num_imm64_operand * 2 > MAX_IMM_32))
|
||||
|| (window_list->imm_size + imm_size == MAX_IMM_SIZE
|
||||
&& num_imm64_operand > 0
|
||||
&& ((window_list->num_imm_64 > 0
|
||||
&& window_list->num_insn >= 2)
|
||||
|| window_list->num_insn >= 3)))
|
||||
return BIG;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((group == disp_load_store
|
||||
&& (window_list->num_loads >= MAX_LOAD
|
||||
|| window_list->num_stores >= MAX_STORE))
|
||||
|| ((group == disp_load
|
||||
|| group == disp_prefetch)
|
||||
&& window_list->num_loads >= MAX_LOAD)
|
||||
|| (group == disp_store
|
||||
&& window_list->num_stores >= MAX_STORE))
|
||||
return BIG;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This function returns true if insn satisfies dispatch rules on the
|
||||
last window scheduled. */
|
||||
|
||||
static bool
|
||||
fits_dispatch_window (rtx insn)
|
||||
{
|
||||
dispatch_windows *window_list = dispatch_window_list;
|
||||
dispatch_windows *window_list_next = dispatch_window_list->next;
|
||||
unsigned int num_restrict;
|
||||
enum dispatch_group group = get_insn_group (insn);
|
||||
enum insn_path path = get_insn_path (insn);
|
||||
int sum;
|
||||
|
||||
/* Make disp_cmp and disp_jcc get scheduled at the latest. These
|
||||
instructions should be given the lowest priority in the
|
||||
scheduling process in Haifa scheduler to make sure they will be
|
||||
scheduled in the same dispatch window as the refrence to them. */
|
||||
if (group == disp_jcc || group == disp_cmp)
|
||||
return false;
|
||||
|
||||
/* Check nonrestricted. */
|
||||
if (group == disp_no_group || group == disp_branch)
|
||||
return true;
|
||||
|
||||
/* Get last dispatch window. */
|
||||
if (window_list_next)
|
||||
window_list = window_list_next;
|
||||
|
||||
if (window_list->window_num == 1)
|
||||
{
|
||||
sum = window_list->prev->window_size + window_list->window_size;
|
||||
|
||||
if (sum == 32
|
||||
|| (min_insn_size (insn) + sum) >= 48)
|
||||
/* Window 1 is full. Go for next window. */
|
||||
return true;
|
||||
}
|
||||
|
||||
num_restrict = count_num_restricted (insn, window_list);
|
||||
|
||||
if (num_restrict > num_allowable_groups[group])
|
||||
return false;
|
||||
|
||||
/* See if it fits in the first window. */
|
||||
if (window_list->window_num == 0)
|
||||
{
|
||||
/* The first widow should have only single and double path
|
||||
uops. */
|
||||
if (path == path_double
|
||||
&& (window_list->num_uops + 2) > MAX_INSN)
|
||||
return false;
|
||||
else if (path != path_single)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Add an instruction INSN with NUM_UOPS micro-operations to the
|
||||
dispatch window WINDOW_LIST. */
|
||||
|
||||
static void
|
||||
add_insn_window (rtx insn, dispatch_windows *window_list, int num_uops)
|
||||
{
|
||||
int byte_len = min_insn_size (insn);
|
||||
int num_insn = window_list->num_insn;
|
||||
int imm_size;
|
||||
sched_insn_info *window = window_list->window;
|
||||
enum dispatch_group group = get_insn_group (insn);
|
||||
enum insn_path path = get_insn_path (insn);
|
||||
int num_imm_operand;
|
||||
int num_imm32_operand;
|
||||
int num_imm64_operand;
|
||||
|
||||
if (!window_list->violation && group != disp_cmp
|
||||
&& !fits_dispatch_window (insn))
|
||||
window_list->violation = true;
|
||||
|
||||
imm_size = get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
|
||||
&num_imm64_operand);
|
||||
|
||||
/* Initialize window with new instruction. */
|
||||
window[num_insn].insn = insn;
|
||||
window[num_insn].byte_len = byte_len;
|
||||
window[num_insn].group = group;
|
||||
window[num_insn].path = path;
|
||||
window[num_insn].imm_bytes = imm_size;
|
||||
|
||||
window_list->window_size += byte_len;
|
||||
window_list->num_insn = num_insn + 1;
|
||||
window_list->num_uops = window_list->num_uops + num_uops;
|
||||
window_list->imm_size += imm_size;
|
||||
window_list->num_imm += num_imm_operand;
|
||||
window_list->num_imm_32 += num_imm32_operand;
|
||||
window_list->num_imm_64 += num_imm64_operand;
|
||||
|
||||
if (group == disp_store)
|
||||
window_list->num_stores += 1;
|
||||
else if (group == disp_load
|
||||
|| group == disp_prefetch)
|
||||
window_list->num_loads += 1;
|
||||
else if (group == disp_load_store)
|
||||
{
|
||||
window_list->num_stores += 1;
|
||||
window_list->num_loads += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adds a scheduled instruction, INSN, to the current dispatch window.
|
||||
If the total bytes of instructions or the number of instructions in
|
||||
the window exceed allowable, it allocates a new window. */
|
||||
|
||||
static void
|
||||
add_to_dispatch_window (rtx insn)
|
||||
{
|
||||
int byte_len;
|
||||
dispatch_windows *window_list;
|
||||
dispatch_windows *next_list;
|
||||
dispatch_windows *window0_list;
|
||||
enum insn_path path;
|
||||
enum dispatch_group insn_group;
|
||||
bool insn_fits;
|
||||
int num_insn;
|
||||
int num_uops;
|
||||
int window_num;
|
||||
int insn_num_uops;
|
||||
int sum;
|
||||
|
||||
if (INSN_CODE (insn) < 0)
|
||||
return;
|
||||
|
||||
byte_len = min_insn_size (insn);
|
||||
window_list = dispatch_window_list;
|
||||
next_list = window_list->next;
|
||||
path = get_insn_path (insn);
|
||||
insn_group = get_insn_group (insn);
|
||||
|
||||
/* Get the last dispatch window. */
|
||||
if (next_list)
|
||||
window_list = dispatch_window_list->next;
|
||||
|
||||
if (path == path_single)
|
||||
insn_num_uops = 1;
|
||||
else if (path == path_double)
|
||||
insn_num_uops = 2;
|
||||
else
|
||||
insn_num_uops = (int) path;
|
||||
|
||||
/* If current window is full, get a new window.
|
||||
Window number zero is full, if MAX_INSN uops are scheduled in it.
|
||||
Window number one is full, if window zero's bytes plus window
|
||||
one's bytes is 32, or if the bytes of the new instruction added
|
||||
to the total makes it greater than 48, or it has already MAX_INSN
|
||||
instructions in it. */
|
||||
num_insn = window_list->num_insn;
|
||||
num_uops = window_list->num_uops;
|
||||
window_num = window_list->window_num;
|
||||
insn_fits = fits_dispatch_window (insn);
|
||||
|
||||
if (num_insn >= MAX_INSN
|
||||
|| num_uops + insn_num_uops > MAX_INSN
|
||||
|| !(insn_fits))
|
||||
{
|
||||
window_num = ~window_num & 1;
|
||||
window_list = allocate_next_window (window_num);
|
||||
}
|
||||
|
||||
if (window_num == 0)
|
||||
{
|
||||
add_insn_window (insn, window_list, insn_num_uops);
|
||||
if (window_list->num_insn >= MAX_INSN
|
||||
&& insn_group == disp_branch)
|
||||
{
|
||||
process_end_window ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (window_num == 1)
|
||||
{
|
||||
window0_list = window_list->prev;
|
||||
sum = window0_list->window_size + window_list->window_size;
|
||||
if (sum == 32
|
||||
|| (byte_len + sum) >= 48)
|
||||
{
|
||||
process_end_window ();
|
||||
window_list = dispatch_window_list;
|
||||
}
|
||||
|
||||
add_insn_window (insn, window_list, insn_num_uops);
|
||||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
if (is_end_basic_block (insn_group))
|
||||
{
|
||||
/* End of basic block is reached do end-basic-block process. */
|
||||
process_end_window ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the dispatch window, WINDOW_NUM, to FILE. */
|
||||
|
||||
DEBUG_FUNCTION static void
|
||||
debug_dispatch_window_file (FILE *file, int window_num)
|
||||
{
|
||||
dispatch_windows *list;
|
||||
int i;
|
||||
|
||||
if (window_num == 0)
|
||||
list = dispatch_window_list;
|
||||
else
|
||||
list = dispatch_window_list1;
|
||||
|
||||
fprintf (file, "Window #%d:\n", list->window_num);
|
||||
fprintf (file, " num_insn = %d, num_uops = %d, window_size = %d\n",
|
||||
list->num_insn, list->num_uops, list->window_size);
|
||||
fprintf (file, " num_imm = %d, num_imm_32 = %d, num_imm_64 = %d, imm_size = %d\n",
|
||||
list->num_imm, list->num_imm_32, list->num_imm_64, list->imm_size);
|
||||
|
||||
fprintf (file, " num_loads = %d, num_stores = %d\n", list->num_loads,
|
||||
list->num_stores);
|
||||
fprintf (file, " insn info:\n");
|
||||
|
||||
for (i = 0; i < MAX_INSN; i++)
|
||||
{
|
||||
if (!list->window[i].insn)
|
||||
break;
|
||||
fprintf (file, " group[%d] = %s, insn[%d] = %p, path[%d] = %d byte_len[%d] = %d, imm_bytes[%d] = %d\n",
|
||||
i, group_name[list->window[i].group],
|
||||
i, (void *)list->window[i].insn,
|
||||
i, list->window[i].path,
|
||||
i, list->window[i].byte_len,
|
||||
i, list->window[i].imm_bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print to stdout a dispatch window. */
|
||||
|
||||
DEBUG_FUNCTION void
|
||||
debug_dispatch_window (int window_num)
|
||||
{
|
||||
debug_dispatch_window_file (stdout, window_num);
|
||||
}
|
||||
|
||||
/* Print INSN dispatch information to FILE. */
|
||||
|
||||
DEBUG_FUNCTION static void
|
||||
debug_insn_dispatch_info_file (FILE *file, rtx insn)
|
||||
{
|
||||
int byte_len;
|
||||
enum insn_path path;
|
||||
enum dispatch_group group;
|
||||
int imm_size;
|
||||
int num_imm_operand;
|
||||
int num_imm32_operand;
|
||||
int num_imm64_operand;
|
||||
|
||||
if (INSN_CODE (insn) < 0)
|
||||
return;
|
||||
|
||||
byte_len = min_insn_size (insn);
|
||||
path = get_insn_path (insn);
|
||||
group = get_insn_group (insn);
|
||||
imm_size = get_num_immediates (insn, &num_imm_operand, &num_imm32_operand,
|
||||
&num_imm64_operand);
|
||||
|
||||
fprintf (file, " insn info:\n");
|
||||
fprintf (file, " group = %s, path = %d, byte_len = %d\n",
|
||||
group_name[group], path, byte_len);
|
||||
fprintf (file, " num_imm = %d, num_imm_32 = %d, num_imm_64 = %d, imm_size = %d\n",
|
||||
num_imm_operand, num_imm32_operand, num_imm64_operand, imm_size);
|
||||
}
|
||||
|
||||
/* Print to STDERR the status of the ready list with respect to
|
||||
dispatch windows. */
|
||||
|
||||
DEBUG_FUNCTION void
|
||||
debug_ready_dispatch (void)
|
||||
{
|
||||
int i;
|
||||
int no_ready = number_in_ready ();
|
||||
|
||||
fprintf (stdout, "Number of ready: %d\n", no_ready);
|
||||
|
||||
for (i = 0; i < no_ready; i++)
|
||||
debug_insn_dispatch_info_file (stdout, get_ready_element (i));
|
||||
}
|
||||
|
||||
/* This routine is the driver of the dispatch scheduler. */
|
||||
|
||||
static void
|
||||
do_dispatch (rtx insn, int mode)
|
||||
{
|
||||
if (mode == DISPATCH_INIT)
|
||||
init_dispatch_sched ();
|
||||
else if (mode == ADD_TO_DISPATCH_WINDOW)
|
||||
add_to_dispatch_window (insn);
|
||||
}
|
||||
|
||||
/* Return TRUE if Dispatch Scheduling is supported. */
|
||||
|
||||
static bool
|
||||
has_dispatch (rtx insn, int action)
|
||||
{
|
||||
if (ix86_tune == PROCESSOR_BDVER1 && flag_dispatch_scheduler)
|
||||
switch (action)
|
||||
{
|
||||
default:
|
||||
return false;
|
||||
|
||||
case IS_DISPATCH_ON:
|
||||
return true;
|
||||
break;
|
||||
|
||||
case IS_CMP:
|
||||
return is_cmp (insn);
|
||||
|
||||
case DISPATCH_VIOLATION:
|
||||
return dispatch_violation ();
|
||||
|
||||
case FITS_DISPATCH_WINDOW:
|
||||
return fits_dispatch_window (insn);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_RETURN_IN_MEMORY
|
||||
#define TARGET_RETURN_IN_MEMORY ix86_return_in_memory
|
||||
|
|
|
@ -2375,6 +2375,9 @@ struct GTY(()) machine_function {
|
|||
#define SYMBOL_REF_DLLEXPORT_P(X) \
|
||||
((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_DLLEXPORT) != 0)
|
||||
|
||||
extern void debug_ready_dispatch (void);
|
||||
extern void debug_dispatch_window (int);
|
||||
|
||||
/*
|
||||
Local variables:
|
||||
version-control: t
|
||||
|
|
|
@ -254,6 +254,11 @@ Enable automatic generation of fused floating point multiply-add instructions
|
|||
if the ISA supports such instructions. The -mfused-madd option is on by
|
||||
default.
|
||||
|
||||
mdispatch-scheduler
|
||||
Target RejectNegative Var(flag_dispatch_scheduler)
|
||||
Do dispatch scheduling if processor is bdver1 and Haifa scheduling
|
||||
is selected.
|
||||
|
||||
;; ISA support
|
||||
|
||||
m32
|
||||
|
|
|
@ -6777,6 +6777,16 @@ bound will be used in case this hook is not implemented: the total number
|
|||
of instructions divided by the issue rate.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} bool TARGET_SCHED_DISPATCH (rtx @var{insn}, int @var{x})
|
||||
This hook is called by Haifa Scheduler. It returns true if dispatch scheduling
|
||||
is supported in hardware and the condition specified in the parameter is true.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {Target Hook} void TARGET_SCHED_DISPATCH_DO (rtx @var{insn}, int @var{x})
|
||||
This hook is called by Haifa Scheduler. It performs the operation specified
|
||||
in its second parameter.
|
||||
@end deftypefn
|
||||
|
||||
@node Sections
|
||||
@section Dividing the Output into Sections (Texts, Data, @dots{})
|
||||
@c the above section title is WAY too long. maybe cut the part between
|
||||
|
|
|
@ -6777,6 +6777,16 @@ bound will be used in case this hook is not implemented: the total number
|
|||
of instructions divided by the issue rate.
|
||||
@end deftypefn
|
||||
|
||||
@hook TARGET_SCHED_DISPATCH
|
||||
This hook is called by Haifa Scheduler. It returns true if dispatch scheduling
|
||||
is supported in hardware and the condition specified in the parameter is true.
|
||||
@end deftypefn
|
||||
|
||||
@hook TARGET_SCHED_DISPATCH_DO
|
||||
This hook is called by Haifa Scheduler. It performs the operation specified
|
||||
in its second parameter.
|
||||
@end deftypefn
|
||||
|
||||
@node Sections
|
||||
@section Dividing the Output into Sections (Texts, Data, @dots{})
|
||||
@c the above section title is WAY too long. maybe cut the part between
|
||||
|
|
|
@ -532,6 +532,7 @@ static void extend_h_i_d (void);
|
|||
|
||||
static void ready_add (struct ready_list *, rtx, bool);
|
||||
static rtx ready_remove_first (struct ready_list *);
|
||||
static rtx ready_remove_first_dispatch (struct ready_list *ready);
|
||||
|
||||
static void queue_to_ready (struct ready_list *);
|
||||
static int early_queue_to_ready (state_t, struct ready_list *);
|
||||
|
@ -2642,7 +2643,11 @@ choose_ready (struct ready_list *ready, rtx *insn_ptr)
|
|||
if (lookahead <= 0 || SCHED_GROUP_P (ready_element (ready, 0))
|
||||
|| DEBUG_INSN_P (ready_element (ready, 0)))
|
||||
{
|
||||
*insn_ptr = ready_remove_first (ready);
|
||||
if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
|
||||
*insn_ptr = ready_remove_first_dispatch (ready);
|
||||
else
|
||||
*insn_ptr = ready_remove_first (ready);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
|
@ -3140,6 +3145,10 @@ schedule_block (basic_block *target_bb)
|
|||
last_scheduled_insn);
|
||||
|
||||
move_insn (insn, last_scheduled_insn, current_sched_info->next_tail);
|
||||
|
||||
if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
|
||||
targetm.sched.dispatch_do (insn, ADD_TO_DISPATCH_WINDOW);
|
||||
|
||||
reemit_notes (insn);
|
||||
last_scheduled_insn = insn;
|
||||
|
||||
|
@ -3364,8 +3373,12 @@ sched_init (void)
|
|||
flag_schedule_speculative_load = 0;
|
||||
#endif
|
||||
|
||||
if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
|
||||
targetm.sched.dispatch_do (NULL_RTX, DISPATCH_INIT);
|
||||
|
||||
sched_pressure_p = (flag_sched_pressure && ! reload_completed
|
||||
&& common_sched_info->sched_pass_id == SCHED_RGN_PASS);
|
||||
|
||||
if (sched_pressure_p)
|
||||
ira_setup_eliminable_regset ();
|
||||
|
||||
|
@ -5557,4 +5570,73 @@ sched_emit_insn (rtx pat)
|
|||
return insn;
|
||||
}
|
||||
|
||||
/* This function returns a candidate satisfying dispatch constraints from
|
||||
the ready list. */
|
||||
|
||||
static rtx
|
||||
ready_remove_first_dispatch (struct ready_list *ready)
|
||||
{
|
||||
int i;
|
||||
rtx insn = ready_element (ready, 0);
|
||||
|
||||
if (ready->n_ready == 1
|
||||
|| INSN_CODE (insn) < 0
|
||||
|| !INSN_P (insn)
|
||||
|| !active_insn_p (insn)
|
||||
|| targetm.sched.dispatch (insn, FITS_DISPATCH_WINDOW))
|
||||
return ready_remove_first (ready);
|
||||
|
||||
for (i = 1; i < ready->n_ready; i++)
|
||||
{
|
||||
insn = ready_element (ready, i);
|
||||
|
||||
if (INSN_CODE (insn) < 0
|
||||
|| !INSN_P (insn)
|
||||
|| !active_insn_p (insn))
|
||||
continue;
|
||||
|
||||
if (targetm.sched.dispatch (insn, FITS_DISPATCH_WINDOW))
|
||||
{
|
||||
/* Return ith element of ready. */
|
||||
insn = ready_remove (ready, i);
|
||||
return insn;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetm.sched.dispatch (NULL_RTX, DISPATCH_VIOLATION))
|
||||
return ready_remove_first (ready);
|
||||
|
||||
for (i = 1; i < ready->n_ready; i++)
|
||||
{
|
||||
insn = ready_element (ready, i);
|
||||
|
||||
if (INSN_CODE (insn) < 0
|
||||
|| !INSN_P (insn)
|
||||
|| !active_insn_p (insn))
|
||||
continue;
|
||||
|
||||
/* Return i-th element of ready. */
|
||||
if (targetm.sched.dispatch (insn, IS_CMP))
|
||||
return ready_remove (ready, i);
|
||||
}
|
||||
|
||||
return ready_remove_first (ready);
|
||||
}
|
||||
|
||||
/* Get number of ready insn in the ready list. */
|
||||
|
||||
int
|
||||
number_in_ready (void)
|
||||
{
|
||||
return ready.n_ready;
|
||||
}
|
||||
|
||||
/* Get number of ready's in the ready list. */
|
||||
|
||||
rtx
|
||||
get_ready_element (int i)
|
||||
{
|
||||
return ready_element (&ready, i);
|
||||
}
|
||||
|
||||
#endif /* INSN_SCHEDULING */
|
||||
|
|
15
gcc/hooks.c
15
gcc/hooks.c
|
@ -340,3 +340,18 @@ hook_tree_const_tree_null (const_tree t ATTRIBUTE_UNUSED)
|
|||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Generic hook that takes a rtx and an int and returns a bool. */
|
||||
|
||||
bool
|
||||
hook_bool_rtx_int_false (rtx insn ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Generic hook that takes a rtx and an int and returns void. */
|
||||
|
||||
void
|
||||
hook_void_rtx_int (rtx insn ATTRIBUTE_UNUSED, int mode ATTRIBUTE_UNUSED)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ extern bool hook_bool_const_tree_hwi_hwi_const_tree_true (const_tree,
|
|||
HOST_WIDE_INT,
|
||||
const_tree);
|
||||
extern bool hook_bool_rtx_false (rtx);
|
||||
extern bool hook_bool_rtx_int_false (rtx, int);
|
||||
extern bool hook_bool_uintp_uintp_false (unsigned int *, unsigned int *);
|
||||
extern bool hook_bool_rtx_int_int_intp_bool_false (rtx, int, int, int *, bool);
|
||||
extern bool hook_bool_size_t_constcharptr_int_true (size_t, const char *, int);
|
||||
|
@ -55,6 +56,7 @@ extern bool hook_bool_tree_bool_false (tree, bool);
|
|||
|
||||
extern void hook_void_void (void);
|
||||
extern void hook_void_constcharptr (const char *);
|
||||
extern void hook_void_rtx_int (rtx, int);
|
||||
extern void hook_void_FILEptr_constcharptr (FILE *, const char *);
|
||||
extern void hook_void_tree (tree);
|
||||
extern void hook_void_tree_treeptr (tree, tree *);
|
||||
|
|
|
@ -1269,6 +1269,8 @@ extern void add_block (basic_block, basic_block);
|
|||
extern rtx bb_note (basic_block);
|
||||
extern void concat_note_lists (rtx, rtx *);
|
||||
extern rtx sched_emit_insn (rtx);
|
||||
extern rtx get_ready_element (int);
|
||||
extern int number_in_ready (void);
|
||||
|
||||
|
||||
/* Types and functions in sched-rgn.c. */
|
||||
|
@ -1477,6 +1479,13 @@ sd_iterator_next (sd_iterator_def *it_ptr)
|
|||
sd_iterator_cond (&(ITER), &(DEP)); \
|
||||
sd_iterator_next (&(ITER)))
|
||||
|
||||
#define IS_DISPATCH_ON 1
|
||||
#define IS_CMP 2
|
||||
#define DISPATCH_VIOLATION 3
|
||||
#define FITS_DISPATCH_WINDOW 4
|
||||
#define DISPATCH_INIT 5
|
||||
#define ADD_TO_DISPATCH_WINDOW 6
|
||||
|
||||
extern int sd_lists_size (const_rtx, sd_list_types_def);
|
||||
extern bool sd_lists_empty_p (const_rtx, sd_list_types_def);
|
||||
extern void sd_init_insn (rtx);
|
||||
|
|
|
@ -777,6 +777,24 @@ DEFHOOK
|
|||
"",
|
||||
int, (struct ddg *g), NULL)
|
||||
|
||||
/* The following member value is a function that initializes dispatch
|
||||
schedling and adds instructions to dispatch window according to its
|
||||
parameters. */
|
||||
DEFHOOK
|
||||
(dispatch_do,
|
||||
"",
|
||||
void, (rtx insn, int x),
|
||||
hook_void_rtx_int)
|
||||
|
||||
/* The following member value is a a function that returns true is
|
||||
dispatch schedling is supported in hardware and condition passed
|
||||
as the second parameter is true. */
|
||||
DEFHOOK
|
||||
(dispatch,
|
||||
"",
|
||||
bool, (rtx insn, int x),
|
||||
hook_bool_rtx_int_false)
|
||||
|
||||
HOOK_VECTOR_END (sched)
|
||||
|
||||
/* Functions relating to vectorization. */
|
||||
|
|
Loading…
Reference in New Issue