[rl78] optimize prologues
diff mbox

Message ID 201309172110.r8HLAf8D009442@greed.delorie.com
State New
Headers show

Commit Message

DJ Delorie Sept. 17, 2013, 9:10 p.m. UTC
Committed.

2013-09-17  Nick Clifton  <nickc@redhat.com>

	* config/rl78/rl78.c (need_to_save): Change return type to bool.
	For interrupt functions: save all call clobbered registers if the
	interrupt handler is not a leaf function.
	(rl78_expand_prologue): Always recompute the frame information.
	For interrupt functions: only select bank 0 if one of the bank 0
	registers is going to be psuhed.

Patch
diff mbox

Index: config/rl78/rl78.c
===================================================================
--- config/rl78/rl78.c	(revision 202666)
+++ config/rl78/rl78.c	(working copy)
@@ -537,40 +537,45 @@  rl78_force_nonfar_3 (rtx *operands, rtx 
 static bool
 rl78_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to ATTRIBUTE_UNUSED)
 {
   return true;
 }
 
-/* Returns nonzero if the given register needs to be saved by the
+/* Returns true if the given register needs to be saved by the
    current function.  */
-static int
-need_to_save (int regno)
+static bool
+need_to_save (unsigned int regno)
 {
   if (is_interrupt_func (cfun->decl))
     {
-      if (regno < 8)
-	return 1; /* don't know what devirt will need */
+       /* We don't need to save registers that have
+	  been reserved for interrupt handlers.  */
       if (regno > 23)
-	return 0; /* don't need to save interrupt registers */
-      if (crtl->is_leaf)
-	{
-	  return df_regs_ever_live_p (regno);
-	}
-      else
-	return 1;
+	return false;
+
+      /* If the handler is a non-leaf function then it may call
+	 non-interrupt aware routines which will happily clobber
+	 any call_used registers, so we have to preserve them.  */
+      if (!crtl->is_leaf && call_used_regs[regno])
+	return true;
+
+      /* Otherwise we only have to save a register, call_used
+	 or not, if it is used by this handler.  */
+      return df_regs_ever_live_p (regno);
     }
+
   if (regno == FRAME_POINTER_REGNUM && frame_pointer_needed)
-    return 1;
+    return true;
   if (fixed_regs[regno])
-    return 0;
+    return false;
   if (crtl->calls_eh_return)
-    return 1;
+    return true;
   if (df_regs_ever_live_p (regno)
       && !call_used_regs[regno])
-    return 1;
-  return 0;
+    return true;
+  return false;
 }
 
 /* We use this to wrap all emitted insns in the prologue.  */
 static rtx
 F (rtx x)
 {
@@ -1023,20 +1028,26 @@  rl78_expand_prologue (void)
   rtx sp = gen_rtx_REG (HImode, STACK_POINTER_REGNUM);
   int rb = 0;
 
   if (rl78_is_naked_func ())
     return;
 
-  if (!cfun->machine->computed)
-    rl78_compute_frame_info ();
+  /* Always re-compute the frame info - the register usage may have changed.  */
+  rl78_compute_frame_info ();
 
   if (flag_stack_usage_info)
     current_function_static_stack_size = cfun->machine->framesize;
 
   if (is_interrupt_func (cfun->decl) && !TARGET_G10)
-    emit_insn (gen_sel_rb (GEN_INT (0)));
+    for (i = 0; i < 4; i++)
+      if (cfun->machine->need_to_push [i])
+	{
+	  /* Select Bank 0 if we are using any registers from Bank 0.   */
+	  emit_insn (gen_sel_rb (GEN_INT (0)));
+	  break;
+	}
 
   for (i = 0; i < 16; i++)
     if (cfun->machine->need_to_push [i])
       {
 	if (TARGET_G10)
 	  {