#include "config.h"
#include "system.h"
#include "toplev.h"
#include "rtl.h"
#include "tm_p.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "regs.h"
#include "function.h"
#include "flags.h"
#include "insn-config.h"
#include "insn-attr.h"
#include "except.h"
#include "toplev.h"
#include "recog.h"
#include "cfglayout.h"
#include "sched-int.h"
static int target_n_insns;
static int sched_n_insns;
static void init_ready_list PARAMS ((struct ready_list *));
static int can_schedule_ready_p PARAMS ((rtx));
static int new_ready PARAMS ((rtx));
static int schedule_more_p PARAMS ((void));
static const char *print_insn PARAMS ((rtx, int));
static int rank PARAMS ((rtx, rtx));
static int contributes_to_priority PARAMS ((rtx, rtx));
static void compute_jump_reg_dependencies PARAMS ((rtx, regset));
static void schedule_ebb PARAMS ((rtx, rtx));
static int
schedule_more_p ()
{
return sched_n_insns < target_n_insns;
}
static void
init_ready_list (ready)
struct ready_list *ready;
{
rtx prev_head = current_sched_info->prev_head;
rtx next_tail = current_sched_info->next_tail;
rtx insn;
target_n_insns = 0;
sched_n_insns = 0;
#if 0
if (sched_verbose >= 5)
debug_dependencies ();
#endif
for (insn = NEXT_INSN (prev_head); insn != next_tail; insn = NEXT_INSN (insn))
{
rtx next;
if (! INSN_P (insn))
continue;
next = NEXT_INSN (insn);
if (INSN_DEP_COUNT (insn) == 0
&& (SCHED_GROUP_P (next) == 0 || ! INSN_P (next)))
ready_add (ready, insn);
if (!(SCHED_GROUP_P (insn)))
target_n_insns++;
}
}
static int
can_schedule_ready_p (insn)
rtx insn ATTRIBUTE_UNUSED;
{
sched_n_insns++;
return 1;
}
static int
new_ready (next)
rtx next ATTRIBUTE_UNUSED;
{
return 1;
}
static const char *
print_insn (insn, aligned)
rtx insn;
int aligned ATTRIBUTE_UNUSED;
{
static char tmp[80];
sprintf (tmp, "%4d", INSN_UID (insn));
return tmp;
}
static int
rank (insn1, insn2)
rtx insn1 ATTRIBUTE_UNUSED, insn2 ATTRIBUTE_UNUSED;
{
return 0;
}
static int
contributes_to_priority (next, insn)
rtx next ATTRIBUTE_UNUSED, insn ATTRIBUTE_UNUSED;
{
return 1;
}
static void
compute_jump_reg_dependencies (insn, set)
rtx insn;
regset set;
{
basic_block b = BLOCK_FOR_INSN (insn);
edge e;
for (e = b->succ; e; e = e->succ_next)
if ((e->flags & EDGE_FALLTHRU) == 0)
{
bitmap_operation (set, set, e->dest->global_live_at_start,
BITMAP_IOR);
}
}
static struct sched_info ebb_sched_info =
{
init_ready_list,
can_schedule_ready_p,
schedule_more_p,
new_ready,
rank,
print_insn,
contributes_to_priority,
compute_jump_reg_dependencies,
NULL, NULL,
NULL, NULL,
0, 1
};
static void
schedule_ebb (head, tail)
rtx head, tail;
{
int n_insns;
struct deps tmp_deps;
if (no_real_insns_p (head, tail))
return;
init_deps_global ();
init_deps (&tmp_deps);
sched_analyze (&tmp_deps, head, tail);
free_deps (&tmp_deps);
compute_forward_dependences (head, tail);
n_insns = set_priorities (head, tail);
current_sched_info->prev_head = PREV_INSN (head);
current_sched_info->next_tail = NEXT_INSN (tail);
if (write_symbols != NO_DEBUG)
{
save_line_notes (0, head, tail);
rm_line_notes (head, tail);
}
if (INSN_P (head))
{
rtx note;
for (note = REG_NOTES (head); note; note = XEXP (note, 1))
if (REG_NOTE_KIND (note) == REG_SAVE_NOTE)
{
remove_note (head, note);
note = XEXP (note, 1);
remove_note (head, note);
}
}
rm_other_notes (head, tail);
current_sched_info->queue_must_finish_empty = 1;
schedule_block (-1, n_insns);
if (sched_n_insns != n_insns)
abort ();
head = current_sched_info->head;
tail = current_sched_info->tail;
if (write_symbols != NO_DEBUG)
restore_line_notes (head, tail);
finish_deps_global ();
}
void
schedule_ebbs (dump_file)
FILE *dump_file;
{
int i;
if (n_basic_blocks == 0)
return;
scope_to_insns_initialize ();
sched_init (dump_file);
current_sched_info = &ebb_sched_info;
allocate_reg_life_data ();
compute_bb_for_insn (get_max_uid ());
for (i = 0; i < n_basic_blocks; i++)
{
rtx head = BASIC_BLOCK (i)->head;
rtx tail;
for (;;)
{
basic_block b = BASIC_BLOCK (i);
edge e;
tail = b->end;
if (i + 1 == n_basic_blocks
|| GET_CODE (BLOCK_HEAD (i + 1)) == CODE_LABEL)
break;
for (e = b->succ; e; e = e->succ_next)
if ((e->flags & EDGE_FALLTHRU) != 0)
break;
if (! e)
break;
if (GET_CODE (tail) == JUMP_INSN)
{
rtx x = find_reg_note (tail, REG_BR_PROB, 0);
if (x)
{
int pred_val = INTVAL (XEXP (x, 0));
if (pred_val > REG_BR_PROB_BASE / 2)
break;
}
}
i++;
}
while (head != tail)
{
if (GET_CODE (head) == NOTE)
head = NEXT_INSN (head);
else if (GET_CODE (tail) == NOTE)
tail = PREV_INSN (tail);
else if (GET_CODE (head) == CODE_LABEL)
head = NEXT_INSN (head);
else
break;
}
schedule_ebb (head, tail);
}
if (reload_completed)
reposition_prologue_and_epilogue_notes (get_insns ());
if (write_symbols != NO_DEBUG)
rm_redundant_line_notes ();
scope_to_insns_finalize ();
sched_finish ();
}