static void update_eliminables (HARD_REG_SET *);
static void spill_hard_reg (unsigned int, int);
static int finish_spills (int);
-static void ior_hard_reg_set (HARD_REG_SET *, HARD_REG_SET *);
static void scan_paradoxical_subregs (rtx);
static void count_pseudo (int);
static void order_regs_for_reload (struct insn_chain *);
static void add_auto_inc_notes (rtx, rtx);
#endif
static void copy_eh_notes (rtx, rtx);
+static int reloads_conflict (int, int);
+static rtx gen_reload (rtx, rtx, int, enum reload_type);
\f
/* Initialize the reload pass once per compilation. */
compute_use_by_pseudos (HARD_REG_SET *to, regset from)
{
unsigned int regno;
+ reg_set_iterator rsi;
- EXECUTE_IF_SET_IN_REG_SET
- (from, FIRST_PSEUDO_REGISTER, regno,
- {
- int r = reg_renumber[regno];
- int nregs;
-
- if (r < 0)
- {
- /* reload_combine uses the information from
- BASIC_BLOCK->global_live_at_start, which might still
- contain registers that have not actually been allocated
- since they have an equivalence. */
- gcc_assert (reload_completed);
- }
- else
- {
- nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
- while (nregs-- > 0)
- SET_HARD_REG_BIT (*to, r + nregs);
- }
- });
+ EXECUTE_IF_SET_IN_REG_SET (from, FIRST_PSEUDO_REGISTER, regno, rsi)
+ {
+ int r = reg_renumber[regno];
+ int nregs;
+
+ if (r < 0)
+ {
+ /* reload_combine uses the information from
+ BASIC_BLOCK->global_live_at_start, which might still
+ contain registers that have not actually been allocated
+ since they have an equivalence. */
+ gcc_assert (reload_completed);
+ }
+ else
+ {
+ nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
+ while (nregs-- > 0)
+ SET_HARD_REG_BIT (*to, r + nregs);
+ }
+ }
}
/* Replace all pseudos found in LOC with their corresponding
if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
regs_ever_live[i] = 1;
-#ifdef NON_SAVING_SETJMP
- /* A function that calls setjmp should save and restore all the
- call-saved registers on a system where longjmp clobbers them. */
- if (NON_SAVING_SETJMP && current_function_calls_setjmp)
- {
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (! call_used_regs[i])
- regs_ever_live[i] = 1;
- }
-#endif
-
/* Find all the pseudo registers that didn't get hard regs
but do have known equivalent constants or memory slots.
These include parameters (known equivalent to parameter slots)
static void
order_regs_for_reload (struct insn_chain *chain)
{
- int i;
+ unsigned i;
HARD_REG_SET used_by_pseudos;
HARD_REG_SET used_by_pseudos2;
+ reg_set_iterator rsi;
COPY_HARD_REG_SET (bad_spill_regs, fixed_reg_set);
CLEAR_REG_SET (&pseudos_counted);
EXECUTE_IF_SET_IN_REG_SET
- (&chain->live_throughout, FIRST_PSEUDO_REGISTER, i,
- {
- count_pseudo (i);
- });
+ (&chain->live_throughout, FIRST_PSEUDO_REGISTER, i, rsi)
+ {
+ count_pseudo (i);
+ }
EXECUTE_IF_SET_IN_REG_SET
- (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, i,
- {
- count_pseudo (i);
- });
+ (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, i, rsi)
+ {
+ count_pseudo (i);
+ }
CLEAR_REG_SET (&pseudos_counted);
}
\f
int k;
HARD_REG_SET not_usable;
HARD_REG_SET used_by_other_reload;
+ reg_set_iterator rsi;
COPY_HARD_REG_SET (not_usable, bad_spill_regs);
IOR_HARD_REG_SET (not_usable, bad_spill_regs_global);
rl->regno = best_reg;
EXECUTE_IF_SET_IN_REG_SET
- (&chain->live_throughout, FIRST_PSEUDO_REGISTER, j,
- {
- count_spilled_pseudo (best_reg, rl->nregs, j);
- });
+ (&chain->live_throughout, FIRST_PSEUDO_REGISTER, j, rsi)
+ {
+ count_spilled_pseudo (best_reg, rl->nregs, j);
+ }
EXECUTE_IF_SET_IN_REG_SET
- (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, j,
- {
- count_spilled_pseudo (best_reg, rl->nregs, j);
- });
+ (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, j, rsi)
+ {
+ count_spilled_pseudo (best_reg, rl->nregs, j);
+ }
for (i = 0; i < rl->nregs; i++)
{
/* If we have a decl for the original register, set it for the
memory. If this is a shared MEM, make a copy. */
if (REG_EXPR (regno_reg_rtx[i])
- && TREE_CODE_CLASS (TREE_CODE (REG_EXPR (regno_reg_rtx[i]))) == 'd')
+ && DECL_P (REG_EXPR (regno_reg_rtx[i])))
{
rtx decl = DECL_RTL_IF_SET (REG_EXPR (regno_reg_rtx[i]));
return;
case LABEL_REF:
- set_label_offsets (XEXP (SET_SRC (x), 0), insn, initial_p);
+ set_label_offsets (SET_SRC (x), insn, initial_p);
return;
case IF_THEN_ELSE:
num_not_at_initial_offset = 0;
}
+/* Subroutine of set_initial_label_offsets called via for_each_eh_label. */
+
+static void
+set_initial_eh_label_offset (rtx label)
+{
+ set_label_offsets (label, NULL_RTX, 1);
+}
+
/* Initialize the known label offsets.
Set a known offset for each forced label to be at the initial offset
of each elimination. We do this because we assume that all
for (x = forced_labels; x; x = XEXP (x, 1))
if (XEXP (x, 0))
set_label_offsets (XEXP (x, 0), NULL_RTX, 1);
+
+ for_each_eh_label (set_initial_eh_label_offset);
}
/* Set all elimination offsets to the known values for the code label given
SET_REGNO_REG_SET (&spilled_pseudos, i);
}
-/* I'm getting weird preprocessor errors if I use IOR_HARD_REG_SET
- from within EXECUTE_IF_SET_IN_REG_SET. Hence this awkwardness. */
-
-static void
-ior_hard_reg_set (HARD_REG_SET *set1, HARD_REG_SET *set2)
-{
- IOR_HARD_REG_SET (*set1, *set2);
-}
-
/* After find_reload_regs has been run for all insn that need reloads,
and/or spill_hard_regs was called, this function is used to actually
spill pseudo registers and try to reallocate them. It also sets up the
{
struct insn_chain *chain;
int something_changed = 0;
- int i;
+ unsigned i;
+ reg_set_iterator rsi;
/* Build the spill_regs array for the function. */
/* If there are some registers still to eliminate and one of the spill regs
else
spill_reg_order[i] = -1;
- EXECUTE_IF_SET_IN_REG_SET
- (&spilled_pseudos, FIRST_PSEUDO_REGISTER, i,
- {
- /* Record the current hard register the pseudo is allocated to in
- pseudo_previous_regs so we avoid reallocating it to the same
- hard reg in a later pass. */
- gcc_assert (reg_renumber[i] >= 0);
-
- SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
- /* Mark it as no longer having a hard register home. */
- reg_renumber[i] = -1;
- /* We will need to scan everything again. */
- something_changed = 1;
- });
+ EXECUTE_IF_SET_IN_REG_SET (&spilled_pseudos, FIRST_PSEUDO_REGISTER, i, rsi)
+ {
+ /* Record the current hard register the pseudo is allocated to in
+ pseudo_previous_regs so we avoid reallocating it to the same
+ hard reg in a later pass. */
+ gcc_assert (reg_renumber[i] >= 0);
+
+ SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
+ /* Mark it as no longer having a hard register home. */
+ reg_renumber[i] = -1;
+ /* We will need to scan everything again. */
+ something_changed = 1;
+ }
/* Retry global register allocation if possible. */
if (global)
for (chain = insns_need_reload; chain; chain = chain->next_need_reload)
{
EXECUTE_IF_SET_IN_REG_SET
- (&chain->live_throughout, FIRST_PSEUDO_REGISTER, i,
- {
- ior_hard_reg_set (pseudo_forbidden_regs + i,
- &chain->used_spill_regs);
- });
+ (&chain->live_throughout, FIRST_PSEUDO_REGISTER, i, rsi)
+ {
+ IOR_HARD_REG_SET (pseudo_forbidden_regs[i],
+ chain->used_spill_regs);
+ }
EXECUTE_IF_SET_IN_REG_SET
- (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, i,
- {
- ior_hard_reg_set (pseudo_forbidden_regs + i,
- &chain->used_spill_regs);
- });
+ (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, i, rsi)
+ {
+ IOR_HARD_REG_SET (pseudo_forbidden_regs[i],
+ chain->used_spill_regs);
+ }
}
/* Retry allocating the spilled pseudos. For each reg, merge the
and call retry_global_alloc.
We change spill_pseudos here to only contain pseudos that did not
get a new hard register. */
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ for (i = FIRST_PSEUDO_REGISTER; i < (unsigned)max_regno; i++)
if (reg_old_renumber[i] != reg_renumber[i])
{
HARD_REG_SET forbidden;
}
/* Let alter_reg modify the reg rtx's for the modified pseudos. */
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+ for (i = FIRST_PSEUDO_REGISTER; i < (unsigned)max_regno; i++)
{
int regno = reg_renumber[i];
if (reg_old_renumber[i] == regno)
This function uses the same algorithm as reload_reg_free_p above. */
-int
+static int
reloads_conflict (int r1, int r2)
{
enum reload_type r1_type = rld[r1].when_needed;
reloads for the operand. The RELOAD_OTHER output reloads are
output in descending order by reload number. */
- emit_insn_before_sameloc (other_input_address_reload_insns, insn);
- emit_insn_before_sameloc (other_input_reload_insns, insn);
+ emit_insn_before (other_input_address_reload_insns, insn);
+ emit_insn_before (other_input_reload_insns, insn);
for (j = 0; j < reload_n_operands; j++)
{
- emit_insn_before_sameloc (inpaddr_address_reload_insns[j], insn);
- emit_insn_before_sameloc (input_address_reload_insns[j], insn);
- emit_insn_before_sameloc (input_reload_insns[j], insn);
+ emit_insn_before (inpaddr_address_reload_insns[j], insn);
+ emit_insn_before (input_address_reload_insns[j], insn);
+ emit_insn_before (input_reload_insns[j], insn);
}
- emit_insn_before_sameloc (other_operand_reload_insns, insn);
- emit_insn_before_sameloc (operand_reload_insns, insn);
+ emit_insn_before (other_operand_reload_insns, insn);
+ emit_insn_before (operand_reload_insns, insn);
for (j = 0; j < reload_n_operands; j++)
{
- rtx x = emit_insn_after_sameloc (outaddr_address_reload_insns[j], insn);
- x = emit_insn_after_sameloc (output_address_reload_insns[j], x);
- x = emit_insn_after_sameloc (output_reload_insns[j], x);
- emit_insn_after_sameloc (other_output_reload_insns[j], x);
+ rtx x = emit_insn_after (outaddr_address_reload_insns[j], insn);
+ x = emit_insn_after (output_address_reload_insns[j], x);
+ x = emit_insn_after (output_reload_insns[j], x);
+ emit_insn_after (other_output_reload_insns[j], x);
}
/* For all the spill regs newly reloaded in this instruction,
Returns first insn emitted. */
-rtx
+static rtx
gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
{
rtx last = get_last_insn ();
FOR_EACH_BB (bb)
{
edge e;
+ edge_iterator ei;
/* Look for cases we are interested in - calls or instructions causing
exceptions. */
- for (e = bb->succ; e; e = e->succ_next)
+ FOR_EACH_EDGE (e, ei, bb->succs)
{
if (e->flags & EDGE_ABNORMAL_CALL)
break;
{
rtx insn = BB_END (bb), stop = NEXT_INSN (BB_END (bb));
rtx next;
- for (e = bb->succ; e; e = e->succ_next)
+ FOR_EACH_EDGE (e, ei, bb->succs)
if (e->flags & EDGE_FALLTHRU)
break;
/* Get past the new insns generated. Allow notes, as the insns may