OSDN Git Service

* builtins.c (expand_builtin_setjmp_setup): Update comment.
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 21 May 2007 10:58:29 +0000 (10:58 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 21 May 2007 10:58:29 +0000 (10:58 +0000)
* function.h (struct function): Move va_list_gpr_size,
va_list_fpr_size, function_frequency to front of bitfields.  Add
calls_unwind_init.
(current_function_calls_unwind_init): New.
* except.c (expand_builtin_unwind_init): Set
current_function_calls_unwind_init not
current_function_has_nonlocal_label.
* reload1.c (has_nonexceptional_receiver): New.
(reload): Use it and current_function_calls_unwind_init to
determine whether call-saved regs must be saved.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@124898 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/except.c
gcc/function.h
gcc/reload1.c

index 3d358c2..7318869 100644 (file)
@@ -1,3 +1,17 @@
+2007-05-21  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * builtins.c (expand_builtin_setjmp_setup): Update comment.
+       * function.h (struct function): Move va_list_gpr_size,
+       va_list_fpr_size, function_frequency to front of bitfields.  Add
+       calls_unwind_init.
+       (current_function_calls_unwind_init): New.
+       * except.c (expand_builtin_unwind_init): Set
+       current_function_calls_unwind_init not
+       current_function_has_nonlocal_label.
+       * reload1.c (has_nonexceptional_receiver): New.
+       (reload): Use it and current_function_calls_unwind_init to
+       determine whether call-saved regs must be saved.
+
 2007-05-20  Jan Hubicka  <jh@suse.cz>
 
        * gengtype.c (adjust_field_rtx_def): Use NOTE_KIND instead of
index 9a987ea..b4f6186 100644 (file)
@@ -696,8 +696,7 @@ expand_builtin_setjmp_setup (rtx buf_addr, rtx receiver_label)
      need to go on during alloca.  */
   current_function_calls_setjmp = 1;
 
-  /* Set this so all the registers get saved in our frame; we need to be
-     able to copy the saved values for any registers from frames we unwind.  */
+  /* We have a nonlocal label.   */
   current_function_has_nonlocal_label = 1;
 }
 
index 832d9ea..29a28d7 100644 (file)
@@ -2859,7 +2859,7 @@ expand_builtin_unwind_init (void)
 {
   /* Set this so all the registers get saved in our frame; we need to be
      able to copy the saved values for any registers from frames we unwind.  */
-  current_function_has_nonlocal_label = 1;
+  current_function_calls_unwind_init = 1;
 
 #ifdef SETUP_FRAME_ADDRESSES
   SETUP_FRAME_ADDRESSES ();
index c4faaf1..3367380 100644 (file)
@@ -374,6 +374,19 @@ struct function GTY(())
 
   /* Collected bit flags.  */
 
+  /* Number of units of general registers that need saving in stdarg
+     function.  What unit is depends on the backend, either it is number
+     of bytes, or it can be number of registers.  */
+  unsigned int va_list_gpr_size : 8;
+
+  /* Number of units of floating point registers that need saving in stdarg
+     function.  */
+  unsigned int va_list_fpr_size : 8;
+
+  /* How commonly executed the function is.  Initialized during branch
+     probabilities pass.  */
+  ENUM_BITFIELD (function_frequency) function_frequency : 2;
+
   /* Nonzero if function being compiled needs to be given an address
      where the value should be stored.  */
   unsigned int returns_struct : 1;
@@ -403,6 +416,9 @@ struct function GTY(())
      from nested functions.  */
   unsigned int has_nonlocal_label : 1;
 
+  /* Nonzero if function calls builtin_unwind_init.  */
+  unsigned int calls_unwind_init : 1;
+  
   /* Nonzero if function being compiled has nonlocal gotos to parent
      function.  */
   unsigned int has_nonlocal_goto : 1;
@@ -459,19 +475,6 @@ struct function GTY(())
   /* Set when the tail call has been produced.  */
   unsigned int tail_call_emit : 1;
 
-  /* How commonly executed the function is.  Initialized during branch
-     probabilities pass.  */
-  ENUM_BITFIELD (function_frequency) function_frequency : 2;
-
-  /* Number of units of general registers that need saving in stdarg
-     function.  What unit is depends on the backend, either it is number
-     of bytes, or it can be number of registers.  */
-  unsigned int va_list_gpr_size : 8;
-
-  /* Number of units of floating point registers that need saving in stdarg
-     function.  */
-  unsigned int va_list_fpr_size : 8;
-
   /* FIXME tuples: This bit is temporarily here to mark when a
      function has been gimplified, so we can make sure we're not
      creating non GIMPLE tuples after gimplification.  */
@@ -520,6 +523,7 @@ extern int trampolines_created;
 #define current_function_uses_const_pool (cfun->uses_const_pool)
 #define current_function_epilogue_delay_list (cfun->epilogue_delay_list)
 #define current_function_has_nonlocal_label (cfun->has_nonlocal_label)
+#define current_function_calls_unwind_init (cfun->calls_unwind_init)
 #define current_function_has_nonlocal_goto (cfun->has_nonlocal_goto)
 
 #define return_label (cfun->x_return_label)
index 4d2dea5..dd79b0b 100644 (file)
@@ -622,6 +622,61 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
        replace_pseudos_in (& XVECEXP (x, i, j), mem_mode, usage);
 }
 
