This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Blackfin: saveall attribute fixes
- From: Bernd Schmidt <bernds_cb1 at t-online dot de>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 25 Sep 2007 15:01:09 +0200
- Subject: Blackfin: saveall attribute fixes
Mike Frysinger pointed out that the saveall attribute doesn't have an
effect on regular functions. While it originally was intended to work
only on interrupt handlers, we can easily change that. This even counts
as a bugfix, as we generated incorrect prologues before rather than
completely ignoring the attribute.
Committed as 128762.
Bernd
--
This footer brought to you by insane German lawmakers.
Analog Devices GmbH Wilhelm-Wagenfeld-Str. 6 80807 Muenchen
Sitz der Gesellschaft Muenchen, Registergericht Muenchen HRB 40368
Geschaeftsfuehrer Thomas Wessel, William A. Martin, Margaret Seif
Index: ChangeLog
===================================================================
--- ChangeLog (revision 128761)
+++ ChangeLog (working copy)
@@ -1,3 +1,14 @@
+2007-09-25 Bernd Schmidt <bernd.schmidt@analog.com>
+
+ * config/bfin/bfin.c (expand_prologue_reg_save,
+ expand_epilogue_reg_restore): Code to save and restore I/M/B/L regs and
+ ASTAT moved here...
+ (expand_interrupt_handler_prologue, expand_interrupt_handler_epilogue):
+ ... from here. New argument ALL; callers changed.
+ (n_regs_saved_by_prologue): Count ASTAT for plain saveall functions.
+ (bfin_expand_prologue, bfin_expand_epilogue): Deal with functions that
+ have the "saveall" attribute.
+
2007-09-25 Hans-Peter Nilsson <hp@bitrange.com>
* config/mmix/mmix.h (FUNCTION_INCOMING_ARG_REGNO_P): Don't define
Index: config/bfin/bfin.c
===================================================================
--- config/bfin/bfin.c (revision 128761)
+++ config/bfin/bfin.c (working copy)
@@ -416,6 +416,8 @@ stack_frame_needed_p (void)
static void
expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
{
+ rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
+ rtx predec = gen_rtx_MEM (SImode, predec1);
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;
@@ -424,7 +426,13 @@ expand_prologue_reg_save (rtx spreg, int
int i;
rtx pat, insn, val;
- if (total == 0)
+ if (saveall || is_inthandler)
+ {
+ insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ if (total == 0 && !saveall)
return;
val = GEN_INT (-total * 4);
@@ -458,6 +466,20 @@ expand_prologue_reg_save (rtx spreg, int
}
insn = emit_insn (pat);
RTX_FRAME_RELATED_P (insn) = 1;
+
+ for (i = REG_P7 + 1; i < REG_CC; i++)
+ if (saveall
+ || (is_inthandler
+ && (df_regs_ever_live_p (i)
+ || (!leaf_function_p () && call_used_regs[i]))))
+ {
+ if (i == REG_A0 || i == REG_A1)
+ insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
+ gen_rtx_REG (PDImode, i));
+ else
+ insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
}
/* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
@@ -468,12 +490,35 @@ expand_prologue_reg_save (rtx spreg, int
static void
expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
{
+ rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
+ rtx postinc = gen_rtx_MEM (SImode, postinc1);
+
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;
+ /* A slightly crude technique to stop flow from trying to delete "dead"
+ insns. */
+ MEM_VOLATILE_P (postinc) = 1;
+
+ for (i = REG_CC - 1; i > REG_P7; i--)
+ if (saveall
+ || (is_inthandler
+ && (df_regs_ever_live_p (i)
+ || (!leaf_function_p () && call_used_regs[i]))))
+ {
+ if (i == REG_A0 || i == REG_A1)
+ {
+ rtx mem = gen_rtx_MEM (PDImode, postinc1);
+ MEM_VOLATILE_P (mem) = 1;
+ emit_move_insn (gen_rtx_REG (PDImode, i), mem);
+ }
+ else
+ emit_move_insn (gen_rtx_REG (SImode, i), postinc);
+ }
+
if (total == 0)
return;
@@ -507,6 +552,9 @@ expand_epilogue_reg_restore (rtx spreg,
insn = emit_insn (pat);
RTX_FRAME_RELATED_P (insn) = 1;
+
+ if (saveall || is_inthandler)
+ emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
}
/* Perform any needed actions needed for a function that is receiving a
@@ -591,6 +639,7 @@ n_regs_saved_by_prologue (void)
int ndregs = all ? 8 : n_dregs_to_save (is_inthandler);
int npregs = all ? 6 : n_pregs_to_save (is_inthandler);
int n = ndregs + npregs;
+ int i;
if (all || stack_frame_needed_p ())
/* We use a LINK instruction in this case. */
@@ -603,23 +652,24 @@ n_regs_saved_by_prologue (void)
n++;
}
+ if (fkind != SUBROUTINE || all)
+ /* Increment once for ASTAT. */
+ n++;
+
if (fkind != SUBROUTINE)
{
- int i;
-
- /* Increment once for ASTAT. */
- n++;
-
/* RETE/X/N. */
if (lookup_attribute ("nesting", attrs))
n++;
-
- for (i = REG_P7 + 1; i < REG_CC; i++)
- if (all
- || df_regs_ever_live_p (i)
- || (!leaf_function_p () && call_used_regs[i]))
- n += i == REG_A0 || i == REG_A1 ? 2 : 1;
}
+
+ for (i = REG_P7 + 1; i < REG_CC; i++)
+ if (all
+ || (fkind != SUBROUTINE
+ && (df_regs_ever_live_p (i)
+ || (!leaf_function_p () && call_used_regs[i]))))
+ n += i == REG_A0 || i == REG_A1 ? 2 : 1;
+
return n;
}
@@ -882,15 +932,13 @@ do_unlink (rtx spreg, HOST_WIDE_INT fram
SPREG contains (reg:SI REG_SP). */
static void
-expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
+expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
{
- int i;
HOST_WIDE_INT frame_size = get_frame_size ();
rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
rtx predec = gen_rtx_MEM (SImode, predec1);
rtx insn;
tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
- bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
tree kspisusp = lookup_attribute ("kspisusp", attrs);
if (kspisusp)
@@ -907,28 +955,12 @@ expand_interrupt_handler_prologue (rtx s
RTX_FRAME_RELATED_P (insn) = 1;
}
- insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
- RTX_FRAME_RELATED_P (insn) = 1;
-
/* 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
- || df_regs_ever_live_p (i)
- || (!leaf_function_p () && call_used_regs[i]))
- {
- if (i == REG_A0 || i == REG_A1)
- insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
- gen_rtx_REG (PDImode, i));
- else
- insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
if (lookup_attribute ("nesting", attrs))
{
rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
@@ -961,13 +993,11 @@ expand_interrupt_handler_prologue (rtx s
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, bool all)
{
- int i;
+ tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
rtx postinc = gen_rtx_MEM (SImode, postinc1);
- tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
- bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
/* A slightly crude technique to stop flow from trying to delete "dead"
insns. */
@@ -988,25 +1018,8 @@ expand_interrupt_handler_epilogue (rtx s
if (!current_function_is_leaf)
all = true;
- for (i = REG_CC - 1; i > REG_P7; i--)
- if (all
- || df_regs_ever_live_p (i)
- || (!leaf_function_p () && call_used_regs[i]))
- {
- if (i == REG_A0 || i == REG_A1)
- {
- rtx mem = gen_rtx_MEM (PDImode, postinc1);
- MEM_VOLATILE_P (mem) = 1;
- emit_move_insn (gen_rtx_REG (PDImode, i), mem);
- }
- else
- emit_move_insn (gen_rtx_REG (SImode, i), postinc);
- }
-
expand_epilogue_reg_restore (spreg, all, true);
- emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
-
/* Deallocate any space we left on the stack in case we needed to save the
argument registers. */
if (fkind == EXCPT_HANDLER)
@@ -1051,10 +1064,12 @@ bfin_expand_prologue (void)
rtx spreg = gen_rtx_REG (Pmode, REG_SP);
e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
rtx pic_reg_loaded = NULL_RTX;
+ tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+ bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
if (fkind != SUBROUTINE)
{
- expand_interrupt_handler_prologue (spreg, fkind);
+ expand_interrupt_handler_prologue (spreg, fkind, all);
return;
}
@@ -1104,7 +1119,7 @@ bfin_expand_prologue (void)
emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
emit_insn (gen_trapifcc ());
}
- expand_prologue_reg_save (spreg, 0, false);
+ expand_prologue_reg_save (spreg, all, false);
do_link (spreg, frame_size, false);
@@ -1126,16 +1141,18 @@ bfin_expand_epilogue (int need_return, i
rtx spreg = gen_rtx_REG (Pmode, REG_SP);
e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
int e = sibcall_p ? -1 : 1;
+ tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
+ bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
if (fkind != SUBROUTINE)
{
- expand_interrupt_handler_epilogue (spreg, fkind);
+ expand_interrupt_handler_epilogue (spreg, fkind, all);
return;
}
do_unlink (spreg, get_frame_size (), false, e);
- expand_epilogue_reg_restore (spreg, false, false);
+ expand_epilogue_reg_restore (spreg, all, false);
/* Omit the return insn if this is for a sibcall. */
if (! need_return)