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

Reply via email to