mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-29 07:00:24 +08:00
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
This commit is contained in:
parent
082276588e
commit
5058c03758
@ -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
|
||||
|
@ -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++)
|
||||
|
@ -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)
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user