aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-inline-analysis.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2011-04-16 11:13:08 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2011-04-16 09:13:08 +0000
commite7f2301855b432e057acd267e5df455fee60abef (patch)
treebc526e252532d488b8afaaa3574faf2363fc5fde /gcc/ipa-inline-analysis.c
parente81b856471b18de439f9157932ee8aa0fa190928 (diff)
downloadgcc-e7f2301855b432e057acd267e5df455fee60abef.zip
gcc-e7f2301855b432e057acd267e5df455fee60abef.tar.gz
gcc-e7f2301855b432e057acd267e5df455fee60abef.tar.bz2
cgraphbuild.c: Include ipa-inline.h.
* cgraphbuild.c: Include ipa-inline.h. (reset_inline_failed): Use initialize_inline_failed. * cgraph.c: Include ipa-inline.h. (cgraph_create_node_1): Do not initialize estimated_growth. (initialize_inline_failed): More to ipa-inline-analysis.c (dump_cgraph_node): Do not dump inline flags. * cgraph.h (cgraph_local_info): Remove inlineable, versionable and disregard_inline_limits flags. (cgrpah_global_info): Remove estimated_stack_size, stack_frame_offset, time, size, estimated_growth. * ipa-cp.c (ipcp_versionable_function_p, ipcp_generate_summary): Update. * cgraphunit.c (cgraph_decide_is_function_needed): Use DECL_DISREGARD_INLINE_LIMITS. (cgraph_analyze_function): Do not initialize node->local.disregard_inline_limits. * lto-cgraph.c (lto_output_node, input_overwrite_node): Do not stream inlinable, versionable and disregard_inline_limits. * ipa-inline.c (cgraph_clone_inlined_nodes, cgraph_mark_inline_edge, cgraph_check_inline_limits, cgraph_default_inline_p, cgraph_edge_badness, update_caller_keys, update_callee_keys, add_new_edges_to_heap): Update. (cgraph_decide_inlining_of_small_function): Update; set CIF_FUNCTION_NOT_INLINABLE for uninlinable functions. (cgraph_decide_inlining, cgraph_edge_early_inlinable_p, cgraph_decide_inlining_incrementally): Update. * ipa-inline.h (inline_summary): Add inlinable, versionable, disregard_inline_limits, estimated_stack_size, stack_frame_offset, time, size and estimated_growth parameters. (estimate_edge_growth): Update. (initialize_inline_failed): Declare. * ipa-split.c: Include ipa-inline.h (execute_split_functions): Update. * ipa.c (cgraph_postorder): Use DECL_DISREGARD_INLINE_LIMITS. (cgraph_remove_unreachable_nodes): Do not clear inlinable flag. (record_cdtor_fn): Use DECL_DISREGARD_INLINE_LIMITS. * ipa-inline-analysis.c (inline_node_removal_hook): Update; set estimated_growth to INT_MIN. (inline_node_duplication_hook): Likewise. (dump_inline_summary): Dump new fields. (compute_inline_parameters): Update. (estimate_edge_time, estimate_time_after_inlining, estimate_size_after_inlining, estimate_growth, inline_read_summary, inline_write_summary): (initialize_inline_failed): Move here from cgraph.c. * tree-sra.c: Include ipa-inline.h. (ipa_sra_preliminary_function_checks): Update. * lto/lto.c (lto_balanced_map): Update. Update. * Makefile.in: (cgraph.o, cgraphbuild.o): Add dependency on ipa-inline.h From-SVN: r172581
Diffstat (limited to 'gcc/ipa-inline-analysis.c')
-rw-r--r--gcc/ipa-inline-analysis.c115
1 files changed, 85 insertions, 30 deletions
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index 47bd2a8..6ab3e47 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -100,11 +100,13 @@ inline_summary_alloc (void)
static void
inline_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
{
+ struct inline_summary *info;
if (VEC_length (inline_summary_t, inline_summary_vec)
<= (unsigned)node->uid)
return;
- memset (inline_summary (node),
- 0, sizeof (inline_summary_t));
+ info = inline_summary (node);
+ info->estimated_growth = INT_MIN;
+ memset (info, 0, sizeof (inline_summary_t));
}
/* Hook that is called by cgraph.c when a node is duplicated. */
@@ -113,9 +115,12 @@ static void
inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
ATTRIBUTE_UNUSED void *data)
{
+ struct inline_summary *info;
inline_summary_alloc ();
- memcpy (inline_summary (dst), inline_summary (src),
+ info = inline_summary (dst);
+ memcpy (info, inline_summary (src),
sizeof (struct inline_summary));
+ info->estimated_growth = INT_MIN;
}
static void
@@ -124,18 +129,24 @@ dump_inline_summary (FILE *f, struct cgraph_node *node)
if (node->analyzed)
{
struct inline_summary *s = inline_summary (node);
- fprintf (f, "Inline summary for %s/%i\n", cgraph_node_name (node),
+ fprintf (f, "Inline summary for %s/%i", cgraph_node_name (node),
node->uid);
- fprintf (f, " self time: %i, benefit: %i\n",
+ if (s->disregard_inline_limits)
+ fprintf (f, " always_inline");
+ if (s->inlinable)
+ fprintf (f, " inlinable");
+ if (s->versionable)
+ fprintf (f, " versionable");
+ fprintf (f, "\n self time: %i, benefit: %i\n",
s->self_time, s->time_inlining_benefit);
- fprintf (f, " global time: %i\n", node->global.time);
+ fprintf (f, " global time: %i\n", s->time);
fprintf (f, " self size: %i, benefit: %i\n",
s->self_size, s->size_inlining_benefit);
- fprintf (f, " global size: %i", node->global.size);
+ fprintf (f, " global size: %i", s->size);
fprintf (f, " self stack: %i\n",
(int)s->estimated_self_stack_size);
fprintf (f, " global stack: %i\n\n",
- (int)node->global.estimated_stack_size);
+ (int)s->estimated_stack_size);
}
}
@@ -155,6 +166,26 @@ dump_inline_summaries (FILE *f)
dump_inline_summary (f, node);
}
+/* Give initial reasons why inlining would fail on EDGE. This gets either
+ nullified or usually overwritten by more precise reasons later. */
+
+void
+initialize_inline_failed (struct cgraph_edge *e)
+{
+ struct cgraph_node *callee = e->callee;
+
+ if (e->indirect_unknown_callee)
+ e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL;
+ else if (!callee->analyzed)
+ e->inline_failed = CIF_BODY_NOT_AVAILABLE;
+ else if (callee->local.redefined_extern_inline)
+ e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
+ else if (e->call_stmt && gimple_call_cannot_inline_p (e->call_stmt))
+ e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
+ else
+ e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
+}
+
/* See if statement might disappear after inlining.
0 - means not eliminated
1 - half of statements goes away
@@ -317,24 +348,27 @@ compute_inline_parameters (struct cgraph_node *node)
{
HOST_WIDE_INT self_stack_size;
struct cgraph_edge *e;
+ struct inline_summary *info;
gcc_assert (!node->global.inlined_to);
inline_summary_alloc ();
+ info = inline_summary (node);
+
/* Estimate the stack size for the function if we're optimizing. */
self_stack_size = optimize ? estimated_stack_frame_size (node) : 0;
- inline_summary (node)->estimated_self_stack_size = self_stack_size;
- node->global.estimated_stack_size = self_stack_size;
- node->global.stack_frame_offset = 0;
+ info->estimated_self_stack_size = self_stack_size;
+ info->estimated_stack_size = self_stack_size;
+ info->stack_frame_offset = 0;
/* Can this function be inlined at all? */
- node->local.inlinable = tree_inlinable_function_p (node->decl);
- if (!node->local.inlinable)
- node->local.disregard_inline_limits = 0;
+ info->inlinable = tree_inlinable_function_p (node->decl);
+ if (!info->inlinable)
+ info->disregard_inline_limits = 0;
/* Inlinable functions always can change signature. */
- if (node->local.inlinable)
+ if (info->inlinable)
node->local.can_change_signature = true;
else
{
@@ -349,8 +383,13 @@ compute_inline_parameters (struct cgraph_node *node)
estimate_function_body_sizes (node);
/* Inlining characteristics are maintained by the cgraph_mark_inline. */
- node->global.time = inline_summary (node)->self_time;
- node->global.size = inline_summary (node)->self_size;
+ info->time = info->self_time;
+ info->size = info->self_size;
+ info->estimated_growth = INT_MIN;
+ info->stack_frame_offset = 0;
+ info->estimated_stack_size = info->estimated_self_stack_size;
+ info->disregard_inline_limits
+ = DECL_DISREGARD_INLINE_LIMITS (node->decl);
}
@@ -390,10 +429,12 @@ static inline int
estimate_edge_time (struct cgraph_edge *edge)
{
int call_stmt_time;
+ struct inline_summary *info = inline_summary (edge->callee);
+
call_stmt_time = edge->call_stmt_time;
gcc_checking_assert (call_stmt_time);
- return (((gcov_type)edge->callee->global.time
- - inline_summary (edge->callee)->time_inlining_benefit
+ return (((gcov_type)info->time
+ - info->time_inlining_benefit
- call_stmt_time) * edge->frequency
+ CGRAPH_FREQ_BASE / 2) / CGRAPH_FREQ_BASE;
}
@@ -405,7 +446,7 @@ int
estimate_time_after_inlining (struct cgraph_node *node,
struct cgraph_edge *edge)
{
- gcov_type time = node->global.time + estimate_edge_time (edge);
+ gcov_type time = inline_summary (node)->time + estimate_edge_time (edge);
if (time < 0)
time = 0;
if (time > MAX_TIME)
@@ -421,7 +462,7 @@ int
estimate_size_after_inlining (struct cgraph_node *node,
struct cgraph_edge *edge)
{
- int size = node->global.size + estimate_edge_growth (edge);
+ int size = inline_summary (node)->size + estimate_edge_growth (edge);
gcc_assert (size >= 0);
return size;
}
@@ -435,9 +476,10 @@ estimate_growth (struct cgraph_node *node)
int growth = 0;
struct cgraph_edge *e;
bool self_recursive = false;
+ struct inline_summary *info = inline_summary (node);
- if (node->global.estimated_growth != INT_MIN)
- return node->global.estimated_growth;
+ if (info->estimated_growth != INT_MIN)
+ return info->estimated_growth;
for (e = node->callers; e; e = e->next_caller)
{
@@ -453,15 +495,15 @@ estimate_growth (struct cgraph_node *node)
some inlining. */
if (cgraph_will_be_removed_from_program_if_no_direct_calls (node)
&& !DECL_EXTERNAL (node->decl) && !self_recursive)
- growth -= node->global.size;
+ growth -= info->size;
/* COMDAT functions are very often not shared across multiple units since they
come from various template instantiations. Take this into account. */
else if (DECL_COMDAT (node->decl) && !self_recursive
&& cgraph_can_remove_if_no_direct_calls_p (node))
- growth -= (node->global.size
+ growth -= (info->size
* (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY)) + 50) / 100;
- node->global.estimated_growth = growth;
+ info->estimated_growth = growth;
return growth;
}
@@ -561,19 +603,25 @@ inline_read_summary (void)
struct cgraph_node *node;
struct inline_summary *info;
lto_cgraph_encoder_t encoder;
+ struct bitpack_d bp;
index = lto_input_uleb128 (ib);
encoder = file_data->cgraph_node_encoder;
node = lto_cgraph_encoder_deref (encoder, index);
info = inline_summary (node);
- node->global.estimated_stack_size
+ info->estimated_stack_size
= info->estimated_self_stack_size = lto_input_uleb128 (ib);
- node->global.time = info->self_time = lto_input_uleb128 (ib);
+ info->time = info->self_time = lto_input_uleb128 (ib);
info->time_inlining_benefit = lto_input_uleb128 (ib);
- node->global.size = info->self_size = lto_input_uleb128 (ib);
+ info->size = info->self_size = lto_input_uleb128 (ib);
info->size_inlining_benefit = lto_input_uleb128 (ib);
- node->global.estimated_growth = INT_MIN;
+ info->estimated_growth = INT_MIN;
+
+ bp = lto_input_bitpack (ib);
+ info->inlinable = bp_unpack_value (&bp, 1);
+ info->versionable = bp_unpack_value (&bp, 1);
+ info->disregard_inline_limits = bp_unpack_value (&bp, 1);
}
lto_destroy_simple_input_block (file_data,
@@ -623,6 +671,8 @@ inline_write_summary (cgraph_node_set set,
if (node->analyzed)
{
struct inline_summary *info = inline_summary (node);
+ struct bitpack_d bp;
+
lto_output_uleb128_stream (ob->main_stream,
lto_cgraph_encoder_encode (encoder, node));
lto_output_sleb128_stream (ob->main_stream,
@@ -635,6 +685,11 @@ inline_write_summary (cgraph_node_set set,
info->self_time);
lto_output_sleb128_stream (ob->main_stream,
info->time_inlining_benefit);
+ bp = bitpack_create (ob->main_stream);
+ bp_pack_value (&bp, info->inlinable, 1);
+ bp_pack_value (&bp, info->versionable, 1);
+ bp_pack_value (&bp, info->disregard_inline_limits, 1);
+ lto_output_bitpack (&bp);
}
}
lto_destroy_simple_output_block (ob);