in_fallthru_bb_p (rtx insn, rtx succ)
{
basic_block bb = BLOCK_FOR_INSN (insn);
+ edge e;
if (bb == BLOCK_FOR_INSN (succ))
return true;
- if (find_fallthru_edge (bb))
- bb = find_fallthru_edge (bb)->dest;
+ e = find_fallthru_edge_from (bb);
+ if (e)
+ bb = e->dest;
else
return false;
/* Can't use regs which aren't saved by
the prologue. */
|| !TEST_HARD_REG_BIT (sel_hrd.regs_ever_used, cur_reg + i)
+ /* Can't use regs with non-null REG_BASE_VALUE, because adjusting
+ it affects aliasing globally and invalidates all AV sets. */
+ || get_reg_base_value (cur_reg + i)
#ifdef LEAF_REGISTERS
/* We can't use a non-leaf register if we're in a
leaf function. */
frame pointer, or we could not discover its class. */
if (fixed_regs[regno]
|| global_regs[regno]
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
|| (frame_pointer_needed && regno == HARD_FRAME_POINTER_REGNUM)
#else
|| (frame_pointer_needed && regno == FRAME_POINTER_REGNUM)
SET_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs,
FRAME_POINTER_REGNUM + i);
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
for (i = hard_regno_nregs[HARD_FRAME_POINTER_REGNUM][Pmode]; i--;)
SET_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs,
HARD_FRAME_POINTER_REGNUM + i);
}
/* Sort the vector. */
- qsort (VEC_address (expr_t, vec_av_set), VEC_length (expr_t, vec_av_set),
- sizeof (expr_t), sel_rank_for_schedule);
+ VEC_qsort (expr_t, vec_av_set, sel_rank_for_schedule);
/* We record maximal priority of insns in av set for current instruction
group. */
{
expr_t expr = VEC_index (expr_t, vec_av_set, n);
insn_t insn = EXPR_INSN_RTX (expr);
- char target_available;
+ signed char target_available;
bool is_orig_reg_p = true;
int need_cycles, new_prio;
gcc_assert (min_need_stall == 0);
/* Sort the vector. */
- qsort (VEC_address (expr_t, vec_av_set), VEC_length (expr_t, vec_av_set),
- sizeof (expr_t), sel_rank_for_schedule);
+ VEC_qsort (expr_t, vec_av_set, sel_rank_for_schedule);
if (sched_verbose >= 4)
{
if (dfa_lookahead > 0)
{
cycle_issued_insns = FENCE_ISSUED_INSNS (fence);
+ /* TODO: pass equivalent of first_cycle_insn_p to max_issue (). */
can_issue = max_issue (&ready, privileged_n,
- FENCE_STATE (fence), index);
+ FENCE_STATE (fence), true, index);
if (sched_verbose >= 2)
sel_print ("max_issue: we can issue %d insns, already did %d insns\n",
can_issue, FENCE_ISSUED_INSNS (fence));
{
can_issue_more = invoke_aftermath_hooks (fence, EXPR_INSN_RTX (best),
can_issue_more);
- if (can_issue_more == 0)
+ if (targetm.sched.variable_issue
+ && can_issue_more == 0)
*pneed_stall = 1;
}
move_cond_jump (rtx insn, bnd_t bnd)
{
edge ft_edge;
- basic_block block_from, block_next, block_new;
- rtx next, prev, link;
+ basic_block block_from, block_next, block_new, block_bnd, bb;
+ rtx next, prev, link, head;
- /* BLOCK_FROM holds basic block of the jump. */
block_from = BLOCK_FOR_INSN (insn);
+ block_bnd = BLOCK_FOR_INSN (BND_TO (bnd));
+ prev = BND_TO (bnd);
- /* Moving of jump should not cross any other jumps or
- beginnings of new basic blocks. */
- gcc_assert (block_from == BLOCK_FOR_INSN (BND_TO (bnd)));
+#ifdef ENABLE_CHECKING
+ /* Moving of jump should not cross any other jumps or beginnings of new
+ basic blocks. The only exception is when we move a jump through
+ mutually exclusive insns along fallthru edges. */
+ if (block_from != block_bnd)
+ {
+ bb = block_from;
+ for (link = PREV_INSN (insn); link != PREV_INSN (prev);
+ link = PREV_INSN (link))
+ {
+ if (INSN_P (link))
+ gcc_assert (sched_insns_conditions_mutex_p (insn, link));
+ if (BLOCK_FOR_INSN (link) && BLOCK_FOR_INSN (link) != bb)
+ {
+ gcc_assert (single_pred (bb) == BLOCK_FOR_INSN (link));
+ bb = BLOCK_FOR_INSN (link);
+ }
+ }
+ }
+#endif
/* Jump is moved to the boundary. */
- prev = BND_TO (bnd);
next = PREV_INSN (insn);
BND_TO (bnd) = insn;
- ft_edge = find_fallthru_edge (block_from);
+ ft_edge = find_fallthru_edge_from (block_from);
block_next = ft_edge->dest;
/* There must be a fallthrough block (or where should go
control flow in case of false jump predicate otherwise?). */
gcc_assert (block_new->next_bb == block_next
&& block_from->next_bb == block_new);
- gcc_assert (BB_END (block_from) == insn);
-
- /* Move all instructions except INSN from BLOCK_FROM to
- BLOCK_NEW. */
- for (link = prev; link != insn; link = NEXT_INSN (link))
+ /* Move all instructions except INSN to BLOCK_NEW. */
+ bb = block_bnd;
+ head = BB_HEAD (block_new);
+ while (bb != block_from->next_bb)
{
- EXPR_ORIG_BB_INDEX (INSN_EXPR (link)) = block_new->index;
- df_insn_change_bb (link, block_new);
- }
+ rtx from, to;
+ from = bb == block_bnd ? prev : sel_bb_head (bb);
+ to = bb == block_from ? next : sel_bb_end (bb);
- /* Set correct basic block and instructions properties. */
- BB_END (block_new) = PREV_INSN (insn);
+ /* The jump being moved can be the first insn in the block.
+ In this case we don't have to move anything in this block. */
+ if (NEXT_INSN (to) != from)
+ {
+ reorder_insns (from, to, head);
+
+ for (link = to; link != head; link = PREV_INSN (link))
+ EXPR_ORIG_BB_INDEX (INSN_EXPR (link)) = block_new->index;
+ head = to;
+ }
- NEXT_INSN (PREV_INSN (prev)) = insn;
- PREV_INSN (insn) = PREV_INSN (prev);
+ /* Cleanup possibly empty blocks left. */
+ block_next = bb->next_bb;
+ if (bb != block_from)
+ tidy_control_flow (bb, false);
+ bb = block_next;
+ }
/* Assert there is no jump to BLOCK_NEW, only fallthrough edge. */
gcc_assert (NOTE_INSN_BASIC_BLOCK_P (BB_HEAD (block_new)));
- PREV_INSN (prev) = BB_HEAD (block_new);
- NEXT_INSN (next) = NEXT_INSN (BB_HEAD (block_new));
- NEXT_INSN (BB_HEAD (block_new)) = prev;
- PREV_INSN (NEXT_INSN (next)) = next;
gcc_assert (!sel_bb_empty_p (block_from)
&& !sel_bb_empty_p (block_new));
blist_t *bnds_tailp1, *bndsp;
expr_t expr_vliw;
int need_stall;
- int was_stall = 0, scheduled_insns = 0, stall_iterations = 0;
+ int was_stall = 0, scheduled_insns = 0;
int max_insns = pipelining_p ? issue_rate : 2 * issue_rate;
int max_stall = pipelining_p ? 1 : 3;
bool last_insn_was_debug = false;
do
{
expr_vliw = find_best_expr (&av_vliw, bnds, fence, &need_stall);
- if (!expr_vliw && need_stall)
+ if (! expr_vliw && need_stall)
{
/* All expressions required a stall. Do not recompute av sets
as we'll get the same answer (modulo the insns between
the fence and its boundary, which will not be available for
- pipelining). */
- gcc_assert (! expr_vliw && stall_iterations < 2);
- was_stall++;
- /* If we are going to stall for too long, break to recompute av
+ pipelining).
+ If we are going to stall for too long, break to recompute av
sets and bring more insns for pipelining. */
+ was_stall++;
if (need_stall <= 3)
stall_for_cycles (fence, need_stall);
else
bookkeeping generated for another fence or for another path in current
move_op. */
gcc_assert (res == 1
- || (res == 0
- && av_set_could_be_blocked_by_bookkeeping_p (orig_ops,
+ || (res == 0
+ && av_set_could_be_blocked_by_bookkeeping_p (orig_ops,
static_params))
- || res == -1);
+ || res == -1);
#endif
/* Merge data, clean up, etc. */
init_seqno_1 (succ, visited_bbs, blocks_to_reschedule);
}
+ else if (blocks_to_reschedule)
+ bitmap_set_bit (forced_ebb_heads, succ->index);
}
for (insn = BB_END (bb); insn != note; insn = PREV_INSN (insn))
int last_clock = 0;
int haifa_last_clock = -1;
int haifa_clock = 0;
+ int issued_insns = 0;
insn_t insn;
if (targetm.sched.init)
haifa_cost = cost;
after_stall = 1;
}
-
+ if (haifa_cost == 0
+ && issued_insns == issue_rate)
+ haifa_cost = 1;
if (haifa_cost > 0)
{
int i = 0;
while (haifa_cost--)
{
advance_state (curr_state);
+ issued_insns = 0;
i++;
if (sched_verbose >= 2)
}
haifa_clock += i;
+ if (sched_verbose >= 2)
+ sel_print ("haifa clock: %d\n", haifa_clock);
}
else
gcc_assert (haifa_cost == 0);
&sort_p))
{
advance_state (curr_state);
+ issued_insns = 0;
haifa_clock++;
if (sched_verbose >= 2)
{
sel_print ("advance_state (dfa_new_cycle)\n");
debug_state (curr_state);
+ sel_print ("haifa clock: %d\n", haifa_clock + 1);
}
}
if (real_insn)
{
cost = state_transition (curr_state, insn);
+ issued_insns++;
if (sched_verbose >= 2)
- debug_state (curr_state);
-
+ {
+ sel_print ("scheduled insn %d, clock %d\n", INSN_UID (insn),
+ haifa_clock + 1);
+ debug_state (curr_state);
+ }
gcc_assert (cost < 0);
}
continue;
}
- if (bitmap_clear_bit (blocks_to_reschedule, bb->index))
+ if (bitmap_bit_p (blocks_to_reschedule, bb->index))
{
flist_tail_init (new_fences);