ipa-inline-analysis.c (redirect_to_unreachable): New function.
authorJan Hubicka <hubicka@ucw.cz>
Thu, 26 Mar 2015 19:54:44 +0000 (20:54 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 26 Mar 2015 19:54:44 +0000 (19:54 +0000)
* ipa-inline-analysis.c (redirect_to_unreachable): New function.
(edge_set_predicate): Use it to mark unreachable edges.
(inline_summary_t::duplicate): Remove unnecesary code.
(remap_edge_summaries): Likewise.
(dump_inline_summary): Report contains_cilk_spawn.
(compute_inline_parameters): Compute contains_cilk_spawn.
(inline_read_section, inline_write_summary): Stream
contains_cilk_spawn.
* ipa-inline.c (can_inline_edge_p): Do not tuch
DECL_STRUCT_FUNCTION that may not be available;
use CIF_CILK_SPAWN for cilk; fix optimization attribute checks;
remove check for callee_fun->can_throw_non_call_exceptions and
replace it by optimization attribute check; check for flag_exceptions.
* ipa-inline-transform.c (inline_call): Maintain
DECL_FUNCTION_PERSONALITY
* ipa-inline.h (inline_summary): Add contains_cilk_spawn.

From-SVN: r221706

gcc/ChangeLog
gcc/ipa-inline-analysis.c
gcc/ipa-inline-transform.c
gcc/ipa-inline.c
gcc/ipa-inline.h

index 50610b5..d9b125e 100644 (file)
@@ -1,3 +1,22 @@
+2015-03-26  Jan Hubicka  <hubicka@ucw.cz>
+
+       * ipa-inline-analysis.c (redirect_to_unreachable): New function.
+       (edge_set_predicate): Use it to mark unreachable edges.
+       (inline_summary_t::duplicate): Remove unnecesary code.
+       (remap_edge_summaries): Likewise.
+       (dump_inline_summary): Report contains_cilk_spawn.
+       (compute_inline_parameters): Compute contains_cilk_spawn.
+       (inline_read_section, inline_write_summary): Stream
+       contains_cilk_spawn.
+       * ipa-inline.c (can_inline_edge_p): Do not tuch 
+       DECL_STRUCT_FUNCTION that may not be available;
+       use CIF_CILK_SPAWN for cilk; fix optimization attribute checks;
+       remove check for callee_fun->can_throw_non_call_exceptions and
+       replace it by optimization attribute check; check for flag_exceptions.
+       * ipa-inline-transform.c (inline_call): Maintain
+       DECL_FUNCTION_PERSONALITY
+       * ipa-inline.h (inline_summary): Add contains_cilk_spawn.
+
 2015-03-26  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/65551
index 5707f6c..6f34c47 100644 (file)
@@ -760,6 +760,31 @@ account_size_time (struct inline_summary *summary, int size, int time,
     }
 }
 
