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:
Bernd Schmidt 2005-11-05 11:29:33 +00:00 committed by Bernd Schmidt
parent 460d832b00
commit e989202f01
2 changed files with 69 additions and 36 deletions

View file

@ -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

View file

@ -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