FILE *dumpfile;
{
register int class;
- register int i, j;
+ register int i, j, k;
register rtx insn;
register struct elim_table *ep;
int old_code = INSN_CODE (insn);
rtx old_notes = REG_NOTES (insn);
int did_elimination = 0;
- int max_total_input_groups = 0, max_total_output_groups = 0;
/* To compute the number of reload registers of each class
needed for an insn, we must similate what choose_reload_regs
The total number of registers needed is the maximum of the
inputs and outputs. */
- /* These just count RELOAD_OTHER. */
- int insn_needs[N_REG_CLASSES];
- int insn_groups[N_REG_CLASSES];
- int insn_nongroups[N_REG_CLASSES];
- int insn_total_groups = 0;
-
- /* Count RELOAD_FOR_INPUT reloads. */
- int insn_needs_for_inputs[N_REG_CLASSES];
- int insn_nongroups_for_inputs[N_REG_CLASSES];
- int insn_groups_for_inputs[N_REG_CLASSES];
- int insn_total_groups_for_inputs = 0;
-
- /* Count RELOAD_FOR_OUTPUT reloads. */
- int insn_needs_for_outputs[N_REG_CLASSES];
- int insn_nongroups_for_outputs[N_REG_CLASSES];
- int insn_groups_for_outputs[N_REG_CLASSES];
- int insn_total_groups_for_outputs = 0;
-
- /* Count RELOAD_FOR_INSN reloads. */
- int insn_needs_for_insn[N_REG_CLASSES];
- int insn_nongroups_for_insn[N_REG_CLASSES];
- int insn_groups_for_insn[N_REG_CLASSES];
- int insn_total_groups_for_insn = 0;
-
- /* Count RELOAD_FOR_OTHER_ADDRESS reloads. */
- int insn_needs_for_other_addr[N_REG_CLASSES];
- int insn_nongroups_for_other_addr[N_REG_CLASSES];
- int insn_groups_for_other_addr[N_REG_CLASSES];
- int insn_total_groups_for_other_addr = 0;
-
- /* Count RELOAD_FOR_INPUT_ADDRESS reloads. */
- int insn_needs_for_in_addr[MAX_RECOG_OPERANDS][N_REG_CLASSES];
- int insn_nongroups_for_in_addr[MAX_RECOG_OPERANDS][N_REG_CLASSES];
- int insn_groups_for_in_addr[MAX_RECOG_OPERANDS][N_REG_CLASSES];
- int insn_total_groups_for_in_addr[MAX_RECOG_OPERANDS];
-
- /* Count RELOAD_FOR_OUTPUT_ADDRESS reloads. */
- int insn_needs_for_out_addr[MAX_RECOG_OPERANDS][N_REG_CLASSES];
- int insn_nongroups_for_out_addr[MAX_RECOG_OPERANDS][N_REG_CLASSES];
- int insn_groups_for_out_addr[MAX_RECOG_OPERANDS][N_REG_CLASSES];
- int insn_total_groups_for_out_addr[MAX_RECOG_OPERANDS];
-
- /* Count RELOAD_FOR_OPERAND_ADDRESS reloads. */
- int insn_needs_for_op_addr[N_REG_CLASSES];
- int insn_nongroups_for_op_addr[N_REG_CLASSES];
- int insn_groups_for_op_addr[N_REG_CLASSES];
- int insn_total_groups_for_op_addr = 0;
-
-#if 0 /* This wouldn't work nowadays, since optimize_bit_field
- looks for non-strict memory addresses. */
- /* Optimization: a bit-field instruction whose field
- happens to be a byte or halfword in memory
- can be changed to a move instruction. */
-
- if (GET_CODE (PATTERN (insn)) == SET)
+ struct needs
{
- rtx dest = SET_DEST (PATTERN (insn));
- rtx src = SET_SRC (PATTERN (insn));
-
- if (GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT)
- optimize_bit_field (PATTERN (insn), insn, reg_equiv_mem);
- if (GET_CODE (src) == ZERO_EXTRACT
- || GET_CODE (src) == SIGN_EXTRACT)
- optimize_bit_field (PATTERN (insn), insn, reg_equiv_mem);
- }
-#endif
+ /* [0] is normal, [1] is nongroup. */
+ int regs[2][N_REG_CLASSES];
+ int groups[N_REG_CLASSES];
+ };
+
+ /* Each `struct needs' corresponds to one RELOAD_... type. */
+ struct {
+ struct needs other;
+ struct needs input;
+ struct needs output;
+ struct needs insn;
+ struct needs other_addr;
+ struct needs op_addr;
+ struct needs in_addr[MAX_RECOG_OPERANDS];
+ struct needs out_addr[MAX_RECOG_OPERANDS];
+ } insn_needs;
/* If needed, eliminate any eliminable registers. */
if (num_eliminable)
continue;
something_needs_reloads = 1;
+ bzero (&insn_needs, sizeof insn_needs);
- for (i = 0; i < N_REG_CLASSES; i++)
- {
- insn_needs[i] = 0, insn_nongroups[i] = 0,
- insn_groups[i] = 0;
-
- insn_needs_for_inputs[i] = 0,
- insn_nongroups_for_inputs[i] = 0,
- insn_groups_for_inputs[i] = 0;
-
- insn_needs_for_outputs[i] = 0,
- insn_nongroups_for_outputs[i] = 0,
- insn_groups_for_outputs[i] = 0;
-
- insn_needs_for_insn[i] = 0,
- insn_nongroups_for_insn[i] = 0,
- insn_groups_for_insn[i] = 0;
-
- insn_needs_for_op_addr[i] = 0,
- insn_nongroups_for_op_addr[i] = 0,
- insn_groups_for_op_addr[i] = 0;
-
- insn_needs_for_other_addr[i] = 0,
- insn_nongroups_for_other_addr[i] = 0,
- insn_groups_for_other_addr[i] = 0;
- }
-
- for (i = 0; i < reload_n_operands; i++)
- {
- insn_total_groups_for_in_addr[i] = 0;
- insn_total_groups_for_out_addr[i] = 0;
-
- for (j = 0; j < N_REG_CLASSES; j++)
- {
- insn_needs_for_in_addr[i][j] = 0;
- insn_needs_for_out_addr[i][j] = 0;
- insn_nongroups_for_in_addr[i][j] = 0;
- insn_nongroups_for_out_addr[i][j] = 0;
- insn_groups_for_in_addr[i][j] = 0;
- insn_groups_for_out_addr[i][j] = 0;
- }
- }
-
/* Count each reload once in every class
containing the reload's own class. */
int size;
enum machine_mode mode;
int nongroup_need;
- int *this_groups;
- int *this_needs;
- int *this_total_groups;
+ struct needs *this_needs;
/* Don't count the dummy reloads, for which one of the
regs mentioned in the insn can be used for reloading.
mode = reload_outmode[i];
size = CLASS_MAX_NREGS (class, mode);
- /* If this class doesn't want a group determine if
- we have a nongroup need or a regular need. We have
- a nongroup need if this reload conflicts with a
- group reload whose class intersects with this reload's
- class. */
+ /* If this class doesn't want a group, determine if we have
+ a nongroup need or a regular need. We have a nongroup
+ need if this reload conflicts with a group reload whose
+ class intersects with this reload's class. */
nongroup_need = 0;
if (size == 1)
switch (reload_when_needed[i])
{
case RELOAD_OTHER:
- if (nongroup_need)
- this_needs = insn_nongroups;
- else
- this_needs = insn_needs;
- this_groups = insn_groups;
- this_total_groups = &insn_total_groups;
+ this_needs = &insn_needs.other;
break;
-
case RELOAD_FOR_INPUT:
- if (nongroup_need)
- this_needs = insn_nongroups_for_inputs;
- else
- this_needs = insn_needs_for_inputs;
- this_groups = insn_groups_for_inputs;
- this_total_groups = &insn_total_groups_for_inputs;
+ this_needs = &insn_needs.input;
break;
-
case RELOAD_FOR_OUTPUT:
- if (nongroup_need)
- this_needs = insn_nongroups_for_outputs;
- else
- this_needs = insn_needs_for_outputs;
- this_groups = insn_groups_for_outputs;
- this_total_groups = &insn_total_groups_for_outputs;
+ this_needs = &insn_needs.output;
break;
-
case RELOAD_FOR_INSN:
- if (nongroup_need)
- this_needs = insn_nongroups_for_insn;
- else
- this_needs = insn_needs_for_insn;
- this_groups = insn_groups_for_insn;
- this_total_groups = &insn_total_groups_for_insn;
+ this_needs = &insn_needs.insn;
break;
-
case RELOAD_FOR_OTHER_ADDRESS:
- if (nongroup_need)
- this_needs = insn_nongroups_for_other_addr;
- else
- this_needs = insn_needs_for_other_addr;
- this_groups = insn_groups_for_other_addr;
- this_total_groups = &insn_total_groups_for_other_addr;
+ this_needs = &insn_needs.other_addr;
break;
-
case RELOAD_FOR_INPUT_ADDRESS:
- if (nongroup_need)
- this_needs = insn_nongroups_for_in_addr[reload_opnum[i]];
- else
- this_needs = insn_needs_for_in_addr[reload_opnum[i]];
- this_groups = insn_groups_for_in_addr[reload_opnum[i]];
- this_total_groups
- = &insn_total_groups_for_in_addr[reload_opnum[i]];
+ this_needs = &insn_needs.in_addr[reload_opnum[i]];
break;
-
case RELOAD_FOR_OUTPUT_ADDRESS:
- if (nongroup_need)
- this_needs = insn_nongroups_for_out_addr[reload_opnum[i]];
- else
- this_needs = insn_needs_for_out_addr[reload_opnum[i]];
- this_groups = insn_groups_for_out_addr[reload_opnum[i]];
- this_total_groups
- = &insn_total_groups_for_out_addr[reload_opnum[i]];
+ this_needs = &insn_needs.out_addr[reload_opnum[i]];
break;
-
case RELOAD_FOR_OPERAND_ADDRESS:
- if (nongroup_need)
- this_needs = insn_nongroups_for_op_addr;
- else
- this_needs = insn_needs_for_op_addr;
- this_groups = insn_groups_for_op_addr;
- this_total_groups = &insn_total_groups_for_op_addr;
+ this_needs = &insn_needs.op_addr;
break;
}
/* Count number of groups needed separately from
number of individual regs needed. */
- this_groups[(int) class]++;
+ this_needs->groups[(int) class]++;
p = reg_class_superclasses[(int) class];
while (*p != LIM_REG_CLASSES)
- this_groups[(int) *p++]++;
- (*this_total_groups)++;
+ this_needs->groups[(int) *p++]++;
/* Record size and mode of a group of this class. */
/* If more than one size group is needed,
/* Crash if two dissimilar machine modes both need
groups of consecutive regs of the same class. */
- if (other_mode != VOIDmode
- && other_mode != allocate_mode
+ if (other_mode != VOIDmode && other_mode != allocate_mode
&& ! modes_equiv_for_class_p (allocate_mode,
- other_mode,
- class))
+ other_mode, class))
abort ();
}
else if (size == 1)
{
- this_needs[(int) class] += 1;
+ this_needs->regs[nongroup_need][(int) class] += 1;
p = reg_class_superclasses[(int) class];
while (*p != LIM_REG_CLASSES)
- this_needs[(int) *p++] += 1;
+ this_needs->regs[nongroup_need][(int) *p++] += 1;
}
else
abort ();
{
int in_max, out_max;
- for (in_max = 0, out_max = 0, j = 0;
- j < reload_n_operands; j++)
+ /* Compute normal and nongroup needs. */
+ for (j = 0; j <= 1; j++)
{
- in_max = MAX (in_max, insn_needs_for_in_addr[j][i]);
- out_max = MAX (out_max, insn_needs_for_out_addr[j][i]);
- }
+ for (in_max = 0, out_max = 0, k = 0;
+ k < reload_n_operands; k++)
+ {
+ in_max
+ = MAX (in_max, insn_needs.in_addr[k].regs[j][i]);
+ out_max
+ = MAX (out_max, insn_needs.out_addr[k].regs[j][i]);
+ }
- /* RELOAD_FOR_INSN reloads conflict with inputs, outputs,
- and operand addresses but not things used to reload them.
- Similarly, RELOAD_FOR_OPERAND_ADDRESS reloads don't
- conflict with things needed to reload inputs or
- outputs. */
+ /* RELOAD_FOR_INSN reloads conflict with inputs, outputs,
+ and operand addresses but not things used to reload
+ them. Similarly, RELOAD_FOR_OPERAND_ADDRESS reloads
+ don't conflict with things needed to reload inputs or
+ outputs. */
- in_max = MAX (in_max, insn_needs_for_op_addr[i]);
- out_max = MAX (out_max, insn_needs_for_insn[i]);
+ in_max = MAX (in_max, insn_needs.op_addr.regs[j][i]);
+ out_max = MAX (out_max, insn_needs.insn.regs[j][i]);
- insn_needs_for_inputs[i]
- = MAX (insn_needs_for_inputs[i]
- + insn_needs_for_op_addr[i]
- + insn_needs_for_insn[i],
- in_max + insn_needs_for_inputs[i]);
+ insn_needs.input.regs[j][i]
+ = MAX (insn_needs.input.regs[j][i]
+ + insn_needs.op_addr.regs[j][i]
+ + insn_needs.insn.regs[j][i],
+ in_max + insn_needs.input.regs[j][i]);
- insn_needs_for_outputs[i] += out_max;
- insn_needs[i] += MAX (MAX (insn_needs_for_inputs[i],
- insn_needs_for_outputs[i]),
- insn_needs_for_other_addr[i]);
+ insn_needs.output.regs[j][i] += out_max;
+ insn_needs.other.regs[j][i]
+ += MAX (MAX (insn_needs.input.regs[j][i],
+ insn_needs.output.regs[j][i]),
+ insn_needs.other_addr.regs[j][i]);
- for (in_max = 0, out_max = 0, j = 0;
- j < reload_n_operands; j++)
- {
- in_max = MAX (in_max, insn_nongroups_for_in_addr[j][i]);
- out_max = MAX (out_max, insn_nongroups_for_out_addr[j][i]);
}
- in_max = MAX (in_max, insn_nongroups_for_op_addr[i]);
- out_max = MAX (out_max, insn_nongroups_for_insn[i]);
-
- insn_nongroups_for_inputs[i]
- = MAX (insn_nongroups_for_inputs[i]
- + insn_nongroups_for_op_addr[i]
- + insn_nongroups_for_insn[i],
- in_max + insn_nongroups_for_inputs[i]);
-
- insn_nongroups_for_outputs[i] += out_max;
- insn_nongroups[i] += MAX (MAX (insn_nongroups_for_inputs[i],
- insn_nongroups_for_outputs[i]),
- insn_nongroups_for_other_addr[i]);
-
+ /* Now compute group needs. */
for (in_max = 0, out_max = 0, j = 0;
j < reload_n_operands; j++)
{
- in_max = MAX (in_max, insn_groups_for_in_addr[j][i]);
- out_max = MAX (out_max, insn_groups_for_out_addr[j][i]);
+ in_max = MAX (in_max, insn_needs.in_addr[j].groups[i]);
+ out_max
+ = MAX (out_max, insn_needs.out_addr[j].groups[i]);
}
- in_max = MAX (in_max, insn_groups_for_op_addr[i]);
- out_max = MAX (out_max, insn_groups_for_insn[i]);
+ in_max = MAX (in_max, insn_needs.op_addr.groups[i]);
+ out_max = MAX (out_max, insn_needs.insn.groups[i]);
- insn_groups_for_inputs[i]
- = MAX (insn_groups_for_inputs[i]
- + insn_groups_for_op_addr[i]
- + insn_groups_for_insn[i],
- in_max + insn_groups_for_inputs[i]);
+ insn_needs.input.groups[i]
+ = MAX (insn_needs.input.groups[i]
+ + insn_needs.op_addr.groups[i]
+ + insn_needs.insn.groups[i],
+ in_max + insn_needs.input.groups[i]);
- insn_groups_for_outputs[i] += out_max;
- insn_groups[i] += MAX (MAX (insn_groups_for_inputs[i],
- insn_groups_for_outputs[i]),
- insn_groups_for_other_addr[i]);
+ insn_needs.output.groups[i] += out_max;
+ insn_needs.other.groups[i]
+ += MAX (MAX (insn_needs.input.groups[i],
+ insn_needs.output.groups[i]),
+ insn_needs.other_addr.groups[i]);
}
- for (i = 0; i < reload_n_operands; i++)
- {
- max_total_input_groups
- = MAX (max_total_input_groups,
- insn_total_groups_for_in_addr[i]);
- max_total_output_groups
- = MAX (max_total_output_groups,
- insn_total_groups_for_out_addr[i]);
- }
-
- max_total_input_groups = MAX (max_total_input_groups,
- insn_total_groups_for_op_addr);
- max_total_output_groups = MAX (max_total_output_groups,
- insn_total_groups_for_insn);
-
- insn_total_groups_for_inputs
- = MAX (max_total_input_groups + insn_total_groups_for_op_addr
- + insn_total_groups_for_insn,
- max_total_input_groups + insn_total_groups_for_inputs);
-
- insn_total_groups_for_outputs += max_total_output_groups;
-
- insn_total_groups += MAX (MAX (insn_total_groups_for_outputs,
- insn_total_groups_for_inputs),
- insn_total_groups_for_other_addr);
-
/* If this is a CALL_INSN and caller-saves will need
a spill register, act as if the spill register is
needed for this insn. However, the spill register
if (GET_CODE (insn) == CALL_INSN
&& caller_save_spill_class != NO_REGS)
{
- int *caller_save_needs
- = (caller_save_group_size > 1 ? insn_groups : insn_needs);
+ /* See if this register would conflict with any reload
+ that needs a group. */
+ int nongroup_need = 0;
+ int *caller_save_needs;
+
+ for (j = 0; j < n_reloads; j++)
+ if ((CLASS_MAX_NREGS (reload_reg_class[j],
+ (GET_MODE_SIZE (reload_outmode[j])
+ > GET_MODE_SIZE (reload_inmode[j]))
+ ? reload_outmode[j]
+ : reload_inmode[j])
+ > 1)
+ && reg_classes_intersect_p (caller_save_spill_class,
+ reload_reg_class[j]))
+ {
+ nongroup_need = 1;
+ break;
+ }
+
+ caller_save_needs
+ = (caller_save_group_size > 1
+ ? insn_needs.other.groups
+ : insn_needs.other.regs[nongroup_need]);
if (caller_save_needs[(int) caller_save_spill_class] == 0)
{
caller_save_needs[(int) *p++] += 1;
}
- if (caller_save_group_size > 1)
- insn_total_groups = MAX (insn_total_groups, 1);
-
-
- /* Show that this basic block will need a register of
+ /* Show that this basic block will need a register of
this class. */
- if (global
- && ! (basic_block_needs[(int) caller_save_spill_class]
- [this_block]))
- {
- basic_block_needs[(int) caller_save_spill_class]
- [this_block] = 1;
- new_basic_block_needs = 1;
- }
+ if (global
+ && ! (basic_block_needs[(int) caller_save_spill_class]
+ [this_block]))
+ {
+ basic_block_needs[(int) caller_save_spill_class]
+ [this_block] = 1;
+ new_basic_block_needs = 1;
+ }
}
#ifdef SMALL_REGISTER_CLASSES
then add add an extra need in that class.
This makes sure we have a register available that does
not overlap the return value. */
+
if (avoid_return_reg)
{
int regno = REGNO (avoid_return_reg);
need only in the smallest class in which it
is required. */
- bcopy (insn_needs, basic_needs, sizeof basic_needs);
- bcopy (insn_groups, basic_groups, sizeof basic_groups);
+ bcopy (insn_needs.other.regs[0], basic_needs,
+ sizeof basic_needs);
+ bcopy (insn_needs.other.groups, basic_groups,
+ sizeof basic_groups);
for (i = 0; i < N_REG_CLASSES; i++)
{
{
enum reg_class *p;
- insn_needs[i]++;
+ insn_needs.other.regs[0][i]++;
p = reg_class_superclasses[i];
while (*p != LIM_REG_CLASSES)
- insn_needs[(int) *p++]++;
+ insn_needs.other.regs[0][(int) *p++]++;
}
}
}
for (i = 0; i < N_REG_CLASSES; i++)
{
- if (max_needs[i] < insn_needs[i])
+ if (max_needs[i] < insn_needs.other.regs[0][i])
{
- max_needs[i] = insn_needs[i];
+ max_needs[i] = insn_needs.other.regs[0][i];
max_needs_insn[i] = insn;
}
- if (max_groups[i] < insn_groups[i])
+ if (max_groups[i] < insn_needs.other.groups[i])
{
- max_groups[i] = insn_groups[i];
+ max_groups[i] = insn_needs.other.groups[i];
max_groups_insn[i] = insn;
}
- if (max_nongroups[i] < insn_nongroups[i])
+ if (max_nongroups[i] < insn_needs.other.regs[1][i])
{
- max_nongroups[i] = insn_nongroups[i];
+ max_nongroups[i] = insn_needs.other.regs[1][i];
max_nongroups_insn[i] = insn;
}
}