patch for local alloc / global alloc / reload problem (version 2)
John Wehle
john@feith.com
Sat Sep 5 15:04:00 GMT 1998
[ The only change from the previous patch is the updating of
some comments. ]
This change allows gcc to attempt and find a hard register
for a pseudo register which was allocated to a hard register
by local-alloc and later spilled by reload. The effect of
the patch can be seen by compiling:
int
func(int a, int b, int c, int d)
{
int g;
int h;
int i;
int j;
int m;
g = a;
h = b;
i = c;
j = d;
for (m = g; m < j; m += j) {
j = j / m;
m %= g * j;
}
return m;
}
on an x86 using -O -S -da and looking at the resulting .greg
and .s files. Without the patch a local register is spilled
to the stack, with the patch the register is spilled and ends
up back in a hard register.
ChangeLog:
Sat Sep 5 16:34:34 EDT 1998 John Wehle (john@feith.com)
* global.c: Update comments.
(global_alloc): Assign allocation-numbers
even for registers allocated by local_alloc in case
they are later spilled and retry_global_alloc is called.
(mark_reg_store, mark_reg_clobber,
mark_reg_conflicts, mark_reg_death): Always record a
conflict with a pseudo register even if it has been
assigned to a hard register.
(dump_conflicts): Don't dump pseudo registers already
assigned to a hard register.
* local-alloc.c: Update comment.
Enjoy!
-- John Wehle
------------------8<------------------------8<------------------------
*** gcc/global.c.ORIGINAL Wed Aug 26 00:45:45 1998
--- gcc/global.c Sat Sep 5 16:38:07 1998
*************** Boston, MA 02111-1307, USA. */
*** 45,52 ****
reg for it. The reload pass is independent in other respects
and it is run even when stupid register allocation is in use.
! 1. count the pseudo-registers still needing allocation
! and assign allocation-numbers (allocnos) to them.
Set up tables reg_allocno and allocno_reg to map
reg numbers to allocnos and vice versa.
max_allocno gets the number of allocnos in use.
--- 45,53 ----
reg for it. The reload pass is independent in other respects
and it is run even when stupid register allocation is in use.
! 1. Assign allocation-numbers (allocnos) to the pseudo-registers
! still needing allocations and to the pseudo-registers currently
! allocated by local-alloc which may be spilled by reload.
Set up tables reg_allocno and allocno_reg to map
reg numbers to allocnos and vice versa.
max_allocno gets the number of allocnos in use.
*************** Boston, MA 02111-1307, USA. */
*** 56,68 ****
for conflicts between allocnos and explicit hard register use
(which includes use of pseudo-registers allocated by local_alloc).
! 3. for each basic block
walk forward through the block, recording which
! unallocated registers and which hardware registers are live.
! Build the conflict matrix between the unallocated registers
! and another of unallocated registers versus hardware registers.
Also record the preferred hardware registers
! for each unallocated one.
4. Sort a table of the allocnos into order of
desirability of the variables.
--- 57,69 ----
for conflicts between allocnos and explicit hard register use
(which includes use of pseudo-registers allocated by local_alloc).
! 3. For each basic block
walk forward through the block, recording which
! pseudo-registers and which hardware registers are live.
! Build the conflict matrix between the pseudo-registers
! and another of pseudo-registers versus hardware registers.
Also record the preferred hardware registers
! for each pseudo-register.
4. Sort a table of the allocnos into order of
desirability of the variables.
*************** Boston, MA 02111-1307, USA. */
*** 70,82 ****
5. Allocate the variables in that order; each if possible into
a preferred register, else into another register. */
! /* Number of pseudo-registers still requiring allocation
! (not allocated by local_allocate). */
static int max_allocno;
/* Indexed by (pseudo) reg number, gives the allocno, or -1
! for pseudo registers already allocated by local_allocate. */
int *reg_allocno;
--- 71,82 ----
5. Allocate the variables in that order; each if possible into
a preferred register, else into another register. */
! /* Number of pseudo-registers which are candidates for allocation. */
static int max_allocno;
/* Indexed by (pseudo) reg number, gives the allocno, or -1
! for pseudo registers which are not to be allocated. */
int *reg_allocno;
*************** global_alloc (file)
*** 389,401 ****
/* Note that reg_live_length[i] < 0 indicates a "constant" reg
that we are supposed to refrain from putting in a hard reg.
-2 means do make an allocno but don't allocate it. */
! if (REG_N_REFS (i) != 0 && reg_renumber[i] < 0 && REG_LIVE_LENGTH (i) != -1
/* Don't allocate pseudos that cross calls,
if this function receives a nonlocal goto. */
&& (! current_function_has_nonlocal_label
|| REG_N_CALLS_CROSSED (i) == 0))
{
! if (reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
reg_allocno[i] = reg_allocno[reg_may_share[i]];
else
reg_allocno[i] = max_allocno++;
--- 389,401 ----
/* Note that reg_live_length[i] < 0 indicates a "constant" reg
that we are supposed to refrain from putting in a hard reg.
-2 means do make an allocno but don't allocate it. */
! if (REG_N_REFS (i) != 0 && REG_LIVE_LENGTH (i) != -1
/* Don't allocate pseudos that cross calls,
if this function receives a nonlocal goto. */
&& (! current_function_has_nonlocal_label
|| REG_N_CALLS_CROSSED (i) == 0))
{
! if (reg_renumber[i] < 0 && reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
reg_allocno[i] = reg_allocno[reg_may_share[i]];
else
reg_allocno[i] = max_allocno++;
*************** global_alloc (file)
*** 433,439 ****
bzero ((char *) local_reg_live_length, sizeof local_reg_live_length);
bzero ((char *) local_reg_n_refs, sizeof local_reg_n_refs);
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
! if (reg_allocno[i] < 0 && reg_renumber[i] >= 0)
{
int regno = reg_renumber[i];
int endregno = regno + HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
--- 433,439 ----
bzero ((char *) local_reg_live_length, sizeof local_reg_live_length);
bzero ((char *) local_reg_n_refs, sizeof local_reg_n_refs);
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
! if (reg_renumber[i] >= 0)
{
int regno = reg_renumber[i];
int endregno = regno + HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
*************** global_alloc (file)
*** 561,567 ****
except for parameters marked with reg_live_length[regno] == -2. */
for (i = 0; i < max_allocno; i++)
! if (REG_LIVE_LENGTH (allocno_reg[allocno_order[i]]) >= 0)
{
/* If we have more than one register class,
first try allocating in the class that is cheapest
--- 561,568 ----
except for parameters marked with reg_live_length[regno] == -2. */
for (i = 0; i < max_allocno; i++)
! if (reg_renumber[allocno_reg[allocno_order[i]]] < 0
! && REG_LIVE_LENGTH (allocno_reg[allocno_order[i]]) >= 0)
{
/* If we have more than one register class,
first try allocating in the class that is cheapest
*************** mark_reg_store (orig_reg, setter)
*** 1364,1372 ****
regno = REGNO (reg);
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno] /* + word */;
-
/* Either this is one of the max_allocno pseudo regs not allocated,
or it is or has a hardware reg. First handle the pseudo-regs. */
if (regno >= FIRST_PSEUDO_REGISTER)
--- 1365,1370 ----
*************** mark_reg_store (orig_reg, setter)
*** 1377,1384 ****
record_one_conflict (regno);
}
}
/* Handle hardware regs (and pseudos allocated to hard regs). */
! else if (! fixed_regs[regno])
{
register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (regno < last)
--- 1375,1386 ----
record_one_conflict (regno);
}
}
+
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno] /* + word */;
+
/* Handle hardware regs (and pseudos allocated to hard regs). */
! if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
{
register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (regno < last)
*************** mark_reg_clobber (reg, setter)
*** 1420,1428 ****
regno = REGNO (reg);
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno] /* + word */;
-
/* Either this is one of the max_allocno pseudo regs not allocated,
or it is or has a hardware reg. First handle the pseudo-regs. */
if (regno >= FIRST_PSEUDO_REGISTER)
--- 1422,1427 ----
*************** mark_reg_clobber (reg, setter)
*** 1433,1440 ****
record_one_conflict (regno);
}
}
/* Handle hardware regs (and pseudos allocated to hard regs). */
! else if (! fixed_regs[regno])
{
register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (regno < last)
--- 1432,1443 ----
record_one_conflict (regno);
}
}
+
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno] /* + word */;
+
/* Handle hardware regs (and pseudos allocated to hard regs). */
! if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
{
register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (regno < last)
*************** mark_reg_conflicts (reg)
*** 1463,1471 ****
regno = REGNO (reg);
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno];
-
/* Either this is one of the max_allocno pseudo regs not allocated,
or it is or has a hardware reg. First handle the pseudo-regs. */
if (regno >= FIRST_PSEUDO_REGISTER)
--- 1466,1471 ----
*************** mark_reg_conflicts (reg)
*** 1473,1480 ****
if (reg_allocno[regno] >= 0)
record_one_conflict (regno);
}
/* Handle hardware regs (and pseudos allocated to hard regs). */
! else if (! fixed_regs[regno])
{
register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (regno < last)
--- 1473,1484 ----
if (reg_allocno[regno] >= 0)
record_one_conflict (regno);
}
+
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno];
+
/* Handle hardware regs (and pseudos allocated to hard regs). */
! if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
{
register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (regno < last)
*************** mark_reg_death (reg)
*** 1494,1503 ****
{
register int regno = REGNO (reg);
- /* For pseudo reg, see if it has been assigned a hardware reg. */
- if (reg_renumber[regno] >= 0)
- regno = reg_renumber[regno];
-
/* Either this is one of the max_allocno pseudo regs not allocated,
or it is a hardware reg. First handle the pseudo-regs. */
if (regno >= FIRST_PSEUDO_REGISTER)
--- 1498,1503 ----
*************** mark_reg_death (reg)
*** 1505,1512 ****
if (reg_allocno[regno] >= 0)
CLEAR_ALLOCNO_LIVE (reg_allocno[regno]);
}
/* Handle hardware regs (and pseudos allocated to hard regs). */
! else if (! fixed_regs[regno])
{
/* Pseudo regs already assigned hardware regs are treated
almost the same as explicit hardware regs. */
--- 1505,1517 ----
if (reg_allocno[regno] >= 0)
CLEAR_ALLOCNO_LIVE (reg_allocno[regno]);
}
+
+ /* For pseudo reg, see if it has been assigned a hardware reg. */
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno];
+
/* Handle hardware regs (and pseudos allocated to hard regs). */
! if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
{
/* Pseudo regs already assigned hardware regs are treated
almost the same as explicit hardware regs. */
*************** dump_conflicts (file)
*** 1661,1670 ****
{
register int i;
register int has_preferences;
! fprintf (file, ";; %d regs to allocate:", max_allocno);
for (i = 0; i < max_allocno; i++)
{
int j;
fprintf (file, " %d", allocno_reg[allocno_order[i]]);
for (j = 0; j < max_regno; j++)
if (reg_allocno[j] == allocno_order[i]
--- 1666,1685 ----
{
register int i;
register int has_preferences;
! register int nregs;
! nregs = 0;
! for (i = 0; i < max_allocno; i++)
! {
! if (reg_renumber[allocno_reg[allocno_order[i]]] >= 0)
! continue;
! nregs++;
! }
! fprintf (file, ";; %d regs to allocate:", nregs);
for (i = 0; i < max_allocno; i++)
{
int j;
+ if (reg_renumber[allocno_reg[allocno_order[i]]] >= 0)
+ continue;
fprintf (file, " %d", allocno_reg[allocno_order[i]]);
for (j = 0; j < max_regno; j++)
if (reg_allocno[j] == allocno_order[i]
*************** dump_conflicts (file)
*** 1678,1683 ****
--- 1693,1700 ----
for (i = 0; i < max_allocno; i++)
{
register int j;
+ if (reg_renumber[allocno_reg[i]] >= 0)
+ continue;
fprintf (file, ";; %d conflicts:", allocno_reg[i]);
for (j = 0; j < max_allocno; j++)
if (CONFLICTP (i, j) || CONFLICTP (j, i))
*** gcc/local-alloc.c.ORIGINAL Fri Jul 3 23:25:54 1998
--- gcc/local-alloc.c Sat Sep 5 15:56:03 1998
*************** Boston, MA 02111-1307, USA. */
*** 55,62 ****
But this is currently disabled since tying in global_alloc is not
yet implemented. */
! /* Pseudos allocated here cannot be reallocated by global.c if the hard
! register is used as a spill register. So we don't allocate such pseudos
here if their preferred class is likely to be used by spills. */
#include "config.h"
--- 55,62 ----
But this is currently disabled since tying in global_alloc is not
yet implemented. */
! /* Pseudos allocated here can be reallocated by global.c if the hard register
! is used as a spill register. Currently we don't allocate such pseudos
here if their preferred class is likely to be used by spills. */
#include "config.h"
-------------------------------------------------------------------------
| Feith Systems | Voice: 1-215-646-8000 | Email: john@feith.com |
| John Wehle | Fax: 1-215-540-5495 | |
-------------------------------------------------------------------------
More information about the Gcc-patches
mailing list