re PR c++/59813 (tail-call elimination didn't fire for left-shift of char to cout)
authorJakub Jelinek <jakub@redhat.com>
Mon, 20 May 2019 21:33:46 +0000 (23:33 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 20 May 2019 21:33:46 +0000 (23:33 +0200)
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.

From-SVN: r271440

gcc/ChangeLog
gcc/function.h
gcc/gimplify.c
gcc/lto-streamer-in.c
gcc/lto-streamer-out.c
gcc/tree-inline.c
gcc/tree-tailcall.c

index 5d300cab81662b75222f80f80cb5c3da78164951..1c4e714e7d1057fe25579ef4c96845d102c44572 100644 (file)
@@ -1,3 +1,20 @@
+2019-05-20  Jakub Jelinek  <jakub@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.
+
 2019-05-20  Marc Glisse  <marc.glisse@inria.fr>
 
        PR rtl-optimization/43147
index cef093c81467cde46d92b276f5c7f469a950efe0..bfe9919a760fb3412c7ceda21dd3ce35d1740280 100644 (file)
@@ -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;
index bc2000d4d80328c3410005c3aea2e4f1a182f0f3..5bacb255ba75901a3cd95e3b99b1f274216bf85d 100644 (file)
@@ -3297,6 +3297,10 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value)
          break;
        }
 
+      case BUILT_IN_EH_RETURN:
+       cfun->calls_eh_return = true;
+       break;
+
       default:
         ;
       }
index b78b7cb1ad2e5d9a7ef0fdc30916cb1b4ef2507c..49fd5730c7030608bb2e53aae7282d8c2e47a069 100644 (file)
@@ -1005,6 +1005,7 @@ input_struct_function_base (struct function *fn, struct data_in *data_in,
   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);
index b6e395b53fd994cf5171a23a74338316e95fb191..e22a9e596e1dd4cdaff0aac4e887125d6c56a552 100644 (file)
@@ -2029,6 +2029,7 @@ output_struct_function_base (struct output_block *ob, struct function *fn)
   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);
index 7598674f39c58db7524be9a6f83af4629035dd2e..719846ac9a2e45c1a0407290a559e84e0966cc5f 100644 (file)
@@ -2662,6 +2662,7 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, profile_count count)
   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, gimple *stmt, copy_body_data *id)
   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);
 
index f4835854e00bda09f817e690e2f26d31de069770..a99cd113ce660cd5f09efa4765c962acf418a583 100644 (file)
@@ -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);