Commit e989202f by Bernd Schmidt Committed by Bernd Schmidt

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
parent 460d832b
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> 2005-11-05 Jan Hubicka <jh@suse.cz>
PR rtl-optimization/23490 PR rtl-optimization/23490
......
...@@ -212,16 +212,18 @@ legitimize_pic_address (rtx orig, rtx reg, rtx picreg) ...@@ -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. /* Compute the number of DREGS to save with a push_multiple operation.
This could include registers that aren't modified in the function, 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 static int
n_dregs_to_save (void) n_dregs_to_save (bool is_inthandler)
{ {
unsigned i; unsigned i;
for (i = REG_R0; i <= REG_R7; 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; return REG_R7 - i + 1;
if (current_function_calls_eh_return) if (current_function_calls_eh_return)
...@@ -244,12 +246,12 @@ n_dregs_to_save (void) ...@@ -244,12 +246,12 @@ n_dregs_to_save (void)
/* Like n_dregs_to_save, but compute number of PREGS to save. */ /* Like n_dregs_to_save, but compute number of PREGS to save. */
static int static int
n_pregs_to_save (void) n_pregs_to_save (bool is_inthandler)
{ {
unsigned i; unsigned i;
for (i = REG_P0; i <= REG_P5; 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 || (i == PIC_OFFSET_TABLE_REGNUM
&& (current_function_uses_pic_offset_table && (current_function_uses_pic_offset_table
|| (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf)))) || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
...@@ -262,7 +264,7 @@ n_pregs_to_save (void) ...@@ -262,7 +264,7 @@ n_pregs_to_save (void)
static bool static bool
must_save_fp_p (void) 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 static bool
...@@ -277,13 +279,14 @@ stack_frame_needed_p (void) ...@@ -277,13 +279,14 @@ stack_frame_needed_p (void)
/* Emit code to save registers in the prologue. SAVEALL is nonzero if we /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
must save all registers; this is used for interrupt handlers. 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 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 ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
int npregs = saveall ? 6 : n_pregs_to_save (); int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
int dregno = REG_R7 + 1 - ndregs; int dregno = REG_R7 + 1 - ndregs;
int pregno = REG_P5 + 1 - npregs; int pregno = REG_P5 + 1 - npregs;
int total = ndregs + npregs; int total = ndregs + npregs;
...@@ -328,13 +331,14 @@ expand_prologue_reg_save (rtx spreg, int saveall) ...@@ -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 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
must save all registers; this is used for interrupt handlers. 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 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 ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
int npregs = saveall ? 6 : n_pregs_to_save (); int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
int total = ndregs + npregs; int total = ndregs + npregs;
int i, regno; int i, regno;
rtx pat, insn; rtx pat, insn;
...@@ -449,9 +453,15 @@ static int ...@@ -449,9 +453,15 @@ static int
n_regs_saved_by_prologue (void) n_regs_saved_by_prologue (void)
{ {
e_funkind fkind = funkind (TREE_TYPE (current_function_decl)); 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. */ /* We use a LINK instruction in this case. */
n += 2; n += 2;
else else
...@@ -464,8 +474,6 @@ n_regs_saved_by_prologue (void) ...@@ -464,8 +474,6 @@ n_regs_saved_by_prologue (void)
if (fkind != SUBROUTINE) if (fkind != SUBROUTINE)
{ {
tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
tree all = lookup_attribute ("saveall", attrs);
int i; int i;
/* Increment once for ASTAT. */ /* Increment once for ASTAT. */
...@@ -640,14 +648,16 @@ arg_area_size (void) ...@@ -640,14 +648,16 @@ arg_area_size (void)
return 0; 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 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 (); frame_size += arg_area_size ();
if (stack_frame_needed_p () if (all || stack_frame_needed_p ()
|| (must_save_fp_p () && ! current_function_is_leaf)) || (must_save_fp_p () && ! current_function_is_leaf))
emit_link_insn (spreg, frame_size); emit_link_insn (spreg, frame_size);
else else
...@@ -675,11 +685,11 @@ do_link (rtx spreg, HOST_WIDE_INT frame_size) ...@@ -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. */ /* Like do_link, but used for epilogues to deallocate the stack frame. */
static void 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 (); frame_size += arg_area_size ();
if (stack_frame_needed_p ()) if (all || stack_frame_needed_p ())
emit_insn (gen_unlink ()); emit_insn (gen_unlink ());
else else
{ {
...@@ -713,7 +723,7 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind) ...@@ -713,7 +723,7 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
rtx predec = gen_rtx_MEM (SImode, predec1); rtx predec = gen_rtx_MEM (SImode, predec1);
rtx insn; rtx insn;
tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); 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); tree kspisusp = lookup_attribute ("kspisusp", attrs);
if (kspisusp) if (kspisusp)
...@@ -733,7 +743,11 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind) ...@@ -733,7 +743,11 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT)); insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
RTX_FRAME_RELATED_P (insn) = 1; 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++) for (i = REG_P7 + 1; i < REG_CC; i++)
if (all if (all
...@@ -757,7 +771,7 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind) ...@@ -757,7 +771,7 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
RTX_FRAME_RELATED_P (insn) = 1; RTX_FRAME_RELATED_P (insn) = 1;
} }
do_link (spreg, frame_size); do_link (spreg, frame_size, all);
if (fkind == EXCPT_HANDLER) if (fkind == EXCPT_HANDLER)
{ {
...@@ -792,19 +806,19 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind) ...@@ -792,19 +806,19 @@ expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
SPREG contains (reg:SI REG_SP). */ SPREG contains (reg:SI REG_SP). */
static void static void
expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind) expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
{ {
int i; int i;
rtx postinc1 = gen_rtx_POST_INC (SImode, spreg); rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
rtx postinc = gen_rtx_MEM (SImode, postinc1); rtx postinc = gen_rtx_MEM (SImode, postinc1);
tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl)); 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" /* A slightly crude technique to stop flow from trying to delete "dead"
insns. */ insns. */
MEM_VOLATILE_P (postinc) = 1; MEM_VOLATILE_P (postinc) = 1;
do_unlink (spreg, get_frame_size ()); do_unlink (spreg, get_frame_size (), all);
if (lookup_attribute ("nesting", attrs)) if (lookup_attribute ("nesting", attrs))
{ {
...@@ -814,9 +828,14 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind) ...@@ -814,9 +828,14 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
emit_move_insn (srcreg, postinc); 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--) for (i = REG_CC - 1; i > REG_P7; i--)
if (all if (all
|| regs_ever_live[i] || regs_ever_live[i]
|| (!leaf_function_p () && call_used_regs[i])) || (!leaf_function_p () && call_used_regs[i]))
{ {
if (i == REG_A0 || i == REG_A1) if (i == REG_A0 || i == REG_A1)
...@@ -829,7 +848,7 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind) ...@@ -829,7 +848,7 @@ expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
emit_move_insn (gen_rtx_REG (SImode, i), postinc); 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); emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
...@@ -909,9 +928,9 @@ bfin_expand_prologue (void) ...@@ -909,9 +928,9 @@ bfin_expand_prologue (void)
emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim)); emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
emit_insn (gen_trapifcc ()); 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 if (TARGET_ID_SHARED_LIBRARY
&& (current_function_uses_pic_offset_table && (current_function_uses_pic_offset_table
...@@ -935,9 +954,9 @@ bfin_expand_epilogue (int need_return, int eh_return) ...@@ -935,9 +954,9 @@ bfin_expand_epilogue (int need_return, int eh_return)
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. */ /* Omit the return insn if this is for a sibcall. */
if (! need_return) if (! need_return)
...@@ -1469,7 +1488,8 @@ static bool ...@@ -1469,7 +1488,8 @@ static bool
bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
tree exp 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 /* Emit RTL insns to initialize the variable parts of a trampoline at
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment