This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]