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