diff options
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/builtins.c | 3 | ||||
-rw-r--r-- | gcc/except.c | 2 | ||||
-rw-r--r-- | gcc/function.h | 30 | ||||
-rw-r--r-- | gcc/reload1.c | 62 |
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; |