/* Swing Modulo Scheduling implementation.
- Copyright (C) 2004, 2005
+ Copyright (C) 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by Ayal Zaks and Mustafa Hagog <zaks,mustafa@il.ibm.com>
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "gcov-io.h"
#include "df.h"
#include "ddg.h"
+#include "timevar.h"
+#include "tree-pass.h"
#ifdef INSN_SCHEDULING
-partial_schedule_ptr create_partial_schedule (int ii, ddg_ptr, int history);
-void free_partial_schedule (partial_schedule_ptr);
-void reset_partial_schedule (partial_schedule_ptr, int new_ii);
+static partial_schedule_ptr create_partial_schedule (int ii, ddg_ptr, int history);
+static void free_partial_schedule (partial_schedule_ptr);
+static void reset_partial_schedule (partial_schedule_ptr, int new_ii);
void print_partial_schedule (partial_schedule_ptr, FILE *);
static int kernel_number_of_cycles (rtx first_insn, rtx last_insn);
static ps_insn_ptr ps_add_node_check_conflicts (partial_schedule_ptr,
static int issue_rate;
-/* For printing statistics. */
-static FILE *stats_file;
-
static int sms_order_nodes (ddg_ptr, int, int * result);
static void set_node_sched_params (ddg_ptr);
-static partial_schedule_ptr sms_schedule_by_order (ddg_ptr, int, int,
- int *, FILE*);
+static partial_schedule_ptr sms_schedule_by_order (ddg_ptr, int, int, int *);
static void permute_partial_schedule (partial_schedule_ptr ps, rtx last);
static void generate_prolog_epilog (partial_schedule_ptr ,struct loop * loop, rtx);
static void duplicate_insns_of_cycles (partial_schedule_ptr ps,
return tmp;
}
-static int
-contributes_to_priority (rtx next, rtx insn)
-{
- return BLOCK_NUM (next) == BLOCK_NUM (insn);
-}
-
static void
compute_jump_reg_dependencies (rtx insn ATTRIBUTE_UNUSED,
regset cond_exec ATTRIBUTE_UNUSED,
NULL,
NULL,
sms_print_insn,
- contributes_to_priority,
+ NULL,
compute_jump_reg_dependencies,
NULL, NULL,
NULL, NULL,
- 0, 0, 0
+ 0, 0, 0,
+
+ NULL, NULL, NULL, NULL, NULL,
+#ifdef ENABLE_CHECKING
+ NULL,
+#endif
+ 0
};
-/* Return the register decremented and tested or zero if it is not a decrement
- and branch jump insn (similar to doloop_condition_get). */
+/* Return the register decremented and tested in INSN,
+ or zero if it is not a decrement-and-branch insn. */
+
static rtx
-doloop_register_get (rtx insn, rtx *comp)
+doloop_register_get (rtx insn ATTRIBUTE_UNUSED)
{
- rtx pattern, cmp, inc, reg, condition;
-
- if (!JUMP_P (insn))
- return NULL_RTX;
- pattern = PATTERN (insn);
-
- /* The canonical doloop pattern we expect is:
-
- (parallel [(set (pc) (if_then_else (condition)
- (label_ref (label))
- (pc)))
- (set (reg) (plus (reg) (const_int -1)))
- (additional clobbers and uses)])
-
- where condition is further restricted to be
- (ne (reg) (const_int 1)). */
-
- if (GET_CODE (pattern) != PARALLEL)
- return NULL_RTX;
-
- cmp = XVECEXP (pattern, 0, 0);
- inc = XVECEXP (pattern, 0, 1);
- /* Return the compare rtx. */
- *comp = cmp;
-
- /* Check for (set (reg) (something)). */
- if (GET_CODE (inc) != SET || ! REG_P (SET_DEST (inc)))
- return NULL_RTX;
-
- /* Extract loop counter register. */
- reg = SET_DEST (inc);
-
- /* Check if something = (plus (reg) (const_int -1)). */
- if (GET_CODE (SET_SRC (inc)) != PLUS
- || XEXP (SET_SRC (inc), 0) != reg
- || XEXP (SET_SRC (inc), 1) != constm1_rtx)
- return NULL_RTX;
+#ifdef HAVE_doloop_end
+ rtx pattern, reg, condition;
- /* Check for (set (pc) (if_then_else (condition)
- (label_ref (label))
- (pc))). */
- if (GET_CODE (cmp) != SET
- || SET_DEST (cmp) != pc_rtx
- || GET_CODE (SET_SRC (cmp)) != IF_THEN_ELSE
- || GET_CODE (XEXP (SET_SRC (cmp), 1)) != LABEL_REF
- || XEXP (SET_SRC (cmp), 2) != pc_rtx)
+ if (! JUMP_P (insn))
return NULL_RTX;
- /* Extract loop termination condition. */
- condition = XEXP (SET_SRC (cmp), 0);
-
- /* Check if condition = (ne (reg) (const_int 1)), which is more
- restrictive than the check in doloop_condition_get:
- if ((GET_CODE (condition) != GE && GET_CODE (condition) != NE)
- || GET_CODE (XEXP (condition, 1)) != CONST_INT). */
- if (GET_CODE (condition) != NE
- || XEXP (condition, 1) != const1_rtx)
+ pattern = PATTERN (insn);
+ condition = doloop_condition_get (pattern);
+ if (! condition)
return NULL_RTX;
- if (XEXP (condition, 0) == reg)
- return reg;
+ if (REG_P (XEXP (condition, 0)))
+ reg = XEXP (condition, 0);
+ else if (GET_CODE (XEXP (condition, 0)) == PLUS
+ && REG_P (XEXP (XEXP (condition, 0), 0)))
+ reg = XEXP (XEXP (condition, 0), 0);
+ else
+ gcc_unreachable ();
+ return reg;
+#else
return NULL_RTX;
+#endif
}
/* Check if COUNT_REG is set to a constant in the PRE_HEADER block, so
if (! pre_header)
return NULL_RTX;
- get_block_head_tail (pre_header->index, &head, &tail);
+ get_ebb_head_tail (pre_header, pre_header, &head, &tail);
for (insn = tail; insn != PREV_INSN (head); insn = PREV_INSN (insn))
if (INSN_P (insn) && single_set (insn) &&
}
static void
-print_node_sched_params (FILE * dump_file, int num_nodes)
+print_node_sched_params (FILE * file, int num_nodes)
{
int i;
- if (! dump_file)
+ if (! file)
return;
for (i = 0; i < num_nodes; i++)
{
rtx reg_move = nsp->first_reg_move;
int j;
- fprintf (dump_file, "Node %d:\n", i);
- fprintf (dump_file, " asap = %d:\n", nsp->asap);
- fprintf (dump_file, " time = %d:\n", nsp->time);
- fprintf (dump_file, " nreg_moves = %d:\n", nsp->nreg_moves);
+ fprintf (file, "Node %d:\n", i);
+ fprintf (file, " asap = %d:\n", nsp->asap);
+ fprintf (file, " time = %d:\n", nsp->time);
+ fprintf (file, " nreg_moves = %d:\n", nsp->nreg_moves);
for (j = 0; j < nsp->nreg_moves; j++)
{
- fprintf (dump_file, " reg_move = ");
- print_rtl_single (dump_file, reg_move);
+ fprintf (file, " reg_move = ");
+ print_rtl_single (file, reg_move);
reg_move = PREV_INSN (reg_move);
}
}
for (i_reg_move = 0; i_reg_move < nreg_moves; i_reg_move++)
{
- int i_use;
+ 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);
last_reg_move = reg_move;
if (!SCHED_FIRST_REG_MOVE (u))
SCHED_FIRST_REG_MOVE (u) = reg_move;
- EXECUTE_IF_SET_IN_SBITMAP (uses_of_defs[i_reg_move], 0, i_use,
+ EXECUTE_IF_SET_IN_SBITMAP (uses_of_defs[i_reg_move], 0, i_use, sbi)
{
struct undo_replace_buff_elem *rep;
}
replace_rtx (g->nodes[i_use].insn, old_reg, new_reg);
- });
+ }
prev_reg = new_reg;
}
+ sbitmap_vector_free (uses_of_defs);
}
return reg_move_replaces;
}
delete_insn (crr);
crr = prev;
}
+ SCHED_FIRST_REG_MOVE (u) = NULL_RTX;
}
while (reg_move_replaces)
/* Make sure that basic blocks other than the header
have only notes labels or jumps. */
- get_block_head_tail (bbs[i]->index, &head, &tail);
+ get_ebb_head_tail (bbs[i], bbs[i], &head, &tail);
for (; head != NEXT_INSN (tail); head = NEXT_INSN (head))
{
if (NOTE_P (head) || LABEL_P (head)
/* Return true if the loop is in its canonical form and false if not.
i.e. SIMPLE_SMS_LOOP_P and have one preheader block, and single exit. */
static bool
-loop_canon_p (struct loop *loop, FILE *dump_file)
+loop_canon_p (struct loop *loop)
{
if (loop->inner || ! loop->outer)
{
expanded_location xloc;
NOTE_EXPANDED_LOCATION (xloc, line_note);
- fprintf (stats_file, " %s %d (file, line)\n",
+ fprintf (dump_file, " %s %d (file, line)\n",
xloc.file, xloc.line);
}
}
{
expanded_location xloc;
NOTE_EXPANDED_LOCATION (xloc, line_note);
- fprintf (stats_file, " %s %d (file, line)\n",
+ fprintf (dump_file, " %s %d (file, line)\n",
xloc.file, xloc.line);
}
}
}
}
-/* Build the loop information without loop
- canonization, the loop canonization will
- be performed if the loop is SMSable. */
-static struct loops *
-build_loops_structure (FILE *dumpfile)
-{
- struct loops *loops = xcalloc (1, sizeof (struct loops));
-
- /* Find the loops. */
-
- if (flow_loops_find (loops) <= 1)
- {
- /* No loops. */
- flow_loops_free (loops);
- free (loops);
-
- return NULL;
- }
-
- /* Not going to update these. */
- free (loops->cfg.rc_order);
- loops->cfg.rc_order = NULL;
- free (loops->cfg.dfs_order);
- loops->cfg.dfs_order = NULL;
-
- create_preheaders (loops, CP_SIMPLE_PREHEADERS);
- mark_single_exit_loops (loops);
- /* Dump loops. */
- flow_loops_dump (loops, dumpfile, NULL, 1);
-
-#ifdef ENABLE_CHECKING
- verify_dominators (CDI_DOMINATORS);
- verify_loop_structure (loops);
-#endif
-
- return loops;
-}
-
/* Main entry point, perform SMS scheduling on the loops of the function
that consist of single basic blocks. */
-void
-sms_schedule (FILE *dump_file)
+static void
+sms_schedule (void)
{
static int passes = 0;
rtx insn;
edge latch_edge;
gcov_type trip_count = 0;
- if (! (loops = build_loops_structure (dump_file)))
+ loops = loop_optimizer_init (LOOPS_HAVE_PREHEADERS
+ | LOOPS_HAVE_MARKED_SINGLE_EXITS);
+ if (!loops)
return; /* There is no loops to schedule. */
-
- stats_file = dump_file;
-
/* Initialize issue_rate. */
if (targetm.sched.issue_rate)
{
/* Initialize the scheduler. */
current_sched_info = &sms_sched_info;
- sched_init (NULL);
+ sched_init ();
/* Init Data Flow analysis, to be used in interloop dep calculation. */
- df = df_init ();
- df_analyze (df, 0, DF_ALL);
+ df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES | DF_SUBREGS);
+ df_rd_add_problem (df, 0);
+ df_ru_add_problem (df, 0);
+ df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN);
+ df_analyze (df);
+
+ if (dump_file)
+ df_dump (df, dump_file);
/* Allocate memory to hold the DDG array one entry for each loop.
We use loop->num as index into this array. */
- g_arr = xcalloc (loops->num, sizeof (ddg_ptr));
+ g_arr = XCNEWVEC (ddg_ptr, loops->num);
/* Build DDGs for all the relevant loops and hold them in G_ARR
for (i = 0; i < loops->num; i++)
{
rtx head, tail;
- rtx count_reg, comp;
+ rtx count_reg;
struct loop *loop = loops->parray[i];
/* For debugging. */
break;
}
- if (! loop_canon_p (loop, dump_file))
+ if (! loop_canon_p (loop))
continue;
if (! loop_single_full_bb_p (loop))
bb = loop->header;
- get_block_head_tail (bb->index, &head, &tail);
+ get_ebb_head_tail (bb, bb, &head, &tail);
latch_edge = loop_latch_edge (loop);
gcc_assert (loop->single_exit);
if (loop->single_exit->count)
if ( latch_edge->count
&& (latch_edge->count < loop->single_exit->count * SMS_LOOP_AVERAGE_COUNT_THRESHOLD))
{
- if (stats_file)
+ if (dump_file)
{
rtx line_note = find_line_note (tail);
{
expanded_location xloc;
NOTE_EXPANDED_LOCATION (xloc, line_note);
- fprintf (stats_file, "SMS bb %s %d (file, line)\n",
+ fprintf (dump_file, "SMS bb %s %d (file, line)\n",
xloc.file, xloc.line);
}
- fprintf (stats_file, "SMS single-bb-loop\n");
+ fprintf (dump_file, "SMS single-bb-loop\n");
if (profile_info && flag_branch_probabilities)
{
- fprintf (stats_file, "SMS loop-count ");
- fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+ fprintf (dump_file, "SMS loop-count ");
+ fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
(HOST_WIDEST_INT) bb->count);
- fprintf (stats_file, "\n");
- fprintf (stats_file, "SMS trip-count ");
- fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+ fprintf (dump_file, "\n");
+ fprintf (dump_file, "SMS trip-count ");
+ fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
(HOST_WIDEST_INT) trip_count);
- fprintf (stats_file, "\n");
- fprintf (stats_file, "SMS profile-sum-max ");
- fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+ fprintf (dump_file, "\n");
+ fprintf (dump_file, "SMS profile-sum-max ");
+ fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
(HOST_WIDEST_INT) profile_info->sum_max);
- fprintf (stats_file, "\n");
+ fprintf (dump_file, "\n");
}
}
continue;
}
/* Make sure this is a doloop. */
- if ( !(count_reg = doloop_register_get (tail, &comp)))
+ if ( !(count_reg = doloop_register_get (tail)))
continue;
/* Don't handle BBs with calls or barriers, or !single_set insns. */
if (insn != NEXT_INSN (tail))
{
- if (stats_file)
+ if (dump_file)
{
if (CALL_P (insn))
- fprintf (stats_file, "SMS loop-with-call\n");
+ fprintf (dump_file, "SMS loop-with-call\n");
else if (BARRIER_P (insn))
- fprintf (stats_file, "SMS loop-with-barrier\n");
+ fprintf (dump_file, "SMS loop-with-barrier\n");
else
- fprintf (stats_file, "SMS loop-with-not-single-set\n");
- print_rtl_single (stats_file, insn);
+ fprintf (dump_file, "SMS loop-with-not-single-set\n");
+ print_rtl_single (dump_file, insn);
}
continue;
if (! (g = create_ddg (bb, df, 0)))
{
- if (stats_file)
- fprintf (stats_file, "SMS doloop\n");
+ if (dump_file)
+ fprintf (dump_file, "SMS doloop\n");
continue;
}
/* Release Data Flow analysis data structures. */
df_finish (df);
+ df = NULL;
/* We don't want to perform SMS on new loops - created by versioning. */
num_loops = loops->num;
for (i = 0; i < num_loops; i++)
{
rtx head, tail;
- rtx count_reg, count_init, comp;
+ rtx count_reg, count_init;
int mii, rec_mii;
unsigned stage_count = 0;
HOST_WIDEST_INT loop_count = 0;
if (dump_file)
print_ddg (dump_file, g);
- get_block_head_tail (loop->header->index, &head, &tail);
+ get_ebb_head_tail (loop->header, loop->header, &head, &tail);
latch_edge = loop_latch_edge (loop);
gcc_assert (loop->single_exit);
if (loop->single_exit->count)
trip_count = latch_edge->count / loop->single_exit->count;
- if (stats_file)
+ if (dump_file)
{
rtx line_note = find_line_note (tail);
{
expanded_location xloc;
NOTE_EXPANDED_LOCATION (xloc, line_note);
- fprintf (stats_file, "SMS bb %s %d (file, line)\n",
+ fprintf (dump_file, "SMS bb %s %d (file, line)\n",
xloc.file, xloc.line);
}
- fprintf (stats_file, "SMS single-bb-loop\n");
+ fprintf (dump_file, "SMS single-bb-loop\n");
if (profile_info && flag_branch_probabilities)
{
- fprintf (stats_file, "SMS loop-count ");
- fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+ fprintf (dump_file, "SMS loop-count ");
+ fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
(HOST_WIDEST_INT) bb->count);
- fprintf (stats_file, "\n");
- fprintf (stats_file, "SMS profile-sum-max ");
- fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+ fprintf (dump_file, "\n");
+ fprintf (dump_file, "SMS profile-sum-max ");
+ fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
(HOST_WIDEST_INT) profile_info->sum_max);
- fprintf (stats_file, "\n");
+ fprintf (dump_file, "\n");
}
- fprintf (stats_file, "SMS doloop\n");
- fprintf (stats_file, "SMS built-ddg %d\n", g->num_nodes);
- fprintf (stats_file, "SMS num-loads %d\n", g->num_loads);
- fprintf (stats_file, "SMS num-stores %d\n", g->num_stores);
+ fprintf (dump_file, "SMS doloop\n");
+ fprintf (dump_file, "SMS built-ddg %d\n", g->num_nodes);
+ fprintf (dump_file, "SMS num-loads %d\n", g->num_loads);
+ fprintf (dump_file, "SMS num-stores %d\n", g->num_stores);
}
/* In case of th loop have doloop register it gets special
handling. */
count_init = NULL_RTX;
- if ((count_reg = doloop_register_get (tail, &comp)))
+ if ((count_reg = doloop_register_get (tail)))
{
basic_block pre_header;
}
gcc_assert (count_reg);
- if (stats_file && count_init)
+ if (dump_file && count_init)
{
- fprintf (stats_file, "SMS const-doloop ");
- fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+ fprintf (dump_file, "SMS const-doloop ");
+ fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
loop_count);
- fprintf (stats_file, "\n");
+ fprintf (dump_file, "\n");
}
- node_order = (int *) xmalloc (sizeof (int) * g->num_nodes);
+ node_order = XNEWVEC (int, g->num_nodes);
mii = 1; /* Need to pass some estimate of mii. */
rec_mii = sms_order_nodes (g, mii, node_order);
mii = MAX (res_MII (g), rec_mii);
maxii = (calculate_maxii (g) * SMS_MAX_II_FACTOR) / 100;
- if (stats_file)
- fprintf (stats_file, "SMS iis %d %d %d (rec_mii, mii, maxii)\n",
+ if (dump_file)
+ fprintf (dump_file, "SMS iis %d %d %d (rec_mii, mii, maxii)\n",
rec_mii, mii, maxii);
/* After sms_order_nodes and before sms_schedule_by_order, to copy over
ASAP. */
set_node_sched_params (g);
- ps = sms_schedule_by_order (g, mii, maxii, node_order, dump_file);
+ ps = sms_schedule_by_order (g, mii, maxii, node_order);
if (ps)
stage_count = PS_STAGE_COUNT (ps);
int new_cycles;
struct undo_replace_buff_elem *reg_move_replaces;
- if (stats_file)
+ if (dump_file)
{
- fprintf (stats_file,
+ fprintf (dump_file,
"SMS succeeded %d %d (with ii, sc)\n", ps->ii,
stage_count);
- print_partial_schedule (ps, stats_file);
- fprintf (stats_file,
+ print_partial_schedule (ps, dump_file);
+ fprintf (dump_file,
"SMS Branch (%d) will later be scheduled at cycle %d.\n",
g->closing_branch->cuid, PS_MIN_CYCLE (ps) - 1);
}
/* SMS is not profitable so undo the permutation and reg move generation
and return the kernel to its original state. */
if (dump_file)
- fprintf (dump_file, "Undoing SMS becuase it is not profitable.\n");
+ fprintf (dump_file, "Undoing SMS because it is not profitable.\n");
}
else
rtx comp_rtx = gen_rtx_fmt_ee (GT, VOIDmode, count_reg,
GEN_INT(stage_count));
- nloop = loop_version (loops, loop, comp_rtx, &condition_bb);
+ nloop = loop_version (loops, loop, comp_rtx, &condition_bb,
+ true);
}
/* Set new iteration count of loop kernel. */
free_ddg (g);
}
+ free (g_arr);
+
/* Release scheduler data, needed until now because of DFA. */
sched_finish ();
- loop_optimizer_finalize (loops, dump_file);
+ loop_optimizer_finalize (loops);
}
/* The SMS scheduling algorithm itself
/* This function implements the scheduling algorithm for SMS according to the
above algorithm. */
static partial_schedule_ptr
-sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order, FILE *dump_file)
+sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order)
{
int ii = mii;
int i, c, success;
} /* While try_again_with_larger_ii. */
sbitmap_free (sched_nodes);
+ sbitmap_free (must_precede);
+ sbitmap_free (must_follow);
+ sbitmap_free (tobe_scheduled);
if (ii >= maxii)
{
static int
find_max_asap (ddg_ptr g, sbitmap nodes)
{
- int u;
+ unsigned int u = 0;
int max_asap = -1;
int result = -1;
+ sbitmap_iterator sbi;
- EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u,
+ EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
{
ddg_node_ptr u_node = &g->nodes[u];
max_asap = ASAP (u_node);
result = u;
}
- });
+ }
return result;
}
static int
find_max_hv_min_mob (ddg_ptr g, sbitmap nodes)
{
- int u;
+ unsigned int u = 0;
int max_hv = -1;
int min_mob = INT_MAX;
int result = -1;
+ sbitmap_iterator sbi;
- EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u,
+ EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
{
ddg_node_ptr u_node = &g->nodes[u];
min_mob = MOB (u_node);
result = u;
}
- });
+ }
return result;
}
static int
find_max_dv_min_mob (ddg_ptr g, sbitmap nodes)
{
- int u;
+ unsigned int u = 0;
int max_dv = -1;
int min_mob = INT_MAX;
int result = -1;
+ sbitmap_iterator sbi;
- EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u,
+ EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
{
ddg_node_ptr u_node = &g->nodes[u];
min_mob = MOB (u_node);
result = u;
}
- });
+ }
return result;
}
modulo scheduling. */
/* Create a partial schedule and allocate a memory to hold II rows. */
-partial_schedule_ptr
+
+static partial_schedule_ptr
create_partial_schedule (int ii, ddg_ptr g, int history)
{
- partial_schedule_ptr ps = (partial_schedule_ptr)
- xmalloc (sizeof (struct partial_schedule));
+ partial_schedule_ptr ps = XNEW (struct partial_schedule);
ps->rows = (ps_insn_ptr *) xcalloc (ii, sizeof (ps_insn_ptr));
ps->ii = ii;
ps->history = history;
}
/* Free all the memory allocated to the partial schedule. */
-void
+
+static void
free_partial_schedule (partial_schedule_ptr ps)
{
if (!ps)
/* Clear the rows array with its PS_INSNs, and create a new one with
NEW_II rows. */
-void
+
+static void
reset_partial_schedule (partial_schedule_ptr ps, int new_ii)
{
if (!ps)
static ps_insn_ptr
create_ps_insn (ddg_node_ptr node, int rest_count, int cycle)
{
- ps_insn_ptr ps_i = xmalloc (sizeof (struct ps_insn));
+ ps_insn_ptr ps_i = XNEW (struct ps_insn);
ps_i->node = node;
ps_i->next_in_row = NULL;
return remove_node_from_ps (ps, ps_i);
}
-#endif /* INSN_SCHEDULING*/
+#endif /* INSN_SCHEDULING */
+\f
+static bool
+gate_handle_sms (void)
+{
+ return (optimize > 0 && flag_modulo_sched);
+}
+
+
+/* Run instruction scheduler. */
+/* Perform SMS module scheduling. */
+static unsigned int
+rest_of_handle_sms (void)
+{
+#ifdef INSN_SCHEDULING
+ basic_block bb;
+
+ /* We want to be able to create new pseudos. */
+ no_new_pseudos = 0;
+ /* Collect loop information to be used in SMS. */
+ cfg_layout_initialize (CLEANUP_UPDATE_LIFE);
+ sms_schedule ();
+
+ /* Update the life information, because we add pseudos. */
+ max_regno = max_reg_num ();
+ allocate_reg_info (max_regno, FALSE, FALSE);
+ update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
+ (PROP_DEATH_NOTES
+ | PROP_REG_INFO
+ | PROP_KILL_DEAD_CODE
+ | PROP_SCAN_DEAD_CODE));
+
+ no_new_pseudos = 1;
+
+ /* Finalize layout changes. */
+ FOR_EACH_BB (bb)
+ if (bb->next_bb != EXIT_BLOCK_PTR)
+ bb->aux = bb->next_bb;
+ cfg_layout_finalize ();
+ free_dominance_info (CDI_DOMINATORS);
+#endif /* INSN_SCHEDULING */
+ return 0;
+}
+
+struct tree_opt_pass pass_sms =
+{
+ "sms", /* name */
+ gate_handle_sms, /* gate */
+ rest_of_handle_sms, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_SMS, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ TODO_dump_func, /* todo_flags_start */
+ TODO_dump_func |
+ TODO_ggc_collect, /* todo_flags_finish */
+ 'm' /* letter */
+};