From a848cf52b5e71ebeb05a23888ff3660c4f5012b8 Mon Sep 17 00:00:00 2001
From: Bernd Schmidt <bernd.schmidt@analog.com>
Date: Wed, 29 Oct 2008 15:12:28 +0000
Subject: [PATCH] bfin.c (struct machine_function): New member
 has_loopreg_clobber.

	* config/bfin/bfin.c (struct machine_function): New member
	has_loopreg_clobber.
	(bfin_expand_movmem): Set it when generating memcpy insns.
	(n_regs_saved_by_prologue, expand_prologue_reg_save,
	expand_epilogue_reg_restore): If we have hardware loops,
	memcpy insns (indicated by has_loopreg_clobber) or function
	calls, we need to save the loop registers.

From-SVN: r141425
---
 gcc/ChangeLog          | 10 ++++++++++
 gcc/config/bfin/bfin.c | 37 ++++++++++++++++++++++++++++++++++---
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4e367978936b..643ca32594b1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2008-10-29  Bernd Schmidt  <bernd.schmidt@analog.com>
+
+	* config/bfin/bfin.c (struct machine_function): New member
+	has_loopreg_clobber.
+	(bfin_expand_movmem): Set it when generating memcpy insns.
+	(n_regs_saved_by_prologue, expand_prologue_reg_save,
+	expand_epilogue_reg_restore): If we have hardware loops,
+	memcpy insns (indicated by has_loopreg_clobber) or function
+	calls, we need to save the loop registers.
+
 2008-10-28  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* config/i386/i386.c (core2_cost): Fix typos in comments.
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 3421dd07f786..5a289dfccf4b 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -60,7 +60,11 @@
    This is added to the cfun structure.  */
 struct machine_function GTY(())
 {
+  /* Set if we are notified by the doloop pass that a hardware loop
+     was created.  */
   int has_hardware_loops;
+  /* Set if we create a memcpy pattern that uses loop registers.  */
+  int has_loopreg_clobber;
 };
 
 /* Test and compare insns in bfin.md store the information needed to
@@ -544,7 +548,16 @@ expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
   if (saveall || is_inthandler)
     {
       rtx insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
+
       RTX_FRAME_RELATED_P (insn) = 1;
+      if (! current_function_is_leaf
+	  || cfun->machine->has_hardware_loops
+	  || cfun->machine->has_loopreg_clobber)
+	for (dregno = REG_LT0; dregno <= REG_LB1; dregno++)
+	  {
+	    insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno));
+	    RTX_FRAME_RELATED_P (insn) = 1;
+	  }
     }
 
   if (total_consec != 0)
@@ -714,7 +727,15 @@ expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
       RTX_FRAME_RELATED_P (insn) = 1;
     }
   if (saveall || is_inthandler)
-    emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
+    {
+      if (! current_function_is_leaf
+	  || cfun->machine->has_hardware_loops
+	  || cfun->machine->has_loopreg_clobber)
+	for (regno = REG_LB1; regno >= REG_LT0; regno--)
+	  emit_move_insn (gen_rtx_REG (SImode, regno), postinc);
+
+      emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
+    }
 }
 
 /* Perform any needed actions needed for a function that is receiving a
@@ -813,8 +834,16 @@ n_regs_saved_by_prologue (void)
     }
 
   if (fkind != SUBROUTINE || all)
-    /* Increment once for ASTAT.  */
-    n++;
+    {
+      /* Increment once for ASTAT.  */
+      n++;
+      if (! current_function_is_leaf
+	  || cfun->machine->has_hardware_loops
+	  || cfun->machine->has_loopreg_clobber)
+	{
+	  n += 6;
+	}
+    }
 
   if (fkind != SUBROUTINE)
     {
@@ -3398,6 +3427,7 @@ bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
 	      countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
 
 	      emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
+	      cfun->machine->has_loopreg_clobber = true;
 	    }
 	  if (count & 2)
 	    {
@@ -3418,6 +3448,7 @@ bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
 	      countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
 
 	      emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
+	      cfun->machine->has_loopreg_clobber = true;
 	    }
 	}
       if (count & 1)