aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload1.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2007-05-21 10:58:29 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2007-05-21 10:58:29 +0000
commitecaebb9e0bbe36023856d2459c6acd1f14e7ae8c (patch)
tree285b968663b9075e8e13ac5ead7cb3afd6a842d9 /gcc/reload1.c
parent2a0ab51c7944b65fd4bb5acc26d1e66c8550f283 (diff)
downloadgcc-ecaebb9e0bbe36023856d2459c6acd1f14e7ae8c.zip
gcc-ecaebb9e0bbe36023856d2459c6acd1f14e7ae8c.tar.gz
gcc-ecaebb9e0bbe36023856d2459c6acd1f14e7ae8c.tar.bz2
builtins.c (expand_builtin_setjmp_setup): Update comment.
* 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. From-SVN: r124898
Diffstat (limited to 'gcc/reload1.c')
-rw-r--r--gcc/reload1.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 4d2dea5..dd79b0b 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;