modulo-sched.c (ps_insn): Adjust comment.

gcc/
	* modulo-sched.c (ps_insn): Adjust comment.
	(ps_reg_move_info): New structure.
	(partial_schedule): Add reg_moves field.
	(SCHED_PARAMS): Use node_sched_param_vec instead of node_sched_params.
	(node_sched_params): Turn first_reg_move into an identifier.
	(ps_reg_move): New function.
	(ps_rtl_insn): Cope with register moves.
	(ps_first_note): Adjust comment and assert that the instruction
	isn't a register move.
	(node_sched_params): Replace with...
	(node_sched_param_vec): ...this vector.
	(set_node_sched_params): Adjust accordingly.
	(print_node_sched_params): Take a partial schedule instead of a ddg.
	Use ps_rtl_insn and ps_reg_move.
	(generate_reg_moves): Rename to...
	(schedule_reg_moves): ...this.  Remove rescan parameter.  Record each
	move in the partial schedule, but don't emit it here.  Don't perform
	register substitutions here either.
	(apply_reg_moves): New function.
	(duplicate_insns_of_cycles): Use register indices directly,
	rather than finding instructions using PREV_INSN.  Use ps_reg_move.
	(sms_schedule): Call schedule_reg_moves before committing to
	a partial schedule.   Try the next ii if the schedule fails.
	Use apply_reg_moves instead of generate_reg_moves.  Adjust
	call to print_node_sched_params.  Free node_sched_param_vec
	instead of node_sched_params.
	(create_partial_schedule): Initialize reg_moves.
	(free_partial_schedule): Free reg_moves.

From-SVN: r179743
This commit is contained in:
Richard Sandiford 2011-10-10 11:42:38 +00:00 committed by Richard Sandiford
parent 88e9c867a9
commit 1287d8ea2c
2 changed files with 241 additions and 124 deletions

View File

@ -1,3 +1,34 @@
2011-10-10 Richard Sandiford <richard.sandiford@linaro.org>
* modulo-sched.c (ps_insn): Adjust comment.
(ps_reg_move_info): New structure.
(partial_schedule): Add reg_moves field.
(SCHED_PARAMS): Use node_sched_param_vec instead of node_sched_params.
(node_sched_params): Turn first_reg_move into an identifier.
(ps_reg_move): New function.
(ps_rtl_insn): Cope with register moves.
(ps_first_note): Adjust comment and assert that the instruction
isn't a register move.
(node_sched_params): Replace with...
(node_sched_param_vec): ...this vector.
(set_node_sched_params): Adjust accordingly.
(print_node_sched_params): Take a partial schedule instead of a ddg.
Use ps_rtl_insn and ps_reg_move.
(generate_reg_moves): Rename to...
(schedule_reg_moves): ...this. Remove rescan parameter. Record each
move in the partial schedule, but don't emit it here. Don't perform
register substitutions here either.
(apply_reg_moves): New function.
(duplicate_insns_of_cycles): Use register indices directly,
rather than finding instructions using PREV_INSN. Use ps_reg_move.
(sms_schedule): Call schedule_reg_moves before committing to
a partial schedule. Try the next ii if the schedule fails.
Use apply_reg_moves instead of generate_reg_moves. Adjust
call to print_node_sched_params. Free node_sched_param_vec
instead of node_sched_params.
(create_partial_schedule): Initialize reg_moves.
(free_partial_schedule): Free reg_moves.
2011-10-10 Richard Sandiford <richard.sandiford@linaro.org> 2011-10-10 Richard Sandiford <richard.sandiford@linaro.org>
* modulo-sched.c (ps_insn): Replace node field with an identifier. * modulo-sched.c (ps_insn): Replace node field with an identifier.

View File

