Commit 8b3e912b by Richard Kenner

(reload): When accumulating needs, use nested structures to simplify

and speed up the code.

From-SVN: r7038
parent 1c2bdc60
...@@ -441,7 +441,7 @@ reload (first, global, dumpfile) ...@@ -441,7 +441,7 @@ reload (first, global, dumpfile)
FILE *dumpfile; FILE *dumpfile;
{ {
register int class; register int class;
register int i, j; register int i, j, k;
register rtx insn; register rtx insn;
register struct elim_table *ep; register struct elim_table *ep;
...@@ -907,7 +907,6 @@ reload (first, global, dumpfile) ...@@ -907,7 +907,6 @@ reload (first, global, dumpfile)
int old_code = INSN_CODE (insn); int old_code = INSN_CODE (insn);
rtx old_notes = REG_NOTES (insn); rtx old_notes = REG_NOTES (insn);
int did_elimination = 0; 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 /* To compute the number of reload registers of each class
needed for an insn, we must similate what choose_reload_regs needed for an insn, we must similate what choose_reload_regs
...@@ -927,73 +926,24 @@ reload (first, global, dumpfile) ...@@ -927,73 +926,24 @@ reload (first, global, dumpfile)
The total number of registers needed is the maximum of the The total number of registers needed is the maximum of the
inputs and outputs. */ inputs and outputs. */
/* These just count RELOAD_OTHER. */ struct needs
int insn_needs[N_REG_CLASSES]; {
int insn_groups[N_REG_CLASSES]; /* [0] is normal, [1] is nongroup. */
int insn_nongroups[N_REG_CLASSES]; int regs[2][N_REG_CLASSES];
int insn_total_groups = 0; int groups[N_REG_CLASSES];
};
/* Count RELOAD_FOR_INPUT reloads. */
int insn_needs_for_inputs[N_REG_CLASSES]; /* Each `struct needs' corresponds to one RELOAD_... type. */
int insn_nongroups_for_inputs[N_REG_CLASSES]; struct {
int insn_groups_for_inputs[N_REG_CLASSES]; struct needs other;
int insn_total_groups_for_inputs = 0; struct needs input;
struct needs output;
/* Count RELOAD_FOR_OUTPUT reloads. */ struct needs insn;
int insn_needs_for_outputs[N_REG_CLASSES]; struct needs other_addr;
int insn_nongroups_for_outputs[N_REG_CLASSES]; struct needs op_addr;
int insn_groups_for_outputs[N_REG_CLASSES]; struct needs in_addr[MAX_RECOG_OPERANDS];
int insn_total_groups_for_outputs = 0; struct needs out_addr[MAX_RECOG_OPERANDS];
} insn_needs;
/* 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)
{
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
/* If needed, eliminate any eliminable registers. */ /* If needed, eliminate any eliminable registers. */
if (num_eliminable) if (num_eliminable)
...@@ -1065,48 +1015,7 @@ reload (first, global, dumpfile) ...@@ -1065,48 +1015,7 @@ reload (first, global, dumpfile)
continue; continue;
something_needs_reloads = 1; 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 /* Count each reload once in every class
containing the reload's own class. */ containing the reload's own class. */
...@@ -1118,9 +1027,7 @@ reload (first, global, dumpfile) ...@@ -1118,9 +1027,7 @@ reload (first, global, dumpfile)
int size; int size;
enum machine_mode mode; enum machine_mode mode;
int nongroup_need; int nongroup_need;
int *this_groups; struct needs *this_needs;
int *this_needs;
int *this_total_groups;
/* Don't count the dummy reloads, for which one of the /* Don't count the dummy reloads, for which one of the
regs mentioned in the insn can be used for reloading. regs mentioned in the insn can be used for reloading.
...@@ -1148,11 +1055,10 @@ reload (first, global, dumpfile) ...@@ -1148,11 +1055,10 @@ reload (first, global, dumpfile)
mode = reload_outmode[i]; mode = reload_outmode[i];
size = CLASS_MAX_NREGS (class, mode); size = CLASS_MAX_NREGS (class, mode);
/* If this class doesn't want a group determine if /* If this class doesn't want a group, determine if we have
we have a nongroup need or a regular need. We have a nongroup need or a regular need. We have a nongroup
a nongroup need if this reload conflicts with a need if this reload conflicts with a group reload whose
group reload whose class intersects with this reload's class intersects with this reload's class. */
class. */
nongroup_need = 0; nongroup_need = 0;
if (size == 1) if (size == 1)
...@@ -1175,77 +1081,28 @@ reload (first, global, dumpfile) ...@@ -1175,77 +1081,28 @@ reload (first, global, dumpfile)
switch (reload_when_needed[i]) switch (reload_when_needed[i])
{ {
case RELOAD_OTHER: case RELOAD_OTHER:
if (nongroup_need) this_needs = &insn_needs.other;
this_needs = insn_nongroups;
else
this_needs = insn_needs;
this_groups = insn_groups;
this_total_groups = &insn_total_groups;
break; break;
case RELOAD_FOR_INPUT: case RELOAD_FOR_INPUT:
if (nongroup_need) this_needs = &insn_needs.input;
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;
break; break;
case RELOAD_FOR_OUTPUT: case RELOAD_FOR_OUTPUT:
if (nongroup_need) this_needs = &insn_needs.output;
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;
break; break;
case RELOAD_FOR_INSN: case RELOAD_FOR_INSN:
if (nongroup_need) this_needs = &insn_needs.insn;
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;
break; break;
case RELOAD_FOR_OTHER_ADDRESS: case RELOAD_FOR_OTHER_ADDRESS:
if (nongroup_need) this_needs = &insn_needs.other_addr;
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;
break; break;
case RELOAD_FOR_INPUT_ADDRESS: case RELOAD_FOR_INPUT_ADDRESS:
if (nongroup_need) this_needs = &insn_needs.in_addr[reload_opnum[i]];
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]];
break; break;
case RELOAD_FOR_OUTPUT_ADDRESS: case RELOAD_FOR_OUTPUT_ADDRESS:
if (nongroup_need) this_needs = &insn_needs.out_addr[reload_opnum[i]];
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]];
break; break;
case RELOAD_FOR_OPERAND_ADDRESS: case RELOAD_FOR_OPERAND_ADDRESS:
if (nongroup_need) this_needs = &insn_needs.op_addr;
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;
break; break;
} }
...@@ -1255,11 +1112,10 @@ reload (first, global, dumpfile) ...@@ -1255,11 +1112,10 @@ reload (first, global, dumpfile)
/* Count number of groups needed separately from /* Count number of groups needed separately from
number of individual regs needed. */ number of individual regs needed. */
this_groups[(int) class]++; this_needs->groups[(int) class]++;
p = reg_class_superclasses[(int) class]; p = reg_class_superclasses[(int) class];
while (*p != LIM_REG_CLASSES) while (*p != LIM_REG_CLASSES)
this_groups[(int) *p++]++; this_needs->groups[(int) *p++]++;
(*this_total_groups)++;
/* Record size and mode of a group of this class. */ /* Record size and mode of a group of this class. */
/* If more than one size group is needed, /* If more than one size group is needed,
...@@ -1281,19 +1137,17 @@ reload (first, global, dumpfile) ...@@ -1281,19 +1137,17 @@ reload (first, global, dumpfile)
/* Crash if two dissimilar machine modes both need /* Crash if two dissimilar machine modes both need
groups of consecutive regs of the same class. */ groups of consecutive regs of the same class. */
if (other_mode != VOIDmode if (other_mode != VOIDmode && other_mode != allocate_mode
&& other_mode != allocate_mode
&& ! modes_equiv_for_class_p (allocate_mode, && ! modes_equiv_for_class_p (allocate_mode,
other_mode, other_mode, class))
class))
abort (); abort ();
} }
else if (size == 1) else if (size == 1)
{ {
this_needs[(int) class] += 1; this_needs->regs[nongroup_need][(int) class] += 1;
p = reg_class_superclasses[(int) class]; p = reg_class_superclasses[(int) class];
while (*p != LIM_REG_CLASSES) while (*p != LIM_REG_CLASSES)
this_needs[(int) *p++] += 1; this_needs->regs[nongroup_need][(int) *p++] += 1;
} }
else else
abort (); abort ();
...@@ -1308,102 +1162,66 @@ reload (first, global, dumpfile) ...@@ -1308,102 +1162,66 @@ reload (first, global, dumpfile)
{ {
int in_max, out_max; int in_max, out_max;
for (in_max = 0, out_max = 0, j = 0; /* Compute normal and nongroup needs. */
j < reload_n_operands; j++) for (j = 0; j <= 1; j++)
{ {
in_max = MAX (in_max, insn_needs_for_in_addr[j][i]); for (in_max = 0, out_max = 0, k = 0;
out_max = MAX (out_max, insn_needs_for_out_addr[j][i]); 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, /* RELOAD_FOR_INSN reloads conflict with inputs, outputs,
and operand addresses but not things used to reload them. and operand addresses but not things used to reload
Similarly, RELOAD_FOR_OPERAND_ADDRESS reloads don't them. Similarly, RELOAD_FOR_OPERAND_ADDRESS reloads
conflict with things needed to reload inputs or don't conflict with things needed to reload inputs or
outputs. */ outputs. */
in_max = MAX (in_max, insn_needs_for_op_addr[i]); in_max = MAX (in_max, insn_needs.op_addr.regs[j][i]);
out_max = MAX (out_max, insn_needs_for_insn[i]); out_max = MAX (out_max, insn_needs.insn.regs[j][i]);
insn_needs_for_inputs[i] insn_needs.input.regs[j][i]
= MAX (insn_needs_for_inputs[i] = MAX (insn_needs.input.regs[j][i]
+ insn_needs_for_op_addr[i] + insn_needs.op_addr.regs[j][i]
+ insn_needs_for_insn[i], + insn_needs.insn.regs[j][i],
in_max + insn_needs_for_inputs[i]); in_max + insn_needs.input.regs[j][i]);
insn_needs_for_outputs[i] += out_max; insn_needs.output.regs[j][i] += out_max;
insn_needs[i] += MAX (MAX (insn_needs_for_inputs[i], insn_needs.other.regs[j][i]
insn_needs_for_outputs[i]), += MAX (MAX (insn_needs.input.regs[j][i],
insn_needs_for_other_addr[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]); /* Now compute group needs. */
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]);
for (in_max = 0, out_max = 0, j = 0; for (in_max = 0, out_max = 0, j = 0;
j < reload_n_operands; j++) j < reload_n_operands; j++)
{ {
in_max = MAX (in_max, insn_groups_for_in_addr[j][i]); in_max = MAX (in_max, insn_needs.in_addr[j].groups[i]);
out_max = MAX (out_max, insn_groups_for_out_addr[j][i]); out_max
= MAX (out_max, insn_needs.out_addr[j].groups[i]);
} }
in_max = MAX (in_max, insn_groups_for_op_addr[i]); in_max = MAX (in_max, insn_needs.op_addr.groups[i]);
out_max = MAX (out_max, insn_groups_for_insn[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_groups_for_outputs[i] += out_max; insn_needs.input.groups[i]
insn_groups[i] += MAX (MAX (insn_groups_for_inputs[i], = MAX (insn_needs.input.groups[i]
insn_groups_for_outputs[i]), + insn_needs.op_addr.groups[i]
insn_groups_for_other_addr[i]); + insn_needs.insn.groups[i],
} in_max + insn_needs.input.groups[i]);
for (i = 0; i < reload_n_operands; i++) insn_needs.output.groups[i] += out_max;
{ insn_needs.other.groups[i]
max_total_input_groups += MAX (MAX (insn_needs.input.groups[i],
= MAX (max_total_input_groups, insn_needs.output.groups[i]),
insn_total_groups_for_in_addr[i]); insn_needs.other_addr.groups[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 /* If this is a CALL_INSN and caller-saves will need
a spill register, act as if the spill register is a spill register, act as if the spill register is
needed for this insn. However, the spill register needed for this insn. However, the spill register
...@@ -1423,8 +1241,29 @@ reload (first, global, dumpfile) ...@@ -1423,8 +1241,29 @@ reload (first, global, dumpfile)
if (GET_CODE (insn) == CALL_INSN if (GET_CODE (insn) == CALL_INSN
&& caller_save_spill_class != NO_REGS) && caller_save_spill_class != NO_REGS)
{ {
int *caller_save_needs /* See if this register would conflict with any reload
= (caller_save_group_size > 1 ? insn_groups : insn_needs); 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) if (caller_save_needs[(int) caller_save_spill_class] == 0)
{ {
...@@ -1437,10 +1276,6 @@ reload (first, global, dumpfile) ...@@ -1437,10 +1276,6 @@ reload (first, global, dumpfile)
caller_save_needs[(int) *p++] += 1; 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. */ this class. */
...@@ -1462,6 +1297,7 @@ reload (first, global, dumpfile) ...@@ -1462,6 +1297,7 @@ reload (first, global, dumpfile)
then add add an extra need in that class. then add add an extra need in that class.
This makes sure we have a register available that does This makes sure we have a register available that does
not overlap the return value. */ not overlap the return value. */
if (avoid_return_reg) if (avoid_return_reg)
{ {
int regno = REGNO (avoid_return_reg); int regno = REGNO (avoid_return_reg);
...@@ -1474,8 +1310,10 @@ reload (first, global, dumpfile) ...@@ -1474,8 +1310,10 @@ reload (first, global, dumpfile)
need only in the smallest class in which it need only in the smallest class in which it
is required. */ is required. */
bcopy (insn_needs, basic_needs, sizeof basic_needs); bcopy (insn_needs.other.regs[0], basic_needs,
bcopy (insn_groups, basic_groups, sizeof basic_groups); sizeof basic_needs);
bcopy (insn_needs.other.groups, basic_groups,
sizeof basic_groups);
for (i = 0; i < N_REG_CLASSES; i++) for (i = 0; i < N_REG_CLASSES; i++)
{ {
...@@ -1509,10 +1347,10 @@ reload (first, global, dumpfile) ...@@ -1509,10 +1347,10 @@ reload (first, global, dumpfile)
{ {
enum reg_class *p; enum reg_class *p;
insn_needs[i]++; insn_needs.other.regs[0][i]++;
p = reg_class_superclasses[i]; p = reg_class_superclasses[i];
while (*p != LIM_REG_CLASSES) while (*p != LIM_REG_CLASSES)
insn_needs[(int) *p++]++; insn_needs.other.regs[0][(int) *p++]++;
} }
} }
} }
...@@ -1522,19 +1360,19 @@ reload (first, global, dumpfile) ...@@ -1522,19 +1360,19 @@ reload (first, global, dumpfile)
for (i = 0; i < N_REG_CLASSES; i++) 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; 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; 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; max_nongroups_insn[i] = insn;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment