From: Jan Hubicka Date: Thu, 26 Mar 2015 19:54:44 +0000 (+0100) Subject: ipa-inline-analysis.c (redirect_to_unreachable): New function. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5058c037581a2015d2e2ea86c50628dcde72f646;p=gcc.git ipa-inline-analysis.c (redirect_to_unreachable): New function. * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 50610b51a7f..d9b125ec7ff 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2015-03-26 Jan Hubicka + + * 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 PR tree-optimization/65551 diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 5707f6c9603..6f34c47449b 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -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++) diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index 43bb41fa8fa..952659c99fd 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -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) diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 851ef3fa8e7..49af4cec13d 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -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. */ diff --git a/gcc/ipa-inline.h b/gcc/ipa-inline.h index dfc0053838e..ed4d66fef4a 100644 --- a/gcc/ipa-inline.h +++ b/gcc/ipa-inline.h @@ -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