+/* Determine if the current function has an exception receiver block
+   that reaches the exit block via non-exceptional edges  */
+
+static bool
+has_nonexceptional_receiver (void)
+{
+  edge e;
+  edge_iterator ei;
+  basic_block *tos, *worklist, bb;
+
+  /* If we're not optimizing, then just err on the safe side.  */
+  if (!optimize)
+    return true;
+  
+  /* First determine which blocks can reach exit via normal paths.  */
+  tos = worklist = xmalloc (sizeof (basic_block) * (n_basic_blocks + 1));
+
+  FOR_EACH_BB (bb)
+    bb->flags &= ~BB_REACHABLE;
+
+  /* Place the exit block on our worklist.  */
+  EXIT_BLOCK_PTR->flags |= BB_REACHABLE;
+  *tos++ = EXIT_BLOCK_PTR;
+  
+  /* Iterate: find everything reachable from what we've already seen.  */
+  while (tos != worklist)
+    {
+      bb = *--tos;
+
+      FOR_EACH_EDGE (e, ei, bb->preds)
+       if (!(e->flags & EDGE_ABNORMAL))
+         {
+           basic_block src = e->src;
+
+           if (!(src->flags & BB_REACHABLE))
+             {
+               src->flags |= BB_REACHABLE;
+               *tos++ = src;
+             }
+         }
+    }
+  free (worklist);
+
+  /* Now see if there's a reachable block with an exceptional incoming
+     edge.  */
+  FOR_EACH_BB (bb)
+    if (bb->flags & BB_REACHABLE)
+      FOR_EACH_EDGE (e, ei, bb->preds)
+       if (e->flags & EDGE_ABNORMAL)
+         return true;
+
+  /* No exceptional block reached exit unexceptionally.  */
+  return false;
+}
+
 \f
 /* Global variables used by reload and its subroutines.  */
 
@@ -688,9 +743,12 @@ reload (rtx first, int global)
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     mark_home_live (i);
 
-  /* A function that receives a nonlocal goto must save all call-saved
+  /* A function that has a nonlocal label that can reach the exit
+     block via non-exceptional paths must save all call-saved
      registers.  */
-  if (current_function_has_nonlocal_label)
+  if (current_function_calls_unwind_init
+      || (current_function_has_nonlocal_label
+         && has_nonexceptional_receiver ()))
     for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
       if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
        regs_ever_live[i] = 1;