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