diff options
author | Nathan Sidwell <nathan@codesourcery.com> | 2007-05-21 10:58:29 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2007-05-21 10:58:29 +0000 |
commit | ecaebb9e0bbe36023856d2459c6acd1f14e7ae8c (patch) | |
tree | 285b968663b9075e8e13ac5ead7cb3afd6a842d9 /gcc/reload1.c | |
parent | 2a0ab51c7944b65fd4bb5acc26d1e66c8550f283 (diff) | |
download | gcc-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.c | 62 |
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; |