On Tue, May 14, 2019 at 01:08:27PM -0600, Jeff Law wrote: > > In https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00484.html I've posted a > > patch that would set it earlier (or it could be set during gimplification > > and propagated during inlining, would need to be in cfun->calls_eh_return > > instead of crtl->calls_eh_return) and then targets for which we do not want > > to bother with it or where it is not beneficial to have tail calls in > > functions that call __builtin_eh_return (as I said in the thread, e.g. on > > x86_64-linux it is both smaller and faster), the targets which we expect to > > fail currently or even have a proof of that can just punt. > I would go with a patch that got the info set earlier and just punt in > the generic code. I just don't see this case as terribly important to > optimize.
So like this? Bootstrapped/regtested on x86_64-linux and i686-linux, verified _Unwind_Resume_or_Rethrow no longer has a tail call. 2019-05-14 Jakub Jelinek <ja...@redhat.com> PR c++/59813 PR target/90418 * function.h (struct function): Add calls_eh_return member. * gimplify.c (gimplify_call_expr): Set cfun->calls_eh_return when gimplifying __builtin_eh_return call. * tree-inline.c (initialize_cfun): Copy calls_eh_return from src_cfun to cfun. (expand_call_inline): Or in src_cfun->calls_eh_return into dst_cfun->calls_eh_return. * tree-tailcall.c (suitable_for_tail_call_opt_p): Return false if cfun->calls_eh_return. * lto-streamer-in.c (input_struct_function_base): Read calls_eh_return. * lto-streamer-out.c (output_struct_function_base): Write calls_eh_return. --- gcc/function.h.jj 2019-01-01 12:37:15.383004075 +0100 +++ gcc/function.h 2019-05-14 21:40:13.837715081 +0200 @@ -327,6 +327,9 @@ struct GTY(()) function { either as a subroutine or builtin. */ unsigned int calls_alloca : 1; + /* Nonzero if function being compiled can call __builtin_eh_return. */ + unsigned int calls_eh_return : 1; + /* Nonzero if function being compiled receives nonlocal gotos from nested functions. */ unsigned int has_nonlocal_label : 1; --- gcc/gimplify.c.jj 2019-05-03 15:22:07.416401170 +0200 +++ gcc/gimplify.c 2019-05-14 21:51:38.700288873 +0200 @@ -3297,6 +3297,10 @@ gimplify_call_expr (tree *expr_p, gimple break; } + case BUILT_IN_EH_RETURN: + cfun->calls_eh_return = true; + break; + default: ; } --- gcc/tree-inline.c.jj 2019-05-10 10:15:40.704283180 +0200 +++ gcc/tree-inline.c 2019-05-14 21:49:19.038617963 +0200 @@ -2662,6 +2662,7 @@ initialize_cfun (tree new_fndecl, tree c cfun->va_list_gpr_size = src_cfun->va_list_gpr_size; cfun->va_list_fpr_size = src_cfun->va_list_fpr_size; cfun->has_nonlocal_label = src_cfun->has_nonlocal_label; + cfun->calls_eh_return = src_cfun->calls_eh_return; cfun->stdarg = src_cfun->stdarg; cfun->after_inlining = src_cfun->after_inlining; cfun->can_throw_non_call_exceptions @@ -4778,6 +4779,7 @@ expand_call_inline (basic_block bb, gimp src_properties = id->src_cfun->curr_properties & prop_mask; if (src_properties != prop_mask) dst_cfun->curr_properties &= src_properties | ~prop_mask; + dst_cfun->calls_eh_return |= id->src_cfun->calls_eh_return; gcc_assert (!id->src_cfun->after_inlining); --- gcc/tree-tailcall.c.jj 2019-05-10 23:20:33.849768476 +0200 +++ gcc/tree-tailcall.c 2019-05-14 21:54:34.733353248 +0200 @@ -140,6 +140,7 @@ suitable_for_tail_opt_p (void) return true; } + /* Returns false when the function is not suitable for tail call optimization for some reason (e.g. if it takes variable number of arguments). This test must pass in addition to suitable_for_tail_opt_p in order to make @@ -168,6 +169,11 @@ suitable_for_tail_call_opt_p (void) if (cfun->calls_setjmp) return false; + /* Various targets don't handle tail calls correctly in functions + that call __builtin_eh_return. */ + if (cfun->calls_eh_return) + return false; + /* ??? It is OK if the argument of a function is taken in some cases, but not in all cases. See PR15387 and PR19616. Revisit for 4.1. */ for (param = DECL_ARGUMENTS (current_function_decl); --- gcc/lto-streamer-in.c.jj 2019-03-08 11:43:35.062317743 +0100 +++ gcc/lto-streamer-in.c 2019-05-14 21:41:48.900128559 +0200 @@ -1005,6 +1005,7 @@ input_struct_function_base (struct funct fn->has_forced_label_in_static = bp_unpack_value (&bp, 1); fn->calls_alloca = bp_unpack_value (&bp, 1); fn->calls_setjmp = bp_unpack_value (&bp, 1); + fn->calls_eh_return = bp_unpack_value (&bp, 1); fn->has_force_vectorize_loops = bp_unpack_value (&bp, 1); fn->has_simduid_loops = bp_unpack_value (&bp, 1); fn->va_list_fpr_size = bp_unpack_value (&bp, 8); --- gcc/lto-streamer-out.c.jj 2019-03-08 11:43:35.062317743 +0100 +++ gcc/lto-streamer-out.c 2019-05-14 21:42:05.262855481 +0200 @@ -2029,6 +2029,7 @@ output_struct_function_base (struct outp bp_pack_value (&bp, fn->has_forced_label_in_static, 1); bp_pack_value (&bp, fn->calls_alloca, 1); bp_pack_value (&bp, fn->calls_setjmp, 1); + bp_pack_value (&bp, fn->calls_eh_return, 1); bp_pack_value (&bp, fn->has_force_vectorize_loops, 1); bp_pack_value (&bp, fn->has_simduid_loops, 1); bp_pack_value (&bp, fn->va_list_fpr_size, 8); Jakub