/* Instruction scheduling pass.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
and currently maintained by, Jim Wilson (wilson@cygnus.com)
/* Number of instructions in current scheduling region. */
static int rgn_n_insns;
-static int may_trap_exp (rtx, int);
+static int may_trap_exp (const_rtx, int);
/* Nonzero iff the address is comprised from at most 1 register. */
#define CONST_BASED_ADDRESS_P(x) \
as found by analyzing insn's expression. */
static int
-may_trap_exp (rtx x, int is_store)
+may_trap_exp (const_rtx x, int is_store)
{
enum rtx_code code;
}
}
-/* Classifies insn for the purpose of verifying that it can be
- moved speculatively, by examining it's patterns, returning:
+/* Classifies rtx X of an insn for the purpose of verifying that X can be
+ executed speculatively (and consequently the insn can be moved
+ speculatively), by examining X, returning:
TRAP_RISKY: store, or risky non-load insn (e.g. division by variable).
TRAP_FREE: non-load insn.
IFREE: load from a globally safe location.
PFREE_CANDIDATE, PRISKY_CANDIDATE: load that need to be checked for
being either PFREE or PRISKY. */
-int
-haifa_classify_insn (rtx insn)
+static int
+haifa_classify_rtx (const_rtx x)
{
- rtx pat = PATTERN (insn);
int tmp_class = TRAP_FREE;
int insn_class = TRAP_FREE;
enum rtx_code code;
- if (GET_CODE (pat) == PARALLEL)
+ if (GET_CODE (x) == PARALLEL)
{
- int i, len = XVECLEN (pat, 0);
+ int i, len = XVECLEN (x, 0);
for (i = len - 1; i >= 0; i--)
{
- code = GET_CODE (XVECEXP (pat, 0, i));
- switch (code)
- {
- case CLOBBER:
- /* Test if it is a 'store'. */
- tmp_class = may_trap_exp (XEXP (XVECEXP (pat, 0, i), 0), 1);
- break;
- case SET:
- /* Test if it is a store. */
- tmp_class = may_trap_exp (SET_DEST (XVECEXP (pat, 0, i)), 1);
- if (tmp_class == TRAP_RISKY)
- break;
- /* Test if it is a load. */
- tmp_class
- = WORST_CLASS (tmp_class,
- may_trap_exp (SET_SRC (XVECEXP (pat, 0, i)),
- 0));
- break;
- case COND_EXEC:
- case TRAP_IF:
- tmp_class = TRAP_RISKY;
- break;
- default:
- ;
- }
+ tmp_class = haifa_classify_rtx (XVECEXP (x, 0, i));
insn_class = WORST_CLASS (insn_class, tmp_class);
if (insn_class == TRAP_RISKY || insn_class == IRISKY)
break;
}
else
{
- code = GET_CODE (pat);
+ code = GET_CODE (x);
switch (code)
{
case CLOBBER:
/* Test if it is a 'store'. */
- tmp_class = may_trap_exp (XEXP (pat, 0), 1);
+ tmp_class = may_trap_exp (XEXP (x, 0), 1);
break;
case SET:
/* Test if it is a store. */
- tmp_class = may_trap_exp (SET_DEST (pat), 1);
+ tmp_class = may_trap_exp (SET_DEST (x), 1);
if (tmp_class == TRAP_RISKY)
break;
/* Test if it is a load. */
tmp_class =
WORST_CLASS (tmp_class,
- may_trap_exp (SET_SRC (pat), 0));
+ may_trap_exp (SET_SRC (x), 0));
break;
case COND_EXEC:
+ tmp_class = haifa_classify_rtx (COND_EXEC_CODE (x));
+ if (tmp_class == TRAP_RISKY)
+ break;
+ tmp_class = WORST_CLASS (tmp_class,
+ may_trap_exp (COND_EXEC_TEST (x), 0));
+ break;
case TRAP_IF:
tmp_class = TRAP_RISKY;
break;
return insn_class;
}
+int
+haifa_classify_insn (const_rtx insn)
+{
+ return haifa_classify_rtx (PATTERN (insn));
+}
+
+
/* A typedef for rtx vector. */
typedef VEC(rtx, heap) *rtx_vec_t;
static void swap_sort (rtx *, int);
static void queue_insn (rtx, int);
static int schedule_insn (rtx);
-static int find_set_reg_weight (rtx);
+static int find_set_reg_weight (const_rtx);
static void find_insn_reg_weight (basic_block);
static void find_insn_reg_weight1 (rtx);
static void adjust_priority (rtx);
#ifdef ENABLE_CHECKING
static int has_edge_p (VEC(edge,gc) *, int);
static void check_cfg (rtx, rtx);
-static void check_sched_flags (void);
#endif
#endif /* INSN_SCHEDULING */
HAIFA_INLINE static void
advance_one_cycle (void)
{
+ if (targetm.sched.dfa_pre_advance_cycle)
+ targetm.sched.dfa_pre_advance_cycle ();
+
if (targetm.sched.dfa_pre_cycle_insn)
state_transition (curr_state,
targetm.sched.dfa_pre_cycle_insn ());
if (targetm.sched.dfa_post_cycle_insn)
state_transition (curr_state,
targetm.sched.dfa_post_cycle_insn ());
+
+ if (targetm.sched.dfa_post_advance_cycle)
+ targetm.sched.dfa_post_advance_cycle ();
}
/* Clock at which the previous instruction was issued. */
/* Return nonzero if there are no real insns in the range [ HEAD, TAIL ]. */
int
-no_real_insns_p (rtx head, rtx tail)
+no_real_insns_p (const_rtx head, const_rtx tail)
{
while (head != NEXT_INSN (tail))
{
a new register is not needed. */
static int
-find_set_reg_weight (rtx x)
+find_set_reg_weight (const_rtx x)
{
if (GET_CODE (x) == CLOBBER
&& register_operand (SET_DEST (x), VOIDmode))
{
int cost;
+ if (prev_insn == current_sched_info->prev_head)
+ {
+ prev_insn = NULL;
+ break;
+ }
+
if (!NOTE_P (prev_insn))
{
dep_t dep;
gcc_assert (BB_END (bb) == last);
}
- set_block_for_insn (insn, bb);
- df_insn_change_bb (insn);
+ df_insn_change_bb (insn, bb);
/* Update BB_END, if needed. */
if (BB_END (bb) == last)
else
/* So we won't read anything accidentally. */
spec_info = 0;
-#ifdef ENABLE_CHECKING
- check_sched_flags ();
-#endif
}
else
/* So we won't read anything accidentally. */
else
{
/* One of the NEXT's dependencies has been resolved.
- Recalcute NEXT's status. */
+ Recalculate NEXT's status. */
*ts &= ~SPECULATIVE & ~HARD_DEP;
due to backend decision. Hence we can't let the
probability of the speculative dep to decrease. */
dep_weak (ds) <= dep_weak (fs))
- /* Transform it to be in speculative. */
- ds = (ds & ~BEGIN_SPEC) | fs;
+ {
+ ds_t new_ds;
+
+ new_ds = (ds & ~BEGIN_SPEC) | fs;
+
+ if (/* consumer can 'be in speculative'. */
+ sched_insn_is_legitimate_for_speculation_p (consumer,
+ new_ds))
+ /* Transform it to be in speculative. */
+ ds = new_ds;
+ }
}
else
/* Mark the dep as 'be in speculative'. */
DONE_SPEC (insn) = ts & BEGIN_SPEC;
CHECK_SPEC (check) = ts & BEGIN_SPEC;
- /* Luckyness of future speculations solely depends upon initial
+ /* Luckiness of future speculations solely depends upon initial
BEGIN speculation. */
if (ts & BEGIN_DATA)
fs = set_dep_weak (fs, BE_IN_DATA, get_dep_weak (ts, BEGIN_DATA));
/* Return true if INSN can potentially be speculated with type DS. */
bool
-sched_insn_is_legitimate_for_speculation_p (rtx insn, ds_t ds)
+sched_insn_is_legitimate_for_speculation_p (const_rtx insn, ds_t ds)
{
if (HAS_INTERNAL_DEP (insn))
return false;
gcc_assert (bb == 0);
}
-
-/* Perform a few consistency checks of flags in different data structures. */
-static void
-check_sched_flags (void)
-{
- unsigned int f = current_sched_info->flags;
-
- if (flag_sched_stalled_insns)
- gcc_assert (!(f & DO_SPECULATION));
- if (f & DO_SPECULATION)
- gcc_assert (!flag_sched_stalled_insns
- && spec_info
- && spec_info->mask);
-}
#endif /* ENABLE_CHECKING */
#endif /* INSN_SCHEDULING */