/* Swing Modulo Scheduling implementation.
- Copyright (C) 2004-2014 Free Software Foundation, Inc.
+ Copyright (C) 2004-2015 Free Software Foundation, Inc.
Contributed by Ayal Zaks and Mustafa Hagog <zaks,mustafa@il.ibm.com>
This file is part of GCC.
#include "hard-reg-set.h"
#include "regs.h"
#include "function.h"
+#include "profile.h"
#include "flags.h"
#include "insn-config.h"
#include "insn-attr.h"
#include "except.h"
#include "recog.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgrtl.h"
+#include "predict.h"
+#include "basic-block.h"
#include "sched-int.h"
#include "target.h"
#include "cfgloop.h"
+#include "alias.h"
+#include "symtab.h"
+#include "tree.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
#include "expr.h"
#include "params.h"
#include "gcov-io.h"
+#include "sbitmap.h"
+#include "df.h"
#include "ddg.h"
#include "tree-pass.h"
#include "dbgcnt.h"
-#include "df.h"
+#include "loop-unroll.h"
#ifdef INSN_SCHEDULING
/* 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;
+ rtx_insn *insn;
};
typedef struct ps_reg_move_info ps_reg_move_info;
static int sms_order_nodes (ddg_ptr, int, int *, int *);
static void set_node_sched_params (ddg_ptr);
static partial_schedule_ptr sms_schedule_by_order (ddg_ptr, int, int, int *);
-static void permute_partial_schedule (partial_schedule_ptr, rtx);
+static void permute_partial_schedule (partial_schedule_ptr, rtx_insn *);
static void generate_prolog_epilog (partial_schedule_ptr, struct loop *,
rtx, rtx);
static int calculate_stage_count (partial_schedule_ptr, int);
code in order to use sched_analyze() for computing the dependencies.
They are used when initializing the sched_info structure. */
static const char *
-sms_print_insn (const_rtx insn, int aligned ATTRIBUTE_UNUSED)
+sms_print_insn (const rtx_insn *insn, int aligned ATTRIBUTE_UNUSED)
{
static char tmp[80];
/* Return the rtl instruction that is being scheduled by partial schedule
instruction ID, which belongs to schedule PS. */
-static rtx
+static rtx_insn *
ps_rtl_insn (partial_schedule_ptr ps, int id)
{
if (id < ps->g->num_nodes)
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_insn *
ps_first_note (partial_schedule_ptr ps, int id)
{
gcc_assert (id < ps->g->num_nodes);
more than one occurrence in the loop besides the control part or the
do-loop pattern is not of the form we expect. */
static rtx
-doloop_register_get (rtx head ATTRIBUTE_UNUSED, rtx tail ATTRIBUTE_UNUSED)
+doloop_register_get (rtx_insn *head ATTRIBUTE_UNUSED, rtx_insn *tail ATTRIBUTE_UNUSED)
{
#ifdef HAVE_doloop_end
- rtx reg, condition, insn, first_insn_not_to_check;
+ rtx reg, condition;
+ rtx_insn *insn, *first_insn_not_to_check;
if (!JUMP_P (tail))
return NULL_RTX;
/* Check if COUNT_REG is set to a constant in the PRE_HEADER block, so
that the number of iterations is a compile-time constant. If so,
- return the rtx that sets COUNT_REG to a constant, and set COUNT to
+ return the rtx_insn that sets COUNT_REG to a constant, and set COUNT to
this constant. Otherwise return 0. */
-static rtx
+static rtx_insn *
const_iteration_count (rtx count_reg, basic_block pre_header,
- HOST_WIDEST_INT * count)
+ int64_t * count)
{
- rtx insn;
- rtx head, tail;
+ rtx_insn *insn;
+ rtx_insn *head, *tail;
if (! pre_header)
- return NULL_RTX;
+ return NULL;
get_ebb_head_tail (pre_header, pre_header, &head, &tail);
return insn;
}
- return NULL_RTX;
+ return NULL;
}
- return NULL_RTX;
+ return NULL;
}
/* A very simple resource-based lower bound on the initiation interval.
int start, end, c, ii;
sbitmap_iterator sbi;
ps_reg_move_info *move;
- rtx this_insn;
+ rtx_insn *this_insn;
ps_insn_ptr psi;
move = ps_reg_move (ps, i_reg_move);
if (dump_file)
{
/* Print the scheduling times after the rotation. */
- rtx insn = ps_rtl_insn (ps, u);
+ rtx_insn *insn = ps_rtl_insn (ps, u);
fprintf (dump_file, "crr_insn->node=%d (insn id %d), "
"crr_insn->cycle=%d, min_cycle=%d", u,
row ii-1, and position them right before LAST. This schedules
the insns of the loop kernel. */
static void
-permute_partial_schedule (partial_schedule_ptr ps, rtx last)
+permute_partial_schedule (partial_schedule_ptr ps, rtx_insn *last)
{
int ii = ps->ii;
int row;
for (row = 0; row < ii ; row++)
for (ps_ij = ps->rows[row]; ps_ij; ps_ij = ps_ij->next_in_row)
{
- rtx insn = ps_rtl_insn (ps, ps_ij->id);
+ rtx_insn *insn = ps_rtl_insn (ps, ps_ij->id);
if (PREV_INSN (last) != insn)
{
{
int u = ps_ij->id;
int first_u, last_u;
- rtx u_insn;
+ rtx_insn *u_insn;
/* Do not duplicate any insn which refers to count_reg as it
belongs to the control part.
for (i = 0; i < loop->num_nodes ; i++)
{
- rtx head, tail;
+ rtx_insn *head, *tail;
bool empty_bb = true;
if (bbs[i] == loop->header)
/* Dump file:line from INSN's location info to dump_file. */
static void
-dump_insn_location (rtx insn)
+dump_insn_location (rtx_insn *insn)
{
- if (dump_file && INSN_LOCATION (insn))
+ if (dump_file && INSN_HAS_LOCATION (insn))
{
- const char *file = insn_file (insn);
- if (file)
- fprintf (dump_file, " %s:%i", file, insn_line (insn));
+ expanded_location xloc = insn_location (insn);
+ fprintf (dump_file, " %s:%i", xloc.file, xloc.line);
}
}
{
if (dump_file)
{
- rtx insn = BB_END (loop->header);
+ rtx_insn *insn = BB_END (loop->header);
fprintf (dump_file, "SMS loop many exits");
dump_insn_location (insn);
{
if (dump_file)
{
- rtx insn = BB_END (loop->header);
+ rtx_insn *insn = BB_END (loop->header);
fprintf (dump_file, "SMS loop many BBs.");
dump_insn_location (insn);
static void
sms_schedule (void)
{
- rtx insn;
+ rtx_insn *insn;
ddg_ptr *g_arr, g;
int * node_order;
int maxii, max_asap;
indexed by the loop index. */
FOR_EACH_LOOP (loop, 0)
{
- rtx head, tail;
+ rtx_insn *head, *tail;
rtx count_reg;
/* For debugging. */
if (dump_file)
{
- rtx insn = BB_END (loop->header);
+ rtx_insn *insn = BB_END (loop->header);
fprintf (dump_file, "SMS loop num: %d", loop->num);
dump_insn_location (insn);
if (profile_info && flag_branch_probabilities)
{
fprintf (dump_file, "SMS loop-count ");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) bb->count);
+ fprintf (dump_file, "%" PRId64,
+ (int64_t) bb->count);
fprintf (dump_file, "\n");
fprintf (dump_file, "SMS trip-count ");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) trip_count);
+ fprintf (dump_file, "%" PRId64,
+ (int64_t) trip_count);
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 (dump_file, "%" PRId64,
+ (int64_t) profile_info->sum_max);
fprintf (dump_file, "\n");
}
}
/* We don't want to perform SMS on new loops - created by versioning. */
FOR_EACH_LOOP (loop, 0)
{
- rtx head, tail;
- rtx count_reg, count_init;
+ rtx_insn *head, *tail;
+ rtx count_reg;
+ rtx_insn *count_init;
int mii, rec_mii, stage_count, min_cycle;
- HOST_WIDEST_INT loop_count = 0;
+ int64_t loop_count = 0;
bool opt_sc_p;
if (! (g = g_arr[loop->num]))
if (dump_file)
{
- rtx insn = BB_END (loop->header);
+ rtx_insn *insn = BB_END (loop->header);
fprintf (dump_file, "SMS loop num: %d", loop->num);
dump_insn_location (insn);
if (profile_info && flag_branch_probabilities)
{
fprintf (dump_file, "SMS loop-count ");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
- (HOST_WIDEST_INT) bb->count);
+ fprintf (dump_file, "%" PRId64,
+ (int64_t) bb->count);
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 (dump_file, "%" PRId64,
+ (int64_t) profile_info->sum_max);
fprintf (dump_file, "\n");
}
fprintf (dump_file, "SMS doloop\n");
/* In case of th loop have doloop register it gets special
handling. */
- count_init = NULL_RTX;
+ count_init = NULL;
if ((count_reg = doloop_register_get (head, tail)))
{
basic_block pre_header;
if (dump_file && count_init)
{
fprintf (dump_file, "SMS const-doloop ");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
+ fprintf (dump_file, "%" PRId64,
loop_count);
fprintf (dump_file, "\n");
}
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, "%" PRId64, loop_count);
fprintf (dump_file, ", trip-count=");
- fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC, trip_count);
+ fprintf (dump_file, "%" PRId64, trip_count);
fprintf (dump_file, ")\n");
}
break;
node close to its successors. */
if (pss_not_empty && count_succs >= count_preds)
{
- int tmp = end;
- end = start;
- start = tmp;
+ std::swap (start, end);
step = -1;
}
{
int u = nodes_order[i];
ddg_node_ptr u_node = &ps->g->nodes[u];
- rtx insn = u_node->insn;
+ rtx_insn *insn = u_node->insn;
if (!NONDEBUG_INSN_P (insn))
{
fprintf (dump, "\n[ROW %d ]: ", i);
while (ps_i)
{
- rtx insn = ps_rtl_insn (ps, ps_i->id);
+ rtx_insn *insn = ps_rtl_insn (ps, ps_i->id);
if (JUMP_P (insn))
fprintf (dump, "%d (branch), ", INSN_UID (insn));
crr_insn;
crr_insn = crr_insn->next_in_row)
{
- rtx insn = ps_rtl_insn (ps, crr_insn->id);
+ rtx_insn *insn = ps_rtl_insn (ps, crr_insn->id);
if (!NONDEBUG_INSN_P (insn))
continue;
RTL_PASS, /* type */
"sms", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_execute */
TV_SMS, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- ( TODO_df_finish | TODO_verify_flow
- | TODO_verify_rtl_sharing ), /* todo_flags_finish */
+ TODO_df_finish, /* todo_flags_finish */
};
class pass_sms : public rtl_opt_pass