bfin.c (n_dregs_to_save, [...]): New argument IS_INTHANDLER; all callers changed.
* config/bfin/bfin.c (n_dregs_to_save, n_pregs_to_save, expand_prologue_reg_save, expand_epilogue_reg_restore): New argument IS_INTHANDLER; all callers changed. (n_regs_saved_by_prologue): Take interrupt handler attributes into account. (do_link, do_unlink): New argument ALL; all callers changed. (expand_interrupt_handler_prologue, expand_interrupt_handler_epilogue): If function isn't leaf, save and restore all registers. (bfin_function_ok_for_sibcall): Only true if not an interrupt or exception handler. From-SVN: r106526
This commit is contained in:
parent
460d832b00
commit
e989202f01
2 changed files with 69 additions and 36 deletions
|
@ -1,3 +1,16 @@
|
|||
2005-11-05 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||
|
||||
* config/bfin/bfin.c (n_dregs_to_save, n_pregs_to_save,
|
||||
expand_prologue_reg_save, expand_epilogue_reg_restore): New argument
|
||||
IS_INTHANDLER; all callers changed.
|
||||
(n_regs_saved_by_prologue): Take interrupt handler attributes into
|
||||
account.
|
||||
(do_link, do_unlink): New argument ALL; all callers changed.
|
||||
(expand_interrupt_handler_prologue, expand_interrupt_handler_epilogue):
|
||||
If function isn't leaf, save and restore all registers.
|
||||
(bfin_function_ok_for_sibcall): Only true if not an interrupt or
|
||||
exception handler.
|
||||
|
||||
2005-11-05 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
PR rtl-optimization/23490
|
||||
|
|
|
@ -212,16 +212,18 @@ legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
|
|||
|
||||
/* Compute the number of DREGS to save with a push_multiple operation.
|
||||
This could include registers that aren't modified in the function,
|
||||
since push_multiple only takes a range of registers. */
|
||||
since push_multiple only takes a range of registers.
|
||||
If IS_INTHANDLER, then everything that is live must be saved, even
|
||||
if normally call-clobbered. */
|
||||
|
||||
static int
|
||||
n_dregs_to_save (void)
|
||||
n_dregs_to_save (bool is_inthandler)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = REG_R0; i <= REG_R7; i++)
|
||||
{
|
||||
if (regs_ever_live[i] && ! call_used_regs[i])
|
||||
if (regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
|
||||
return REG_R7 - i + 1;
|
||||
|
||||
if (current_function_calls_eh_return)
|
||||
|
@ -244,12 +246,12 @@ n_dregs_to_save (void)
|
|||
/* Like n_dregs_to_save, but compute number of PREGS to save. */
|
||||
|
||||
static int
|
||||
n_pregs_to_save (void)
|
||||
n_pregs_to_save (bool is_inthandler)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = REG_P0; i <= REG_P5; i++)
|
||||
if ((regs_ever_live[i] && ! call_used_regs[i])
|
||||
if ((regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
|
||||
|| (i == PIC_OFFSET_TABLE_REGNUM
|
||||
&& (current_function_uses_pic_offset_table
|
||||
|| (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
|
||||
|
@ -262,7 +264,7 @@ n_pregs_to_save (void)
|
|||
static bool
|
||||
must_save_fp_p (void)
|
||||
{
|
||||
return (frame_pointer_needed || regs_ever_live[REG_FP]);
|
||||
return frame_pointer_needed || regs_ever_live[REG_FP];
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -277,13 +279,14 @@ stack_frame_needed_p (void)
|
|||
|
||||
/* Emit code to save registers in the prologue. SAVEALL is nonzero if we
|
||||
must save all registers; this is used for interrupt handlers.
|
||||
SPREG contains (reg:SI REG_SP). */
|
||||
SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
|
||||
this for an interrupt (or exception) handler. */
|
||||
|
||||
static void
|
||||
expand_prologue_reg_save (rtx spreg, int saveall)
|
||||
expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
|
||||
{
|
||||
int ndregs = saveall ? 8 : n_dregs_to_save ();
|
||||
int npregs = saveall ? 6 : n_pregs_to_save ();
|
||||
int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
|
||||
int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
|
||||
int dregno = REG_R7 + 1 - ndregs;
|
||||
int pregno = REG_P5 + 1 - npregs;
|
||||
int total = ndregs + npregs;
|
||||
|
@ -328,13 +331,14 @@ expand_prologue_reg_save (rtx spreg, int saveall)
|
|||
|
||||
/* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
|
||||
must save all registers; this is used for interrupt handlers.
|
||||
SPREG contains (reg:SI REG_SP). */
|
||||
SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
|
||||
this for an interrupt (or exception) handler. */
|
||||
|
||||
static void
|
||||
expand_epilogue_reg_restore (rtx spreg, int saveall)
|
||||
expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
|
||||
{
|
||||
int ndregs = saveall ? 8 : n_dregs_to_save ();
|
||||
int npregs = saveall ? 6 : n_pregs_to_save ();
|
||||
int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
|
||||
int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
|
||||
int total = ndregs + npregs;
|
||||
int i, regno;
|
||||
rtx pat, insn;
|
||||
|
@ -449,9 +453,15 @@ static int
|
|||
n_regs_saved_by_prologue (void)
|
||||
{
|
||||
e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
|
||||
int n = n_dregs_to_save () + n_pregs_to_save ();
|
||||
bool is_inthandler = fkind != SUBROUTINE;
|
||||
tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
|
||||
bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
|
||||
|| (is_inthandler && !current_function_is_leaf));
|
||||
int ndregs = all ? 8 : n_dregs_to_save (is_inthandler);
|
||||
int npregs = all ? 6 : n_pregs_to_save (is_inthandler);
|
||||
int n = ndregs + npregs;
|
||||
|
||||
if (stack_frame_needed_p ())
|
||||
if (all || stack_frame_needed_p ())
|
||||
/* We use a LINK instruction in this case. */
|
||||
n += 2;
|
||||
else
|
||||
|
@ -464,8 +474,6 @@ n_regs_saved_by_prologue (void)
|
|||
|
||||
if (fkind != SUBROUTINE)
|
||||
{
|
||||
tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
|
||||
tree all = lookup_attribute ("saveall", attrs);
|
||||
int i;
|
||||
|
||||
/* Increment once for ASTAT. */
|
||||
|
@ -640,14 +648,16 @@ arg_area_size (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Save RETS and FP, and allocate a stack frame. */
|
||||
/* Save RETS and FP, and allocate a stack frame. ALL is true if the
|
||||
function must save all its registers (true only for certain interrupt
|
||||
handlers). */
|
||||
|
||||
static void
|
||||
do_link (rtx spreg, HOST_WIDE_INT frame_size)
|
||||
do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
|
||||
{
|
||||
frame_size += arg_area_size ();
|
||||
|
||||
if (stack_frame_needed_p ()
|
||||
if (all || stack_frame_needed_p ()
|
||||
|| (must_save_fp_p () && ! current_function_is_leaf))
|
||||
emit_link_insn (spreg, frame_size);
|
||||
else
|
||||
|
@ -675,11 +685,11 @@ do_link (rtx spreg, HOST_WIDE_INT frame_size)
|
|||
/* Like do_link, but used for epilogues to deallocate the stack frame. */
|
||||
|
||||
static void
|
||||
do_unlink (rtx spreg, HOST_WIDE_INT frame_size)
|
||||
do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all)
|
||||
{
|
||||
frame_size += arg_area_size ();
|
||||
|
||||
if (stack_frame_needed_p ())
|
||||
if (all || stack_frame_needed_p ())
|
||||
emit_insn (gen_unlink ());
|
||||
else
|
||||
{
|
||||
|
@ -713,7 +723,7 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
|
|||
rtx predec = gen_rtx_MEM (SImode, predec1);
|
||||
rtx insn;
|
||||
tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
|
||||
tree all = lookup_attribute ("saveall", attrs);
|
||||
bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
|
||||
tree kspisusp = lookup_attribute ("kspisusp", attrs);
|
||||
|
||||
if (kspisusp)
|
||||
|
@ -733,7 +743,11 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
|
|||
insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
|
||||
expand_prologue_reg_save (spreg, all != NULL_TREE);
|
||||
/* If we're calling other functions, they won't save their call-clobbered
|
||||
registers, so we must save everything here. */
|
||||
if (!current_function_is_leaf)
|
||||
all = true;
|
||||
expand_prologue_reg_save (spreg, all, true);
|
||||
|
||||
for (i = REG_P7 + 1; i < REG_CC; i++)
|
||||
if (all
|
||||
|
@ -757,7 +771,7 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
|
|||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
}
|
||||
|
||||
do_link (spreg, frame_size);
|
||||
do_link (spreg, frame_size, all);
|
||||
|
||||
if (fkind == EXCPT_HANDLER)
|
||||
{
|
||||
|
@ -792,19 +806,19 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
|
|||
SPREG contains (reg:SI REG_SP). */
|
||||
|
||||
static void
|
||||
expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
|
||||
expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
|
||||
{
|
||||
int i;
|
||||
rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
|
||||
rtx postinc = gen_rtx_MEM (SImode, postinc1);
|
||||
tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
|
||||
tree all = lookup_attribute ("saveall", attrs);
|
||||
bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
|
||||
|
||||
/* A slightly crude technique to stop flow from trying to delete "dead"
|
||||
insns. */
|
||||
MEM_VOLATILE_P (postinc) = 1;
|
||||
|
||||
do_unlink (spreg, get_frame_size ());
|
||||
do_unlink (spreg, get_frame_size (), all);
|
||||
|
||||
if (lookup_attribute ("nesting", attrs))
|
||||
{
|
||||
|
@ -814,9 +828,14 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
|
|||
emit_move_insn (srcreg, postinc);
|
||||
}
|
||||
|
||||
/* If we're calling other functions, they won't save their call-clobbered
|
||||
registers, so we must save (and restore) everything here. */
|
||||
if (!current_function_is_leaf)
|
||||
all = true;
|
||||
|
||||
for (i = REG_CC - 1; i > REG_P7; i--)
|
||||
if (all
|
||||
|| regs_ever_live[i]
|
||||
|| regs_ever_live[i]
|
||||
|| (!leaf_function_p () && call_used_regs[i]))
|
||||
{
|
||||
if (i == REG_A0 || i == REG_A1)
|
||||
|
@ -829,7 +848,7 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
|
|||
emit_move_insn (gen_rtx_REG (SImode, i), postinc);
|
||||
}
|
||||
|
||||
expand_epilogue_reg_restore (spreg, all != NULL_TREE);
|
||||
expand_epilogue_reg_restore (spreg, all, true);
|
||||
|
||||
emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
|
||||
|
||||
|
@ -909,9 +928,9 @@ bfin_expand_prologue (void)
|
|||
emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
|
||||
emit_insn (gen_trapifcc ());
|
||||
}
|
||||
expand_prologue_reg_save (spreg, 0);
|
||||
expand_prologue_reg_save (spreg, 0, false);
|
||||
|
||||
do_link (spreg, frame_size);
|
||||
do_link (spreg, frame_size, false);
|
||||
|
||||
if (TARGET_ID_SHARED_LIBRARY
|
||||
&& (current_function_uses_pic_offset_table
|
||||
|
@ -935,9 +954,9 @@ bfin_expand_epilogue (int need_return, int eh_return)
|
|||
return;
|
||||
}
|
||||
|
||||
do_unlink (spreg, get_frame_size ());
|
||||
do_unlink (spreg, get_frame_size (), false);
|
||||
|
||||
expand_epilogue_reg_restore (spreg, 0);
|
||||
expand_epilogue_reg_restore (spreg, false, false);
|
||||
|
||||
/* Omit the return insn if this is for a sibcall. */
|
||||
if (! need_return)
|
||||
|
@ -1469,7 +1488,8 @@ static bool
|
|||
bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
|
||||
tree exp ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return true;
|
||||
e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
|
||||
return fkind == SUBROUTINE;
|
||||
}
|
||||
|
||||
/* Emit RTL insns to initialize the variable parts of a trampoline at
|
||||
|
|
Loading…
Add table
Reference in a new issue