Ian Lance Taylor wrote:
Kenneth Zadeck <[EMAIL PROTECTED]> writes:
For complete accuracy, there are probably going to be some target
specific registers which need to be handled, unfortunately. For
example, on MIPS, with -mabicalls (which is the default on GNU/Linux),
$25 is live on function entry. It holds the address of the function,
and is used to initialize $28, which is PIC_OFFSET_TABLE_REGNUM. I
don't think there is any target independent way of getting at that
fact.
Is the right thing to do to define a target hook for this that
defaults to doing nothing and we only define it in those places where
necessary or should I add a few other macros to the ports as necessary
and just check to see if they are defined? I have noticed that there
are several macros that are only used on a single port.
I think the best approach would be a target hook. I guess you could
pass it the function decl and have it set bits in a bitmap or a
HARD_REG_SET. You might even want to do the whole thing in a target
hook, in which case the code you wrote would become the default
version of the hook (and would probably be called by non-default
versions). I don't have a strong feeling as to which approach would
be best.
Ian
Being the glutton for punishment, lets try this again.
I have one question about EH_USES on the ia-64 (the only place it is
used). The function
that implements this starts out with
int
ia64_eh_uses (int regno)
{
if (! reload_completed)
return 0;
This means that before register allocation, all of the uses of these
registers are hidden.
However, in the definition of REG_ALLOC_ORDER contains all of the
register that are defined in ia64_eh_uses after reload. It is at the
end of the order and there are a large number of registers but it seems
to me that if someone were to write a program that needed a large
boatload of registers, the register allocator might be tempted to use
these registers (unless there are no instruction patterns that use these
registers) and then the instruction exception unwinder would not work.
Is this a latent bug?
Asside from the concern from above and plumbing the target hook, how
does this look?
/* Record the (conservative) set of hard registers that are defined on
entry to the function. */
static void
df_record_entry_block_defs (struct dataflow * dflow)
{
unsigned int i;
bitmap_iterator bi;
rtx r;
struct df * df = dflow->df;
bitmap_clear (df->entry_block_defs);
if (! (df->flags & DF_HARD_REGS))
return;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
if (FUNCTION_ARG_REGNO_P (i))
#ifdef INCOMING_REGNO
bitmap_set_bit (df->entry_block_defs, INCOMING_REGNO (i));
#else
bitmap_set_bit (df->entry_block_defs, i);
#endif
}
/* Once the prologue has been generated, all of these registers
should just show up in the first regular block. */
if (HAVE_prologue && epilogue_completed)
{
/* Defs for the callee saved registers are inserted so that the
pushes have some defining location. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if ((call_used_regs[i] == 0) && (regs_ever_live[i]))
bitmap_set_bit (df->entry_block_defs, i);
}
else
{
if (REG_P (INCOMING_RETURN_ADDR_RTX))
bitmap_set_bit (df->entry_block_defs, REGNO (INCOMING_RETURN_ADDR_RTX));
/* If STATIC_CHAIN_INCOMING_REGNUM == STATIC_CHAIN_REGNUM
only STATIC_CHAIN_REGNUM is defined. If they are different,
we only care about the STATIC_CHAIN_INCOMING_REGNUM. */
#ifdef STATIC_CHAIN_INCOMING_REGNUM
bitmap_set_bit (df->entry_block_defs, STATIC_CHAIN_INCOMING_REGNUM);
#else
#ifdef STATIC_CHAIN_REGNUM
bitmap_set_bit (df->entry_block_defs, STATIC_CHAIN_REGNUM);
#endif
#endif
r = TARGET_STRUCT_VALUE_RTX (current_function_decl, true)
if (r && REG_P (r))
bitmap_set_bit (df->entry_block_defs, REGNO (r));
}
/* These registers are live everywhere. */
if (!reload_completed)
{
/* Any reference to any pseudo before reload is a potential
reference of the frame pointer. */
bitmap_set_bit (df->entry_block_defs, FRAME_POINTER_REGNUM);
#ifdef EH_USES
/* The ia-64, the only machine that uses this, does not define these
until after reload. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (EH_USES (i))
{
bitmap_set_bit (df->entry_block_defs, i);
}
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
/* Pseudos with argument area equivalences may require
reloading via the argument pointer. */
if (fixed_regs[ARG_POINTER_REGNUM])
bitmap_set_bit (df->entry_block_defs, ARG_POINTER_REGNUM);
#endif
#ifdef PIC_OFFSET_TABLE_REGNUM
/* Any constant, or pseudo with constant equivalences, may
require reloading from memory using the pic register. */
if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
&& fixed_regs[PIC_OFFSET_TABLE_REGNUM])
bitmap_set_bit (df->entry_block_defs, PIC_OFFSET_TABLE_REGNUM);
#endif
}
EXECUTE_IF_SET_IN_BITMAP (df->entry_block_defs, 0, i, bi)
{
rtx def = df_reg_def_gen (true, i);
df_ref_create_structure (dflow, regno_reg_rtx[i],
&XEXP (def, 0), ENTRY_BLOCK_PTR, NULL,
DF_REF_REG_DEF, DF_REF_ARTIFICIAL);
}
}