Update: reload register allocation patch

Joern Rennecke amylaar@cygnus.co.uk
Fri Nov 12 13:47:00 GMT 1999


I think that in general, your patch will make some further modifications
simpler.  However, you still haven't addressed the issue of wrong cost
calculation for partial overlap of a pseudo by a spill register.

I have tried my hand at fixing this.  The basic idea is that you consider
two kinds of overlap: an overlap with the start of a pseudo, i.e. with
its first hard register, and an overlap with the end of a pseudo, i.e.
any other of its hard registers.
Any such overlap costs the full amount of spilling, which is currently
considered to be the number of hard registers in the pseudo multiplied
by the number of references to it.  A possible future refinement could be
to calculate the correct cost for subregs...

*** reload1.c-scratch	Fri Nov 12 21:10:15 1999
--- reload1.c-scratch2	Fri Nov 12 21:38:01 1999
*************** static int num_labels;
*** 372,378 ****
  struct hard_reg_n_uses
  {
    int regno;
!   unsigned int uses;
  };
  
  static void maybe_fix_stack_asms	PROTO((void));
--- 372,379 ----
  struct hard_reg_n_uses
  {
    int regno;
!   unsigned int start_uses;
!   unsigned int end_uses;
  };
  
  static void maybe_fix_stack_asms	PROTO((void));
*************** reload_reg_class_lower (r1p, r2p)
*** 1478,1484 ****
  }
  
  /* The cost of spilling each hard reg.  */
! static int spill_cost[FIRST_PSEUDO_REGISTER];
  
  static int
  hard_reg_use_compare (p1p, p2p)
--- 1479,1486 ----
  }
  
  /* The cost of spilling each hard reg.  */
! static int start_spill_cost[FIRST_PSEUDO_REGISTER];
! static int end_spill_cost[FIRST_PSEUDO_REGISTER];
  
  static int
  hard_reg_use_compare (p1p, p2p)
*************** hard_reg_use_compare (p1p, p2p)
*** 1489,1503 ****
    struct hard_reg_n_uses *p2 = (struct hard_reg_n_uses *)p2p;
    int bad1 = TEST_HARD_REG_BIT (bad_spill_regs, p1->regno);
    int bad2 = TEST_HARD_REG_BIT (bad_spill_regs, p2->regno);
    if (bad1 && bad2)
      return p1->regno - p2->regno;
    if (bad1)
      return 1;
    if (bad2)
      return -1;
!   if (p1->uses > p2->uses)
      return 1;
!   if (p1->uses < p2->uses)
      return -1;
    /* If regs are equally good, sort by regno,
       so that the results of qsort leave nothing to chance.  */
--- 1491,1508 ----
    struct hard_reg_n_uses *p2 = (struct hard_reg_n_uses *)p2p;
    int bad1 = TEST_HARD_REG_BIT (bad_spill_regs, p1->regno);
    int bad2 = TEST_HARD_REG_BIT (bad_spill_regs, p2->regno);
+   unsigned int p1_uses, p2_uses;
    if (bad1 && bad2)
      return p1->regno - p2->regno;
    if (bad1)
      return 1;
    if (bad2)
      return -1;
!   p1_uses = p1->start_uses + p1->end_uses;
!   p2_uses = p2->start_uses + p2->end_uses;
!   if (p1_uses > p2_uses)
      return 1;
!   if (p1_uses < p2_uses)
      return -1;
    /* If regs are equally good, sort by regno,
       so that the results of qsort leave nothing to chance.  */
*************** count_pseudo (n_uses, reg)
*** 1516,1521 ****
--- 1521,1527 ----
  {
    int r = reg_renumber[reg];
    int nregs;
+   int uses;
  
    if (REGNO_REG_SET_P (pseudos_counted, reg))
      return;
*************** count_pseudo (n_uses, reg)
*** 1525,1532 ****
      abort ();
  
    nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg));
!   while (nregs-- > 0)
!     n_uses[r++].uses += REG_N_REFS (reg);  
  }
  /* Choose the order to consider regs for use as reload registers
     based on how much trouble would be caused by spilling one.
--- 1531,1540 ----
      abort ();
  
    nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg));
!   uses = nregs * REG_N_REFS (reg);
!   n_uses[r++].start_uses += uses;
!   while (--nregs > 0)
!     n_uses[r++].end_uses += uses;
  }
  /* Choose the order to consider regs for use as reload registers
     based on how much trouble would be caused by spilling one.
*************** order_regs_for_reload (chain)
*** 1550,1556 ****
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      {
        hard_reg_n_uses[i].regno = i;
!       hard_reg_n_uses[i].uses = 0;
  
        /* Test the various reasons why we can't use a register for
  	 spilling in this insn.  */
--- 1558,1565 ----
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      {
        hard_reg_n_uses[i].regno = i;
!       hard_reg_n_uses[i].start_uses = 0;
!       hard_reg_n_uses[i].end_uses = 0;
  
        /* Test the various reasons why we can't use a register for
  	 spilling in this insn.  */
*************** order_regs_for_reload (chain)
*** 1577,1583 ****
    FREE_REG_SET (pseudos_counted);
  
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
!     spill_cost[i] = hard_reg_n_uses[i].uses;
  
    /* Prefer registers not so far used, for use in temporary loading.
       Among them, if REG_ALLOC_ORDER is defined, use that order.
--- 1586,1595 ----
    FREE_REG_SET (pseudos_counted);
  
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
!     {
!       start_spill_cost[i] = hard_reg_n_uses[i].start_uses;
!       end_spill_cost[i] = hard_reg_n_uses[i].end_uses;
!     }
  
    /* Prefer registers not so far used, for use in temporary loading.
       Among them, if REG_ALLOC_ORDER is defined, use that order.
*************** order_regs_for_reload (chain)
*** 1588,1607 ****
      {
        int regno = reg_alloc_order[i];
  
!       if (hard_reg_n_uses[regno].uses == 0
  	  && ! TEST_HARD_REG_BIT (bad_spill_regs, regno))
  	potential_reload_regs[o++] = regno;
      }
  #else
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      {
!       if (hard_reg_n_uses[i].uses == 0 && call_used_regs[i]
  	  && ! TEST_HARD_REG_BIT (bad_spill_regs, i))
  	potential_reload_regs[o++] = i;
      }
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      {
!       if (hard_reg_n_uses[i].uses == 0 && ! call_used_regs[i]
  	  && ! TEST_HARD_REG_BIT (bad_spill_regs, i))
  	potential_reload_regs[o++] = i;
      }
--- 1600,1624 ----
      {
        int regno = reg_alloc_order[i];
  
!       if (hard_reg_n_uses[regno].start_uses == 0
! 	  && hard_reg_n_uses[regno].end_uses == 0
  	  && ! TEST_HARD_REG_BIT (bad_spill_regs, regno))
  	potential_reload_regs[o++] = regno;
      }
  #else
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      {
!       if (hard_reg_n_uses[i].start_uses == 0
! 	  && hard_reg_n_uses[i].end_uses == 0
! 	  && call_used_regs[i]
  	  && ! TEST_HARD_REG_BIT (bad_spill_regs, i))
  	potential_reload_regs[o++] = i;
      }
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
      {
!       if (hard_reg_n_uses[i].start_uses == 0
! 	  && hard_reg_n_uses[i].end_uses == 0
! 	  && ! call_used_regs[i]
  	  && ! TEST_HARD_REG_BIT (bad_spill_regs, i))
  	potential_reload_regs[o++] = i;
      }
*************** order_regs_for_reload (chain)
*** 1615,1621 ****
       registers will be at the end of this list.  */
  
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
!     if (hard_reg_n_uses[i].uses != 0
  	&& ! TEST_HARD_REG_BIT (bad_spill_regs, hard_reg_n_uses[i].regno))
        potential_reload_regs[o++] = hard_reg_n_uses[i].regno;
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
--- 1632,1638 ----
       registers will be at the end of this list.  */
  
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
!     if (hard_reg_n_uses[i].start_uses + hard_reg_n_uses[i].end_uses != 0
  	&& ! TEST_HARD_REG_BIT (bad_spill_regs, hard_reg_n_uses[i].regno))
        potential_reload_regs[o++] = hard_reg_n_uses[i].regno;
    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
*************** find_reg (chain, order, dumpfile)
*** 1687,1699 ****
  	  && ! TEST_HARD_REG_BIT (used_by_other_reload, regno)
  	  && HARD_REGNO_MODE_OK (regno, rl->mode))
  	{
! 	  int this_cost = 0;
  	  int ok = 1;
  	  int this_nregs = HARD_REGNO_NREGS (regno, rl->mode);
  
  	  for (j = 0; j < this_nregs; j++)
  	    {
! 	      this_cost += spill_cost[regno + j];
  	      if ((TEST_HARD_REG_BIT (not_usable, regno + j))
  		  || TEST_HARD_REG_BIT (used_by_other_reload, regno + j))
  		ok = 0;
--- 1704,1716 ----
  	  && ! TEST_HARD_REG_BIT (used_by_other_reload, regno)
  	  && HARD_REGNO_MODE_OK (regno, rl->mode))
  	{
! 	  int this_cost = end_spill_cost[regno];
  	  int ok = 1;
  	  int this_nregs = HARD_REGNO_NREGS (regno, rl->mode);
  
  	  for (j = 0; j < this_nregs; j++)
  	    {
! 	      this_cost += start_spill_cost[regno + j];
  	      if ((TEST_HARD_REG_BIT (not_usable, regno + j))
  		  || TEST_HARD_REG_BIT (used_by_other_reload, regno + j))
  		ok = 0;
*************** find_reg (chain, order, dumpfile)
*** 1717,1723 ****
    rl->regno = best_reg;
    for (i = 0; i < rl->nregs; i++)
      {
!       spill_cost[best_reg + i] = 0;
        SET_HARD_REG_BIT (used_spill_regs_local, best_reg + i);
      }
    return 1;
--- 1734,1741 ----
    rl->regno = best_reg;
    for (i = 0; i < rl->nregs; i++)
      {
!       start_spill_cost[best_reg + i] = 0;
!       end_spill_cost[best_reg + i] = 0;
        SET_HARD_REG_BIT (used_spill_regs_local, best_reg + i);
      }
    return 1;


More information about the Gcc-patches mailing list