Commit a1ed7bdb by Jan Hubicka Committed by Jan Hubicka

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
parent 7e8a11bb
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
......
......@@ -78,100 +78,108 @@ 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. */
/* We maintain two hard register sets that indicate suggested hard registers
for each quantity. The first, qty_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.
int birth;
The former register set is given priority for allocation. This tends to
eliminate copy insns. */
/* 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. */
/* Element Q is a set of hard registers that are suggested for quantity Q by
copy insns. */
int death;
static HARD_REG_SET *qty_phys_copy_sugg;
/* 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). */
/* Element Q is a set of hard registers that are suggested for quantity Q by
arithmetic insns. */
int size;
static HARD_REG_SET *qty_phys_sugg;
/* Number of times a reg tied to given qty lives across a CALL_INSN. */
/* Element Q is the number of suggested registers in qty_phys_copy_sugg. */
int n_calls_crossed;
static short *qty_phys_num_copy_sugg;
/* 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. */
/* Element Q is the number of suggested registers in qty_phys_sugg. */
int first_reg;
static short *qty_phys_num_sugg;
/* 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;
/* Element Q is the number of refs to quantity Q. */
/* Register class within which we allocate given qty if we can't get
its preferred class. */
static int *qty_n_refs;
enum reg_class alternate_class;
/* 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. */
/* This holds the mode of the registers that are tied to given qty,
or VOIDmode if registers with differing modes are tied together. */
static enum reg_class *qty_min_class;
enum machine_mode mode;
/* Insn number (counting from head of basic block)
where quantity Q was born. -1 if birth has not been recorded. */
/* the hard reg number chosen for given quantity,
or -1 if none was found. */
static int *qty_birth;
short phys_reg;
/* 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. */
/* Nonzero if this quantity has been used in a SUBREG that changes
its size. */
static int *qty_death;
char changes_size;
/* 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;
static struct qty *qty;
/* This holds the mode of the registers that are tied to qty Q,
or VOIDmode if registers with differing modes are tied together. */
/* These fields are kept separately to speedup their clearing. */
static enum machine_mode *qty_mode;
/* We maintain two hard register sets that indicate suggested 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.
/* Number of times a reg tied to qty Q lives across a CALL_INSN. */
The former register set is given priority for allocation. This tends to
eliminate copy insns. */
/* Element Q is a set of hard registers that are suggested for quantity Q by
copy insns. */
static int *qty_n_calls_crossed;
static HARD_REG_SET *qty_phys_copy_sugg;
/* Register class within which we allocate qty Q if we can't get
its preferred class. */
/* Element Q is a set of hard registers that are suggested for quantity Q by
arithmetic insns. */
static HARD_REG_SET *qty_phys_sugg;
static enum reg_class *qty_alternate_class;
/* Element Q is the number of suggested registers in qty_phys_copy_sugg. */
/* Element Q is nonzero if this quantity has been used in a SUBREG
that changes its size. */
static short *qty_phys_num_copy_sugg;
static char *qty_changes_size;
/* Element Q is the number of suggested registers in qty_phys_sugg. */
/* 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 short *qty_phys_num_sugg;
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;
......
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