/* Instruction scheduling pass.
- Copyright (C) 1992-2014 Free Software Foundation, Inc.
+ Copyright (C) 1992-2015 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
and currently maintained by, Jim Wilson (wilson@cygnus.com)
#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 "params.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfganal.h"
+#include "predict.h"
+#include "basic-block.h"
#include "sched-int.h"
#include "sel-sched.h"
#include "target.h"
#include "tree-pass.h"
#include "dbgcnt.h"
+#include "emit-rtl.h"
#ifdef INSN_SCHEDULING
static int check_live_1 (int, rtx);
static void update_live_1 (int, rtx);
static int is_pfree (rtx, int, int);
-static int find_conditional_protection (rtx, int);
+static int find_conditional_protection (rtx_insn *, int);
static int is_conditionally_protected (rtx, int, int);
static int is_prisky (rtx, int, int);
-static int is_exception_free (rtx, int, int);
+static int is_exception_free (rtx_insn *, int, int);
static bool sets_likely_spilled (rtx);
static void sets_likely_spilled_1 (rtx, const_rtx, void *);
static void compute_block_dependences (int);
static void schedule_region (int);
-static void concat_insn_mem_list (rtx_insn_list *, rtx,
- rtx_insn_list **, rtx *);
+static void concat_insn_mem_list (rtx_insn_list *, rtx_expr_list *,
+ rtx_insn_list **, rtx_expr_list **);
static void propagate_deps (int, struct deps_desc *);
static void free_pending_lists (void);
if (regno < FIRST_PSEUDO_REGISTER)
{
/* Check for hard registers. */
- int j = hard_regno_nregs[regno][GET_MODE (reg)];
+ int j = REG_NREGS (reg);
while (--j >= 0)
{
for (i = 0; i < candidate_table[src].split_bbs.nr_members; i++)
for (i = 0; i < candidate_table[src].update_bbs.nr_members; i++)
{
basic_block b = candidate_table[src].update_bbs.first_member[i];
-
- if (HARD_REGISTER_NUM_P (regno))
- bitmap_set_range (df_get_live_in (b), regno,
- hard_regno_nregs[regno][GET_MODE (reg)]);
- else
- bitmap_set_bit (df_get_live_in (b), regno);
+ bitmap_set_range (df_get_live_in (b), regno, REG_NREGS (reg));
}
}
}
block src to trg. */
static void
-update_live (rtx insn, int src)
+update_live (rtx_insn *insn, int src)
{
/* Find the registers set by instruction. */
if (GET_CODE (PATTERN (insn)) == SET
branch depending on insn, that guards the speculative load. */
static int
-find_conditional_protection (rtx insn, int load_insn_bb)
+find_conditional_protection (rtx_insn *insn, int load_insn_bb)
{
sd_iterator_def sd_it;
dep_t dep;
and 0 otherwise. */
static int
-is_exception_free (rtx insn, int bb_src, int bb_trg)
+is_exception_free (rtx_insn *insn, int bb_src, int bb_trg)
{
int insn_class = haifa_classify_insn (insn);
static void
init_ready_list (void)
{
- rtx prev_head = current_sched_info->prev_head;
- rtx next_tail = current_sched_info->next_tail;
+ rtx_insn *prev_head = current_sched_info->prev_head;
+ rtx_insn *next_tail = current_sched_info->next_tail;
int bb_src;
rtx_insn *insn;
&& (GET_CODE (PATTERN (insn)) == USE
|| GET_CODE (PATTERN (insn)) == CLOBBER
|| can_throw_internal (insn)
-#ifdef HAVE_cc0
- || sets_cc0_p (PATTERN (insn))
-#endif
+ || (HAVE_cc0 && sets_cc0_p (PATTERN (insn)))
|| (!reload_completed
&& sets_likely_spilled (PATTERN (insn)))))
|| NOTE_P (insn)
static struct deps_desc *bb_deps;
static void
-concat_insn_mem_list (rtx_insn_list *copy_insns, rtx copy_mems,
+concat_insn_mem_list (rtx_insn_list *copy_insns,
+ rtx_expr_list *copy_mems,
rtx_insn_list **old_insns_p,
- rtx *old_mems_p)
+ rtx_expr_list **old_mems_p)
{
rtx_insn_list *new_insns = *old_insns_p;
- rtx new_mems = *old_mems_p;
+ rtx_expr_list *new_mems = *old_mems_p;
while (copy_insns)
{
new_insns = alloc_INSN_LIST (copy_insns->insn (), new_insns);
- new_mems = alloc_EXPR_LIST (VOIDmode, XEXP (copy_mems, 0), new_mems);
+ new_mems = alloc_EXPR_LIST (VOIDmode, copy_mems->element (), new_mems);
copy_insns = copy_insns->next ();
- copy_mems = XEXP (copy_mems, 1);
+ copy_mems = copy_mems->next ();
}
*old_insns_p = new_insns;
return 0;
}
+static unsigned int
+rest_of_handle_sched_fusion (void)
+{
+#ifdef INSN_SCHEDULING
+ sched_fusion = true;
+ schedule_insns ();
+ sched_fusion = false;
+#endif
+ return 0;
+}
+
namespace {
const pass_data pass_data_live_range_shrinkage =
{
return new pass_sched2 (ctxt);
}
+
+namespace {
+
+const pass_data pass_data_sched_fusion =
+{
+ RTL_PASS, /* type */
+ "sched_fusion", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_SCHED_FUSION, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_df_finish, /* todo_flags_finish */
+};
+
+class pass_sched_fusion : public rtl_opt_pass
+{
+public:
+ pass_sched_fusion (gcc::context *ctxt)
+ : rtl_opt_pass (pass_data_sched_fusion, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *);
+ virtual unsigned int execute (function *)
+ {
+ return rest_of_handle_sched_fusion ();
+ }
+
+}; // class pass_sched2
+
+bool
+pass_sched_fusion::gate (function *)
+{
+#ifdef INSN_SCHEDULING
+ /* Scheduling fusion relies on peephole2 to do real fusion work,
+ so only enable it if peephole2 is in effect. */
+ return (optimize > 0 && flag_peephole2
+ && flag_schedule_fusion && targetm.sched.fusion_priority != NULL);
+#else
+ return 0;
+#endif
+}
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_sched_fusion (gcc::context *ctxt)
+{
+ return new pass_sched_fusion (ctxt);
+}