From b6128b8c319487d4ecb240a211c0af9f6a4c2659 Mon Sep 17 00:00:00 2001 From: Stuart Hastings Date: Sun, 25 Aug 2002 05:21:11 +0000 Subject: function.h (struct function): Add flag all_throwers_are_sibcalls. 2002-08-24 Stuart Hastings * function.h (struct function): Add flag all_throwers_are_sibcalls. * except.c (set_nothrow_function_flags): Replaces nothrow_function_p. Set new flag. * except.h (set_nothrow_function_flags): Replaces nothrow_function_p. * dwarf2out.c (struct dw_fde_struct): Add flag all_throwers_are_sibcalls. (output_call_frame_info): Test it. (dwarf2out_begin_prologue) Propagate it from cfun to dw_fde_struct. * toplev.c (rest_of_compilation): Update calls to nothrow_function_p. From-SVN: r56561 --- gcc/ChangeLog | 16 ++++++++++++++++ gcc/dwarf2out.c | 7 +++++-- gcc/except.c | 43 ++++++++++++++++++++++++++++++++++--------- gcc/except.h | 4 ++-- gcc/function.h | 7 +++++++ gcc/toplev.c | 4 ++-- 6 files changed, 66 insertions(+), 15 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3cf590b0ebb..328a765893b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2002-08-24 Stuart Hastings + + * function.h (struct function): Add flag + all_throwers_are_sibcalls. + * except.c (set_nothrow_function_flags): Replaces + nothrow_function_p. Set new flag. + * except.h (set_nothrow_function_flags): Replaces + nothrow_function_p. + * dwarf2out.c (struct dw_fde_struct): Add flag + all_throwers_are_sibcalls. + (output_call_frame_info): Test it. + (dwarf2out_begin_prologue) Propagate it from cfun to + dw_fde_struct. + * toplev.c (rest_of_compilation): Update calls to + nothrow_function_p. + 2002-08-23 Zack Weinberg * ggc-page.c (compute_inverse): Short circuit calculation for diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index cf692d653ee..e8f02e62f5f 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -203,6 +203,7 @@ typedef struct dw_fde_struct const char *dw_fde_end; dw_cfi_ref dw_fde_cfi; unsigned funcdef_number; + unsigned all_throwers_are_sibcalls : 1; unsigned nothrow : 1; unsigned uses_eh_lsda : 1; } @@ -1952,8 +1953,9 @@ output_call_frame_info (for_eh) fde = &fde_table[i]; /* Don't emit EH unwind info for leaf functions that don't need it. */ - if (!flag_asynchronous_unwind_tables && for_eh && fde->nothrow - && ! fde->uses_eh_lsda) + if (!flag_asynchronous_unwind_tables && for_eh + && (fde->nothrow || fde->all_throwers_are_sibcalls) + && !fde->uses_eh_lsda) continue; ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2); @@ -2115,6 +2117,7 @@ dwarf2out_begin_prologue (line, file) fde->funcdef_number = current_function_funcdef_no; fde->nothrow = current_function_nothrow; fde->uses_eh_lsda = cfun->uses_eh_lsda; + fde->all_throwers_are_sibcalls = cfun->all_throwers_are_sibcalls; args_size = old_args_size = 0; diff --git a/gcc/except.c b/gcc/except.c index a2818c3408f..17eeae1bd80 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -2893,25 +2893,50 @@ can_throw_external (insn) return true; } -/* True if nothing in this function can throw outside this function. */ +/* Set current_function_nothrow and cfun->all_throwers_are_sibcalls. */ -bool -nothrow_function_p () +void +set_nothrow_function_flags () { rtx insn; + + current_function_nothrow = 1; - if (! flag_exceptions) - return true; + /* Assume cfun->all_throwers_are_sibcalls until we encounter + something that can throw an exception. We specifically exempt + CALL_INSNs that are SIBLING_CALL_P, as these are really jumps, + and can't throw. Most CALL_INSNs are not SIBLING_CALL_P, so this + is optimistic. */ + cfun->all_throwers_are_sibcalls = 1; + + if (! flag_exceptions) + return; + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) if (can_throw_external (insn)) - return false; + { + current_function_nothrow = 0; + + if (GET_CODE (insn) != CALL_INSN || !SIBLING_CALL_P (insn)) + { + cfun->all_throwers_are_sibcalls = 0; + return; + } + } + for (insn = current_function_epilogue_delay_list; insn; insn = XEXP (insn, 1)) - if (can_throw_external (XEXP (insn, 0))) - return false; + if (can_throw_external (insn)) + { + current_function_nothrow = 0; - return true; + if (GET_CODE (insn) != CALL_INSN || !SIBLING_CALL_P (insn)) + { + cfun->all_throwers_are_sibcalls = 0; + return; + } + } } diff --git a/gcc/except.h b/gcc/except.h index ce91051d5b1..034ce51c8fe 100644 --- a/gcc/except.h +++ b/gcc/except.h @@ -91,8 +91,8 @@ extern void for_each_eh_label PARAMS ((void (*) (rtx))); extern bool can_throw_internal PARAMS ((rtx)); extern bool can_throw_external PARAMS ((rtx)); -/* Return nonzero if nothing in this function can throw. */ -extern bool nothrow_function_p PARAMS ((void)); +/* Set current_function_nothrow and cfun->all_throwers_are_sibcalls. */ +extern void set_nothrow_function_flags PARAMS ((void)); /* After initial rtl generation, call back to finish generating exception support code. */ diff --git a/gcc/function.h b/gcc/function.h index 0ee31d1ed53..ff96b9c2bb2 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -437,6 +437,13 @@ struct function GTY(()) we should try to cut corners where we can. */ unsigned int is_thunk : 1; + /* This bit is used by the exception handling logic. It is set if all + calls (if any) are sibling calls. Such functions do not have to + have EH tables generated, as they cannot throw. A call to such a + function, however, should be treated as throwing if any of its callees + can throw. */ + unsigned int all_throwers_are_sibcalls : 1; + /* Nonzero if instrumentation calls for function entry and exit should be generated. */ unsigned int instrument_entry_exit : 1; diff --git a/gcc/toplev.c b/gcc/toplev.c index aec618f178c..24e3f6a5183 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -2506,7 +2506,7 @@ rest_of_compilation (decl) free_bb_for_insn (); } - current_function_nothrow = nothrow_function_p (); + set_nothrow_function_flags (); if (current_function_nothrow) /* Now we know that this can't throw; set the flag for the benefit of other functions later in this translation unit. */ @@ -3528,7 +3528,7 @@ rest_of_compilation (decl) shorten_branches (get_insns ()); timevar_pop (TV_SHORTEN_BRANCH); - current_function_nothrow = nothrow_function_p (); + set_nothrow_function_flags (); if (current_function_nothrow) /* Now we know that this can't throw; set the flag for the benefit of other functions later in this translation unit. */ -- cgit v1.2.1