#include "target.h"
#include "output.h"
#include "params.h"
+#include "dbgcnt.h"
#ifdef INSN_SCHEDULING
/* Counters of different types of speculative instructions. */
static int nr_begin_data, nr_be_in_data, nr_begin_control, nr_be_in_control;
-/* Pointers to GLAT data. See init_glat for more information. */
-regset *glat_start, *glat_end;
-
/* Array used in {unlink, restore}_bb_notes. */
static rtx *bb_header = 0;
static void ready_remove_insn (rtx);
static int max_issue (struct ready_list *, int *, int);
-static rtx choose_ready (struct ready_list *);
+static int choose_ready (struct ready_list *, rtx *);
static void fix_inter_tick (rtx, rtx);
static int fix_tick_ready (rtx);
static void fix_jump_move (rtx);
static void move_block_after_check (rtx);
static void move_succs (VEC(edge,gc) **, basic_block);
-static void init_glat (void);
-static void init_glat1 (basic_block);
-static void attach_life_info1 (basic_block);
-static void free_glat (void);
static void sched_remove_insn (rtx);
static void clear_priorities (rtx, rtx_vec_t *);
static void calc_priorities (rtx_vec_t);
{
rtx insn;
rtx link;
+ rtx skip_insn;
q_ptr = NEXT_Q (q_ptr);
+ if (dbg_cnt (sched_insn) == false)
+ /* If debug counter is activated do not requeue insn next after
+ last_scheduled_insn. */
+ skip_insn = next_nonnote_insn (last_scheduled_insn);
+ else
+ skip_insn = NULL_RTX;
+
/* Add all pending insns that can be scheduled without stalls to the
ready list. */
for (link = insn_queue[q_ptr]; link; link = XEXP (link, 1))
See the comment in schedule_block for the rationale. */
if (!reload_completed
&& ready->n_ready > MAX_SCHED_READY_INSNS
- && !SCHED_GROUP_P (insn))
+ && !SCHED_GROUP_P (insn)
+ && insn != skip_insn)
{
if (sched_verbose >= 2)
fprintf (sched_dump, "requeued because ready full\n");
}
set_block_for_insn (insn, bb);
+ df_insn_change_bb (insn);
/* Update BB_END, if needed. */
if (BB_END (bb) == last)
/* The following function chooses insn from READY and modifies
*N_READY and READY. The following function is used only for first
- cycle multipass scheduling. */
-
-static rtx
-choose_ready (struct ready_list *ready)
+ cycle multipass scheduling.
+ Return:
+ -1 if cycle should be advanced,
+ 0 if INSN_PTR is set to point to the desirable insn,
+ 1 if choose_ready () should be restarted without advancing the cycle. */
+static int
+choose_ready (struct ready_list *ready, rtx *insn_ptr)
{
- int lookahead = 0;
+ int lookahead;
+
+ if (dbg_cnt (sched_insn) == false)
+ {
+ rtx insn;
+
+ insn = next_nonnote_insn (last_scheduled_insn);
+
+ if (QUEUE_INDEX (insn) == QUEUE_READY)
+ /* INSN is in the ready_list. */
+ {
+ ready_remove_insn (insn);
+ *insn_ptr = insn;
+ return 0;
+ }
+
+ /* INSN is in the queue. Advance cycle to move it to the ready list. */
+ return -1;
+ }
+
+ lookahead = 0;
if (targetm.sched.first_cycle_multipass_dfa_lookahead)
lookahead = targetm.sched.first_cycle_multipass_dfa_lookahead ();
if (lookahead <= 0 || SCHED_GROUP_P (ready_element (ready, 0)))
- return ready_remove_first (ready);
+ {
+ *insn_ptr = ready_remove_first (ready);
+ return 0;
+ }
else
{
/* Try to choose the better insn. */
}
insn = ready_element (ready, 0);
if (INSN_CODE (insn) < 0)
- return ready_remove_first (ready);
+ {
+ *insn_ptr = ready_remove_first (ready);
+ return 0;
+ }
if (spec_info
&& spec_info->flags & (PREFER_NON_DATA_SPEC
list. */
{
change_queue_index (insn, 1);
- return 0;
+ return 1;
}
max_points = ISSUE_POINTS (insn);
}
if (max_issue (ready, &index, max_points) == 0)
- return ready_remove_first (ready);
+ {
+ *insn_ptr = ready_remove_first (ready);
+ return 0;
+ }
else
- return ready_remove (ready, index);
+ {
+ *insn_ptr = ready_remove (ready, index);
+ return 0;
+ }
}
}
";;\t\t before reload => truncated to %d insns\n", i);
}
- /* Delay all insns past it for 1 cycle. */
- while (i < ready.n_ready)
- queue_insn (ready_remove (&ready, i), 1);
+ /* Delay all insns past it for 1 cycle. If debug counter is
+ activated make an exception for the insn right after
+ last_scheduled_insn. */
+ {
+ rtx skip_insn;
+
+ if (dbg_cnt (sched_insn) == false)
+ skip_insn = next_nonnote_insn (last_scheduled_insn);
+ else
+ skip_insn = NULL_RTX;
+
+ while (i < ready.n_ready)
+ {
+ rtx insn;
+
+ insn = ready_remove (&ready, i);
+
+ if (insn != skip_insn)
+ queue_insn (insn, 1);
+ }
+ }
}
/* Now we can restore basic block notes and maintain precise cfg. */
/* Select and remove the insn from the ready list. */
if (sort_p)
{
- insn = choose_ready (&ready);
- if (!insn)
+ int res;
+
+ insn = NULL_RTX;
+ res = choose_ready (&ready, &insn);
+
+ if (res < 0)
+ /* Finish cycle. */
+ break;
+ if (res > 0)
+ /* Restart choose_ready (). */
continue;
+
+ gcc_assert (insn != NULL_RTX);
}
else
insn = ready_remove_first (&ready);
generate_recovery_code (insn);
if (control_flow_insn_p (last_scheduled_insn)
- /* This is used to to switch basic blocks by request
+ /* This is used to switch basic blocks by request
from scheduler front-end (actually, sched-ebb.c only).
This is used to process blocks with single fallthru
edge. If succeeding block has jump, it [jump] will try
init_alias_analysis ();
old_last_basic_block = 0;
- glat_start = 0;
- glat_end = 0;
extend_bb ();
- if (current_sched_info->flags & USE_GLAT)
- init_glat ();
-
/* Compute INSN_REG_WEIGHT for all blocks. We must do this before
removing death notes. */
FOR_EACH_BB_REVERSE (b)
dfa_finish ();
free_dependency_caches ();
end_alias_analysis ();
- free_glat ();
if (targetm.sched.md_finish_global)
targetm.sched.md_finish_global (sched_dump, sched_verbose);
rec = BLOCK_FOR_INSN (check);
- twin = emit_insn_before (copy_rtx (PATTERN (insn)), BB_END (rec));
+ twin = emit_insn_before (copy_insn (PATTERN (insn)), BB_END (rec));
extend_global (twin);
copy_deps_list_change_con (INSN_RESOLVED_BACK_DEPS (twin),
old_last_basic_block = last_basic_block;
- if (current_sched_info->flags & USE_GLAT)
- {
- glat_start = xrealloc (glat_start,
- last_basic_block * sizeof (*glat_start));
- glat_end = xrealloc (glat_end, last_basic_block * sizeof (*glat_end));
- }
-
/* The following is done to keep current_sched_info->next_tail non null. */
insn = BB_END (EXIT_BLOCK_PTR->prev_bb);
void
add_block (basic_block bb, basic_block ebb)
{
- gcc_assert (current_sched_info->flags & DETACH_LIFE_INFO
- && bb->il.rtl->global_live_at_start == 0
- && bb->il.rtl->global_live_at_end == 0);
+ gcc_assert (current_sched_info->flags & NEW_BBS);
extend_bb ();
- glat_start[bb->index] = 0;
- glat_end[bb->index] = 0;
-
if (current_sched_info->add_block)
/* This changes only data structures of the front-end. */
current_sched_info->add_block (bb, ebb);
move_succs (&(jump_bb->succs), bb);
move_succs (&(jump_bb_next->succs), jump_bb);
move_succs (&t, jump_bb_next);
+
+ df_mark_solutions_dirty ();
if (current_sched_info->fix_recovery_cfg)
current_sched_info->fix_recovery_cfg
*succsp = 0;
}
-/* Initialize GLAT (global_live_at_{start, end}) structures.
- GLAT structures are used to substitute global_live_{start, end}
- regsets during scheduling. This is necessary to use such functions as
- split_block (), as they assume consistency of register live information. */
-static void
-init_glat (void)
-{
- basic_block bb;
-
- FOR_ALL_BB (bb)
- init_glat1 (bb);
-}
-
-/* Helper function for init_glat. */
-static void
-init_glat1 (basic_block bb)
-{
- gcc_assert (bb->il.rtl->global_live_at_start != 0
- && bb->il.rtl->global_live_at_end != 0);
-
- glat_start[bb->index] = bb->il.rtl->global_live_at_start;
- glat_end[bb->index] = bb->il.rtl->global_live_at_end;
-
- if (current_sched_info->flags & DETACH_LIFE_INFO)
- {
- bb->il.rtl->global_live_at_start = 0;
- bb->il.rtl->global_live_at_end = 0;
- }
-}
-
-/* Attach reg_live_info back to basic blocks.
- Also save regsets, that should not have been changed during scheduling,
- for checking purposes (see check_reg_live). */
-void
-attach_life_info (void)
-{
- basic_block bb;
-
- FOR_ALL_BB (bb)
- attach_life_info1 (bb);
-}
-
-/* Helper function for attach_life_info. */
-static void
-attach_life_info1 (basic_block bb)
-{
- gcc_assert (bb->il.rtl->global_live_at_start == 0
- && bb->il.rtl->global_live_at_end == 0);
-
- if (glat_start[bb->index])
- {
- gcc_assert (glat_end[bb->index]);
-
- bb->il.rtl->global_live_at_start = glat_start[bb->index];
- bb->il.rtl->global_live_at_end = glat_end[bb->index];
-
- /* Make them NULL, so they won't be freed in free_glat. */
- glat_start[bb->index] = 0;
- glat_end[bb->index] = 0;
-
-#ifdef ENABLE_CHECKING
- if (bb->index < NUM_FIXED_BLOCKS
- || current_sched_info->region_head_or_leaf_p (bb, 0))
- {
- glat_start[bb->index] = ALLOC_REG_SET (®_obstack);
- COPY_REG_SET (glat_start[bb->index],
- bb->il.rtl->global_live_at_start);
- }
-
- if (bb->index < NUM_FIXED_BLOCKS
- || current_sched_info->region_head_or_leaf_p (bb, 1))
- {
- glat_end[bb->index] = ALLOC_REG_SET (®_obstack);
- COPY_REG_SET (glat_end[bb->index], bb->il.rtl->global_live_at_end);
- }
-#endif
- }
- else
- {
- gcc_assert (!glat_end[bb->index]);
-
- bb->il.rtl->global_live_at_start = ALLOC_REG_SET (®_obstack);
- bb->il.rtl->global_live_at_end = ALLOC_REG_SET (®_obstack);
- }
-}
-
-/* Free GLAT information. */
-static void
-free_glat (void)
-{
-#ifdef ENABLE_CHECKING
- if (current_sched_info->flags & DETACH_LIFE_INFO)
- {
- basic_block bb;
-
- FOR_ALL_BB (bb)
- {
- if (glat_start[bb->index])
- FREE_REG_SET (glat_start[bb->index]);
- if (glat_end[bb->index])
- FREE_REG_SET (glat_end[bb->index]);
- }
- }
-#endif
-
- free (glat_start);
- free (glat_end);
-}
-
/* Remove INSN from the instruction stream.
INSN should have any dependencies. */
static void
gcc_assert (!(f & DO_SPECULATION));
if (f & DO_SPECULATION)
gcc_assert (!flag_sched_stalled_insns
- && (f & DETACH_LIFE_INFO)
&& spec_info
&& spec_info->mask);
- if (f & DETACH_LIFE_INFO)
- gcc_assert (f & USE_GLAT);
-}
-
-/* Check global_live_at_{start, end} regsets.
- If FATAL_P is TRUE, then abort execution at the first failure.
- Otherwise, print diagnostics to STDERR (this mode is for calling
- from debugger). */
-void
-check_reg_live (bool fatal_p)
-{
- basic_block bb;
-
- FOR_ALL_BB (bb)
- {
- int i;
-
- i = bb->index;
-
- if (glat_start[i])
- {
- bool b = bitmap_equal_p (bb->il.rtl->global_live_at_start,
- glat_start[i]);
-
- if (!b)
- {
- gcc_assert (!fatal_p);
-
- fprintf (stderr, ";; check_reg_live_at_start (%d) failed.\n", i);
- }
- }
-
- if (glat_end[i])
- {
- bool b = bitmap_equal_p (bb->il.rtl->global_live_at_end,
- glat_end[i]);
-
- if (!b)
- {
- gcc_assert (!fatal_p);
-
- fprintf (stderr, ";; check_reg_live_at_end (%d) failed.\n", i);
- }
- }
- }
}
#endif /* ENABLE_CHECKING */