@ -124,7 +124,9 @@ typedef struct ps_insn *ps_insn_ptr;
/* A single instruction in the partial schedule. */ /* A single instruction in the partial schedule. */
struct ps_insn struct ps_insn
{ {
/* The number of the ddg node whose instruction is being scheduled. */ /* Identifies the instruction to be scheduled. Values smaller than
the ddg's num_nodes refer directly to ddg nodes. A value of
X - num_nodes refers to register move X. */
int id; int id;
/* The (absolute) cycle in which the PS instruction is scheduled. /* The (absolute) cycle in which the PS instruction is scheduled.
@ -137,6 +139,30 @@ struct ps_insn
}; };
/* Information about a register move that has been added to a partial
schedule. */
struct ps_reg_move_info
{
/* The source of the move is defined by the ps_insn with id DEF.
The destination is used by the ps_insns with the ids in USES. */
int def;
sbitmap uses;
/* The original form of USES' instructions used OLD_REG, but they
should now use NEW_REG. */
rtx old_reg;
rtx new_reg;
/* An instruction that sets NEW_REG to the correct value. The first
move associated with DEF will have an rhs of OLD_REG; later moves
use the result of the previous move. */
rtx insn;
};
typedef struct ps_reg_move_info ps_reg_move_info;
DEF_VEC_O (ps_reg_move_info);
DEF_VEC_ALLOC_O (ps_reg_move_info, heap);
/* Holds the partial schedule as an array of II rows. Each entry of the /* Holds the partial schedule as an array of II rows. Each entry of the
array points to a linked list of PS_INSNs, which represents the array points to a linked list of PS_INSNs, which represents the
instructions that are scheduled for that row. */ instructions that are scheduled for that row. */
@ -148,6 +174,10 @@ struct partial_schedule
/* rows[i] points to linked list of insns scheduled in row i (0<=i<ii). */ /* rows[i] points to linked list of insns scheduled in row i (0<=i<ii). */
ps_insn_ptr *rows; ps_insn_ptr *rows;
/* All the moves added for this partial schedule. Index X has
a ps_insn id of X + g->num_nodes. */
VEC (ps_reg_move_info, heap) *reg_moves;
/* rows_length[i] holds the number of instructions in the row. /* rows_length[i] holds the number of instructions in the row.
It is used only (as an optimization) to back off quickly from It is used only (as an optimization) to back off quickly from
trying to schedule a node in a full row; that is, to avoid running trying to schedule a node in a full row; that is, to avoid running
@ -201,7 +231,7 @@ static void remove_node_from_ps (partial_schedule_ptr, ps_insn_ptr);
#define NODE_ASAP(node) ((node)->aux.count) #define NODE_ASAP(node) ((node)->aux.count)
#define SCHED_PARAMS(x) (&node_sched_params[x]) #define SCHED_PARAMS(x) VEC_index (node_sched_params, node_sched_param_vec, x)
#define SCHED_TIME(x) (SCHED_PARAMS (x)->time) #define SCHED_TIME(x) (SCHED_PARAMS (x)->time)
#define SCHED_FIRST_REG_MOVE(x) (SCHED_PARAMS (x)->first_reg_move) #define SCHED_FIRST_REG_MOVE(x) (SCHED_PARAMS (x)->first_reg_move)
#define SCHED_NREG_MOVES(x) (SCHED_PARAMS (x)->nreg_moves) #define SCHED_NREG_MOVES(x) (SCHED_PARAMS (x)->nreg_moves)
@ -214,14 +244,13 @@ typedef struct node_sched_params
{ {
int time; /* The absolute scheduling cycle. */ int time; /* The absolute scheduling cycle. */
/* The following field (first_reg_move) is a pointer to the first /* The following field (first_reg_move) is the ps_insn id of the first
register-move instruction added to handle the modulo-variable-expansion register-move instruction added to handle the modulo-variable-expansion
of the register defined by this node. This register-move copies the of the register defined by this node. This register-move copies the
original register defined by the node. */ original register defined by the node. */
rtx first_reg_move; int first_reg_move;
/* The number of register-move instructions added, immediately preceding /* The number of register-move instructions added. */
first_reg_move. */
int nreg_moves; int nreg_moves;
int row; /* Holds time % ii. */ int row; /* Holds time % ii. */
@ -232,6 +261,9 @@ typedef struct node_sched_params
int column; int column;
} *node_sched_params_ptr; } *node_sched_params_ptr;
typedef struct node_sched_params node_sched_params;
DEF_VEC_O (node_sched_params);
DEF_VEC_ALLOC_O (node_sched_params, heap);
/* The following three functions are copied from the current scheduler /* The following three functions are copied from the current scheduler
code in order to use sched_analyze() for computing the dependencies. code in order to use sched_analyze() for computing the dependencies.
@ -280,20 +312,35 @@ static struct haifa_sched_info sms_sched_info =
0 0
}; };
/* Partial schedule instruction ID in PS is a register move. Return
information about it. */
static struct ps_reg_move_info *
ps_reg_move (partial_schedule_ptr ps, int id)
{
gcc_checking_assert (id >= ps->g->num_nodes);
return VEC_index (ps_reg_move_info, ps->reg_moves, id - ps->g->num_nodes);
}
/* Return the rtl instruction that is being scheduled by partial schedule /* Return the rtl instruction that is being scheduled by partial schedule
instruction ID, which belongs to schedule PS. */ instruction ID, which belongs to schedule PS. */
static rtx static rtx
ps_rtl_insn (partial_schedule_ptr ps, int id) ps_rtl_insn (partial_schedule_ptr ps, int id)
{ {
return ps->g->nodes[id].insn; if (id < ps->g->num_nodes)
return ps->g->nodes[id].insn;
else
return ps_reg_move (ps, id)->insn;
} }
/* Return the first instruction in the original (unscheduled) loop that /* Partial schedule instruction ID, which belongs to PS, occured in
was associated with ps_rtl_insn (PS, ID). If the instruction had the original (unscheduled) loop. Return the first instruction
some notes before it, this is the first of those notes. */ in the loop that was associated with ps_rtl_insn (PS, ID).
If the instruction had some notes before it, this is the first
of those notes. */
static rtx static rtx
ps_first_note (partial_schedule_ptr ps, int id) ps_first_note (partial_schedule_ptr ps, int id)
{ {
gcc_assert (id < ps->g->num_nodes);
return ps->g->nodes[id].first_note; return ps->g->nodes[id].first_note;
} }
@ -397,18 +444,20 @@ res_MII (ddg_ptr g)
} }
/* Points to the array that contains the sched data for each node. */ /* A vector that contains the sched data for each ps_insn. */
static node_sched_params_ptr node_sched_params; static VEC (node_sched_params, heap) *node_sched_param_vec;
/* Allocate sched_params for each node and initialize it. */ /* Allocate sched_params for each node and initialize it. */
static void static void
set_node_sched_params (ddg_ptr g) set_node_sched_params (ddg_ptr g)
{ {
node_sched_params = XCNEWVEC (struct node_sched_params, g->num_nodes); VEC_truncate (node_sched_params, node_sched_param_vec, 0);
VEC_safe_grow_cleared (node_sched_params, heap,
node_sched_param_vec, g->num_nodes);
} }
static void static void
print_node_sched_params (FILE *file, int num_nodes, ddg_ptr g) print_node_sched_params (FILE *file, int num_nodes, partial_schedule_ptr ps)
{ {
int i; int i;
@ -417,19 +466,19 @@ print_node_sched_params (FILE *file, int num_nodes, ddg_ptr g)
for (i = 0; i < num_nodes; i++) for (i = 0; i < num_nodes; i++)
{ {
node_sched_params_ptr nsp = SCHED_PARAMS (i); node_sched_params_ptr nsp = SCHED_PARAMS (i);
rtx reg_move = nsp->first_reg_move;
int j; int j;
fprintf (file, "Node = %d; INSN = %d\n", i, fprintf (file, "Node = %d; INSN = %d\n", i,
(INSN_UID (g->nodes[i].insn))); INSN_UID (ps_rtl_insn (ps, i)));
fprintf (file, " asap = %d:\n", NODE_ASAP (&g->nodes[i])); fprintf (file, " asap = %d:\n", NODE_ASAP (&ps->g->nodes[i]));
fprintf (file, " time = %d:\n", nsp->time); fprintf (file, " time = %d:\n", nsp->time);
fprintf (file, " nreg_moves = %d:\n", nsp->nreg_moves); fprintf (file, " nreg_moves = %d:\n", nsp->nreg_moves);
for (j = 0; j < nsp->nreg_moves; j++) for (j = 0; j < nsp->nreg_moves; j++)
{ {
ps_reg_move_info *move = ps_reg_move (ps, nsp->first_reg_move + j);
fprintf (file, " reg_move = "); fprintf (file, " reg_move = ");
print_rtl_single (file, reg_move); print_rtl_single (file, move->insn);
reg_move = PREV_INSN (reg_move);
} }
} }
} }
@ -445,8 +494,8 @@ print_node_sched_params (FILE *file, int num_nodes, ddg_ptr g)
nreg_moves = ----------------------------------- + 1 - { dependence. nreg_moves = ----------------------------------- + 1 - { dependence.
ii { 1 if not. ii { 1 if not.
*/ */
static void static bool
generate_reg_moves (partial_schedule_ptr ps, bool rescan) schedule_reg_moves (partial_schedule_ptr ps)
{ {
ddg_ptr g = ps->g; ddg_ptr g = ps->g;
int ii = ps->ii; int ii = ps->ii;
@ -457,9 +506,8 @@ generate_reg_moves (partial_schedule_ptr ps, bool rescan)
ddg_node_ptr u = &g->nodes[i]; ddg_node_ptr u = &g->nodes[i];
ddg_edge_ptr e; ddg_edge_ptr e;
int nreg_moves = 0, i_reg_move; int nreg_moves = 0, i_reg_move;
sbitmap *uses_of_defs;
rtx last_reg_move;
rtx prev_reg, old_reg; rtx prev_reg, old_reg;
int first_move;
rtx set = single_set (u->insn); rtx set = single_set (u->insn);
/* Skip instructions that do not set a register. */ /* Skip instructions that do not set a register. */
@ -504,12 +552,35 @@ generate_reg_moves (partial_schedule_ptr ps, bool rescan)
if (nreg_moves == 0) if (nreg_moves == 0)
continue; continue;
/* Create NREG_MOVES register moves. */
first_move = VEC_length (ps_reg_move_info, ps->reg_moves);
VEC_safe_grow_cleared (ps_reg_move_info, heap, ps->reg_moves,
first_move + nreg_moves);
/* Record the moves associated with this node. */
first_move += ps->g->num_nodes;
SCHED_FIRST_REG_MOVE (i) = first_move;
SCHED_NREG_MOVES (i) = nreg_moves;
/* Generate each move. */
old_reg = prev_reg = SET_DEST (single_set (u->insn));
for (i_reg_move = 0; i_reg_move < nreg_moves; i_reg_move++)
{
ps_reg_move_info *move = ps_reg_move (ps, first_move + i_reg_move);
move->def = i_reg_move > 0 ? first_move + i_reg_move - 1 : i;
move->uses = sbitmap_alloc (g->num_nodes);
move->old_reg = old_reg;
move->new_reg = gen_reg_rtx (GET_MODE (prev_reg));
move->insn = gen_move_insn (move->new_reg, copy_rtx (prev_reg));
sbitmap_zero (move->uses);
prev_reg = move->new_reg;
}
/* Every use of the register defined by node may require a different /* Every use of the register defined by node may require a different
copy of this register, depending on the time the use is scheduled. copy of this register, depending on the time the use is scheduled.
Set a bitmap vector, telling which nodes use each copy of this Record which uses require which move results. */
register. */
uses_of_defs = sbitmap_vector_alloc (nreg_moves, g->num_nodes);
sbitmap_vector_zero (uses_of_defs, nreg_moves);
for (e = u->out; e; e = e->next_out) for (e = u->out; e; e = e->next_out)
if (e->type == TRUE_DEP && e->dest != e->src) if (e->type == TRUE_DEP && e->dest != e->src)
{ {
@ -525,40 +596,39 @@ generate_reg_moves (partial_schedule_ptr ps, bool rescan)
dest_copy--; dest_copy--;
if (dest_copy) if (dest_copy)
SET_BIT (uses_of_defs[dest_copy - 1], e->dest->cuid); {
ps_reg_move_info *move;
move = ps_reg_move (ps, first_move + dest_copy - 1);
SET_BIT (move->uses, e->dest->cuid);
}
} }
/* Now generate the reg_moves, attaching relevant uses to them. */
SCHED_NREG_MOVES (i) = nreg_moves;
old_reg = prev_reg = copy_rtx (SET_DEST (single_set (u->insn)));
/* Insert the reg-moves right before the notes which precede
the insn they relates to. */
last_reg_move = u->first_note;
for (i_reg_move = 0; i_reg_move < nreg_moves; i_reg_move++)
{
unsigned int i_use = 0;
rtx new_reg = gen_reg_rtx (GET_MODE (prev_reg));
rtx reg_move = gen_move_insn (new_reg, prev_reg);
sbitmap_iterator sbi;
add_insn_before (reg_move, last_reg_move, NULL);
last_reg_move = reg_move;
if (!SCHED_FIRST_REG_MOVE (i))
SCHED_FIRST_REG_MOVE (i) = reg_move;
EXECUTE_IF_SET_IN_SBITMAP (uses_of_defs[i_reg_move], 0, i_use, sbi)
{
replace_rtx (g->nodes[i_use].insn, old_reg, new_reg);
if (rescan)
df_insn_rescan (g->nodes[i_use].insn);
}
prev_reg = new_reg;
}
sbitmap_vector_free (uses_of_defs);
} }
return true;
}
/* Emit the moves associatied with PS. Apply the substitutions
associated with them. */
static void
apply_reg_moves (partial_schedule_ptr ps)
{
ps_reg_move_info *move;
int i;
FOR_EACH_VEC_ELT (ps_reg_move_info, ps->reg_moves, i, move)
{
unsigned int i_use;
sbitmap_iterator sbi;
EXECUTE_IF_SET_IN_SBITMAP (move->uses, 0, i_use, sbi)
{
replace_rtx (ps->g->nodes[i_use].insn, move->old_reg, move->new_reg);
df_insn_rescan (ps->g->nodes[i_use].insn);
}
}
FOR_EACH_VEC_ELT (ps_reg_move_info, ps->reg_moves, i, move)
add_insn_before (move->insn, ps_first_note (ps, move->def), NULL);
} }
/* Update the sched_params (time, row and stage) for node U using the II, /* Update the sched_params (time, row and stage) for node U using the II,
@ -874,8 +944,7 @@ duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage,
for (ps_ij = ps->rows[row]; ps_ij; ps_ij = ps_ij->next_in_row) for (ps_ij = ps->rows[row]; ps_ij; ps_ij = ps_ij->next_in_row)
{ {
int u = ps_ij->id; int u = ps_ij->id;
int j, i_reg_moves; int j, i_reg_moves, i_reg_move;
rtx reg_move = NULL_RTX;
rtx u_insn; rtx u_insn;
/* Do not duplicate any insn which refers to count_reg as it /* Do not duplicate any insn which refers to count_reg as it
@ -899,12 +968,7 @@ duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage,
i_reg_moves = MIN (i_reg_moves, SCHED_NREG_MOVES (u)); i_reg_moves = MIN (i_reg_moves, SCHED_NREG_MOVES (u));
/* The reg_moves start from the *first* reg_move backwards. */ /* The reg_moves start from the *first* reg_move backwards. */
if (i_reg_moves) i_reg_move = SCHED_FIRST_REG_MOVE (u) + (i_reg_moves - 1);
{
reg_move = SCHED_FIRST_REG_MOVE (u);
for (j = 1; j < i_reg_moves; j++)
reg_move = PREV_INSN (reg_move);
}
} }
else /* It's for the epilog. */ else /* It's for the epilog. */
{ {
@ -918,16 +982,15 @@ duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage,
i_reg_moves = MIN (i_reg_moves, SCHED_NREG_MOVES (u)); i_reg_moves = MIN (i_reg_moves, SCHED_NREG_MOVES (u));
/* The reg_moves start from the *last* reg_move forwards. */ /* The reg_moves start from the *last* reg_move forwards. */
if (i_reg_moves) i_reg_move = SCHED_FIRST_REG_MOVE (u) + (SCHED_NREG_MOVES (u) - 1);
{
reg_move = SCHED_FIRST_REG_MOVE (u);
for (j = 1; j < SCHED_NREG_MOVES (u); j++)
reg_move = PREV_INSN (reg_move);
}
} }
for (j = 0; j < i_reg_moves; j++, reg_move = NEXT_INSN (reg_move)) for (j = 0; j < i_reg_moves; j++)
emit_insn (copy_rtx (PATTERN (reg_move))); {
ps_reg_move_info *move = ps_reg_move (ps, i_reg_move - j);
emit_insn (copy_rtx (PATTERN (move->insn)));
}
if (SCHED_STAGE (u) >= from_stage if (SCHED_STAGE (u) >= from_stage
&& SCHED_STAGE (u) <= to_stage) && SCHED_STAGE (u) <= to_stage)
duplicate_insn_chain (ps_first_note (ps, u), u_insn); duplicate_insn_chain (ps_first_note (ps, u), u_insn);
@ -1313,9 +1376,9 @@ sms_schedule (void)
rtx head, tail; rtx head, tail;
rtx count_reg, count_init; rtx count_reg, count_init;
int mii, rec_mii; int mii, rec_mii;
unsigned stage_count = 0; unsigned stage_count;
HOST_WIDEST_INT loop_count = 0; HOST_WIDEST_INT loop_count = 0;
bool opt_sc_p = false; bool opt_sc_p;
if (! (g = g_arr[loop->num])) if (! (g = g_arr[loop->num]))
continue; continue;
@ -1392,54 +1455,60 @@ sms_schedule (void)
fprintf (dump_file, "SMS iis %d %d %d (rec_mii, mii, maxii)\n", fprintf (dump_file, "SMS iis %d %d %d (rec_mii, mii, maxii)\n",
rec_mii, mii, maxii); rec_mii, mii, maxii);
set_node_sched_params (g); for (;;)
{
set_node_sched_params (g);
ps = sms_schedule_by_order (g, mii, maxii, node_order); stage_count = 0;
opt_sc_p = false;
if (ps) ps = sms_schedule_by_order (g, mii, maxii, node_order);
{
/* Try to achieve optimized SC by normalizing the partial if (ps)
schedule (having the cycles start from cycle zero). {
The branch location must be placed in row ii-1 in the /* Try to achieve optimized SC by normalizing the partial
final scheduling. If failed, shift all instructions to schedule (having the cycles start from cycle zero).
position the branch in row ii-1. */ The branch location must be placed in row ii-1 in the
opt_sc_p = optimize_sc (ps, g); final scheduling. If failed, shift all instructions to
if (opt_sc_p) position the branch in row ii-1. */
stage_count = calculate_stage_count (ps, 0); opt_sc_p = optimize_sc (ps, g);
else if (opt_sc_p)
stage_count = calculate_stage_count (ps, 0);
else
{
/* Bring the branch to cycle ii-1. */
int amount = (SCHED_TIME (g->closing_branch->cuid)
- (ps->ii - 1));
if (dump_file)
fprintf (dump_file, "SMS schedule branch at cycle ii-1\n");
stage_count = calculate_stage_count (ps, amount);
}
gcc_assert (stage_count >= 1);
PS_STAGE_COUNT (ps) = stage_count;
}
/* The default value of PARAM_SMS_MIN_SC is 2 as stage count of
1 means that there is no interleaving between iterations thus
we let the scheduling passes do the job in this case. */
if (stage_count < (unsigned) PARAM_VALUE (PARAM_SMS_MIN_SC)
|| (count_init && (loop_count <= stage_count))
|| (flag_branch_probabilities && (trip_count <= stage_count)))
{ {
/* Bring the branch to cycle ii-1. */
int amount = SCHED_TIME (g->closing_branch->cuid) - (ps->ii - 1);
if (dump_file) if (dump_file)
fprintf (dump_file, "SMS schedule branch at cycle ii-1\n"); {
fprintf (dump_file, "SMS failed... \n");
stage_count = calculate_stage_count (ps, amount); fprintf (dump_file, "SMS sched-failed (stage-count=%d,"
" loop-count=", stage_count);
fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, loop_count);
fprintf (dump_file, ", trip-count=");
fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, trip_count);
fprintf (dump_file, ")\n");
}
break;
} }
gcc_assert (stage_count >= 1);
PS_STAGE_COUNT (ps) = stage_count;
}
/* The default value of PARAM_SMS_MIN_SC is 2 as stage count of
1 means that there is no interleaving between iterations thus
we let the scheduling passes do the job in this case. */
if (stage_count < (unsigned) PARAM_VALUE (PARAM_SMS_MIN_SC)
|| (count_init && (loop_count <= stage_count))
|| (flag_branch_probabilities && (trip_count <= stage_count)))
{
if (dump_file)
{
fprintf (dump_file, "SMS failed... \n");
fprintf (dump_file, "SMS sched-failed (stage-count=%d, loop-count=", stage_count);
fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, loop_count);
fprintf (dump_file, ", trip-count=");
fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, trip_count);
fprintf (dump_file, ")\n");
}
}
else
{
if (!opt_sc_p) if (!opt_sc_p)
{ {
/* Rotate the partial schedule to have the branch in row ii-1. */ /* Rotate the partial schedule to have the branch in row ii-1. */
@ -1451,6 +1520,13 @@ sms_schedule (void)
set_columns_for_ps (ps); set_columns_for_ps (ps);
if (!schedule_reg_moves (ps))
{
mii = ps->ii + 1;
free_partial_schedule (ps);
continue;
}
canon_loop (loop); canon_loop (loop);
if (dump_file) if (dump_file)
@ -1489,15 +1565,16 @@ sms_schedule (void)
/* The life-info is not valid any more. */ /* The life-info is not valid any more. */
df_set_bb_dirty (g->bb); df_set_bb_dirty (g->bb);
generate_reg_moves (ps, true); apply_reg_moves (ps);
if (dump_file) if (dump_file)
print_node_sched_params (dump_file, g->num_nodes, g); print_node_sched_params (dump_file, g->num_nodes, ps);
/* Generate prolog and epilog. */ /* Generate prolog and epilog. */
generate_prolog_epilog (ps, loop, count_reg, count_init); generate_prolog_epilog (ps, loop, count_reg, count_init);
break;
} }
free_partial_schedule (ps); free_partial_schedule (ps);
free (node_sched_params); VEC_free (node_sched_params, heap, node_sched_param_vec);
free (node_order); free (node_order);
free_ddg (g); free_ddg (g);
} }
@ -2584,6 +2661,7 @@ create_partial_schedule (int ii, ddg_ptr g, int history)
partial_schedule_ptr ps = XNEW (struct partial_schedule); partial_schedule_ptr ps = XNEW (struct partial_schedule);
ps->rows = (ps_insn_ptr *) xcalloc (ii, sizeof (ps_insn_ptr)); ps->rows = (ps_insn_ptr *) xcalloc (ii, sizeof (ps_insn_ptr));
ps->rows_length = (int *) xcalloc (ii, sizeof (int)); ps->rows_length = (int *) xcalloc (ii, sizeof (int));
ps->reg_moves = NULL;
ps->ii = ii; ps->ii = ii;
ps->history = history; ps->history = history;
ps->min_cycle = INT_MAX; ps->min_cycle = INT_MAX;
@ -2618,8 +2696,16 @@ free_ps_insns (partial_schedule_ptr ps)
static void static void
free_partial_schedule (partial_schedule_ptr ps) free_partial_schedule (partial_schedule_ptr ps)
{ {
ps_reg_move_info *move;
unsigned int i;
if (!ps) if (!ps)
return; return;
FOR_EACH_VEC_ELT (ps_reg_move_info, ps->reg_moves, i, move)
sbitmap_free (move->uses);
VEC_free (ps_reg_move_info, heap, ps->reg_moves);
free_ps_insns (ps); free_ps_insns (ps);
free (ps->rows); free (ps->rows);
free (ps->rows_length); free (ps->rows_length);