+/* We proved E to be unreachable, redirect it to __bultin_unreachable.  */
+
+static void
+redirect_to_unreachable (struct cgraph_edge *e)
+{
+  struct cgraph_node *callee = !e->inline_failed ? e->callee : NULL;
+  struct inline_edge_summary *es = inline_edge_summary (e);
+
+  if (e->speculative)
+    e->resolve_speculation (builtin_decl_implicit (BUILT_IN_UNREACHABLE));
+  if (!e->callee)
+    e->make_direct (cgraph_node::get_create
+                     (builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
+  else
+    e->redirect_callee (cgraph_node::get_create
+                       (builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
+  e->inline_failed = CIF_UNREACHABLE;
+  e->frequency = 0;
+  e->count = 0;
+  es->call_stmt_size = 0;
+  es->call_stmt_time = 0;
+  if (callee)
+    callee->remove_symbol_and_inline_clones ();
+}
+
 /* Set predicate for edge E.  */
 
 static void
@@ -769,18 +794,8 @@ edge_set_predicate (struct cgraph_edge *e, struct predicate *predicate)
 
   /* If the edge is determined to be never executed, redirect it
      to BUILTIN_UNREACHABLE to save inliner from inlining into it.  */
-  if (predicate && false_predicate_p (predicate) && e->callee)
-    {
-      struct cgraph_node *callee = !e->inline_failed ? e->callee : NULL;
-
-      e->redirect_callee (cgraph_node::get_create
-                           (builtin_decl_implicit (BUILT_IN_UNREACHABLE)));
-      e->inline_failed = CIF_UNREACHABLE;
-      es->call_stmt_size = 0;
-      es->call_stmt_time = 0;
-      if (callee)
-       callee->remove_symbol_and_inline_clones ();
-    }
+  if (predicate && false_predicate_p (predicate))
+    redirect_to_unreachable (e);
   if (predicate && !true_predicate_p (predicate))
     {
       if (!es->predicate)
@@ -1228,10 +1243,7 @@ inline_summary_t::duplicate (cgraph_node *src,
                                                             info);
          if (false_predicate_p (&new_predicate)
              && !false_predicate_p (es->predicate))
-           {
-             optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE;
-             edge->frequency = 0;
-           }
+           optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE;
          edge_set_predicate (edge, &new_predicate);
        }
 
@@ -1250,10 +1262,7 @@ inline_summary_t::duplicate (cgraph_node *src,
                                                             info);
          if (false_predicate_p (&new_predicate)
              && !false_predicate_p (es->predicate))
-           {
-             optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE;
-             edge->frequency = 0;
-           }
+           optimized_out_size += es->call_stmt_size * INLINE_SIZE_SCALE;
          edge_set_predicate (edge, &new_predicate);
        }
       remap_hint_predicate_after_duplication (&info->loop_iterations,
@@ -1441,6 +1450,8 @@ dump_inline_summary (FILE *f, struct cgraph_node *node)
        fprintf (f, " always_inline");
       if (s->inlinable)
        fprintf (f, " inlinable");
+      if (s->contains_cilk_spawn)
+       fprintf (f, " contains_cilk_spawn");
       fprintf (f, "\n  self time:       %i\n", s->self_time);
       fprintf (f, "  global time:     %i\n", s->time);
       fprintf (f, "  self size:       %i\n", s->self_size);
@@ -2925,6 +2936,8 @@ compute_inline_parameters (struct cgraph_node *node, bool early)
   else
     info->inlinable = tree_inlinable_function_p (node->decl);
 
+  info->contains_cilk_spawn = fn_contains_cilk_spawn_p (cfun);
+
   /* Type attributes can use parameter indices to describe them.  */
   if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
     node->local.can_change_signature = false;
@@ -3487,14 +3500,6 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
                                   es->predicate, operand_map, offset_map,
                                   possible_truths, toplev_predicate);
              edge_set_predicate (e, &p);
-             /* TODO: We should remove the edge for code that will be
-                optimized out, but we need to keep verifiers and tree-inline
-                happy.  Make it cold for now.  */
-             if (false_predicate_p (&p))
-               {
-                 e->count = 0;
-                 e->frequency = 0;
-               }
            }
          else
            edge_set_predicate (e, toplev_predicate);
@@ -3516,14 +3521,6 @@ remap_edge_summaries (struct cgraph_edge *inlined_edge,
                               es->predicate, operand_map, offset_map,
                               possible_truths, toplev_predicate);
          edge_set_predicate (e, &p);
-         /* TODO: We should remove the edge for code that will be optimized
-            out, but we need to keep verifiers and tree-inline happy.
-            Make it cold for now.  */
-         if (false_predicate_p (&p))
-           {
-             e->count = 0;
-             e->frequency = 0;
-           }
        }
       else
        edge_set_predicate (e, toplev_predicate);
@@ -4228,6 +4225,7 @@ inline_read_section (struct lto_file_decl_data *file_data, const char *data,
 
       bp = streamer_read_bitpack (&ib);
       info->inlinable = bp_unpack_value (&bp, 1);
+      info->contains_cilk_spawn = bp_unpack_value (&bp, 1);
 
       count2 = streamer_read_uhwi (&ib);
       gcc_assert (!info->conds);
@@ -4393,6 +4391,7 @@ inline_write_summary (void)
          streamer_write_hwi (ob, info->self_time);
          bp = bitpack_create (ob->main_stream);
          bp_pack_value (&bp, info->inlinable, 1);
+         bp_pack_value (&bp, info->contains_cilk_spawn, 1);
          streamer_write_bitpack (&bp);
          streamer_write_uhwi (ob, vec_safe_length (info->conds));
          for (i = 0; vec_safe_iterate (info->conds, i, &c); i++)
index 43bb41f..952659c 100644 (file)
@@ -322,6 +322,10 @@ inline_call (struct cgraph_edge *e, bool update_original,
   if (to->global.inlined_to)
     to = to->global.inlined_to;
 
+  if (DECL_FUNCTION_PERSONALITY (callee->decl))
+    DECL_FUNCTION_PERSONALITY (to->decl)
+      = DECL_FUNCTION_PERSONALITY (callee->decl);
+
   /* If aliases are involved, redirect edge to the actual destination and
      possibly remove the aliases.  */
   if (e->callee != callee)
index 851ef3f..49af4ce 100644 (file)
@@ -142,7 +142,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "ipa-utils.h"
 #include "sreal.h"
 #include "auto-profile.h"
-#include "cilk.h"
 #include "builtins.h"
 #include "fibonacci_heap.h"
 #include "lto-streamer.h"
@@ -329,8 +328,6 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
   tree caller_tree = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (caller->decl);
   tree callee_tree
     = callee ? DECL_FUNCTION_SPECIFIC_OPTIMIZATION (callee->decl) : NULL;
-  struct function *caller_fun = caller->get_fun ();
-  struct function *callee_fun = callee ? callee->get_fun () : NULL;
 
   if (!callee->definition)
     {
@@ -342,12 +339,6 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
       e->inline_failed = CIF_USES_COMDAT_LOCAL;
       inlinable = false;
     }
-  else if (!inline_summaries->get (callee)->inlinable
-          || (caller_fun && fn_contains_cilk_spawn_p (caller_fun)))
-    {
-      e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
-      inlinable = false;
-    }
   else if (avail <= AVAIL_INTERPOSABLE)
     {
       e->inline_failed = CIF_OVERWRITABLE;
@@ -375,16 +366,6 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
       e->inline_failed = CIF_UNSPECIFIED;
       inlinable = false;
     }
-  /* Don't inline if the callee can throw non-call exceptions but the
-     caller cannot.
-     FIXME: this is obviously wrong for LTO where STRUCT_FUNCTION is missing.
-     Move the flag into cgraph node or mirror it in the inline summary.  */
-  else if (callee_fun && callee_fun->can_throw_non_call_exceptions
-          && !(caller_fun && caller_fun->can_throw_non_call_exceptions))
-    {
-      e->inline_failed = CIF_NON_CALL_EXCEPTIONS;
-      inlinable = false;
-    }
   /* Check compatibility of target optimization options.  */
   else if (!targetm.target_option.can_inline_p (caller->decl,
                                                callee->decl))
@@ -392,6 +373,16 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
       e->inline_failed = CIF_TARGET_OPTION_MISMATCH;
       inlinable = false;
     }
+  else if (!inline_summaries->get (callee)->inlinable)
+    {
+      e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
+      inlinable = false;
+    }
+  else if (inline_summaries->get (caller)->contains_cilk_spawn)
+    {
+      e->inline_failed = CIF_CILK_SPAWN;
+      inlinable = false;
+    }
   /* Don't inline a function with mismatched sanitization attributes. */
   else if (!sanitize_attrs_match_for_inline_p (caller->decl, callee->decl))
     {
@@ -416,38 +407,51 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
       /* Strictly speaking only when the callee contains signed integer
          math where overflow is undefined.  */
       if ((opt_for_fn (caller->decl, flag_strict_overflow)
-          != opt_for_fn (caller->decl, flag_strict_overflow))
+          != opt_for_fn (callee->decl, flag_strict_overflow))
          || (opt_for_fn (caller->decl, flag_wrapv)
-             != opt_for_fn (caller->decl, flag_wrapv))
+             != opt_for_fn (callee->decl, flag_wrapv))
          || (opt_for_fn (caller->decl, flag_trapv)
-             != opt_for_fn (caller->decl, flag_trapv))
+             != opt_for_fn (callee->decl, flag_trapv))
          /* Strictly speaking only when the callee contains memory
             accesses that are not using alias-set zero anyway.  */
          || (opt_for_fn (caller->decl, flag_strict_aliasing)
-             != opt_for_fn (caller->decl, flag_strict_aliasing))
+             != opt_for_fn (callee->decl, flag_strict_aliasing))
          /* Strictly speaking only when the callee uses FP math.  */
          || (opt_for_fn (caller->decl, flag_rounding_math)
-             != opt_for_fn (caller->decl, flag_rounding_math))
+             != opt_for_fn (callee->decl, flag_rounding_math))
          || (opt_for_fn (caller->decl, flag_trapping_math)
-             != opt_for_fn (caller->decl, flag_trapping_math))
+             != opt_for_fn (callee->decl, flag_trapping_math))
          || (opt_for_fn (caller->decl, flag_unsafe_math_optimizations)
-             != opt_for_fn (caller->decl, flag_unsafe_math_optimizations))
+             != opt_for_fn (callee->decl, flag_unsafe_math_optimizations))
          || (opt_for_fn (caller->decl, flag_finite_math_only)
-             != opt_for_fn (caller->decl, flag_finite_math_only))
+             != opt_for_fn (callee->decl, flag_finite_math_only))
          || (opt_for_fn (caller->decl, flag_signaling_nans)
-             != opt_for_fn (caller->decl, flag_signaling_nans))
+             != opt_for_fn (callee->decl, flag_signaling_nans))
          || (opt_for_fn (caller->decl, flag_cx_limited_range)
-             != opt_for_fn (caller->decl, flag_cx_limited_range))
+             != opt_for_fn (callee->decl, flag_cx_limited_range))
          || (opt_for_fn (caller->decl, flag_signed_zeros)
-             != opt_for_fn (caller->decl, flag_signed_zeros))
+             != opt_for_fn (callee->decl, flag_signed_zeros))
          || (opt_for_fn (caller->decl, flag_associative_math)
-             != opt_for_fn (caller->decl, flag_associative_math))
+             != opt_for_fn (callee->decl, flag_associative_math))
          || (opt_for_fn (caller->decl, flag_reciprocal_math)
-             != opt_for_fn (caller->decl, flag_reciprocal_math))
+             != opt_for_fn (callee->decl, flag_reciprocal_math))
+         /* We do not want to make code compiled with exceptions to be brought
+            into a non-EH function unless we know that the callee does not
+            throw.  This is tracked by DECL_FUNCTION_PERSONALITY.  */
+         || (opt_for_fn (caller->decl, flag_non_call_exceptions)
+             != opt_for_fn (callee->decl, flag_non_call_exceptions)
+             /* TODO: We also may allow bringing !flag_non_call_exceptions
+                to flag_non_call_exceptions function, but that may need
+                extra work in tree-inline to add the extra EH edges.  */
+             && (!opt_for_fn (callee->decl, flag_non_call_exceptions)
+                 || DECL_FUNCTION_PERSONALITY (callee->decl)))
+         || (!opt_for_fn (caller->decl, flag_exceptions)
+             && opt_for_fn (callee->decl, flag_exceptions)
+             && DECL_FUNCTION_PERSONALITY (callee->decl))
          /* Strictly speaking only when the callee contains function
             calls that may end up setting errno.  */
          || (opt_for_fn (caller->decl, flag_errno_math)
-             != opt_for_fn (caller->decl, flag_errno_math))
+             != opt_for_fn (callee->decl, flag_errno_math))
          /* When devirtualization is diabled for callee, it is not safe
             to inline it as we possibly mangled the type info.
             Allow early inlining of always inlines.  */
index dfc0053..ed4d66f 100644 (file)
@@ -126,6 +126,9 @@ struct GTY(()) inline_summary
 
   /* False when there something makes inlining impossible (such as va_arg).  */
   unsigned inlinable : 1;
+  /* True when function contains cilk spawn (and thus we can not inline
+     into it).  */
+  unsigned contains_cilk_spawn : 1;
 
   /* Information about function that will result after applying all the
      inline decisions present in the callgraph.  Generally kept up to