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. */
- if (! reload_completed)
- abort ();
- }
- 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
*loc = reg_equiv_mem[regno];
else if (reg_equiv_address[regno])
*loc = gen_rtx_MEM (GET_MODE (x), reg_equiv_address[regno]);
- else if (!REG_P (regno_reg_rtx[regno])
- || REGNO (regno_reg_rtx[regno]) != regno)
- *loc = regno_reg_rtx[regno];
else
- abort ();
+ {
+ gcc_assert (!REG_P (regno_reg_rtx[regno])
+ || REGNO (regno_reg_rtx[regno]) != regno);
+ *loc = regno_reg_rtx[regno];
+ }
return;
}
reload_as_needed (global);
- if (old_frame_size != get_frame_size ())
- abort ();
+ gcc_assert (old_frame_size == get_frame_size ());
if (num_eliminable)
verify_initial_elim_offsets ();
MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc[i]);
else
{
- RTX_UNCHANGING_P (reg) = MEM_IN_STRUCT_P (reg)
- = MEM_SCALAR_P (reg) = 0;
+ MEM_IN_STRUCT_P (reg) = MEM_SCALAR_P (reg) = 0;
MEM_ATTRS (reg) = 0;
}
}
SET_REGNO_REG_SET (&pseudos_counted, reg);
- if (r < 0)
- abort ();
+ gcc_assert (r >= 0);
spill_add_cost[r] += freq;
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 (spill_cost[best_reg + i] != 0
- || spill_add_cost[best_reg + i] != 0)
- abort ();
+ gcc_assert (spill_cost[best_reg + i] == 0);
+ gcc_assert (spill_add_cost[best_reg + i] == 0);
SET_HARD_REG_BIT (used_spill_regs_local, best_reg + i);
}
return 1;
{
static const char *const reg_class_names[] = REG_CLASS_NAMES;
if (asm_noperands (PATTERN (insn)) >= 0)
- error_for_asm (insn, "can't find a register in class `%s' while reloading `asm'",
+ error_for_asm (insn, "can't find a register in class %qs while "
+ "reloading %<asm%>",
reg_class_names[class]);
else
{
- error ("unable to find a register to spill in class `%s'",
+ error ("unable to find a register to spill in class %qs",
reg_class_names[class]);
fatal_insn ("this is the insn:", insn);
}
below. */
adjust = inherent_size - total_size;
- RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]);
-
/* Nothing can alias this slot except this pseudo. */
set_mem_alias_set (x, new_alias_set ());
}
/* 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:
case CLOBBER:
case ASM_OPERANDS:
case SET:
- abort ();
+ gcc_unreachable ();
default:
break;
if (! insn_is_asm && icode < 0)
{
- if (GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER
- || GET_CODE (PATTERN (insn)) == ADDR_VEC
- || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
- || GET_CODE (PATTERN (insn)) == ASM_INPUT)
- return 0;
- abort ();
+ gcc_assert (GET_CODE (PATTERN (insn)) == USE
+ || GET_CODE (PATTERN (insn)) == CLOBBER
+ || GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
+ || GET_CODE (PATTERN (insn)) == ASM_INPUT);
+ return 0;
}
if (old_set != 0 && REG_P (SET_DEST (old_set))
PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode, vec);
add_clobbers (PATTERN (insn), INSN_CODE (insn));
}
- if (INSN_CODE (insn) < 0)
- abort ();
+ gcc_assert (INSN_CODE (insn) >= 0);
}
/* If we have a nonzero offset, and the source is already
a simple REG, the following transformation would
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
{
INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, t);
- if (t != ep->initial_offset)
- abort ();
+ gcc_assert (t == ep->initial_offset);
}
#else
INITIAL_FRAME_POINTER_OFFSET (t);
- if (t != reg_eliminate[0].initial_offset)
- abort ();
+ gcc_assert (t == reg_eliminate[0].initial_offset);
#endif
}
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. */
- if (reg_renumber[i] < 0)
- abort ();
-
- 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;
/* Make sure we only enlarge the set. */
GO_IF_HARD_REG_SUBSET (used_by_pseudos2, chain->used_spill_regs, ok);
- abort ();
+ gcc_unreachable ();
ok:;
}
}
/* 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)
|| (extract_insn (p), ! constrain_operands (1))))
{
error_for_asm (insn,
- "`asm' operand requires impossible reload");
+ "%<asm%> operand requires "
+ "impossible reload");
delete_insn (p);
}
}
used_in_set = &reload_reg_used_in_insn;
break;
default:
- abort ();
+ gcc_unreachable ();
}
/* We resolve conflicts with remaining reloads of the same type by
excluding the intervals of reload registers by them from the
case RELOAD_FOR_OTHER_ADDRESS:
return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
+
+ default:
+ gcc_unreachable ();
}
- abort ();
}
/* Return 1 if the value in reload reg REGNO, as used by a reload
return 0;
return 1;
- }
- abort ();
+ default:
+ gcc_unreachable ();
+ }
}
\f
/* Return 1 if the reloads denoted by R1 and R2 cannot share a register.
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;
return 1;
default:
- abort ();
+ gcc_unreachable ();
}
}
\f
/* It's the user's fault; the operand's mode and constraint
don't match. Disable this reload so we don't crash in final. */
error_for_asm (insn,
- "`asm' operand constraint incompatible with operand size");
+ "%<asm%> operand constraint incompatible with operand size");
rld[r].in = 0;
rld[r].out = 0;
rld[r].reg_rtx = 0;
{
if (REG_P (equiv))
regno = REGNO (equiv);
- else if (GET_CODE (equiv) == SUBREG)
+ else
{
/* This must be a SUBREG of a hard register.
Make a new REG since this might be used in an
address and not all machines support SUBREGs
there. */
+ gcc_assert (GET_CODE (equiv) == SUBREG);
regno = subreg_regno (equiv);
equiv = gen_rtx_REG (rld[r].mode, regno);
}
- else
- abort ();
}
/* If we found a spill reg, reject it unless it is free
/* Some sanity tests to verify that the reloads found in the first
pass are identical to the ones we have now. */
- if (chain->n_reloads != n_reloads)
- abort ();
+ gcc_assert (chain->n_reloads == n_reloads);
for (i = 0; i < n_reloads; i++)
{
if (chain->rld[i].regno < 0 || chain->rld[i].reg_rtx != 0)
continue;
- if (chain->rld[i].when_needed != rld[i].when_needed)
- abort ();
+ gcc_assert (chain->rld[i].when_needed == rld[i].when_needed);
for (j = 0; j < n_spills; j++)
if (spill_regs[j] == chain->rld[i].regno)
if (! set_reload_reg (j, i))
SET_HARD_REG_BIT (reg_is_output_reload, i + nr);
}
- if (rld[r].when_needed != RELOAD_OTHER
- && rld[r].when_needed != RELOAD_FOR_OUTPUT
- && rld[r].when_needed != RELOAD_FOR_INSN)
- abort ();
+ gcc_assert (rld[r].when_needed == RELOAD_OTHER
+ || rld[r].when_needed == RELOAD_FOR_OUTPUT
+ || rld[r].when_needed == RELOAD_FOR_INSN);
}
}
}
so abort. */
if (rld[j].reg_rtx)
for (k = 0; k < j; k++)
- if (rld[k].in != 0 && rld[k].reg_rtx != 0
- && rld[k].when_needed == rld[j].when_needed
- && rtx_equal_p (rld[k].reg_rtx, rld[j].reg_rtx)
- && ! rtx_equal_p (rld[k].in, rld[j].in))
- abort ();
+ gcc_assert (rld[k].in == 0 || rld[k].reg_rtx == 0
+ || rld[k].when_needed != rld[j].when_needed
+ || !rtx_equal_p (rld[k].reg_rtx,
+ rld[j].reg_rtx)
+ || rtx_equal_p (rld[k].in,
+ rld[j].in));
}
}
}
where = &other_input_address_reload_insns;
break;
default:
- abort ();
+ gcc_unreachable ();
}
push_to_sequence (*where);
/* We are not going to bother supporting the case where a
incremented register can't be copied directly from
OLDEQUIV since this seems highly unlikely. */
- if (rl->secondary_in_reload >= 0)
- abort ();
+ gcc_assert (rl->secondary_in_reload < 0);
if (reload_inherited[j])
oldequiv = reloadreg;
if (asm_noperands (PATTERN (insn)) < 0)
/* It's the compiler's fault. */
fatal_insn ("VOIDmode on an output", insn);
- error_for_asm (insn, "output operand is constant in `asm'");
+ error_for_asm (insn, "output operand is constant in %<asm%>");
/* Prevent crash--use something we know is valid. */
mode = word_mode;
old = gen_rtx_REG (mode, REGNO (reloadreg));
return;
/* If is a JUMP_INSN, we can't support output reloads yet. */
- if (JUMP_P (insn))
- abort ();
+ gcc_assert (!JUMP_P (insn));
emit_output_reload_insns (chain, rld + j, j);
}
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
&& !can_throw_internal (insn)
&& insn != BB_HEAD (bb))
insn = PREV_INSN (insn);
- if (!CALL_P (insn) && !can_throw_internal (insn))
- abort ();
+ gcc_assert (CALL_P (insn) || can_throw_internal (insn));
BB_END (bb) = insn;
inserted = true;
insn = NEXT_INSN (insn);