sched-int.h (struct haifa_insn_data): New fields: resolved_deps, inter_tick, queue_index.
2006-03-16 Maxim Kuvyrkov <mkuvyrkov@ispras.ru> * sched-int.h (struct haifa_insn_data): New fields: resolved_deps, inter_tick, queue_index. (struct sched_info): Change signature of init_ready_list field. Adjust all initializations. (RESOLVED_DEPS): New access macro. (ready_add): Remove prototype. (try_ready): Add prototype. * sched-rgn.c (init_ready_list): Use try_ready. (schedule_region): Initialize current_sched_info->{sched_max_insns_priority, queue_must_finish_empty}. * sched-ebb.c (new_ready): Remove. Adjust ebb_sched_info. (init_ready_list): Use try_ready. (schedule_ebb): Initialize current_sched_info->sched_max_insns_priority. * lists.c (remove_list_elem): Remove `static'. (remove_free_INSN_LIST_elem): New function. * rtl.h (remove_list_elem, remove_free_INSN_LIST_elem): Add prototypes. * haifa-sched.c (INTER_TICK, QUEUE_INDEX): New macros. (INVALID_TICK, MIN_TICK, QUEUE_SCHEDULED, QUEUE_NOWHERE, QUEUE_READY): New constants. (readyp): New variable. (queue_remove, ready_remove_insn, fix_inter_tick, fix_tick_ready, change_queue_index, resolve_dep): New static functions. (try_ready): New function. Adjust callers in sched-rgn.c and sched-ebb.c to use it instead of ready_add. (clock_var): Move at the begining of file. (rank_for_schedule): Fix typo. (queue_insn): Add assertion. Handle QUEUE_INDEX. (ready_lastpos): Enforce assertion. (ready_add): Make it static. Handle QUEUE_INDEX. Add new argument, update all callers. (ready_remove_first, ready_remove): Handle QUEUE_INDEX. (schedule_insn): Rewrite to use try_ready and resolve_dep. (queue_to_ready): Use free_INSN_LIST_list. (early_queue_to_ready): Fix typo. (schedule_block): Init readyp. Move init_ready_list call after the initialization of clock_var. Fix error in rejecting insn by targetm.sched.dfa_new_cycle. Add call to fix_inter_tick. Remove code that previously corrected INSN_TICKs. Add code for handling QUEUE_INDEX. (set_priorities): Fix typo. (sched_init): Initialize INSN_TICK, INTER_TICK and QUEUE_INDEX. Clarify comment and code that keeps current_sched_info->next_tail non-null. From-SVN: r112127
This commit is contained in:
parent
d08eefb9d2
commit
63f54b1abd
|
@ -1,3 +1,49 @@
|
|||
2006-03-16 Maxim Kuvyrkov <mkuvyrkov@ispras.ru>
|
||||
|
||||
* sched-int.h (struct haifa_insn_data): New fields: resolved_deps,
|
||||
inter_tick, queue_index.
|
||||
(struct sched_info): Change signature of init_ready_list field.
|
||||
Adjust all initializations.
|
||||
(RESOLVED_DEPS): New access macro.
|
||||
(ready_add): Remove prototype.
|
||||
(try_ready): Add prototype.
|
||||
* sched-rgn.c (init_ready_list): Use try_ready.
|
||||
(schedule_region): Initialize
|
||||
current_sched_info->{sched_max_insns_priority, queue_must_finish_empty}.
|
||||
* sched-ebb.c (new_ready): Remove. Adjust ebb_sched_info.
|
||||
(init_ready_list): Use try_ready.
|
||||
(schedule_ebb): Initialize current_sched_info->sched_max_insns_priority.
|
||||
* lists.c (remove_list_elem): Remove `static'.
|
||||
(remove_free_INSN_LIST_elem): New function.
|
||||
* rtl.h (remove_list_elem, remove_free_INSN_LIST_elem): Add prototypes.
|
||||
* haifa-sched.c (INTER_TICK, QUEUE_INDEX): New macros.
|
||||
(INVALID_TICK, MIN_TICK, QUEUE_SCHEDULED, QUEUE_NOWHERE, QUEUE_READY):
|
||||
New constants.
|
||||
(readyp): New variable.
|
||||
(queue_remove, ready_remove_insn, fix_inter_tick, fix_tick_ready,
|
||||
change_queue_index, resolve_dep): New static functions.
|
||||
(try_ready): New function. Adjust callers in sched-rgn.c and
|
||||
sched-ebb.c to use it instead of ready_add.
|
||||
(clock_var): Move at the begining of file.
|
||||
(rank_for_schedule): Fix typo.
|
||||
(queue_insn): Add assertion. Handle QUEUE_INDEX.
|
||||
(ready_lastpos): Enforce assertion.
|
||||
(ready_add): Make it static. Handle QUEUE_INDEX. Add new argument,
|
||||
update all callers.
|
||||
(ready_remove_first, ready_remove): Handle QUEUE_INDEX.
|
||||
(schedule_insn): Rewrite to use try_ready and resolve_dep.
|
||||
(queue_to_ready): Use free_INSN_LIST_list.
|
||||
(early_queue_to_ready): Fix typo.
|
||||
(schedule_block): Init readyp. Move init_ready_list call after the
|
||||
initialization of clock_var. Fix error in rejecting insn by
|
||||
targetm.sched.dfa_new_cycle. Add call to fix_inter_tick. Remove code
|
||||
that previously corrected INSN_TICKs. Add code for handling
|
||||
QUEUE_INDEX.
|
||||
(set_priorities): Fix typo.
|
||||
(sched_init): Initialize INSN_TICK, INTER_TICK and QUEUE_INDEX.
|
||||
Clarify comment and code that keeps current_sched_info->next_tail
|
||||
non-null.
|
||||
|
||||
2006-03-16 Maxim Kuvyrkov <mkuvyrkov@ispras.ru>
|
||||
|
||||
* sched-rgn.c (extend_rgns): New static function.
|
||||
|
|
|
@ -187,6 +187,13 @@ struct haifa_insn_data *h_i_d;
|
|||
|
||||
#define LINE_NOTE(INSN) (h_i_d[INSN_UID (INSN)].line_note)
|
||||
#define INSN_TICK(INSN) (h_i_d[INSN_UID (INSN)].tick)
|
||||
#define INTER_TICK(INSN) (h_i_d[INSN_UID (INSN)].inter_tick)
|
||||
|
||||
/* If INSN_TICK of an instruction is equal to INVALID_TICK,
|
||||
then it should be recalculated from scratch. */
|
||||
#define INVALID_TICK (-(max_insn_queue_index + 1))
|
||||
/* The minimal value of the INSN_TICK of an instruction. */
|
||||
#define MIN_TICK (-max_insn_queue_index)
|
||||
|
||||
/* Vector indexed by basic block number giving the starting line-number
|
||||
for each basic block. */
|
||||
|
@ -236,7 +243,7 @@ static rtx note_list;
|
|||
|
||||
/* Implement a circular buffer to delay instructions until sufficient
|
||||
time has passed. For the new pipeline description interface,
|
||||
MAX_INSN_QUEUE_INDEX is a power of two minus one which is larger
|
||||
MAX_INSN_QUEUE_INDEX is a power of two minus one which is not less
|
||||
than maximal time of instruction execution computed by genattr.c on
|
||||
the base maximal time of functional unit reservations and getting a
|
||||
result. This is the longest time an insn may be queued. */
|
||||
|
@ -247,6 +254,17 @@ static int q_size = 0;
|
|||
#define NEXT_Q(X) (((X)+1) & max_insn_queue_index)
|
||||
#define NEXT_Q_AFTER(X, C) (((X)+C) & max_insn_queue_index)
|
||||
|
||||
#define QUEUE_SCHEDULED (-3)
|
||||
#define QUEUE_NOWHERE (-2)
|
||||
#define QUEUE_READY (-1)
|
||||
/* QUEUE_SCHEDULED - INSN is scheduled.
|
||||
QUEUE_NOWHERE - INSN isn't scheduled yet and is neither in
|
||||
queue or ready list.
|
||||
QUEUE_READY - INSN is in ready list.
|
||||
N >= 0 - INSN queued for X [where NEXT_Q_AFTER (q_ptr, X) == N] cycles. */
|
||||
|
||||
#define QUEUE_INDEX(INSN) (h_i_d[INSN_UID (INSN)].queue_index)
|
||||
|
||||
/* The following variable value refers for all current and future
|
||||
reservations of the processor units. */
|
||||
state_t curr_state;
|
||||
|
@ -275,6 +293,12 @@ struct ready_list
|
|||
int n_ready;
|
||||
};
|
||||
|
||||
/* The pointer to the ready list. */
|
||||
static struct ready_list *readyp;
|
||||
|
||||
/* Scheduling clock. */
|
||||
static int clock_var;
|
||||
|
||||
static int may_trap_exp (rtx, int);
|
||||
|
||||
/* Nonzero iff the address is comprised from at most 1 register. */
|
||||
|
@ -442,7 +466,7 @@ static int priority (rtx);
|
|||
static int rank_for_schedule (const void *, const void *);
|
||||
static void swap_sort (rtx *, int);
|
||||
static void queue_insn (rtx, int);
|
||||
static int schedule_insn (rtx, struct ready_list *, int);
|
||||
static int schedule_insn (rtx);
|
||||
static int find_set_reg_weight (rtx);
|
||||
static void find_insn_reg_weight (int);
|
||||
static void adjust_priority (rtx);
|
||||
|
@ -476,6 +500,7 @@ static rtx unlink_line_notes (rtx, rtx);
|
|||
static rtx reemit_notes (rtx, rtx);
|
||||
|
||||
static rtx *ready_lastpos (struct ready_list *);
|
||||
static void ready_add (struct ready_list *, rtx, bool);
|
||||
static void ready_sort (struct ready_list *);
|
||||
static rtx ready_remove_first (struct ready_list *);
|
||||
|
||||
|
@ -491,10 +516,16 @@ static rtx move_insn (rtx, rtx);
|
|||
on the first cycle. */
|
||||
static rtx ready_element (struct ready_list *, int);
|
||||
static rtx ready_remove (struct ready_list *, int);
|
||||
static void ready_remove_insn (rtx);
|
||||
static int max_issue (struct ready_list *, int *);
|
||||
|
||||
static rtx choose_ready (struct ready_list *);
|
||||
|
||||
static void fix_inter_tick (rtx, rtx);
|
||||
static int fix_tick_ready (rtx);
|
||||
static void change_queue_index (rtx, int);
|
||||
static void resolve_dep (rtx, rtx);
|
||||
|
||||
#endif /* INSN_SCHEDULING */
|
||||
|
||||
/* Point to state used for the current scheduling pass. */
|
||||
|
@ -663,7 +694,7 @@ rank_for_schedule (const void *x, const void *y)
|
|||
return info_val;
|
||||
|
||||
/* Compare insns based on their relation to the last-scheduled-insn. */
|
||||
if (last_scheduled_insn)
|
||||
if (INSN_P (last_scheduled_insn))
|
||||
{
|
||||
/* Classify the instructions into three classes:
|
||||
1) Data dependent on last schedule insn.
|
||||
|
@ -736,6 +767,9 @@ queue_insn (rtx insn, int n_cycles)
|
|||
{
|
||||
int next_q = NEXT_Q_AFTER (q_ptr, n_cycles);
|
||||
rtx link = alloc_INSN_LIST (insn, insn_queue[next_q]);
|
||||
|
||||
gcc_assert (n_cycles <= max_insn_queue_index);
|
||||
|
||||
insn_queue[next_q] = link;
|
||||
q_size += 1;
|
||||
|
||||
|
@ -746,6 +780,18 @@ queue_insn (rtx insn, int n_cycles)
|
|||
|
||||
fprintf (sched_dump, "queued for %d cycles.\n", n_cycles);
|
||||
}
|
||||
|
||||
QUEUE_INDEX (insn) = next_q;
|
||||
}
|
||||
|
||||
/* Remove INSN from queue. */
|
||||
static void
|
||||
queue_remove (rtx insn)
|
||||
{
|
||||
gcc_assert (QUEUE_INDEX (insn) >= 0);
|
||||
remove_free_INSN_LIST_elem (insn, &insn_queue[QUEUE_INDEX (insn)]);
|
||||
q_size--;
|
||||
QUEUE_INDEX (insn) = QUEUE_NOWHERE;
|
||||
}
|
||||
|
||||
/* Return a pointer to the bottom of the ready list, i.e. the insn
|
||||
|
@ -754,25 +800,45 @@ queue_insn (rtx insn, int n_cycles)
|
|||
HAIFA_INLINE static rtx *
|
||||
ready_lastpos (struct ready_list *ready)
|
||||
{
|
||||
gcc_assert (ready->n_ready);
|
||||
gcc_assert (ready->n_ready >= 1);
|
||||
return ready->vec + ready->first - ready->n_ready + 1;
|
||||
}
|
||||
|
||||
/* Add an element INSN to the ready list so that it ends up with the lowest
|
||||
priority. */
|
||||
/* Add an element INSN to the ready list so that it ends up with the
|
||||
lowest/highest priority dependending on FIRST_P. */
|
||||
|
||||
HAIFA_INLINE void
|
||||
ready_add (struct ready_list *ready, rtx insn)
|
||||
HAIFA_INLINE static void
|
||||
ready_add (struct ready_list *ready, rtx insn, bool first_p)
|
||||
{
|
||||
if (ready->first == ready->n_ready)
|
||||
if (!first_p)
|
||||
{
|
||||
memmove (ready->vec + ready->veclen - ready->n_ready,
|
||||
ready_lastpos (ready),
|
||||
ready->n_ready * sizeof (rtx));
|
||||
ready->first = ready->veclen - 1;
|
||||
if (ready->first == ready->n_ready)
|
||||
{
|
||||
memmove (ready->vec + ready->veclen - ready->n_ready,
|
||||
ready_lastpos (ready),
|
||||
ready->n_ready * sizeof (rtx));
|
||||
ready->first = ready->veclen - 1;
|
||||
}
|
||||
ready->vec[ready->first - ready->n_ready] = insn;
|
||||
}
|
||||
ready->vec[ready->first - ready->n_ready] = insn;
|
||||
else
|
||||
{
|
||||
if (ready->first == ready->veclen - 1)
|
||||
{
|
||||
if (ready->n_ready)
|
||||
/* ready_lastpos() fails when called with (ready->n_ready == 0). */
|
||||
memmove (ready->vec + ready->veclen - ready->n_ready - 1,
|
||||
ready_lastpos (ready),
|
||||
ready->n_ready * sizeof (rtx));
|
||||
ready->first = ready->veclen - 2;
|
||||
}
|
||||
ready->vec[++(ready->first)] = insn;
|
||||
}
|
||||
|
||||
ready->n_ready++;
|
||||
|
||||
gcc_assert (QUEUE_INDEX (insn) != QUEUE_READY);
|
||||
QUEUE_INDEX (insn) = QUEUE_READY;
|
||||
}
|
||||
|
||||
/* Remove the element with the highest priority from the ready list and
|
||||
|
@ -789,6 +855,10 @@ ready_remove_first (struct ready_list *ready)
|
|||
/* If the queue becomes empty, reset it. */
|
||||
if (ready->n_ready == 0)
|
||||
ready->first = ready->veclen - 1;
|
||||
|
||||
gcc_assert (QUEUE_INDEX (t) == QUEUE_READY);
|
||||
QUEUE_INDEX (t) = QUEUE_NOWHERE;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -825,9 +895,24 @@ ready_remove (struct ready_list *ready, int index)
|
|||
ready->n_ready--;
|
||||
for (i = index; i < ready->n_ready; i++)
|
||||
ready->vec[ready->first - i] = ready->vec[ready->first - i - 1];
|
||||
QUEUE_INDEX (t) = QUEUE_NOWHERE;
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Remove INSN from the ready list. */
|
||||
static void
|
||||
ready_remove_insn (rtx insn)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < readyp->n_ready; i++)
|
||||
if (ready_element (readyp, i) == insn)
|
||||
{
|
||||
ready_remove (readyp, i);
|
||||
return;
|
||||
}
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Sort the ready list READY by ascending priority, using the SCHED_SORT
|
||||
macro. */
|
||||
|
@ -883,11 +968,10 @@ static int last_clock_var;
|
|||
zero for insns in a schedule group). */
|
||||
|
||||
static int
|
||||
schedule_insn (rtx insn, struct ready_list *ready, int clock)
|
||||
schedule_insn (rtx insn)
|
||||
{
|
||||
rtx link;
|
||||
int advance = 0;
|
||||
int premature_issue = 0;
|
||||
|
||||
if (sched_verbose >= 1)
|
||||
{
|
||||
|
@ -895,7 +979,7 @@ schedule_insn (rtx insn, struct ready_list *ready, int clock)
|
|||
|
||||
print_insn (buf, insn, 0);
|
||||
buf[40] = 0;
|
||||
fprintf (sched_dump, ";;\t%3i--> %-40s:", clock, buf);
|
||||
fprintf (sched_dump, ";;\t%3i--> %-40s:", clock_var, buf);
|
||||
|
||||
if (recog_memoized (insn) < 0)
|
||||
fprintf (sched_dump, "nothing");
|
||||
|
@ -904,52 +988,44 @@ schedule_insn (rtx insn, struct ready_list *ready, int clock)
|
|||
fputc ('\n', sched_dump);
|
||||
}
|
||||
|
||||
if (INSN_TICK (insn) > clock)
|
||||
{
|
||||
/* 'insn' has been prematurely moved from the queue to the
|
||||
ready list. */
|
||||
premature_issue = INSN_TICK (insn) - clock;
|
||||
}
|
||||
/* Scheduling instruction should have all its dependencies resolved and
|
||||
should have been removed from the ready list. */
|
||||
gcc_assert (INSN_DEP_COUNT (insn) == 0);
|
||||
gcc_assert (!LOG_LINKS (insn));
|
||||
gcc_assert (QUEUE_INDEX (insn) == QUEUE_NOWHERE);
|
||||
|
||||
for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1))
|
||||
QUEUE_INDEX (insn) = QUEUE_SCHEDULED;
|
||||
|
||||
/* Now we can free RESOLVED_DEPS list. */
|
||||
if (current_sched_info->flags & USE_DEPS_LIST)
|
||||
free_DEPS_LIST_list (&RESOLVED_DEPS (insn));
|
||||
else
|
||||
free_INSN_LIST_list (&RESOLVED_DEPS (insn));
|
||||
|
||||
gcc_assert (INSN_TICK (insn) >= MIN_TICK);
|
||||
if (INSN_TICK (insn) > clock_var)
|
||||
/* INSN has been prematurely moved from the queue to the ready list.
|
||||
This is possible only if following flag is set. */
|
||||
gcc_assert (flag_sched_stalled_insns);
|
||||
|
||||
/* ??? Probably, if INSN is scheduled prematurely, we should leave
|
||||
INSN_TICK untouched. This is a machine-dependent issue, actually. */
|
||||
INSN_TICK (insn) = clock_var;
|
||||
|
||||
/* Update dependent instructions. */
|
||||
for (link = INSN_DEPEND (insn); link; link = XEXP (link, 1))
|
||||
{
|
||||
int effective_cost;
|
||||
rtx next = XEXP (link, 0);
|
||||
int cost = insn_cost (insn, link, next);
|
||||
|
||||
INSN_TICK (next) = MAX (INSN_TICK (next), clock + cost + premature_issue);
|
||||
resolve_dep (next, insn);
|
||||
|
||||
if ((INSN_DEP_COUNT (next) -= 1) == 0)
|
||||
{
|
||||
int effective_cost = INSN_TICK (next) - clock;
|
||||
|
||||
if (! (*current_sched_info->new_ready) (next))
|
||||
continue;
|
||||
|
||||
if (sched_verbose >= 2)
|
||||
{
|
||||
fprintf (sched_dump, ";;\t\tdependences resolved: insn %s ",
|
||||
(*current_sched_info->print_insn) (next, 0));
|
||||
|
||||
if (effective_cost < 1)
|
||||
fprintf (sched_dump, "into ready\n");
|
||||
else
|
||||
fprintf (sched_dump, "into queue with cost=%d\n",
|
||||
effective_cost);
|
||||
}
|
||||
|
||||
/* Adjust the priority of NEXT and either put it on the ready
|
||||
list or queue it. */
|
||||
adjust_priority (next);
|
||||
if (effective_cost < 1)
|
||||
ready_add (ready, next);
|
||||
else
|
||||
{
|
||||
queue_insn (next, effective_cost);
|
||||
|
||||
if (SCHED_GROUP_P (next) && advance < effective_cost)
|
||||
advance = effective_cost;
|
||||
}
|
||||
}
|
||||
effective_cost = try_ready (next);
|
||||
|
||||
if (effective_cost >= 0
|
||||
&& SCHED_GROUP_P (next)
|
||||
&& advance < effective_cost)
|
||||
advance = effective_cost;
|
||||
}
|
||||
|
||||
/* Annotate the instruction with issue information -- TImode
|
||||
|
@ -962,9 +1038,10 @@ schedule_insn (rtx insn, struct ready_list *ready, int clock)
|
|||
&& GET_CODE (PATTERN (insn)) != CLOBBER)
|
||||
{
|
||||
if (reload_completed)
|
||||
PUT_MODE (insn, clock > last_clock_var ? TImode : VOIDmode);
|
||||
last_clock_var = clock;
|
||||
PUT_MODE (insn, clock_var > last_clock_var ? TImode : VOIDmode);
|
||||
last_clock_var = clock_var;
|
||||
}
|
||||
|
||||
return advance;
|
||||
}
|
||||
|
||||
|
@ -1354,9 +1431,6 @@ find_insn_reg_weight (int b)
|
|||
}
|
||||
}
|
||||
|
||||
/* Scheduling clock, modified in schedule_block() and queue_to_ready (). */
|
||||
static int clock_var;
|
||||
|
||||
/* Move insns that became ready to fire from queue to ready list. */
|
||||
|
||||
static void
|
||||
|
@ -1378,11 +1452,11 @@ queue_to_ready (struct ready_list *ready)
|
|||
fprintf (sched_dump, ";;\t\tQ-->Ready: insn %s: ",
|
||||
(*current_sched_info->print_insn) (insn, 0));
|
||||
|
||||
ready_add (ready, insn);
|
||||
ready_add (ready, insn, false);
|
||||
if (sched_verbose >= 2)
|
||||
fprintf (sched_dump, "moving to ready without stalls\n");
|
||||
}
|
||||
insn_queue[q_ptr] = 0;
|
||||
free_INSN_LIST_list (&insn_queue[q_ptr]);
|
||||
|
||||
/* If there are no ready insns, stall until one is ready and add all
|
||||
of the pending insns at that point to the ready list. */
|
||||
|
@ -1403,11 +1477,11 @@ queue_to_ready (struct ready_list *ready)
|
|||
fprintf (sched_dump, ";;\t\tQ-->Ready: insn %s: ",
|
||||
(*current_sched_info->print_insn) (insn, 0));
|
||||
|
||||
ready_add (ready, insn);
|
||||
ready_add (ready, insn, false);
|
||||
if (sched_verbose >= 2)
|
||||
fprintf (sched_dump, "moving to ready with %d stalls\n", stalls);
|
||||
}
|
||||
insn_queue[NEXT_Q_AFTER (q_ptr, stalls)] = 0;
|
||||
free_INSN_LIST_list (&insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]);
|
||||
|
||||
advance_one_cycle ();
|
||||
|
||||
|
@ -1542,7 +1616,7 @@ early_queue_to_ready (state_t state, struct ready_list *ready)
|
|||
{
|
||||
/* move from Q to R */
|
||||
q_size -= 1;
|
||||
ready_add (ready, insn);
|
||||
ready_add (ready, insn, false);
|
||||
|
||||
if (prev_link)
|
||||
XEXP (prev_link, 1) = next_link;
|
||||
|
@ -1557,7 +1631,8 @@ early_queue_to_ready (state_t state, struct ready_list *ready)
|
|||
|
||||
insns_removed++;
|
||||
if (insns_removed == flag_sched_stalled_insns)
|
||||
/* Remove only one insn from Q at a time. */
|
||||
/* Remove no more than flag_sched_stalled_insns insns
|
||||
from Q at a time. */
|
||||
return insns_removed;
|
||||
}
|
||||
}
|
||||
|
@ -1872,6 +1947,7 @@ schedule_block (int b, int rgn_n_insns)
|
|||
state_reset (curr_state);
|
||||
|
||||
/* Allocate the ready list. */
|
||||
readyp = &ready;
|
||||
ready.veclen = rgn_n_insns + 1 + issue_rate;
|
||||
ready.first = ready.veclen - 1;
|
||||
ready.vec = XNEWVEC (rtx, ready.veclen);
|
||||
|
@ -1884,8 +1960,6 @@ schedule_block (int b, int rgn_n_insns)
|
|||
for (i = 0; i <= rgn_n_insns; i++)
|
||||
choice_stack[i].state = xmalloc (dfa_state_size);
|
||||
|
||||
(*current_sched_info->init_ready_list) (&ready);
|
||||
|
||||
if (targetm.sched.md_init)
|
||||
targetm.sched.md_init (sched_dump, sched_verbose, ready.veclen);
|
||||
|
||||
|
@ -1899,10 +1973,16 @@ schedule_block (int b, int rgn_n_insns)
|
|||
|
||||
insn_queue = alloca ((max_insn_queue_index + 1) * sizeof (rtx));
|
||||
memset (insn_queue, 0, (max_insn_queue_index + 1) * sizeof (rtx));
|
||||
last_clock_var = -1;
|
||||
|
||||
/* Start just before the beginning of time. */
|
||||
clock_var = -1;
|
||||
|
||||
/* We need queue and ready lists and clock_var be initialized
|
||||
in try_ready () (which is called through init_ready_list ()). */
|
||||
(*current_sched_info->init_ready_list) ();
|
||||
|
||||
last_clock_var = -1;
|
||||
|
||||
advance = 0;
|
||||
|
||||
sort_p = TRUE;
|
||||
|
@ -2002,9 +2082,20 @@ schedule_block (int b, int rgn_n_insns)
|
|||
&& targetm.sched.dfa_new_cycle (sched_dump, sched_verbose,
|
||||
insn, last_clock_var,
|
||||
clock_var, &sort_p))
|
||||
/* SORT_P is used by the target to override sorting
|
||||
of the ready list. This is needed when the target
|
||||
has modified its internal structures expecting that
|
||||
the insn will be issued next. As we need the insn
|
||||
to have the highest priority (so it will be returned by
|
||||
the ready_remove_first call above), we invoke
|
||||
ready_add (&ready, insn, true).
|
||||
But, still, there is one issue: INSN can be later
|
||||
discarded by scheduler's front end through
|
||||
current_sched_info->can_schedule_ready_p, hence, won't
|
||||
be issued next. */
|
||||
{
|
||||
ready_add (&ready, insn);
|
||||
break;
|
||||
ready_add (&ready, insn, true);
|
||||
break;
|
||||
}
|
||||
|
||||
sort_p = TRUE;
|
||||
|
@ -2051,8 +2142,10 @@ schedule_block (int b, int rgn_n_insns)
|
|||
last_scheduled_insn = move_insn (insn, last_scheduled_insn);
|
||||
|
||||
if (memcmp (curr_state, temp_state, dfa_state_size) != 0)
|
||||
cycle_issued_insns++;
|
||||
memcpy (curr_state, temp_state, dfa_state_size);
|
||||
{
|
||||
cycle_issued_insns++;
|
||||
memcpy (curr_state, temp_state, dfa_state_size);
|
||||
}
|
||||
|
||||
if (targetm.sched.variable_issue)
|
||||
can_issue_more =
|
||||
|
@ -2064,7 +2157,7 @@ schedule_block (int b, int rgn_n_insns)
|
|||
&& GET_CODE (PATTERN (insn)) != CLOBBER)
|
||||
can_issue_more--;
|
||||
|
||||
advance = schedule_insn (insn, &ready, clock_var);
|
||||
advance = schedule_insn (insn);
|
||||
|
||||
/* After issuing an asm insn we should start a new cycle. */
|
||||
if (advance == 0 && asm_p)
|
||||
|
@ -2094,9 +2187,6 @@ schedule_block (int b, int rgn_n_insns)
|
|||
}
|
||||
}
|
||||
|
||||
if (targetm.sched.md_finish)
|
||||
targetm.sched.md_finish (sched_dump, sched_verbose);
|
||||
|
||||
/* Debug info. */
|
||||
if (sched_verbose)
|
||||
{
|
||||
|
@ -2104,17 +2194,24 @@ schedule_block (int b, int rgn_n_insns)
|
|||
debug_ready_list (&ready);
|
||||
}
|
||||
|
||||
/* Sanity check -- queue must be empty now. Meaningless if region has
|
||||
multiple bbs. */
|
||||
gcc_assert (!current_sched_info->queue_must_finish_empty || !q_size);
|
||||
|
||||
/* Update head/tail boundaries. */
|
||||
head = NEXT_INSN (prev_head);
|
||||
tail = last_scheduled_insn;
|
||||
|
||||
if (!reload_completed)
|
||||
if (current_sched_info->queue_must_finish_empty)
|
||||
/* Sanity check -- queue must be empty now. Meaningless if region has
|
||||
multiple bbs. */
|
||||
gcc_assert (!q_size && !ready.n_ready);
|
||||
else
|
||||
{
|
||||
rtx insn, link, next;
|
||||
/* We must maintain QUEUE_INDEX between blocks in region. */
|
||||
for (i = ready.n_ready - 1; i >= 0; i--)
|
||||
QUEUE_INDEX (ready_element (&ready, i)) = QUEUE_NOWHERE;
|
||||
|
||||
if (q_size)
|
||||
for (i = 0; i <= max_insn_queue_index; i++)
|
||||
{
|
||||
rtx link;
|
||||
for (link = insn_queue[i]; link; link = XEXP (link, 1))
|
||||
QUEUE_INDEX (XEXP (link, 0)) = QUEUE_NOWHERE;
|
||||
free_INSN_LIST_list (&insn_queue[i]);
|
||||
}
|
||||
|
||||
/* INSN_TICK (minimum clock tick at which the insn becomes
|
||||
ready) may be not correct for the insn in the subsequent
|
||||
|
@ -2122,17 +2219,16 @@ schedule_block (int b, int rgn_n_insns)
|
|||
`clock_var' or modify INSN_TICK. It is better to keep
|
||||
clock_var value equal to 0 at the start of a basic block.
|
||||
Therefore we modify INSN_TICK here. */
|
||||
for (insn = head; insn != tail; insn = NEXT_INSN (insn))
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1))
|
||||
{
|
||||
next = XEXP (link, 0);
|
||||
INSN_TICK (next) -= clock_var;
|
||||
}
|
||||
}
|
||||
fix_inter_tick (NEXT_INSN (prev_head), last_scheduled_insn);
|
||||
}
|
||||
|
||||
if (targetm.sched.md_finish)
|
||||
targetm.sched.md_finish (sched_dump, sched_verbose);
|
||||
|
||||
/* Update head/tail boundaries. */
|
||||
head = NEXT_INSN (prev_head);
|
||||
tail = last_scheduled_insn;
|
||||
|
||||
/* Restore-other-notes: NOTE_LIST is the end of a chain of notes
|
||||
previously found among the insns. Insert them at the beginning
|
||||
of the insns. */
|
||||
|
@ -2183,16 +2279,15 @@ set_priorities (rtx head, rtx tail)
|
|||
current_sched_info->sched_max_insns_priority;
|
||||
rtx prev_head;
|
||||
|
||||
prev_head = PREV_INSN (head);
|
||||
|
||||
if (head == tail && (! INSN_P (head)))
|
||||
return 0;
|
||||
|
||||
n_insn = 0;
|
||||
sched_max_insns_priority = 0;
|
||||
|
||||
prev_head = PREV_INSN (head);
|
||||
for (insn = tail; insn != prev_head; insn = PREV_INSN (insn))
|
||||
{
|
||||
if (NOTE_P (insn))
|
||||
if (!INSN_P (insn))
|
||||
continue;
|
||||
|
||||
n_insn++;
|
||||
|
@ -2202,9 +2297,8 @@ set_priorities (rtx head, rtx tail)
|
|||
sched_max_insns_priority =
|
||||
MAX (sched_max_insns_priority, INSN_PRIORITY (insn));
|
||||
}
|
||||
sched_max_insns_priority += 1;
|
||||
current_sched_info->sched_max_insns_priority =
|
||||
sched_max_insns_priority;
|
||||
|
||||
current_sched_info->sched_max_insns_priority = sched_max_insns_priority;
|
||||
|
||||
return n_insn;
|
||||
}
|
||||
|
@ -2253,7 +2347,12 @@ sched_init (void)
|
|||
h_i_d = XCNEWVEC (struct haifa_insn_data, old_max_uid);
|
||||
|
||||
for (i = 0; i < old_max_uid; i++)
|
||||
h_i_d [i].cost = -1;
|
||||
{
|
||||
h_i_d[i].cost = -1;
|
||||
h_i_d[i].queue_index = QUEUE_NOWHERE;
|
||||
h_i_d[i].tick = INVALID_TICK;
|
||||
h_i_d[i].inter_tick = INVALID_TICK;
|
||||
}
|
||||
|
||||
if (targetm.sched.init_dfa_pre_cycle_insn)
|
||||
targetm.sched.init_dfa_pre_cycle_insn ();
|
||||
|
@ -2320,8 +2419,7 @@ sched_init (void)
|
|||
}
|
||||
}
|
||||
|
||||
/* ??? Add a NOTE after the last insn of the last basic block. It is not
|
||||
known why this is done. */
|
||||
/* The following is done to keep current_sched_info->next_tail non null. */
|
||||
|
||||
insn = BB_END (EXIT_BLOCK_PTR->prev_bb);
|
||||
if (NEXT_INSN (insn) == 0
|
||||
|
@ -2330,9 +2428,9 @@ sched_init (void)
|
|||
/* Don't emit a NOTE if it would end up before a BARRIER. */
|
||||
&& !BARRIER_P (NEXT_INSN (insn))))
|
||||
{
|
||||
emit_note_after (NOTE_INSN_DELETED, BB_END (EXIT_BLOCK_PTR->prev_bb));
|
||||
emit_note_after (NOTE_INSN_DELETED, insn);
|
||||
/* Make insn to appear outside BB. */
|
||||
BB_END (EXIT_BLOCK_PTR->prev_bb) = PREV_INSN (BB_END (EXIT_BLOCK_PTR->prev_bb));
|
||||
BB_END (EXIT_BLOCK_PTR->prev_bb) = insn;
|
||||
}
|
||||
|
||||
/* Compute INSN_REG_WEIGHT for all blocks. We must do this before
|
||||
|
@ -2362,4 +2460,208 @@ sched_finish (void)
|
|||
|
||||
current_sched_info = NULL;
|
||||
}
|
||||
|
||||
/* Fix INSN_TICKs of the instructions in the current block as well as
|
||||
INSN_TICKs of their dependants.
|
||||
HEAD and TAIL are the begin and the end of the current scheduled block. */
|
||||
static void
|
||||
fix_inter_tick (rtx head, rtx tail)
|
||||
{
|
||||
/* Set of instructions with corrected INSN_TICK. */
|
||||
bitmap_head processed;
|
||||
int next_clock = clock_var + 1;
|
||||
|
||||
bitmap_initialize (&processed, 0);
|
||||
|
||||
/* Iterates over scheduled instructions and fix their INSN_TICKs and
|
||||
INSN_TICKs of dependent instructions, so that INSN_TICKs are consistent
|
||||
across different blocks. */
|
||||
for (tail = NEXT_INSN (tail); head != tail; head = NEXT_INSN (head))
|
||||
{
|
||||
if (INSN_P (head))
|
||||
{
|
||||
int tick;
|
||||
rtx link;
|
||||
|
||||
tick = INSN_TICK (head);
|
||||
gcc_assert (tick >= MIN_TICK);
|
||||
|
||||
/* Fix INSN_TICK of instruction from just scheduled block. */
|
||||
if (!bitmap_bit_p (&processed, INSN_LUID (head)))
|
||||
{
|
||||
bitmap_set_bit (&processed, INSN_LUID (head));
|
||||
tick -= next_clock;
|
||||
|
||||
if (tick < MIN_TICK)
|
||||
tick = MIN_TICK;
|
||||
|
||||
INSN_TICK (head) = tick;
|
||||
}
|
||||
|
||||
for (link = INSN_DEPEND (head); link; link = XEXP (link, 1))
|
||||
{
|
||||
rtx next;
|
||||
|
||||
next = XEXP (link, 0);
|
||||
tick = INSN_TICK (next);
|
||||
|
||||
if (tick != INVALID_TICK
|
||||
/* If NEXT has its INSN_TICK calculated, fix it.
|
||||
If not - it will be properly calculated from
|
||||
scratch later in fix_tick_ready. */
|
||||
&& !bitmap_bit_p (&processed, INSN_LUID (next)))
|
||||
{
|
||||
bitmap_set_bit (&processed, INSN_LUID (next));
|
||||
tick -= next_clock;
|
||||
|
||||
if (tick < MIN_TICK)
|
||||
tick = MIN_TICK;
|
||||
|
||||
if (tick > INTER_TICK (next))
|
||||
INTER_TICK (next) = tick;
|
||||
else
|
||||
tick = INTER_TICK (next);
|
||||
|
||||
INSN_TICK (next) = tick;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bitmap_clear (&processed);
|
||||
}
|
||||
|
||||
/* Check if NEXT is ready to be added to the ready or queue list.
|
||||
If "yes", add it to the proper list.
|
||||
Returns:
|
||||
-1 - is not ready yet,
|
||||
0 - added to the ready list,
|
||||
0 < N - queued for N cycles. */
|
||||
int
|
||||
try_ready (rtx next)
|
||||
{
|
||||
if (LOG_LINKS (next)
|
||||
|| (current_sched_info->new_ready
|
||||
&& !current_sched_info->new_ready (next)))
|
||||
{
|
||||
gcc_assert (QUEUE_INDEX (next) == QUEUE_NOWHERE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sched_verbose >= 2)
|
||||
fprintf (sched_dump, ";;\t\tdependencies resolved: insn %s\n",
|
||||
(*current_sched_info->print_insn) (next, 0));
|
||||
|
||||
adjust_priority (next);
|
||||
|
||||
return fix_tick_ready (next);
|
||||
}
|
||||
|
||||
/* Calculate INSN_TICK of NEXT and add it to either ready or queue list. */
|
||||
static int
|
||||
fix_tick_ready (rtx next)
|
||||
{
|
||||
rtx link;
|
||||
int tick, delay;
|
||||
|
||||
link = RESOLVED_DEPS (next);
|
||||
|
||||
if (link)
|
||||
{
|
||||
int full_p;
|
||||
|
||||
tick = INSN_TICK (next);
|
||||
/* if tick is note equals to INVALID_TICK, then update
|
||||
INSN_TICK of NEXT with the most recent resolved dependence
|
||||
cost. Overwise, recalculate from scratch. */
|
||||
full_p = tick == INVALID_TICK;
|
||||
do
|
||||
{
|
||||
rtx pro;
|
||||
int tick1;
|
||||
|
||||
pro = XEXP (link, 0);
|
||||
gcc_assert (INSN_TICK (pro) >= MIN_TICK);
|
||||
/* We should specify FORWARD link to insn_cost,
|
||||
but are giving a BACKWARD one.
|
||||
This is ok, because only REG_NOTE_KIND of link is used.
|
||||
May be substitute LINK with REG_NOTE_KIND? */
|
||||
tick1 = INSN_TICK (pro) + insn_cost (pro, link, next);
|
||||
if (tick1 > tick)
|
||||
tick = tick1;
|
||||
}
|
||||
while ((link = XEXP (link, 1)) && full_p);
|
||||
}
|
||||
else
|
||||
tick = -1;
|
||||
|
||||
INSN_TICK (next) = tick;
|
||||
|
||||
delay = tick - clock_var;
|
||||
if (delay <= 0)
|
||||
delay = QUEUE_READY;
|
||||
|
||||
change_queue_index (next, delay);
|
||||
|
||||
return delay;
|
||||
}
|
||||
|
||||
/* Move NEXT to the proper queue list with (DELAY >= 1),
|
||||
or add it to the ready list (DELAY == QUEUE_READY),
|
||||
or remove it from ready and queue lists at all (DELAY == QUEUE_NOWHERE). */
|
||||
static void
|
||||
change_queue_index (rtx next, int delay)
|
||||
{
|
||||
int i = QUEUE_INDEX (next);
|
||||
|
||||
gcc_assert (QUEUE_NOWHERE <= delay && delay <= max_insn_queue_index
|
||||
&& delay != 0);
|
||||
gcc_assert (i != QUEUE_SCHEDULED);
|
||||
|
||||
if ((delay > 0 && NEXT_Q_AFTER (q_ptr, delay) == i)
|
||||
|| (delay < 0 && delay == i))
|
||||
/* We have nothing to do. */
|
||||
return;
|
||||
|
||||
/* Remove NEXT from whereever it is now. */
|
||||
if (i == QUEUE_READY)
|
||||
ready_remove_insn (next);
|
||||
else if (i >= 0)
|
||||
queue_remove (next);
|
||||
|
||||
/* Add it to the proper place. */
|
||||
if (delay == QUEUE_READY)
|
||||
ready_add (readyp, next, false);
|
||||
else if (delay >= 1)
|
||||
queue_insn (next, delay);
|
||||
|
||||
if (sched_verbose >= 2)
|
||||
{
|
||||
fprintf (sched_dump, ";;\t\ttick updated: insn %s",
|
||||
(*current_sched_info->print_insn) (next, 0));
|
||||
|
||||
if (delay == QUEUE_READY)
|
||||
fprintf (sched_dump, " into ready\n");
|
||||
else if (delay >= 1)
|
||||
fprintf (sched_dump, " into queue with cost=%d\n", delay);
|
||||
else
|
||||
fprintf (sched_dump, " removed from ready or queue lists\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* INSN is being scheduled. Resolve the dependence between INSN and NEXT. */
|
||||
static void
|
||||
resolve_dep (rtx next, rtx insn)
|
||||
{
|
||||
rtx dep;
|
||||
|
||||
INSN_DEP_COUNT (next)--;
|
||||
|
||||
dep = remove_list_elem (insn, &LOG_LINKS (next));
|
||||
XEXP (dep, 1) = RESOLVED_DEPS (next);
|
||||
RESOLVED_DEPS (next) = dep;
|
||||
|
||||
gcc_assert ((INSN_DEP_COUNT (next) != 0 || !LOG_LINKS (next))
|
||||
&& (LOG_LINKS (next) || INSN_DEP_COUNT (next) == 0));
|
||||
}
|
||||
|
||||
#endif /* INSN_SCHEDULING */
|
||||
|
|
10
gcc/lists.c
10
gcc/lists.c
|
@ -98,7 +98,7 @@ remove_list_node (rtx *listp)
|
|||
|
||||
/* Removes corresponding to ELEM node from the list pointed to by LISTP.
|
||||
Returns that node. */
|
||||
static rtx
|
||||
rtx
|
||||
remove_list_elem (rtx elem, rtx *listp)
|
||||
{
|
||||
rtx node;
|
||||
|
@ -241,4 +241,12 @@ remove_free_DEPS_LIST_elem (rtx elem, rtx *listp)
|
|||
free_DEPS_LIST_node (remove_list_elem (elem, listp));
|
||||
}
|
||||
|
||||
/* Remove and free corresponding to ELEM node in the INSN_LIST pointed to
|
||||
by LISTP. */
|
||||
void
|
||||
remove_free_INSN_LIST_elem (rtx elem, rtx *listp)
|
||||
{
|
||||
free_INSN_LIST_node (remove_list_elem (elem, listp));
|
||||
}
|
||||
|
||||
#include "gt-lists.h"
|
||||
|
|
|
@ -1756,6 +1756,8 @@ rtx alloc_EXPR_LIST (int, rtx, rtx);
|
|||
void free_DEPS_LIST_list (rtx *);
|
||||
rtx alloc_DEPS_LIST (rtx, rtx, HOST_WIDE_INT);
|
||||
void remove_free_DEPS_LIST_elem (rtx, rtx *);
|
||||
void remove_free_INSN_LIST_elem (rtx, rtx *);
|
||||
rtx remove_list_elem (rtx, rtx *);
|
||||
|
||||
/* regclass.c */
|
||||
|
||||
|
|
|
@ -49,9 +49,8 @@ static int target_n_insns;
|
|||
static int sched_n_insns;
|
||||
|
||||
/* Implementations of the sched_info functions for region scheduling. */
|
||||
static void init_ready_list (struct ready_list *);
|
||||
static void init_ready_list (void);
|
||||
static int can_schedule_ready_p (rtx);
|
||||
static int new_ready (rtx);
|
||||
static int schedule_more_p (void);
|
||||
static const char *ebb_print_insn (rtx, int);
|
||||
static int rank (rtx, rtx);
|
||||
|
@ -76,7 +75,7 @@ schedule_more_p (void)
|
|||
once before scheduling a set of insns. */
|
||||
|
||||
static void
|
||||
init_ready_list (struct ready_list *ready)
|
||||
init_ready_list (void)
|
||||
{
|
||||
rtx prev_head = current_sched_info->prev_head;
|
||||
rtx next_tail = current_sched_info->next_tail;
|
||||
|
@ -95,8 +94,7 @@ init_ready_list (struct ready_list *ready)
|
|||
Count number of insns in the target block being scheduled. */
|
||||
for (insn = NEXT_INSN (prev_head); insn != next_tail; insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (INSN_DEP_COUNT (insn) == 0)
|
||||
ready_add (ready, insn);
|
||||
try_ready (insn);
|
||||
target_n_insns++;
|
||||
}
|
||||
}
|
||||
|
@ -111,15 +109,6 @@ can_schedule_ready_p (rtx insn ATTRIBUTE_UNUSED)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Called after INSN has all its dependencies resolved. Return nonzero
|
||||
if it should be moved to the ready list or the queue, or zero if we
|
||||
should silently discard it. */
|
||||
static int
|
||||
new_ready (rtx next ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return a string that contains the insn uid and optionally anything else
|
||||
necessary to identify this insn in an output. It's valid to use a
|
||||
static buffer for this. The ALIGNED parameter should cause the string
|
||||
|
@ -197,7 +186,7 @@ static struct sched_info ebb_sched_info =
|
|||
init_ready_list,
|
||||
can_schedule_ready_p,
|
||||
schedule_more_p,
|
||||
new_ready,
|
||||
NULL,
|
||||
rank,
|
||||
ebb_print_insn,
|
||||
contributes_to_priority,
|
||||
|
@ -524,7 +513,9 @@ schedule_ebb (rtx head, rtx tail)
|
|||
targetm.sched.dependencies_evaluation_hook (head, tail);
|
||||
|
||||
/* Set priorities. */
|
||||
current_sched_info->sched_max_insns_priority = 0;
|
||||
n_insns = set_priorities (head, tail);
|
||||
current_sched_info->sched_max_insns_priority++;
|
||||
|
||||
current_sched_info->prev_head = PREV_INSN (head);
|
||||
current_sched_info->next_tail = NEXT_INSN (tail);
|
||||
|
|
|
@ -142,7 +142,7 @@ struct sched_info
|
|||
{
|
||||
/* Add all insns that are initially ready to the ready list. Called once
|
||||
before scheduling a set of insns. */
|
||||
void (*init_ready_list) (struct ready_list *);
|
||||
void (*init_ready_list) (void);
|
||||
/* Called after taking an insn from the ready list. Returns nonzero if
|
||||
this insn can be scheduled, nonzero if we should silently discard it. */
|
||||
int (*can_schedule_ready_p) (rtx);
|
||||
|
@ -203,6 +203,10 @@ struct haifa_insn_data
|
|||
it represents forward dependencies. */
|
||||
rtx depend;
|
||||
|
||||
/* A list of scheduled producers of the instruction. Links are being moved
|
||||
from LOG_LINKS to RESOLVED_DEPS during scheduling. */
|
||||
rtx resolved_deps;
|
||||
|
||||
/* The line number note in effect for each insn. For line number
|
||||
notes, this indicates whether the note may be reused. */
|
||||
rtx line_note;
|
||||
|
@ -225,6 +229,13 @@ struct haifa_insn_data
|
|||
used to note timing constraints for the insns in the pending list. */
|
||||
int tick;
|
||||
|
||||
/* INTER_TICK is used to adjust INSN_TICKs of instructions from the
|
||||
subsequent blocks in a region. */
|
||||
int inter_tick;
|
||||
|
||||
/* See comment on QUEUE_INDEX macro in haifa-sched.c. */
|
||||
int queue_index;
|
||||
|
||||
short cost;
|
||||
|
||||
/* This weight is an estimation of the insn's contribution to
|
||||
|
@ -252,6 +263,7 @@ extern struct haifa_insn_data *h_i_d;
|
|||
/* Accessor macros for h_i_d. There are more in haifa-sched.c and
|
||||
sched-rgn.c. */
|
||||
#define INSN_DEPEND(INSN) (h_i_d[INSN_UID (INSN)].depend)
|
||||
#define RESOLVED_DEPS(INSN) (h_i_d[INSN_UID (INSN)].resolved_deps)
|
||||
#define INSN_LUID(INSN) (h_i_d[INSN_UID (INSN)].luid)
|
||||
#define CANT_MOVE(insn) (h_i_d[INSN_UID (insn)].cant_move)
|
||||
#define INSN_DEP_COUNT(INSN) (h_i_d[INSN_UID (INSN)].dep_count)
|
||||
|
@ -513,6 +525,6 @@ extern void schedule_block (int, int);
|
|||
extern void sched_init (void);
|
||||
extern void sched_finish (void);
|
||||
|
||||
extern void ready_add (struct ready_list *, rtx);
|
||||
extern int try_ready (rtx);
|
||||
|
||||
#endif /* GCC_SCHED_INT_H */
|
||||
|
|
|
@ -1884,7 +1884,7 @@ static int sched_n_insns;
|
|||
static int last_was_jump;
|
||||
|
||||
/* Implementations of the sched_info functions for region scheduling. */
|
||||
static void init_ready_list (struct ready_list *);
|
||||
static void init_ready_list (void);
|
||||
static int can_schedule_ready_p (rtx);
|
||||
static int new_ready (rtx);
|
||||
static int schedule_more_p (void);
|
||||
|
@ -1905,7 +1905,7 @@ schedule_more_p (void)
|
|||
once before scheduling a set of insns. */
|
||||
|
||||
static void
|
||||
init_ready_list (struct ready_list *ready)
|
||||
init_ready_list (void)
|
||||
{
|
||||
rtx prev_head = current_sched_info->prev_head;
|
||||
rtx next_tail = current_sched_info->next_tail;
|
||||
|
@ -1943,15 +1943,8 @@ init_ready_list (struct ready_list *ready)
|
|||
/* Initialize ready list with all 'ready' insns in target block.
|
||||
Count number of insns in the target block being scheduled. */
|
||||
for (insn = NEXT_INSN (prev_head); insn != next_tail; insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (INSN_DEP_COUNT (insn) == 0)
|
||||
{
|
||||
ready_add (ready, insn);
|
||||
|
||||
if (targetm.sched.adjust_priority)
|
||||
INSN_PRIORITY (insn) =
|
||||
targetm.sched.adjust_priority (insn, INSN_PRIORITY (insn));
|
||||
}
|
||||
{
|
||||
try_ready (insn);
|
||||
target_n_insns++;
|
||||
}
|
||||
|
||||
|
@ -1970,26 +1963,8 @@ init_ready_list (struct ready_list *ready)
|
|||
src_head = head;
|
||||
|
||||
for (insn = src_head; insn != src_next_tail; insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (! INSN_P (insn))
|
||||
continue;
|
||||
|
||||
if (!CANT_MOVE (insn)
|
||||
&& (!IS_SPECULATIVE_INSN (insn)
|
||||
|| ((recog_memoized (insn) < 0
|
||||
|| min_insn_conflict_delay (curr_state,
|
||||
insn, insn) <= 3)
|
||||
&& check_live (insn, bb_src)
|
||||
&& is_exception_free (insn, bb_src, target_bb))))
|
||||
if (INSN_DEP_COUNT (insn) == 0)
|
||||
{
|
||||
ready_add (ready, insn);
|
||||
|
||||
if (targetm.sched.adjust_priority)
|
||||
INSN_PRIORITY (insn) =
|
||||
targetm.sched.adjust_priority (insn, INSN_PRIORITY (insn));
|
||||
}
|
||||
}
|
||||
if (INSN_P (insn))
|
||||
try_ready (insn);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2638,6 +2613,7 @@ schedule_region (int rgn)
|
|||
}
|
||||
|
||||
/* Set priorities. */
|
||||
current_sched_info->sched_max_insns_priority = 0;
|
||||
for (bb = 0; bb < current_nr_blocks; bb++)
|
||||
{
|
||||
rtx head, tail;
|
||||
|
@ -2645,6 +2621,7 @@ schedule_region (int rgn)
|
|||
|
||||
rgn_n_insns += set_priorities (head, tail);
|
||||
}
|
||||
current_sched_info->sched_max_insns_priority++;
|
||||
|
||||
/* Compute interblock info: probabilities, split-edges, dominators, etc. */
|
||||
if (current_nr_blocks > 1)
|
||||
|
@ -2727,8 +2704,8 @@ schedule_region (int rgn)
|
|||
|
||||
target_bb = bb;
|
||||
|
||||
current_sched_info->queue_must_finish_empty
|
||||
= current_nr_blocks > 1 && !flag_schedule_interblock;
|
||||
gcc_assert (flag_schedule_interblock || current_nr_blocks == 1);
|
||||
current_sched_info->queue_must_finish_empty = current_nr_blocks == 1;
|
||||
|
||||
schedule_block (b, rgn_n_insns);
|
||||
sched_rgn_n_insns += sched_n_insns;
|
||||
|
|
Loading…
Reference in New Issue