Fix the direction of the scheduling window & Fix scheduling order within a row
From-SVN: r130567
This commit is contained in:
parent
083f0d3a04
commit
d48b46e04d
5 changed files with 270 additions and 51 deletions
|
@ -1,3 +1,19 @@
|
|||
2007-12-02 Ayal Zaks <zaks@il.ibm.com>
|
||||
Revital Eres <eres@il.ibm.com>
|
||||
|
||||
* modulo-sched.c (calculate_must_precede_follow,
|
||||
try_scheduling_node_in_cycle): New functions.
|
||||
(sms_schedule_by_order): Call the new functions.
|
||||
(ps_insn_find_column): Use must_follow and must_precede only if
|
||||
they are not NULL.
|
||||
(ps_insn_advance_column): Likewise.
|
||||
|
||||
2007-12-02 Ayal Zaks <zaks@il.ibm.com>
|
||||
Revital Eres <eres@il.ibm.com>
|
||||
|
||||
* modulo-sched.c (get_sched_window): Fix the direction of the
|
||||
scheduling window and add dump info.
|
||||
|
||||
2007-12-02 Samuel Tardieu <sam@rfc1149.net>
|
||||
|
||||
* config/sh/sh.md (cmpgeusi_t): Fix condition.
|
||||
|
|
|
@ -1343,8 +1343,9 @@ get_sched_window (partial_schedule_ptr ps, int *nodes_order, int i,
|
|||
MAX (early_start, p_st + e->latency - (e->distance * ii));
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "pred st = %d; early_start = %d; ", p_st,
|
||||
early_start);
|
||||
fprintf (dump_file,
|
||||
"pred st = %d; early_start = %d; latency: %d",
|
||||
p_st, early_start, e->latency);
|
||||
|
||||
if (e->data_type == MEM_DEP)
|
||||
end = MIN (end, SCHED_TIME (v_node) + ii - 1);
|
||||
|
@ -1354,6 +1355,7 @@ get_sched_window (partial_schedule_ptr ps, int *nodes_order, int i,
|
|||
}
|
||||
start = early_start;
|
||||
end = MIN (end, early_start + ii);
|
||||
/* Schedule the node close to it's predecessors. */
|
||||
step = 1;
|
||||
|
||||
if (dump_file)
|
||||
|
@ -1390,8 +1392,9 @@ get_sched_window (partial_schedule_ptr ps, int *nodes_order, int i,
|
|||
s_st - e->latency + (e->distance * ii));
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "succ st = %d; late_start = %d;", s_st,
|
||||
late_start);
|
||||
fprintf (dump_file,
|
||||
"succ st = %d; late_start = %d; latency = %d",
|
||||
s_st, late_start, e->latency);
|
||||
|
||||
if (e->data_type == MEM_DEP)
|
||||
end = MAX (end, SCHED_TIME (v_node) - ii + 1);
|
||||
|
@ -1405,6 +1408,7 @@ get_sched_window (partial_schedule_ptr ps, int *nodes_order, int i,
|
|||
}
|
||||
start = late_start;
|
||||
end = MAX (end, late_start - ii);
|
||||
/* Schedule the node close to it's successors. */
|
||||
step = -1;
|
||||
|
||||
if (dump_file)
|
||||
|
@ -1418,6 +1422,8 @@ get_sched_window (partial_schedule_ptr ps, int *nodes_order, int i,
|
|||
{
|
||||
int early_start = INT_MIN;
|
||||
int late_start = INT_MAX;
|
||||
int count_preds = 0;
|
||||
int count_succs = 0;
|
||||
|
||||
start = INT_MIN;
|
||||
end = INT_MAX;
|
||||
|
@ -1445,8 +1451,12 @@ get_sched_window (partial_schedule_ptr ps, int *nodes_order, int i,
|
|||
- (e->distance * ii));
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "pred st = %d; early_start = %d;", p_st,
|
||||
early_start);
|
||||
fprintf (dump_file,
|
||||
"pred st = %d; early_start = %d; latency = %d",
|
||||
p_st, early_start, e->latency);
|
||||
|
||||
if (e->type == TRUE_DEP && e->data_type == REG_DEP)
|
||||
count_preds++;
|
||||
|
||||
if (e->data_type == MEM_DEP)
|
||||
end = MIN (end, SCHED_TIME (v_node) + ii - 1);
|
||||
|
@ -1478,9 +1488,13 @@ get_sched_window (partial_schedule_ptr ps, int *nodes_order, int i,
|
|||
s_st - e->latency
|
||||
+ (e->distance * ii));
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "succ st = %d; late_start = %d;", s_st,
|
||||
late_start);
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"succ st = %d; late_start = %d; latency = %d",
|
||||
s_st, late_start, e->latency);
|
||||
|
||||
if (e->type == TRUE_DEP && e->data_type == REG_DEP)
|
||||
count_succs++;
|
||||
|
||||
if (e->data_type == MEM_DEP)
|
||||
start = MAX (start, SCHED_TIME (v_node) - ii + 1);
|
||||
|
@ -1492,6 +1506,16 @@ get_sched_window (partial_schedule_ptr ps, int *nodes_order, int i,
|
|||
start = MAX (start, early_start);
|
||||
end = MIN (end, MIN (early_start + ii, late_start + 1));
|
||||
step = 1;
|
||||
/* If there are more successors than predecessors schedule the
|
||||
node close to it's successors. */
|
||||
if (count_succs >= count_preds)
|
||||
{
|
||||
int old_start = start;
|
||||
|
||||
start = end - 1;
|
||||
end = old_start - 1;
|
||||
step = -1;
|
||||
}
|
||||
}
|
||||
else /* psp is empty && pss is empty. */
|
||||
{
|
||||
|
@ -1517,6 +1541,114 @@ get_sched_window (partial_schedule_ptr ps, int *nodes_order, int i,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate MUST_PRECEDE/MUST_FOLLOW bitmaps of U_NODE; which is the
|
||||
node currently been scheduled. At the end of the calculation
|
||||
MUST_PRECEDE/MUST_FOLLOW contains all predecessors/successors of U_NODE
|
||||
which are in SCHED_NODES (already scheduled nodes) and scheduled at
|
||||
the same row as the first/last row of U_NODE's scheduling window.
|
||||
The first and last rows are calculated using the following paramaters:
|
||||
START/END rows - The cycles that begins/ends the traversal on the window;
|
||||
searching for an empty cycle to schedule U_NODE.
|
||||
STEP - The direction in which we traverse the window.
|
||||
II - The initiation interval.
|
||||
TODO: We can add an insn to the must_precede/must_follow bitmap only
|
||||
if it has tight dependence to U and they are both scheduled in the
|
||||
same row. The current check is more conservative and content with
|
||||
the fact that both U and the insn are scheduled in the same row. */
|
||||
|
||||
static void
|
||||
calculate_must_precede_follow (ddg_node_ptr u_node, int start, int end,
|
||||
int step, int ii, sbitmap sched_nodes,
|
||||
sbitmap must_precede, sbitmap must_follow)
|
||||
{
|
||||
ddg_edge_ptr e;
|
||||
int first_cycle_in_window, last_cycle_in_window;
|
||||
int first_row_in_window, last_row_in_window;
|
||||
|
||||
gcc_assert (must_precede && must_follow);
|
||||
|
||||
/* Consider the following scheduling window:
|
||||
{first_cycle_in_window, first_cycle_in_window+1, ...,
|
||||
last_cycle_in_window}. If step is 1 then the following will be
|
||||
the order we traverse the window: {start=first_cycle_in_window,
|
||||
first_cycle_in_window+1, ..., end=last_cycle_in_window+1},
|
||||
or {start=last_cycle_in_window, last_cycle_in_window-1, ...,
|
||||
end=first_cycle_in_window-1} if step is -1. */
|
||||
first_cycle_in_window = (step == 1) ? start : end - step;
|
||||
last_cycle_in_window = (step == 1) ? end - step : start;
|
||||
|
||||
first_row_in_window = SMODULO (first_cycle_in_window, ii);
|
||||
last_row_in_window = SMODULO (last_cycle_in_window, ii);
|
||||
|
||||
sbitmap_zero (must_precede);
|
||||
sbitmap_zero (must_follow);
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "\nmust_precede: ");
|
||||
|
||||
for (e = u_node->in; e != 0; e = e->next_in)
|
||||
if (TEST_BIT (sched_nodes, e->src->cuid)
|
||||
&& (SMODULO (SCHED_TIME (e->src), ii) == first_row_in_window))
|
||||
{
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "%d ", e->src->cuid);
|
||||
|
||||
SET_BIT (must_precede, e->src->cuid);
|
||||
}
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "\nmust_follow: ");
|
||||
|
||||
for (e = u_node->out; e != 0; e = e->next_out)
|
||||
if (TEST_BIT (sched_nodes, e->dest->cuid)
|
||||
&& (SMODULO (SCHED_TIME (e->dest), ii) == last_row_in_window))
|
||||
{
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "%d ", e->dest->cuid);
|
||||
|
||||
SET_BIT (must_follow, e->dest->cuid);
|
||||
}
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
|
||||
/* Return 1 if U_NODE can be scheduled in CYCLE. Use the following
|
||||
parameters to decide if that's possible:
|
||||
PS - The partial schedule.
|
||||
U - The serial number of U_NODE.
|
||||
NUM_SPLITS - The number of row spilts made so far.
|
||||
MUST_PRECEDE - The nodes that must precede U_NODE. (only valid at
|
||||
the first row of the scheduling window)
|
||||
MUST_FOLLOW - The nodes that must follow U_NODE. (only valid at the
|
||||
last row of the scheduling window) */
|
||||
|
||||
static bool
|
||||
try_scheduling_node_in_cycle (partial_schedule_ptr ps, ddg_node_ptr u_node,
|
||||
int u, int row, sbitmap sched_nodes,
|
||||
int *num_splits, sbitmap must_precede,
|
||||
sbitmap must_follow)
|
||||
{
|
||||
ps_insn_ptr psi;
|
||||
bool success = 0;
|
||||
|
||||
verify_partial_schedule (ps, sched_nodes);
|
||||
psi = ps_add_node_check_conflicts (ps, u_node, row,
|
||||
must_precede, must_follow);
|
||||
if (psi)
|
||||
{
|
||||
SCHED_TIME (u_node) = row;
|
||||
SET_BIT (sched_nodes, u);
|
||||
success = 1;
|
||||
*num_splits = 0;
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Scheduled w/o split in %d\n", row);
|
||||
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/* This function implements the scheduling algorithm for SMS according to the
|
||||
above algorithm. */
|
||||
static partial_schedule_ptr
|
||||
|
@ -1526,8 +1658,6 @@ sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order)
|
|||
int i, c, success, num_splits = 0;
|
||||
int flush_and_start_over = true;
|
||||
int num_nodes = g->num_nodes;
|
||||
ddg_edge_ptr e;
|
||||
ps_insn_ptr psi;
|
||||
int start, end, step; /* Place together into one struct? */
|
||||
sbitmap sched_nodes = sbitmap_alloc (num_nodes);
|
||||
sbitmap must_precede = sbitmap_alloc (num_nodes);
|
||||
|
@ -1577,53 +1707,43 @@ sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order)
|
|||
fprintf (dump_file, "\nTrying to schedule node %d \
|
||||
INSN = %d in (%d .. %d) step %d\n", u, (INSN_UID
|
||||
(g->nodes[u].insn)), start, end, step);
|
||||
/* Use must_follow & must_precede bitmaps to determine order
|
||||
of nodes within the cycle. */
|
||||
|
||||
/* use must_follow & must_precede bitmaps to determine order
|
||||
of nodes within the cycle. */
|
||||
sbitmap_zero (must_precede);
|
||||
sbitmap_zero (must_follow);
|
||||
/* TODO: We can add an insn to the must_precede or must_follow
|
||||
bitmaps only if it has tight dependence to U and they
|
||||
both scheduled in the same row. The current check is less
|
||||
conservative and content with the fact that both U and the
|
||||
insn are scheduled in the same row. */
|
||||
for (e = u_node->in; e != 0; e = e->next_in)
|
||||
if (TEST_BIT (sched_nodes, e->src->cuid)
|
||||
&& (SMODULO (SCHED_TIME (e->src), ii) ==
|
||||
SMODULO (start, ii)))
|
||||
SET_BIT (must_precede, e->src->cuid);
|
||||
|
||||
for (e = u_node->out; e != 0; e = e->next_out)
|
||||
if (TEST_BIT (sched_nodes, e->dest->cuid)
|
||||
&& (SMODULO (SCHED_TIME (e->dest), ii) ==
|
||||
SMODULO ((end - step), ii)))
|
||||
SET_BIT (must_follow, e->dest->cuid);
|
||||
|
||||
gcc_assert ((step > 0 && start < end)
|
||||
|| (step < 0 && start > end));
|
||||
|
||||
calculate_must_precede_follow (u_node, start, end, step, ii,
|
||||
sched_nodes, must_precede,
|
||||
must_follow);
|
||||
|
||||
for (c = start; c != end; c += step)
|
||||
{
|
||||
verify_partial_schedule (ps, sched_nodes);
|
||||
sbitmap tmp_precede = NULL;
|
||||
sbitmap tmp_follow = NULL;
|
||||
|
||||
psi = ps_add_node_check_conflicts (ps, u_node, c,
|
||||
must_precede,
|
||||
must_follow);
|
||||
|
||||
if (psi)
|
||||
if (c == start)
|
||||
{
|
||||
SCHED_TIME (u_node) = c;
|
||||
SET_BIT (sched_nodes, u);
|
||||
success = 1;
|
||||
num_splits = 0;
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Scheduled w/o split in %d\n", c);
|
||||
|
||||
break;
|
||||
if (step == 1)
|
||||
tmp_precede = must_precede;
|
||||
else /* step == -1. */
|
||||
tmp_follow = must_follow;
|
||||
}
|
||||
if (c == end - step)
|
||||
{
|
||||
if (step == 1)
|
||||
tmp_follow = must_follow;
|
||||
else /* step == -1. */
|
||||
tmp_precede = must_precede;
|
||||
}
|
||||
|
||||
success =
|
||||
try_scheduling_node_in_cycle (ps, u_node, u, c,
|
||||
sched_nodes,
|
||||
&num_splits, tmp_precede,
|
||||
tmp_follow);
|
||||
if (success)
|
||||
break;
|
||||
}
|
||||
|
||||
verify_partial_schedule (ps, sched_nodes);
|
||||
}
|
||||
if (!success)
|
||||
|
@ -2391,10 +2511,10 @@ ps_insn_find_column (partial_schedule_ptr ps, ps_insn_ptr ps_i,
|
|||
next_ps_i;
|
||||
next_ps_i = next_ps_i->next_in_row)
|
||||
{
|
||||
if (TEST_BIT (must_follow, next_ps_i->node->cuid)
|
||||
if (must_follow && TEST_BIT (must_follow, next_ps_i->node->cuid)
|
||||
&& ! first_must_follow)
|
||||
first_must_follow = next_ps_i;
|
||||
if (TEST_BIT (must_precede, next_ps_i->node->cuid))
|
||||
if (must_precede && TEST_BIT (must_precede, next_ps_i->node->cuid))
|
||||
{
|
||||
/* If we have already met a node that must follow, then
|
||||
there is no possible column. */
|
||||
|
@ -2451,7 +2571,7 @@ ps_insn_advance_column (partial_schedule_ptr ps, ps_insn_ptr ps_i,
|
|||
|
||||
/* Check if next_in_row is dependent on ps_i, both having same sched
|
||||
times (typically ANTI_DEP). If so, ps_i cannot skip over it. */
|
||||
if (TEST_BIT (must_follow, next_node->cuid))
|
||||
if (must_follow && TEST_BIT (must_follow, next_node->cuid))
|
||||
return false;
|
||||
|
||||
/* Advance PS_I over its next_in_row in the doubly linked list. */
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
2007-12-02 Revital Eres <eres@il.ibm.com>
|
||||
|
||||
* gcc.dg/sms-4.c: New testcase.
|
||||
|
||||
2007-12-02 Vladimir Yanovsky <yanov@il.ibm.com>
|
||||
Revital Eres <eres@il.ibm.com>
|
||||
|
||||
* gcc.dg/sms-3.c: New testcase.
|
||||
|
||||
2007-12-01 Ollie Wild <aaw@google.com>
|
||||
|
||||
PR c++/8171
|
||||
|
|
39
gcc/testsuite/gcc.dg/sms-3.c
Normal file
39
gcc/testsuite/gcc.dg/sms-3.c
Normal file
|
@ -0,0 +1,39 @@
|
|||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -fmodulo-sched -funroll-loops" } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
int X[1000]={0};
|
||||
int Y[1000]={0};
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
int
|
||||
foo (int len, long a)
|
||||
{
|
||||
int i;
|
||||
long res = a;
|
||||
|
||||
len = 1000;
|
||||
for (i = 0; i < len; i++)
|
||||
res += X[i]* Y[i];
|
||||
|
||||
if (res != 601)
|
||||
abort ();
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
X[0] = Y[1] = 2;
|
||||
Y[0] = X[1] = 21;
|
||||
X[2] = Y[3] = 3;
|
||||
Y[2] = X[3] = 31;
|
||||
X[4] = Y[5] = 4;
|
||||
Y[4] = X[5] = 41;
|
||||
|
||||
foo (6, 3);
|
||||
return 0;
|
||||
}
|
||||
|
35
gcc/testsuite/gcc.dg/sms-4.c
Normal file
35
gcc/testsuite/gcc.dg/sms-4.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/* Inspired from sbitmap_a_or_b_and_c_cg function in sbitmap.c. */
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2 -fmodulo-sched -fmodulo-sched-allow-regmoves" } */
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
int a[5] = { 0, 1, 0, 0, 0 };
|
||||
int b[5] = { 0, 1, 0, 1, 0 };
|
||||
int c[5] = { 0, 0, 1, 1, 0 };
|
||||
int dst[5] = { 0, 0, 0, 0, 0 };
|
||||
|
||||
void
|
||||
foo (int size, int *ap, int *bp, int *cp, int *dstp)
|
||||
{
|
||||
unsigned int i, n = size;
|
||||
int changed = 0;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
const int tmp = *ap++ | (*bp++ & *cp++);
|
||||
changed |= *dstp ^ tmp;
|
||||
*dstp++ = tmp;
|
||||
}
|
||||
|
||||
if (changed == 0)
|
||||
abort ();
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
foo (5, a, b, c, dst);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue