RFA: avoid creating temporary rtl in get/has_hard_reg_initial_val

Richard Sandiford rsandifo@redhat.com
Sat May 7 14:20:00 GMT 2005


integrate.c:has_hard_reg_initial_val() is implemented like this:

    rtx
    has_hard_reg_initial_val (enum machine_mode mode, int regno)
    {
      return has_func_hard_reg_initial_val (cfun, gen_rtx_REG (mode, regno));
..................................................^^^^^^^^^^^^^^^^^^^^^^^^^
    }

This function is the only caller of has_func_hard_reg_initial_val,
which is implemented like this:

    static rtx
    has_func_hard_reg_initial_val (struct function *fun, rtx reg)
    {
      struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
      int i;

      if (ivs == 0)
        return NULL_RTX;

      for (i = 0; i < ivs->num_entries; i++)
        if (rtx_equal_p (ivs->entries[i].hard_reg, reg))
          return ivs->entries[i].pseudo;

      return NULL_RTX;
    }

So we're creating a temporary rtx for the sole purpose of comparing
it against "hard_reg" fields.

One of Red Hat's uncontributed ports makes quite heavy use of
has_hard_reg_initial_val.  The implementations quoted above were
causing gcc to run out of memory on a pathological, but depressingly
short testcase (about O(100) statements).  The port could be changed,
but in principle, has_hard_reg_initial_val ought to be quite a
lightweight function.

The patch below changes has_hard_reg_initial_val so that it compares
the "hard_reg" modes and register numbers against the parameter values.
It also makes get_hard_reg_initial_val call has_hard_reg_initial_val
instead of has_func_hard_reg_initial_val when looking for an existing
pseudo.  This means we'll only create an rtx if a new initial value
entry is needed.

(FWIW, I thought about replacing the hard_reg field with separate mode
and register numbers.  It's not obviously a win though.  There are quite
a few functions in integrate.c that benefit from having an existing
rtx for the hard register.)

Tested on mips64-elf, which (unlike x86) uses this interface.
OK to install?

Richard

[The diff is a bit difficult to follow, sorry.  I hope the description
 and changelog make it clear what's going on.]

	* integrate.c (get_func_hard_reg_initial_val): Delete.
	(has_func_hard_reg_initial_val): Delete.
	(get_hard_reg_initial_val): Inline the old implementation of
	get_func_hard_reg_initial_val.  Use has_hard_reg_initial_val
	instead of has_func_hard_reg_initial_val to test for an existing
	pseudo.  Only create an rtx if a new initial value entry is needed.
	(has_hard_reg_initial_val): Scan the initial value list directly.
	Don't create an rtx.

Index: integrate.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/integrate.c,v
retrieving revision 1.275
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.275 integrate.c
*** integrate.c	28 Apr 2005 05:38:31 -0000	1.275
--- integrate.c	6 May 2005 14:44:24 -0000
*************** 02111-1307, USA.  */
*** 50,56 ****
  #define CEIL_ROUND(VALUE,ALIGN)	(((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
  
  
! /* Private type used by {get/has}_func_hard_reg_initial_val.  */
  typedef struct initial_value_pair GTY(()) {
    rtx hard_reg;
    rtx pseudo;
--- 50,56 ----
  #define CEIL_ROUND(VALUE,ALIGN)	(((VALUE) + (ALIGN) - 1) & ~((ALIGN)- 1))
  
  
! /* Private type used by {get/has}_hard_reg_initial_val.  */
  typedef struct initial_value_pair GTY(()) {
    rtx hard_reg;
    rtx pseudo;
*************** get_hard_reg_initial_reg (struct functio
*** 293,330 ****
    return NULL_RTX;
  }
  
! static rtx
! has_func_hard_reg_initial_val (struct function *fun, rtx reg)
! {
!   struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
!   int i;
! 
!   if (ivs == 0)
!     return NULL_RTX;
! 
!   for (i = 0; i < ivs->num_entries; i++)
!     if (rtx_equal_p (ivs->entries[i].hard_reg, reg))
!       return ivs->entries[i].pseudo;
! 
!   return NULL_RTX;
! }
  
! static rtx
! get_func_hard_reg_initial_val (struct function *fun, rtx reg)
  {
!   struct initial_value_struct *ivs = fun->hard_reg_initial_vals;
!   rtx rv = has_func_hard_reg_initial_val (fun, reg);
  
    if (rv)
      return rv;
  
    if (ivs == 0)
      {
!       fun->hard_reg_initial_vals = ggc_alloc (sizeof (initial_value_struct));
!       ivs = fun->hard_reg_initial_vals;
        ivs->num_entries = 0;
        ivs->max_entries = 5;
        ivs->entries = ggc_alloc (5 * sizeof (initial_value_pair));
      }
  
    if (ivs->num_entries >= ivs->max_entries)
--- 293,319 ----
    return NULL_RTX;
  }
  
! /* Make sure that there's a pseudo register of mode MODE that stores the
!    initial value of hard register REGNO.  Return an rtx for such a pseudo.  */
  
! rtx
! get_hard_reg_initial_val (enum machine_mode mode, int regno)
  {
!   struct initial_value_struct *ivs;
!   rtx rv;
  
+   rv = has_hard_reg_initial_val (mode, regno);
    if (rv)
      return rv;
  
+   ivs = cfun->hard_reg_initial_vals;
    if (ivs == 0)
      {
!       ivs = ggc_alloc (sizeof (initial_value_struct));
        ivs->num_entries = 0;
        ivs->max_entries = 5;
        ivs->entries = ggc_alloc (5 * sizeof (initial_value_pair));
+       cfun->hard_reg_initial_vals = ivs;
      }
  
    if (ivs->num_entries >= ivs->max_entries)
*************** get_func_hard_reg_initial_val (struct fu
*** 335,356 ****
  				  * sizeof (initial_value_pair));
      }
  
!   ivs->entries[ivs->num_entries].hard_reg = reg;
!   ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (GET_MODE (reg));
  
    return ivs->entries[ivs->num_entries++].pseudo;
  }
  
! rtx
! get_hard_reg_initial_val (enum machine_mode mode, int regno)
! {
!   return get_func_hard_reg_initial_val (cfun, gen_rtx_REG (mode, regno));
! }
  
  rtx
  has_hard_reg_initial_val (enum machine_mode mode, int regno)
  {
!   return has_func_hard_reg_initial_val (cfun, gen_rtx_REG (mode, regno));
  }
  
  void
--- 324,353 ----
  				  * sizeof (initial_value_pair));
      }
  
!   ivs->entries[ivs->num_entries].hard_reg = gen_rtx_REG (mode, regno);
!   ivs->entries[ivs->num_entries].pseudo = gen_reg_rtx (mode);
  
    return ivs->entries[ivs->num_entries++].pseudo;
  }
  
! /* See if get_hard_reg_initial_val has been used to create a pseudo
!    for the initial value of hard register REGNO in mode MODE.  Return
!    the associated pseudo if so, otherwise return NULL.  */
  
  rtx
  has_hard_reg_initial_val (enum machine_mode mode, int regno)
  {
!   struct initial_value_struct *ivs;
!   int i;
! 
!   ivs = cfun->hard_reg_initial_vals;
!   if (ivs != 0)
!     for (i = 0; i < ivs->num_entries; i++)
!       if (GET_MODE (ivs->entries[i].hard_reg) == mode
! 	  && REGNO (ivs->entries[i].hard_reg) == (unsigned int) regno)
! 	return ivs->entries[i].pseudo;
! 
!   return NULL_RTX;
  }
  
  void



More information about the Gcc-patches mailing list