summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/builtins.c3
-rw-r--r--gcc/except.c2
-rw-r--r--gcc/function.h30
-rw-r--r--gcc/reload1.c62
5 files changed, 93 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3d358c23d53..731886946dc 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 9a987ea1809..b4f61868205 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -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;
}
diff --git a/gcc/except.c b/gcc/except.c
index 832d9eae2a9..29a28d71546 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -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 ();
diff --git a/gcc/function.h b/gcc/function.h
index c4faaf13df1..3367380eb9d 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -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)
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 4d2dea520b8..dd79b0bcbf2 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -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;
+}
+
/* 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;