This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: NOTHROW handling fixes


On Sat, Mar 28, 2009 at 10:33 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>
> Hi,
> the following check in stmt_could_throw_p:
> ?else if (is_gimple_call (stmt))
> ? ?{
> ? ? ?tree t = gimple_call_fndecl (stmt);
>
> ? ? ?/* Assume that calls to weak functions may trap. ?*/
> ? ? ?if (!t || !DECL_P (t) || DECL_WEAK (t))
> ? ? ? ?return true;
>
> ? ? ?return (gimple_call_flags (stmt) & ECF_NOTHROW) == 0;
> ? ?}
> cause us to assume that all C++ inline comdat functions are throwing. ?This results
> in _a lot_ of redundant EH on tramp3d.
>
> This patch cleans up the stiuation somewhat:
>
> 1) gimple_call_fndecl are always safe to trust. ?For DECL_WEAK functions explicitly declared
> as nothrow, we are still safe to assume nothrow
> 2) dwarf2out.c can assume NOTHROW even if the function body can be overwritten when emitting
> function's EH tables, because the EH tables will be overwritten too. ?This is fixed by adding
> crtl->nothrow flag that is set even for WEAK (not C++ COMDAT)
> 3) updated RTL nothorw pas to set crtl->nothrow. ?TREE_NOTRHOW is set too, but only
> in case function is not overwritable in cgraph sense. ?This is same test as we do
> for other similar changes (pure/const discovery or inlining, for instance)
>
> Bootstrapped/regtested x86_64-linux both mainline and pretty-ipa. ?Comitting to pretty-ipa
> OK for mainline?

Ok if it bootstraps/tests there.

Thanks,
Richard.

