#define SET_REGBIT(TABLE, I, J) SET_HARD_REG_BIT (allocno[I].TABLE, J)
-/* This is turned off because it doesn't work right for DImode.
- (And it is only used for DImode, so the other cases are worthless.)
- The problem is that it isn't true that there is NO possibility of conflict;
- only that there is no conflict if the two pseudos get the exact same regs.
- If they were allocated with a partial overlap, there would be a conflict.
- We can't safely turn off the conflict unless we have another way to
- prevent the partial overlap.
-
- Idea: change hard_reg_conflicts so that instead of recording which
- hard regs the allocno may not overlap, it records where the allocno
- may not start. Change both where it is used and where it is updated.
- Then there is a way to record that (reg:DI 108) may start at 10
- but not at 9 or 11. There is still the question of how to record
- this semi-conflict between two pseudos. */
-#if 0
-/* Reg pairs for which conflict after the current insn
- is inhibited by a REG_NO_CONFLICT note.
- If the table gets full, we ignore any other notes--that is conservative. */
-#define NUM_NO_CONFLICT_PAIRS 4
-/* Number of pairs in use in this insn. */
-int n_no_conflict_pairs;
-static struct { int allocno1, allocno2;}
- no_conflict_pairs[NUM_NO_CONFLICT_PAIRS];
-#endif /* 0 */
-
/* Return true if *LOC contains an asm. */
static int
rtx insn;
FOR_BB_INSNS_REVERSE (bb, insn)
{
- struct df_ref **def_rec;
+ df_ref *def_rec;
if (insn_contains_asm (insn))
for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
{
- struct df_ref *def = *def_rec;
+ df_ref def = *def_rec;
unsigned int dregno = DF_REF_REGNO (def);
if (dregno < FIRST_PSEUDO_REGISTER)
{
/* All registers that can be eliminated. */
-static HARD_REG_SET eliminable_regset;
+HARD_REG_SET eliminable_regset;
static int regno_compare (const void *, const void *);
static int allocno_compare (const void *, const void *);
static void set_preferences (void);
static void find_reg (int, HARD_REG_SET, int, int, int);
static void dump_conflicts (FILE *);
-static void build_insn_chain (void);
\f
/* Look through the list of eliminable registers. Set ELIM_SET to the
This will normally be called with ELIM_SET as the file static
variable eliminable_regset, and NO_GLOBAL_SET as the file static
- variable NO_GLOBAL_ALLOC_REGS. */
+ variable NO_GLOBAL_ALLOC_REGS.
+
+ It also initializes global flag frame_pointer_needed. */
static void
compute_regsets (HARD_REG_SET *elim_set,
/* Like regs_ever_live, but 1 if a reg is set or clobbered from an asm.
Unlike regs_ever_live, elements of this array corresponding to
eliminable regs like the frame pointer are set if an asm sets them. */
- char *regs_asm_clobbered = alloca (FIRST_PSEUDO_REGISTER * sizeof (char));
+ char *regs_asm_clobbered = XALLOCAVEC (char, FIRST_PSEUDO_REGISTER);
#ifdef ELIMINABLE_REGS
static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
size_t i;
#endif
+
+ /* FIXME: If EXIT_IGNORE_STACK is set, we will not save and restore
+ sp for alloca. So we can't eliminate the frame pointer in that
+ case. At some point, we should improve this by emitting the
+ sp-adjusting insns for this case. */
int need_fp
= (! flag_omit_frame_pointer
- || (current_function_calls_alloca && EXIT_IGNORE_STACK)
+ || (cfun->calls_alloca && EXIT_IGNORE_STACK)
+ || crtl->accesses_prior_frames
+ || crtl->stack_realign_needed
|| FRAME_POINTER_REQUIRED);
+ frame_pointer_needed = need_fp;
+
max_regno = max_reg_num ();
compact_blocks ();
{
bool cannot_elim
= (! CAN_ELIMINATE (eliminables[i].from, eliminables[i].to)
- || (eliminables[i].to == STACK_POINTER_REGNUM && need_fp));
+ || (eliminables[i].to == STACK_POINTER_REGNUM
+ && need_fp
+ && (! SUPPORTS_STACK_ALIGNMENT
+ || ! stack_realign_fp)));
if (!regs_asm_clobbered[eliminables[i].from])
{
if (REG_N_REFS (i) != 0 && REG_LIVE_LENGTH (i) != -1
/* Don't allocate pseudos that cross calls,
if this function receives a nonlocal goto. */
- && (! current_function_has_nonlocal_label
+ && (! cfun->has_nonlocal_label
|| REG_N_CALLS_CROSSED (i) == 0))
{
int blk = regno_basic_block (i);
int i, best_reg, pass;
HARD_REG_SET used, used1, used2;
- enum reg_class class = (alt_regs_p
+ enum reg_class rclass = (alt_regs_p
? reg_alternate_class (allocno[num].reg)
: reg_preferred_class (allocno[num].reg));
enum machine_mode mode = PSEUDO_REGNO_MODE (allocno[num].reg);
if (losers)
IOR_HARD_REG_SET (used1, losers);
- IOR_COMPL_HARD_REG_SET (used1, reg_class_contents[(int) class]);
+ IOR_COMPL_HARD_REG_SET (used1, reg_class_contents[(int) rclass]);
#ifdef EH_RETURN_DATA_REGNO
if (allocno[num].no_eh_reg)
if (! accept_call_clobbered
&& allocno[num].calls_crossed != 0
&& allocno[num].throwing_calls_crossed == 0
- && CALLER_SAVE_PROFITABLE (optimize_size ? allocno[num].n_refs : allocno[num].freq,
- optimize_size ? allocno[num].calls_crossed
+ && CALLER_SAVE_PROFITABLE (optimize_function_for_size_p (cfun) ? allocno[num].n_refs : allocno[num].freq,
+ optimize_function_for_size_p (cfun) ? allocno[num].calls_crossed
: allocno[num].freq_calls_crossed))
{
HARD_REG_SET new_losers;
FOR_EACH_BB (bb)
{
- regset r = DF_LIVE_IN (bb);
+ /* We don't use LIVE info in IRA. */
+ regset r = (flag_ira ? DF_LR_IN (bb) : DF_LIVE_IN (bb));
if (REGNO_REG_SET_P (r, from))
{
CLEAR_REGNO_REG_SET (r, from);
print_insn_chain (file, c);
}
+/* Return true if pseudo REGNO should be added to set live_throughout
+ or dead_or_set of the insn chains for reload consideration. */
+
+static bool
+pseudo_for_reload_consideration_p (int regno)
+{
+ /* Consider spilled pseudos too for IRA because they still have a
+ chance to get hard-registers in the reload when IRA is used. */
+ return (reg_renumber[regno] >= 0
+ || (flag_ira && optimize && flag_ira_share_spill_slots));
+}
/* Walk the insns of the current function and build reload_insn_chain,
and record register life information. */
-static void
+void
build_insn_chain (void)
{
unsigned int i;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (TEST_HARD_REG_BIT (eliminable_regset, i))
bitmap_set_bit (elim_regset, i);
-
FOR_EACH_BB_REVERSE (bb)
{
bitmap_iterator bi;
EXECUTE_IF_SET_IN_BITMAP (df_get_live_out (bb), FIRST_PSEUDO_REGISTER, i, bi)
{
- if (reg_renumber[i] >= 0)
+ if (pseudo_for_reload_consideration_p (i))
bitmap_set_bit (live_relevant_regs, i);
}
if (!NOTE_P (insn) && !BARRIER_P (insn))
{
unsigned int uid = INSN_UID (insn);
- struct df_ref **def_rec;
- struct df_ref **use_rec;
+ df_ref *def_rec;
+ df_ref *use_rec;
c = new_insn_chain ();
c->next = next;
if (INSN_P (insn))
for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
{
- struct df_ref *def = *def_rec;
+ df_ref def = *def_rec;
unsigned int regno = DF_REF_REGNO (def);
/* Ignore may clobbers because these are generated
if (!fixed_regs[regno])
bitmap_set_bit (&c->dead_or_set, regno);
}
- else if (reg_renumber[regno] >= 0)
+ else if (pseudo_for_reload_consideration_p (regno))
bitmap_set_bit (&c->dead_or_set, regno);
}
- if ((regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+ if ((regno < FIRST_PSEUDO_REGISTER
+ || reg_renumber[regno] >= 0
+ || (flag_ira && optimize))
&& (!DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL)))
{
rtx reg = DF_REF_REG (def);
if (INSN_P (insn))
for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
{
- struct df_ref *use = *use_rec;
+ df_ref use = *use_rec;
unsigned int regno = DF_REF_REGNO (use);
rtx reg = DF_REF_REG (use);
if (!fixed_regs[regno])
bitmap_set_bit (&c->dead_or_set, regno);
}
- else if (reg_renumber[regno] >= 0)
+ else if (pseudo_for_reload_consideration_p (regno))
bitmap_set_bit (&c->dead_or_set, regno);
}
- if (regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+ if (regno < FIRST_PSEUDO_REGISTER
+ || pseudo_for_reload_consideration_p (regno))
{
if (GET_CODE (reg) == SUBREG
&& !DF_REF_FLAGS_IS_SET (use,
fprintf (file, "\n\n");
}
+
+static bool
+gate_handle_global_alloc (void)
+{
+ return ! flag_ira;
+}
+
/* Run old register allocator. Return TRUE if we must exit
rest_of_compilation upon return. */
static unsigned int
failure = reload (get_insns (), 0);
}
- if (dump_enabled_p (pass_global_alloc.static_pass_number))
+ if (dump_enabled_p (pass_global_alloc.pass.static_pass_number))
{
timevar_push (TV_DUMP);
dump_global_regs (dump_file);
return 0;
}
-struct tree_opt_pass pass_global_alloc =
+struct rtl_opt_pass pass_global_alloc =
{
+ {
+ RTL_PASS,
"greg", /* name */
- NULL, /* gate */
+ gate_handle_global_alloc, /* gate */
rest_of_handle_global_alloc, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func | TODO_verify_rtl_sharing
- | TODO_ggc_collect, /* todo_flags_finish */
- 'g' /* letter */
+ | TODO_ggc_collect /* todo_flags_finish */
+ }
};