Simplify reload register allocation
From-SVN: r30890
This commit is contained in:
parent
2cf4028a7c
commit
f5d8c9f405
6 changed files with 443 additions and 1157 deletions
|
@ -1,3 +1,46 @@
|
|||
1999-12-10 Bernd Schmidt <bernds@cygnus.co.uk>
|
||||
|
||||
* hard-reg-set.h (inv_reg_alloc_order): Declare if REG_ALLOC_ORDER is
|
||||
defined.
|
||||
* regclass.c (inv_reg_alloc_order): New array.
|
||||
(regclass_init): If REG_ALLOC_ORDER is defined, initialize it.
|
||||
|
||||
* reload.h (struct insn_chain): Delete fields group_size, group_mode,
|
||||
counted_for_groups, counted_for_nongroups. Add fields rld and
|
||||
n_reloads.
|
||||
* reload.c (push_secondary_reload): Don't set nongroup field of
|
||||
new reloads.
|
||||
(push_reload): Likewise.
|
||||
(find_reloads): Delete code to compute nongroup fields.
|
||||
* reload1.c (reload_insn_firstobj): New static variable.
|
||||
(pseudos_counted, spilled_pseudos): Now of type regset_head. All
|
||||
users changed.
|
||||
(calculate_needs, find_tworeg_group, find_group, possible_group_p,
|
||||
count_possible_groups, modes_equiv_for_class_p, new_spill_reg,
|
||||
dump_needs, maybe_mark_pseudo_spilled, hard_reg_use_compare): Delete
|
||||
functions.
|
||||
(count_pseudo, select_reload_regs, copy_reloads, find_reg): New
|
||||
functions.
|
||||
(struct hard_reg_n_uses): Deleted.
|
||||
(potential_reload_regs): Deleted.
|
||||
(init_reload): Initialize spilled_pseudos and pseudos_counted.
|
||||
(reload): Don't try to allocate reload registers if we already know
|
||||
we have to make another pass. Call select_reload_regs. Free memory
|
||||
starting with reload_firstobj when starting another pass.
|
||||
Don't allocate spilled_pseudos.
|
||||
(calculate_needs_all_insns): Call copy_reloads for an insn that
|
||||
needs reloads; don't call calculate_needs.
|
||||
(spill_cost): New static array.
|
||||
(used_spill_regs_local): New static variable.
|
||||
(order_regs_for_reload): Rewrite to lose hard_reg_n_uses and the code
|
||||
to compute potential_reload_regs.
|
||||
(find_reload_regs): Completely rewritten to use find_reg.
|
||||
(allocate_reload_reg): Don't test counted_for_groups or
|
||||
counted_for_nongroups. Lose NOERROR arg and code to give an error;
|
||||
all cllers changed.
|
||||
(choose_reload_regs): Add fallback code that uses the existing
|
||||
register allocation from find_reload_regs.
|
||||
|
||||
Mon Dec 13 00:54:14 1999 Philippe De Muyter <phdm@macqel.be>
|
||||
|
||||
* flow.c (create_edge_list): Cast xmalloc return value.
|
||||
|
|
|
@ -429,10 +429,14 @@ extern HARD_REG_SET call_fixed_reg_set;
|
|||
|
||||
extern char global_regs[FIRST_PSEUDO_REGISTER];
|
||||
|
||||
#ifdef REG_ALLOC_ORDER
|
||||
/* Table of register numbers in the order in which to try to use them. */
|
||||
|
||||
#ifdef REG_ALLOC_ORDER /* Avoid undef symbol in certain broken linkers. */
|
||||
extern int reg_alloc_order[FIRST_PSEUDO_REGISTER];
|
||||
|
||||
/* The inverse of reg_alloc_order. */
|
||||
|
||||
extern int inv_reg_alloc_order[FIRST_PSEUDO_REGISTER];
|
||||
#endif
|
||||
|
||||
/* For each reg class, a HARD_REG_SET saying which registers are in it. */
|
||||
|
|
|
@ -118,6 +118,9 @@ char global_regs[FIRST_PSEUDO_REGISTER];
|
|||
/* Table of register numbers in the order in which to try to use them. */
|
||||
#ifdef REG_ALLOC_ORDER
|
||||
int reg_alloc_order[FIRST_PSEUDO_REGISTER] = REG_ALLOC_ORDER;
|
||||
|
||||
/* The inverse of reg_alloc_order. */
|
||||
int inv_reg_alloc_order[FIRST_PSEUDO_REGISTER];
|
||||
#endif
|
||||
|
||||
/* For each reg class, a HARD_REG_SET saying which registers are in it. */
|
||||
|
@ -251,6 +254,11 @@ init_reg_sets ()
|
|||
|
||||
/* Do any additional initialization regsets may need */
|
||||
INIT_ONCE_REG_SET ();
|
||||
|
||||
#ifdef REG_ALLOC_ORDER
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
inv_reg_alloc_order[reg_alloc_order[i]] = i;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* After switches have been processed, which perhaps alter
|
||||
|
|
64
gcc/reload.c
64
gcc/reload.c
|
@ -465,7 +465,6 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
|
|||
rld[t_reload].outmode = ! in_p ? t_mode : VOIDmode;
|
||||
rld[t_reload].reg_rtx = 0;
|
||||
rld[t_reload].optional = optional;
|
||||
rld[t_reload].nongroup = 0;
|
||||
rld[t_reload].inc = 0;
|
||||
/* Maybe we could combine these, but it seems too tricky. */
|
||||
rld[t_reload].nocombine = 1;
|
||||
|
@ -535,7 +534,6 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
|
|||
rld[s_reload].outmode = ! in_p ? mode : VOIDmode;
|
||||
rld[s_reload].reg_rtx = 0;
|
||||
rld[s_reload].optional = optional;
|
||||
rld[s_reload].nongroup = 0;
|
||||
rld[s_reload].inc = 0;
|
||||
/* Maybe we could combine these, but it seems too tricky. */
|
||||
rld[s_reload].nocombine = 1;
|
||||
|
@ -1246,7 +1244,6 @@ push_reload (in, out, inloc, outloc, class,
|
|||
rld[i].outmode = outmode;
|
||||
rld[i].reg_rtx = 0;
|
||||
rld[i].optional = optional;
|
||||
rld[i].nongroup = 0;
|
||||
rld[i].inc = 0;
|
||||
rld[i].nocombine = 0;
|
||||
rld[i].in_reg = inloc ? *inloc : 0;
|
||||
|
@ -4119,67 +4116,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|
|||
abort ();
|
||||
#endif
|
||||
|
||||
/* Set which reloads must use registers not used in any group. Start
|
||||
with those that conflict with a group and then include ones that
|
||||
conflict with ones that are already known to conflict with a group. */
|
||||
|
||||
changed = 0;
|
||||
for (i = 0; i < n_reloads; i++)
|
||||
{
|
||||
enum machine_mode mode = rld[i].inmode;
|
||||
enum reg_class class = rld[i].class;
|
||||
int size;
|
||||
|
||||
if (GET_MODE_SIZE (rld[i].outmode) > GET_MODE_SIZE (mode))
|
||||
mode = rld[i].outmode;
|
||||
size = CLASS_MAX_NREGS (class, mode);
|
||||
|
||||
if (size == 1)
|
||||
for (j = 0; j < n_reloads; j++)
|
||||
if ((CLASS_MAX_NREGS (rld[j].class,
|
||||
(GET_MODE_SIZE (rld[j].outmode)
|
||||
> GET_MODE_SIZE (rld[j].inmode))
|
||||
? rld[j].outmode : rld[j].inmode)
|
||||
> 1)
|
||||
&& !rld[j].optional
|
||||
&& (rld[j].in != 0 || rld[j].out != 0
|
||||
|| rld[j].secondary_p)
|
||||
&& reloads_conflict (i, j)
|
||||
&& reg_classes_intersect_p (class, rld[j].class))
|
||||
{
|
||||
rld[i].nongroup = 1;
|
||||
changed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (changed)
|
||||
{
|
||||
changed = 0;
|
||||
|
||||
for (i = 0; i < n_reloads; i++)
|
||||
{
|
||||
enum machine_mode mode = rld[i].inmode;
|
||||
enum reg_class class = rld[i].class;
|
||||
int size;
|
||||
|
||||
if (GET_MODE_SIZE (rld[i].outmode) > GET_MODE_SIZE (mode))
|
||||
mode = rld[i].outmode;
|
||||
size = CLASS_MAX_NREGS (class, mode);
|
||||
|
||||
if (! rld[i].nongroup && size == 1)
|
||||
for (j = 0; j < n_reloads; j++)
|
||||
if (rld[j].nongroup
|
||||
&& reloads_conflict (i, j)
|
||||
&& reg_classes_intersect_p (class, rld[j].class))
|
||||
{
|
||||
rld[i].nongroup = 1;
|
||||
changed = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute reload_mode and reload_nregs. */
|
||||
for (i = 0; i < n_reloads; i++)
|
||||
{
|
||||
|
|
22
gcc/reload.h
22
gcc/reload.h
|
@ -231,25 +231,9 @@ struct insn_chain
|
|||
regset live_before;
|
||||
regset live_after;
|
||||
|
||||
/* For each class, size of group of consecutive regs
|
||||
that is needed for the reloads of this class. */
|
||||
char group_size[N_REG_CLASSES];
|
||||
/* For each class, the machine mode which requires consecutive
|
||||
groups of regs of that class.
|
||||
If two different modes ever require groups of one class,
|
||||
they must be the same size and equally restrictive for that class,
|
||||
otherwise we can't handle the complexity. */
|
||||
enum machine_mode group_mode[N_REG_CLASSES];
|
||||
|
||||
/* Indicates if a register was counted against the need for
|
||||
groups. 0 means it can count against max_nongroup instead. */
|
||||
HARD_REG_SET counted_for_groups;
|
||||
|
||||
/* Indicates if a register was counted against the need for
|
||||
non-groups. 0 means it can become part of a new group.
|
||||
During choose_reload_regs, 1 here means don't use this reg
|
||||
as part of a group, even if it seems to be otherwise ok. */
|
||||
HARD_REG_SET counted_for_nongroups;
|
||||
/* Copies of the global variables computed by find_reloads. */
|
||||
struct reload *rld;
|
||||
int n_reloads;
|
||||
|
||||
/* Indicates which registers have already been used for spills. */
|
||||
HARD_REG_SET used_spill_regs;
|
||||
|
|
1457
gcc/reload1.c
1457
gcc/reload1.c
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue