local-alloc.c (qty): New structure and static variable.

* local-alloc.c (qty): New structure and static variable.
	(qty_phys_reg): Remove, all references changed to qty.
	(qty_n_refs): Likewise.
	(qty_min_class): Likewise.
	(qty_birth): Likewise.
	(qty_death): Likewise.
	(qty_size): Likewise.
	(qty_mode): Likewise.
	(qty_n_calls_crossed): Likewise.
	(qty_alternate_class): Likewise.
	(qty_changes_size): Likewise.
	(qty_first_reg): Likewise.
	(alloc_qty): Rename variable QTY to QTYNO.
	(finf_free_reg): Likewise.
	(local_alloc): Allocate qty, do not allocate the removed variables.

From-SVN: r30651
This commit is contained in:
Jan Hubicka 1999-11-24 14:14:57 +01:00 committed by Jan Hubicka
parent 7e8a11bb9d
commit a1ed7bdbdd
2 changed files with 164 additions and 161 deletions

View File

@ -1,3 +1,21 @@
Wed Nov 24 14:12:15 MET 1999 Jan Hubicka <hubicka@freesoft.cz>
* local-alloc.c (qty): New structure and static variable.
(qty_phys_reg): Remove, all references changed to qty.
(qty_n_refs): Likewise.
(qty_min_class): Likewise.
(qty_birth): Likewise.
(qty_death): Likewise.
(qty_size): Likewise.
(qty_mode): Likewise.
(qty_n_calls_crossed): Likewise.
(qty_alternate_class): Likewise.
(qty_changes_size): Likewise.
(qty_first_reg): Likewise.
(alloc_qty): Rename variable QTY to QTYNO.
(finf_free_reg): Likewise.
(local_alloc): Allocate qty, do not allocate the removed variables.
Wed Nov 24 17:26:05 1999 Geoffrey Keating <geoffk@cygnus.com>
* config/mips/mips.h (ASM_SPEC): Don't pass -G to the assembler

View File

@ -78,15 +78,80 @@ Boston, MA 02111-1307, USA. */
static int next_qty;
/* In all the following vectors indexed by quantity number. */
/* Information we maitain about each quantity. */
struct qty
{
/* The number of refs to quantity Q. */
/* Element Q is the hard reg number chosen for quantity Q,
or -1 if none was found. */
int n_refs;
static short *qty_phys_reg;
/* Insn number (counting from head of basic block)
where quantity Q was born. -1 if birth has not been recorded. */
int birth;
/* Insn number (counting from head of basic block)
where given quantity died. Due to the way tying is done,
and the fact that we consider in this pass only regs that die but once,
a quantity can die only once. Each quantity's life span
is a set of consecutive insns. -1 if death has not been recorded. */
int death;
/* Number of words needed to hold the data in given quantity.
This depends on its machine mode. It is used for these purposes:
1. It is used in computing the relative importances of qtys,
which determines the order in which we look for regs for them.
2. It is used in rules that prevent tying several registers of
different sizes in a way that is geometrically impossible
(see combine_regs). */
int size;
/* Number of times a reg tied to given qty lives across a CALL_INSN. */
int n_calls_crossed;
/* The register number of one pseudo register whose reg_qty value is Q.
This register should be the head of the chain
maintained in reg_next_in_qty. */
int first_reg;
/* Reg class contained in (smaller than) the preferred classes of all
the pseudo regs that are tied in given quantity.
This is the preferred class for allocating that quantity. */
enum reg_class min_class;
/* Register class within which we allocate given qty if we can't get
its preferred class. */
enum reg_class alternate_class;
/* This holds the mode of the registers that are tied to given qty,
or VOIDmode if registers with differing modes are tied together. */
enum machine_mode mode;
/* the hard reg number chosen for given quantity,
or -1 if none was found. */
short phys_reg;
/* Nonzero if this quantity has been used in a SUBREG that changes
its size. */
char changes_size;
};
static struct qty *qty;
/* These fields are kept separately to speedup their clearing. */
/* We maintain two hard register sets that indicate suggested hard registers
for each quantity. The first, qty_phys_copy_sugg, contains hard registers
for each quantity. The first, phys_copy_sugg, contains hard registers
that are tied to the quantity by a simple copy. The second contains all
hard registers that are tied to the quantity via an arithmetic operation.
@ -111,67 +176,10 @@ static short *qty_phys_num_copy_sugg;
static short *qty_phys_num_sugg;
/* Element Q is the number of refs to quantity Q. */
static int *qty_n_refs;
/* Element Q is a reg class contained in (smaller than) the
preferred classes of all the pseudo regs that are tied in quantity Q.
This is the preferred class for allocating that quantity. */
static enum reg_class *qty_min_class;
/* Insn number (counting from head of basic block)
where quantity Q was born. -1 if birth has not been recorded. */
static int *qty_birth;
/* Insn number (counting from head of basic block)
where quantity Q died. Due to the way tying is done,
and the fact that we consider in this pass only regs that die but once,
a quantity can die only once. Each quantity's life span
is a set of consecutive insns. -1 if death has not been recorded. */
static int *qty_death;
/* Number of words needed to hold the data in quantity Q.
This depends on its machine mode. It is used for these purposes:
1. It is used in computing the relative importances of qtys,
which determines the order in which we look for regs for them.
2. It is used in rules that prevent tying several registers of
different sizes in a way that is geometrically impossible
(see combine_regs). */
static int *qty_size;
/* This holds the mode of the registers that are tied to qty Q,
or VOIDmode if registers with differing modes are tied together. */
static enum machine_mode *qty_mode;
/* Number of times a reg tied to qty Q lives across a CALL_INSN. */
static int *qty_n_calls_crossed;
/* Register class within which we allocate qty Q if we can't get
its preferred class. */
static enum reg_class *qty_alternate_class;
/* Element Q is nonzero if this quantity has been used in a SUBREG
that changes its size. */
static char *qty_changes_size;
/* Element Q is the register number of one pseudo register whose
reg_qty value is Q. This register should be the head of the chain
maintained in reg_next_in_qty. */
static int *qty_first_reg;
/* If (REG N) has been assigned a quantity number, is a register number
of another register assigned the same quantity number, or -1 for the
end of the chain. qty_first_reg point to the head of this chain. */
end of the chain. qty->first_reg point to the head of this chain. */
static int *reg_next_in_qty;
@ -278,21 +286,21 @@ alloc_qty (regno, mode, size, birth)
enum machine_mode mode;
int size, birth;
{
register int qty = next_qty++;
register int qtyno = next_qty++;
reg_qty[regno] = qty;
reg_qty[regno] = qtyno;
reg_offset[regno] = 0;
reg_next_in_qty[regno] = -1;
qty_first_reg[qty] = regno;
qty_size[qty] = size;
qty_mode[qty] = mode;
qty_birth[qty] = birth;
qty_n_calls_crossed[qty] = REG_N_CALLS_CROSSED (regno);
qty_min_class[qty] = reg_preferred_class (regno);
qty_alternate_class[qty] = reg_alternate_class (regno);
qty_n_refs[qty] = REG_N_REFS (regno);
qty_changes_size[qty] = REG_CHANGES_SIZE (regno);
qty[qtyno].first_reg = regno;
qty[qtyno].size = size;
qty[qtyno].mode = mode;
qty[qtyno].birth = birth;
qty[qtyno].n_calls_crossed = REG_N_CALLS_CROSSED (regno);
qty[qtyno].min_class = reg_preferred_class (regno);
qty[qtyno].alternate_class = reg_alternate_class (regno);
qty[qtyno].n_refs = REG_N_REFS (regno);
qty[qtyno].changes_size = REG_CHANGES_SIZE (regno);
}
/* Main entry point of this file. */
@ -326,25 +334,12 @@ local_alloc ()
See the declarations of these variables, above,
for what they mean. */
qty_phys_reg = (short *) xmalloc (max_qty * sizeof (short));
qty = (struct qty *) xmalloc (max_qty * sizeof (struct qty));
qty_phys_copy_sugg
= (HARD_REG_SET *) xmalloc (max_qty * sizeof (HARD_REG_SET));
qty_phys_num_copy_sugg = (short *) xmalloc (max_qty * sizeof (short));
qty_phys_sugg = (HARD_REG_SET *) xmalloc (max_qty * sizeof (HARD_REG_SET));
qty_phys_num_sugg = (short *) xmalloc (max_qty * sizeof (short));
qty_birth = (int *) xmalloc (max_qty * sizeof (int));
qty_death = (int *) xmalloc (max_qty * sizeof (int));
qty_first_reg = (int *) xmalloc (max_qty * sizeof (int));
qty_size = (int *) xmalloc (max_qty * sizeof (int));
qty_mode
= (enum machine_mode *) xmalloc (max_qty * sizeof (enum machine_mode));
qty_n_calls_crossed = (int *) xmalloc (max_qty * sizeof (int));
qty_min_class
= (enum reg_class *) xmalloc (max_qty * sizeof (enum reg_class));
qty_alternate_class
= (enum reg_class *) xmalloc (max_qty * sizeof (enum reg_class));
qty_n_refs = (int *) xmalloc (max_qty * sizeof (int));
qty_changes_size = (char *) xmalloc (max_qty * sizeof (char));
reg_qty = (int *) xmalloc (max_regno * sizeof (int));
reg_offset = (char *) xmalloc (max_regno * sizeof (char));
@ -413,21 +408,11 @@ local_alloc ()
block_alloc (b);
}
free (qty_phys_reg);
free (qty);
free (qty_phys_copy_sugg);
free (qty_phys_num_copy_sugg);
free (qty_phys_sugg);
free (qty_phys_num_sugg);
free (qty_birth);
free (qty_death);
free (qty_first_reg);
free (qty_size);
free (qty_mode);
free (qty_n_calls_crossed);
free (qty_min_class);
free (qty_alternate_class);
free (qty_n_refs);
free (qty_changes_size);
free (reg_qty);
free (reg_offset);
@ -1356,10 +1341,10 @@ block_alloc (b)
{
q = qty_order[i];
if (qty_phys_num_sugg[q] != 0 || qty_phys_num_copy_sugg[q] != 0)
qty_phys_reg[q] = find_free_reg (qty_min_class[q], qty_mode[q], q,
0, 1, qty_birth[q], qty_death[q]);
qty[q].phys_reg = find_free_reg (qty[q].min_class, qty[q].mode, q,
0, 1, qty[q].birth, qty[q].death);
else
qty_phys_reg[q] = -1;
qty[q].phys_reg = -1;
}
/* Order the qtys so we assign them registers in order of
@ -1406,7 +1391,7 @@ block_alloc (b)
for (i = 0; i < next_qty; i++)
{
q = qty_order[i];
if (qty_phys_reg[q] < 0)
if (qty[q].phys_reg < 0)
{
#ifdef INSN_SCHEDULING
/* These values represent the adjusted lifetime of a qty so
@ -1426,9 +1411,9 @@ block_alloc (b)
If allocation using the extended lifetime fails we will try
again with the qty's unadjusted lifetime. */
int fake_birth = MAX (0, qty_birth[q] - 2 + qty_birth[q] % 2);
int fake_birth = MAX (0, qty[q].birth - 2 + qty[q].birth % 2);
int fake_death = MIN (insn_number * 2 + 1,
qty_death[q] + 2 - qty_death[q] % 2);
qty[q].death + 2 - qty[q].death % 2);
#endif
if (N_REG_CLASSES > 1)
@ -1446,17 +1431,17 @@ block_alloc (b)
&& !SMALL_REGISTER_CLASSES)
{
qty_phys_reg[q] = find_free_reg (qty_min_class[q],
qty_mode[q], q, 0, 0,
qty[q].phys_reg = find_free_reg (qty[q].min_class,
qty[q].mode, q, 0, 0,
fake_birth, fake_death);
if (qty_phys_reg[q] >= 0)
if (qty[q].phys_reg >= 0)
continue;
}
#endif
qty_phys_reg[q] = find_free_reg (qty_min_class[q],
qty_mode[q], q, 0, 0,
qty_birth[q], qty_death[q]);
if (qty_phys_reg[q] >= 0)
qty[q].phys_reg = find_free_reg (qty[q].min_class,
qty[q].mode, q, 0, 0,
qty[q].birth, qty[q].death);
if (qty[q].phys_reg >= 0)
continue;
}
@ -1465,15 +1450,15 @@ block_alloc (b)
if (flag_schedule_insns_after_reload
&& !optimize_size
&& !SMALL_REGISTER_CLASSES
&& qty_alternate_class[q] != NO_REGS)
qty_phys_reg[q] = find_free_reg (qty_alternate_class[q],
qty_mode[q], q, 0, 0,
&& qty[q].alternate_class != NO_REGS)
qty[q].phys_reg = find_free_reg (qty[q].alternate_class,
qty[q].mode, q, 0, 0,
fake_birth, fake_death);
#endif
if (qty_alternate_class[q] != NO_REGS)
qty_phys_reg[q] = find_free_reg (qty_alternate_class[q],
qty_mode[q], q, 0, 0,
qty_birth[q], qty_death[q]);
if (qty[q].alternate_class != NO_REGS)
qty[q].phys_reg = find_free_reg (qty[q].alternate_class,
qty[q].mode, q, 0, 0,
qty[q].birth, qty[q].death);
}
}
@ -1481,10 +1466,10 @@ block_alloc (b)
to the pseudo regs belonging to the qtys. */
for (q = 0; q < next_qty; q++)
if (qty_phys_reg[q] >= 0)
if (qty[q].phys_reg >= 0)
{
for (i = qty_first_reg[q]; i >= 0; i = reg_next_in_qty[i])
reg_renumber[i] = qty_phys_reg[q] + reg_offset[i];
for (i = qty[q].first_reg; i >= 0; i = reg_next_in_qty[i])
reg_renumber[i] = qty[q].phys_reg + reg_offset[i];
}
/* Clean up. */
@ -1509,8 +1494,8 @@ block_alloc (b)
QTY_CMP_PRI is also used by qty_sugg_compare. */
#define QTY_CMP_PRI(q) \
((int) (((double) (floor_log2 (qty_n_refs[q]) * qty_n_refs[q] * qty_size[q]) \
/ (qty_death[q] - qty_birth[q])) * 10000))
((int) (((double) (floor_log2 (qty[q].n_refs) * qty[q].n_refs * qty[q].size) \
/ (qty[q].death - qty[q].birth)) * 10000))
static int
qty_compare (q1, q2)
@ -1656,7 +1641,7 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
/* Do not combine with a smaller already-assigned object
if that smaller object is already combined with something bigger. */
|| (ssize > usize && ureg >= FIRST_PSEUDO_REGISTER
&& usize < qty_size[reg_qty[ureg]])
&& usize < qty[reg_qty[ureg]].size)
/* Can't combine if SREG is not a register we can allocate. */
|| (sreg >= FIRST_PSEUDO_REGISTER && reg_qty[sreg] == -1)
/* Don't combine with a pseudo mentioned in a REG_NO_CONFLICT note.
@ -1745,30 +1730,30 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
are compatible. */
if ((already_dead || find_regno_note (insn, REG_DEAD, ureg))
&& reg_meets_class_p (sreg, qty_min_class[reg_qty[ureg]]))
&& reg_meets_class_p (sreg, qty[reg_qty[ureg]].min_class))
{
/* Add SREG to UREG's quantity. */
sqty = reg_qty[ureg];
reg_qty[sreg] = sqty;
reg_offset[sreg] = reg_offset[ureg] + offset;
reg_next_in_qty[sreg] = qty_first_reg[sqty];
qty_first_reg[sqty] = sreg;
reg_next_in_qty[sreg] = qty[sqty].first_reg;
qty[sqty].first_reg = sreg;
/* If SREG's reg class is smaller, set qty_min_class[SQTY]. */
/* If SREG's reg class is smaller, set qty[SQTY].min_class. */
update_qty_class (sqty, sreg);
/* Update info about quantity SQTY. */
qty_n_calls_crossed[sqty] += REG_N_CALLS_CROSSED (sreg);
qty_n_refs[sqty] += REG_N_REFS (sreg);
qty[sqty].n_calls_crossed += REG_N_CALLS_CROSSED (sreg);
qty[sqty].n_refs += REG_N_REFS (sreg);
if (usize < ssize)
{
register int i;
for (i = qty_first_reg[sqty]; i >= 0; i = reg_next_in_qty[i])
for (i = qty[sqty].first_reg; i >= 0; i = reg_next_in_qty[i])
reg_offset[i] -= offset;
qty_size[sqty] = ssize;
qty_mode[sqty] = GET_MODE (setreg);
qty[sqty].size = ssize;
qty[sqty].mode = GET_MODE (setreg);
}
}
else
@ -1791,23 +1776,23 @@ reg_meets_class_p (reg, class)
|| reg_class_subset_p (class, rclass));
}
/* Update the class of QTY assuming that REG is being tied to it. */
/* Update the class of QTYNO assuming that REG is being tied to it. */
static void
update_qty_class (qty, reg)
int qty;
update_qty_class (qtyno, reg)
int qtyno;
int reg;
{
enum reg_class rclass = reg_preferred_class (reg);
if (reg_class_subset_p (rclass, qty_min_class[qty]))
qty_min_class[qty] = rclass;
if (reg_class_subset_p (rclass, qty[qtyno].min_class))
qty[qtyno].min_class = rclass;
rclass = reg_alternate_class (reg);
if (reg_class_subset_p (rclass, qty_alternate_class[qty]))
qty_alternate_class[qty] = rclass;
if (reg_class_subset_p (rclass, qty[qtyno].alternate_class))
qty[qtyno].alternate_class = rclass;
if (REG_CHANGES_SIZE (reg))
qty_changes_size[qty] = 1;
qty[qtyno].changes_size = 1;
}
/* Handle something which alters the value of an rtx REG.
@ -1870,7 +1855,7 @@ reg_is_born (reg, birth)
/* If this register has a quantity number, show that it isn't dead. */
if (reg_qty[regno] >= 0)
qty_death[reg_qty[regno]] = -1;
qty[reg_qty[regno]].death = -1;
}
}
@ -1931,7 +1916,7 @@ wipe_dead_reg (reg, output_p)
}
else if (reg_qty[regno] >= 0)
qty_death[reg_qty[regno]] = 2 * this_insn_number + output_p;
qty[reg_qty[regno]].death = 2 * this_insn_number + output_p;
}
/* Find a block of SIZE words of hard regs in reg_class CLASS
@ -1940,18 +1925,18 @@ wipe_dead_reg (reg, output_p)
and still free between insn BORN_INDEX and insn DEAD_INDEX,
and return the number of the first of them.
Return -1 if such a block cannot be found.
If QTY crosses calls, insist on a register preserved by calls,
If QTYNO crosses calls, insist on a register preserved by calls,
unless ACCEPT_CALL_CLOBBERED is nonzero.
If JUST_TRY_SUGGESTED is non-zero, only try to see if the suggested
register is available. If not, return -1. */
static int
find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested,
born_index, dead_index)
enum reg_class class;
enum machine_mode mode;
int qty;
int qtyno;
int accept_call_clobbered;
int just_try_suggested;
int born_index, dead_index;
@ -1972,12 +1957,12 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
/* Don't let a pseudo live in a reg across a function call
if we might get a nonlocal goto. */
if (current_function_has_nonlocal_label
&& qty_n_calls_crossed[qty] > 0)
&& qty[qtyno].n_calls_crossed > 0)
return -1;
if (accept_call_clobbered)
COPY_HARD_REG_SET (used, call_fixed_reg_set);
else if (qty_n_calls_crossed[qty] == 0)
else if (qty[qtyno].n_calls_crossed == 0)
COPY_HARD_REG_SET (used, fixed_reg_set);
else
COPY_HARD_REG_SET (used, call_used_reg_set);
@ -2009,7 +1994,7 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
#endif
#ifdef CLASS_CANNOT_CHANGE_SIZE
if (qty_changes_size[qty])
if (qty[qtyno].changes_size)
IOR_HARD_REG_SET (used,
reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]);
#endif
@ -2024,10 +2009,10 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
if (just_try_suggested)
{
if (qty_phys_num_copy_sugg[qty] != 0)
IOR_COMPL_HARD_REG_SET (first_used, qty_phys_copy_sugg[qty]);
if (qty_phys_num_copy_sugg[qtyno] != 0)
IOR_COMPL_HARD_REG_SET (first_used, qty_phys_copy_sugg[qtyno]);
else
IOR_COMPL_HARD_REG_SET (first_used, qty_phys_sugg[qty]);
IOR_COMPL_HARD_REG_SET (first_used, qty_phys_sugg[qtyno]);
}
/* If all registers are excluded, we can't do anything. */
@ -2044,7 +2029,7 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
#endif
if (! TEST_HARD_REG_BIT (first_used, regno)
&& HARD_REGNO_MODE_OK (regno, mode)
&& (qty_n_calls_crossed[qty] == 0
&& (qty[qtyno].n_calls_crossed == 0
|| accept_call_clobbered
|| ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
{
@ -2072,12 +2057,12 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
/* If it would be profitable to allocate a call-clobbered register
and save and restore it around calls, do that. */
if (just_try_suggested && qty_phys_num_copy_sugg[qty] != 0
&& qty_phys_num_sugg[qty] != 0)
if (just_try_suggested && qty_phys_num_copy_sugg[qtyno] != 0
&& qty_phys_num_sugg[qtyno] != 0)
{
/* Don't try the copy-suggested regs again. */
qty_phys_num_copy_sugg[qty] = 0;
return find_free_reg (class, mode, qty, accept_call_clobbered, 1,
qty_phys_num_copy_sugg[qtyno] = 0;
return find_free_reg (class, mode, qtyno, accept_call_clobbered, 1,
born_index, dead_index);
}
@ -2088,10 +2073,10 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
if (! accept_call_clobbered
&& flag_caller_saves
&& ! just_try_suggested
&& qty_n_calls_crossed[qty] != 0
&& CALLER_SAVE_PROFITABLE (qty_n_refs[qty], qty_n_calls_crossed[qty]))
&& qty[qtyno].n_calls_crossed != 0
&& CALLER_SAVE_PROFITABLE (qty[qtyno].n_refs, qty[qtyno].n_calls_crossed))
{
i = find_free_reg (class, mode, qty, 1, 0, born_index, dead_index);
i = find_free_reg (class, mode, qtyno, 1, 0, born_index, dead_index);
if (i >= 0)
caller_save_needed = 1;
return i;