> Honza
>
> ? ? ? ?* dwarf2out.c (dwarf2out_begin_prologue): Use crtl->nothrow
> ? ? ? ?* tree-eh.c (stmt_could_throw_p): Remove check for WEAK decls.
> ? ? ? ?* function.h (rtl_data): Add nothrow flag.
> ? ? ? ?* except.c (set_nothrow_function_flags): Use crtl->nothrow;
> ? ? ? ?set DECL_NOTHROW for AVAILABLE functions.
> Index: dwarf2out.c
> ===================================================================
> *** dwarf2out.c (revision 145121)
> --- dwarf2out.c (working copy)
> *************** dwarf2out_begin_prologue (unsigned int l
> *** 3232,3238 ****
> ? ?fde->dw_fde_end = NULL;
> ? ?fde->dw_fde_cfi = NULL;
> ? ?fde->funcdef_number = current_function_funcdef_no;
> ! ? fde->nothrow = TREE_NOTHROW (current_function_decl);
> ? ?fde->uses_eh_lsda = crtl->uses_eh_lsda;
> ? ?fde->all_throwers_are_sibcalls = crtl->all_throwers_are_sibcalls;
> ? ?fde->drap_reg = INVALID_REGNUM;
> --- 3232,3238 ----
> ? ?fde->dw_fde_end = NULL;
> ? ?fde->dw_fde_cfi = NULL;
> ? ?fde->funcdef_number = current_function_funcdef_no;
> ! ? fde->nothrow = crtl->nothrow;
> ? ?fde->uses_eh_lsda = crtl->uses_eh_lsda;
> ? ?fde->all_throwers_are_sibcalls = crtl->all_throwers_are_sibcalls;
> ? ?fde->drap_reg = INVALID_REGNUM;
> Index: tree-eh.c
> ===================================================================
> *** tree-eh.c ? (revision 145121)
> --- tree-eh.c ? (working copy)
> *************** stmt_could_throw_p (gimple stmt)
> *** 2368,2382 ****
> ? ?if (code == GIMPLE_ASSIGN || code == GIMPLE_COND)
> ? ? ?return stmt_could_throw_1_p (stmt);
> ? ?else if (is_gimple_call (stmt))
> ! ? ? {
> ! ? ? ? tree t = gimple_call_fndecl (stmt);
> !
> ! ? ? ? /* Assume that calls to weak functions may trap. ?*/
> ! ? ? ? if (!t || !DECL_P (t) || DECL_WEAK (t))
> ! ? ? ? return true;
> !
> ! ? ? ? return (gimple_call_flags (stmt) & ECF_NOTHROW) == 0;
> ! ? ? }
> ? ?else if (gimple_code (stmt) == GIMPLE_ASM)
> ? ? ?return (gimple_asm_volatile_p (stmt));
> ? ?else
> --- 2368,2374 ----
> ? ?if (code == GIMPLE_ASSIGN || code == GIMPLE_COND)
> ? ? ?return stmt_could_throw_1_p (stmt);
> ? ?else if (is_gimple_call (stmt))
> ! ? ? return (gimple_call_flags (stmt) & ECF_NOTHROW) == 0;
> ? ?else if (gimple_code (stmt) == GIMPLE_ASM)
> ? ? ?return (gimple_asm_volatile_p (stmt));
> ? ?else
> Index: function.h
> ===================================================================
> *** function.h ?(revision 145121)
> --- function.h ?(working copy)
> *************** struct rtl_data GTY(())
> *** 441,446 ****
> --- 441,451 ----
>
> ? ?/* True if dbr_schedule has already been called for this function. ?*/
> ? ?bool dbr_scheduled_p;
> +
> + ? /* True if current function can not throw. ?Unlike TREE_NOTHROW (current_function_decl)
> + ? ? ?it is set even for overwrittable function where currently compiled version of
> + ? ? ?it is nothrow. ?*/
> + ? bool nothrow;
> ?};
>
> ?#define return_label (crtl->x_return_label)
> Index: except.c
> ===================================================================
> *** except.c ? ?(revision 145121)
> --- except.c ? ?(working copy)
> *************** set_nothrow_function_flags (void)
> *** 2823,2835 ****
> ?{
> ? ?rtx insn;
>
> ! ? /* If we don't know that this implementation of the function will
> ! ? ? ?actually be used, then we must not set TREE_NOTHROW, since
> ! ? ? ?callers must not assume that this function does not throw. ?*/
> ! ? if (DECL_REPLACEABLE_P (current_function_decl))
> ! ? ? return 0;
> !
> ! ? TREE_NOTHROW (current_function_decl) = 1;
>
> ? ?/* Assume crtl->all_throwers_are_sibcalls until we encounter
> ? ? ? something that can throw an exception. ?We specifically exempt
> --- 2823,2829 ----
> ?{
> ? ?rtx insn;
>
> ! ? crtl->nothrow = 1;
>
> ? ?/* Assume crtl->all_throwers_are_sibcalls until we encounter
> ? ? ? something that can throw an exception. ?We specifically exempt
> *************** set_nothrow_function_flags (void)
> *** 2839,2851 ****
>
> ? ?crtl->all_throwers_are_sibcalls = 1;
>
> ? ?if (! flag_exceptions)
> ? ? ?return 0;
>
> ? ?for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
> ? ? ?if (can_throw_external (insn))
> ? ? ? ?{
> ! ? ? ? ? TREE_NOTHROW (current_function_decl) = 0;
>
> ? ? ? ?if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
> ? ? ? ? ?{
> --- 2833,2851 ----
>
> ? ?crtl->all_throwers_are_sibcalls = 1;
>
> + ? /* If we don't know that this implementation of the function will
> + ? ? ?actually be used, then we must not set TREE_NOTHROW, since
> + ? ? ?callers must not assume that this function does not throw. ?*/
> + ? if (TREE_NOTHROW (current_function_decl))
> + ? ? return 0;
> +
> ? ?if (! flag_exceptions)
> ? ? ?return 0;
>
> ? ?for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
> ? ? ?if (can_throw_external (insn))
> ? ? ? ?{
> ! ? ? ? ? crtl->nothrow = 0;
>
> ? ? ? ?if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
> ? ? ? ? ?{
> *************** set_nothrow_function_flags (void)
> *** 2858,2864 ****
> ? ? ? ? insn = XEXP (insn, 1))
> ? ? ?if (can_throw_external (insn))
> ? ? ? ?{
> ! ? ? ? ? TREE_NOTHROW (current_function_decl) = 0;
>
> ? ? ? ?if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
> ? ? ? ? ?{
> --- 2858,2864 ----
> ? ? ? ? insn = XEXP (insn, 1))
> ? ? ?if (can_throw_external (insn))
> ? ? ? ?{
> ! ? ? ? ? crtl->nothrow = 0;
>
> ? ? ? ?if (!CALL_P (insn) || !SIBLING_CALL_P (insn))
> ? ? ? ? ?{
> *************** set_nothrow_function_flags (void)
> *** 2866,2871 ****
> --- 2866,2875 ----
> ? ? ? ? ? ?return 0;
> ? ? ? ? ?}
> ? ? ? ?}
> + ? if (crtl->nothrow
> + ? ? ? && (cgraph_function_body_availability (cgraph_node (current_function_decl))
> + ? ? ? ? ? >= AVAIL_AVAILABLE))
> + ? ? TREE_NOTHROW (current_function_decl) = 1;
> ? ?return 0;
> ?}
>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]