Commit e7f23018 by Jan Hubicka Committed by Jan Hubicka

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
parent e81b8564
2011-04-16 Jan Hubicka <jh@suse.cz>
* 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.
* Makefile.in: (cgraph.o, cgraphbuild.o): Add dependency on
ipa-inline.h
2011-04-16 Uros Bizjak <ubizjak@gmail.com> 2011-04-16 Uros Bizjak <ubizjak@gmail.com>
* config/i386/sse.md (V16): New mode iterator. * config/i386/sse.md (V16): New mode iterator.
......
...@@ -2983,7 +2983,8 @@ cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ ...@@ -2983,7 +2983,8 @@ cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
langhooks.h toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \ langhooks.h toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \ gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
$(TREE_INLINE_H) $(TREE_DUMP_H) $(TREE_FLOW_H) cif-code.def \ $(TREE_INLINE_H) $(TREE_DUMP_H) $(TREE_FLOW_H) cif-code.def \
value-prof.h $(EXCEPT_H) $(IPA_UTILS_H) $(DIAGNOSTIC_CORE_H) value-prof.h $(EXCEPT_H) $(IPA_UTILS_H) $(DIAGNOSTIC_CORE_H) \
ipa-inline.h
cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) \ $(TREE_H) langhooks.h $(TREE_INLINE_H) toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) \
$(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \ $(TARGET_H) $(CGRAPH_H) intl.h pointer-set.h $(FUNCTION_H) $(GIMPLE_H) \
...@@ -2993,7 +2994,8 @@ cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ ...@@ -2993,7 +2994,8 @@ cgraphunit.o : cgraphunit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
tree-pretty-print.h gimple-pretty-print.h tree-pretty-print.h gimple-pretty-print.h
cgraphbuild.o : cgraphbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ cgraphbuild.o : cgraphbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(CGRAPH_H) intl.h pointer-set.h $(GIMPLE_H) \ $(TREE_H) langhooks.h $(CGRAPH_H) intl.h pointer-set.h $(GIMPLE_H) \
$(TREE_FLOW_H) $(TREE_PASS_H) $(IPA_UTILS_H) $(EXCEPT_H) $(TREE_FLOW_H) $(TREE_PASS_H) $(IPA_UTILS_H) $(EXCEPT_H) \
ipa-inline.h
varpool.o : varpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ varpool.o : varpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) $(CGRAPH_H) langhooks.h $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) \ $(TREE_H) $(CGRAPH_H) langhooks.h $(DIAGNOSTIC_CORE_H) $(HASHTAB_H) \
$(GGC_H) $(TIMEVAR_H) debug.h $(TARGET_H) output.h $(GIMPLE_H) \ $(GGC_H) $(TIMEVAR_H) debug.h $(TARGET_H) output.h $(GIMPLE_H) \
......
...@@ -98,6 +98,7 @@ The callgraph: ...@@ -98,6 +98,7 @@ The callgraph:
#include "rtl.h" #include "rtl.h"
#include "ipa-utils.h" #include "ipa-utils.h"
#include "lto-streamer.h" #include "lto-streamer.h"
#include "ipa-inline.h"
const char * const ld_plugin_symbol_resolution_names[]= const char * const ld_plugin_symbol_resolution_names[]=
{ {
...@@ -476,7 +477,6 @@ cgraph_create_node_1 (void) ...@@ -476,7 +477,6 @@ cgraph_create_node_1 (void)
if (cgraph_nodes) if (cgraph_nodes)
cgraph_nodes->previous = node; cgraph_nodes->previous = node;
node->previous = NULL; node->previous = NULL;
node->global.estimated_growth = INT_MIN;
node->frequency = NODE_FREQUENCY_NORMAL; node->frequency = NODE_FREQUENCY_NORMAL;
node->count_materialization_scale = REG_BR_PROB_BASE; node->count_materialization_scale = REG_BR_PROB_BASE;
ipa_empty_ref_list (&node->ref_list); ipa_empty_ref_list (&node->ref_list);
...@@ -970,28 +970,6 @@ cgraph_create_edge_including_clones (struct cgraph_node *orig, ...@@ -970,28 +970,6 @@ cgraph_create_edge_including_clones (struct cgraph_node *orig,
} }
} }
/* Give initial reasons why inlining would fail on EDGE. This gets either
nullified or usually overwritten by more precise reasons later. */
static 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 (!callee->local.inlinable)
e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
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;
}
/* Allocate a cgraph_edge structure and fill it with data according to the /* Allocate a cgraph_edge structure and fill it with data according to the
parameters of which only CALLEE can be NULL (when creating an indirect call parameters of which only CALLEE can be NULL (when creating an indirect call
edge). */ edge). */
...@@ -1899,12 +1877,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) ...@@ -1899,12 +1877,6 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
ld_plugin_symbol_resolution_names[(int)node->resolution]); ld_plugin_symbol_resolution_names[(int)node->resolution]);
if (node->local.finalized) if (node->local.finalized)
fprintf (f, " finalized"); fprintf (f, " finalized");
if (node->local.disregard_inline_limits)
fprintf (f, " always_inline");
else if (node->local.inlinable)
fprintf (f, " inlinable");
else if (node->local.versionable)
fprintf (f, " versionable");
if (node->local.redefined_extern_inline) if (node->local.redefined_extern_inline)
fprintf (f, " redefined_extern_inline"); fprintf (f, " redefined_extern_inline");
if (TREE_ASM_WRITTEN (node->decl)) if (TREE_ASM_WRITTEN (node->decl))
......
...@@ -88,20 +88,10 @@ struct GTY(()) cgraph_local_info { ...@@ -88,20 +88,10 @@ struct GTY(()) cgraph_local_info {
/* Set once it has been finalized so we consider it to be output. */ /* Set once it has been finalized so we consider it to be output. */
unsigned finalized : 1; unsigned finalized : 1;
/* False when there something makes inlining impossible (such as va_arg). */
unsigned inlinable : 1;
/* False when there something makes versioning impossible.
Currently computed and used only by ipa-cp. */
unsigned versionable : 1;
/* False when function calling convention and signature can not be changed. /* False when function calling convention and signature can not be changed.
This is the case when __builtin_apply_args is used. */ This is the case when __builtin_apply_args is used. */
unsigned can_change_signature : 1; unsigned can_change_signature : 1;
/* True when function should be inlined independently on its size. */
unsigned disregard_inline_limits : 1;
/* True when the function has been originally extern inline, but it is /* True when the function has been originally extern inline, but it is
redefined now. */ redefined now. */
unsigned redefined_extern_inline : 1; unsigned redefined_extern_inline : 1;
...@@ -115,21 +105,9 @@ struct GTY(()) cgraph_local_info { ...@@ -115,21 +105,9 @@ struct GTY(()) cgraph_local_info {
once compilation is finished. Available only with -funit-at-a-time. */ once compilation is finished. Available only with -funit-at-a-time. */
struct GTY(()) cgraph_global_info { struct GTY(()) cgraph_global_info {
/* Estimated stack frame consumption by the function. */
HOST_WIDE_INT estimated_stack_size;
/* Expected offset of the stack frame of inlined function. */
HOST_WIDE_INT stack_frame_offset;
/* For inline clones this points to the function they will be /* For inline clones this points to the function they will be
inlined into. */ inlined into. */
struct cgraph_node *inlined_to; struct cgraph_node *inlined_to;
/* Estimated size of the function after inlining. */
int time;
int size;
/* Estimated growth after inlining. INT_MIN if not computed. */
int estimated_growth;
}; };
/* Information about the function that is propagated by the RTL backend. /* Information about the function that is propagated by the RTL backend.
......
...@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h" #include "tree-pass.h"
#include "ipa-utils.h" #include "ipa-utils.h"
#include "except.h" #include "except.h"
#include "ipa-inline.h"
/* Context of record_reference. */ /* Context of record_reference. */
struct record_reference_ctx struct record_reference_ctx
...@@ -207,16 +208,7 @@ reset_inline_failed (struct cgraph_node *node) ...@@ -207,16 +208,7 @@ reset_inline_failed (struct cgraph_node *node)
for (e = node->callers; e; e = e->next_caller) for (e = node->callers; e; e = e->next_caller)
{ {
e->callee->global.inlined_to = NULL; e->callee->global.inlined_to = NULL;
if (!node->analyzed) initialize_inline_failed (e);
e->inline_failed = CIF_BODY_NOT_AVAILABLE;
else if (node->local.redefined_extern_inline)
e->inline_failed = CIF_REDEFINED_EXTERN_INLINE;
else if (!node->local.inlinable)
e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
else if (e->call_stmt_cannot_inline_p)
e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
else
e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED;
} }
} }
......
...@@ -172,7 +172,7 @@ cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl) ...@@ -172,7 +172,7 @@ cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
if (flag_keep_inline_functions if (flag_keep_inline_functions
&& DECL_DECLARED_INLINE_P (decl) && DECL_DECLARED_INLINE_P (decl)
&& !DECL_EXTERNAL (decl) && !DECL_EXTERNAL (decl)
&& !lookup_attribute ("always_inline", DECL_ATTRIBUTES (decl))) && !DECL_DISREGARD_INLINE_LIMITS (decl))
return true; return true;
/* If we decided it was needed before, but at the time we didn't have /* If we decided it was needed before, but at the time we didn't have
...@@ -191,7 +191,7 @@ cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl) ...@@ -191,7 +191,7 @@ cgraph_decide_is_function_needed (struct cgraph_node *node, tree decl)
to change the behavior here. */ to change the behavior here. */
if (((TREE_PUBLIC (decl) if (((TREE_PUBLIC (decl)
|| (!optimize || (!optimize
&& !node->local.disregard_inline_limits && !DECL_DISREGARD_INLINE_LIMITS (decl)
&& !DECL_DECLARED_INLINE_P (decl) && !DECL_DECLARED_INLINE_P (decl)
&& !(DECL_CONTEXT (decl) && !(DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL))) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)))
...@@ -783,11 +783,6 @@ cgraph_analyze_function (struct cgraph_node *node) ...@@ -783,11 +783,6 @@ cgraph_analyze_function (struct cgraph_node *node)
assign_assembler_name_if_neeeded (node->decl); assign_assembler_name_if_neeeded (node->decl);
/* disregard_inline_limits affects topological order of the early optimization,
so we need to compute it ahead of rest of inline parameters. */
node->local.disregard_inline_limits
= DECL_DISREGARD_INLINE_LIMITS (node->decl);
/* Make sure to gimplify bodies only once. During analyzing a /* Make sure to gimplify bodies only once. During analyzing a
function we lower it, which will require gimplified nested function we lower it, which will require gimplified nested
functions, so we can end up here with an already gimplified functions, so we can end up here with an already gimplified
......
...@@ -424,7 +424,7 @@ ipcp_versionable_function_p (struct cgraph_node *node) ...@@ -424,7 +424,7 @@ ipcp_versionable_function_p (struct cgraph_node *node)
/* There are a number of generic reasons functions cannot be versioned. We /* There are a number of generic reasons functions cannot be versioned. We
also cannot remove parameters if there are type attributes such as fnspec also cannot remove parameters if there are type attributes such as fnspec
present. */ present. */
if (!node->local.versionable if (!inline_summary (node)->versionable
|| TYPE_ATTRIBUTES (TREE_TYPE (node->decl))) || TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
return false; return false;
...@@ -1577,7 +1577,7 @@ ipcp_generate_summary (void) ...@@ -1577,7 +1577,7 @@ ipcp_generate_summary (void)
/* Unreachable nodes should have been eliminated before ipcp. */ /* Unreachable nodes should have been eliminated before ipcp. */
gcc_assert (node->needed || node->reachable); gcc_assert (node->needed || node->reachable);
node->local.versionable = tree_versionable_function_p (node->decl); inline_summary (node)->versionable = tree_versionable_function_p (node->decl);
ipa_analyze_node (node); ipa_analyze_node (node);
} }
} }
......
...@@ -100,11 +100,13 @@ inline_summary_alloc (void) ...@@ -100,11 +100,13 @@ inline_summary_alloc (void)
static void static void
inline_node_removal_hook (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) 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) if (VEC_length (inline_summary_t, inline_summary_vec)
<= (unsigned)node->uid) <= (unsigned)node->uid)
return; return;
memset (inline_summary (node), info = inline_summary (node);
0, sizeof (inline_summary_t)); info->estimated_growth = INT_MIN;
memset (info, 0, sizeof (inline_summary_t));
} }
/* Hook that is called by cgraph.c when a node is duplicated. */ /* Hook that is called by cgraph.c when a node is duplicated. */
...@@ -113,9 +115,12 @@ static void ...@@ -113,9 +115,12 @@ static void
inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, inline_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
ATTRIBUTE_UNUSED void *data) ATTRIBUTE_UNUSED void *data)
{ {
struct inline_summary *info;
inline_summary_alloc (); inline_summary_alloc ();
memcpy (inline_summary (dst), inline_summary (src), info = inline_summary (dst);
memcpy (info, inline_summary (src),
sizeof (struct inline_summary)); sizeof (struct inline_summary));
info->estimated_growth = INT_MIN;
} }
static void static void
...@@ -124,18 +129,24 @@ dump_inline_summary (FILE *f, struct cgraph_node *node) ...@@ -124,18 +129,24 @@ dump_inline_summary (FILE *f, struct cgraph_node *node)
if (node->analyzed) if (node->analyzed)
{ {
struct inline_summary *s = inline_summary (node); 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); 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); 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", fprintf (f, " self size: %i, benefit: %i\n",
s->self_size, s->size_inlining_benefit); 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", fprintf (f, " self stack: %i\n",
(int)s->estimated_self_stack_size); (int)s->estimated_self_stack_size);
fprintf (f, " global stack: %i\n\n", 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) ...@@ -155,6 +166,26 @@ dump_inline_summaries (FILE *f)
dump_inline_summary (f, node); 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. /* See if statement might disappear after inlining.
0 - means not eliminated 0 - means not eliminated
1 - half of statements goes away 1 - half of statements goes away
...@@ -317,24 +348,27 @@ compute_inline_parameters (struct cgraph_node *node) ...@@ -317,24 +348,27 @@ compute_inline_parameters (struct cgraph_node *node)
{ {
HOST_WIDE_INT self_stack_size; HOST_WIDE_INT self_stack_size;
struct cgraph_edge *e; struct cgraph_edge *e;
struct inline_summary *info;
gcc_assert (!node->global.inlined_to); gcc_assert (!node->global.inlined_to);
inline_summary_alloc (); inline_summary_alloc ();
info = inline_summary (node);
/* Estimate the stack size for the function if we're optimizing. */ /* Estimate the stack size for the function if we're optimizing. */
self_stack_size = optimize ? estimated_stack_frame_size (node) : 0; self_stack_size = optimize ? estimated_stack_frame_size (node) : 0;
inline_summary (node)->estimated_self_stack_size = self_stack_size; info->estimated_self_stack_size = self_stack_size;
node->global.estimated_stack_size = self_stack_size; info->estimated_stack_size = self_stack_size;
node->global.stack_frame_offset = 0; info->stack_frame_offset = 0;
/* Can this function be inlined at all? */ /* Can this function be inlined at all? */
node->local.inlinable = tree_inlinable_function_p (node->decl); info->inlinable = tree_inlinable_function_p (node->decl);
if (!node->local.inlinable) if (!info->inlinable)
node->local.disregard_inline_limits = 0; info->disregard_inline_limits = 0;
/* Inlinable functions always can change signature. */ /* Inlinable functions always can change signature. */
if (node->local.inlinable) if (info->inlinable)
node->local.can_change_signature = true; node->local.can_change_signature = true;
else else
{ {
...@@ -349,8 +383,13 @@ compute_inline_parameters (struct cgraph_node *node) ...@@ -349,8 +383,13 @@ compute_inline_parameters (struct cgraph_node *node)
estimate_function_body_sizes (node); estimate_function_body_sizes (node);
/* Inlining characteristics are maintained by the cgraph_mark_inline. */ /* Inlining characteristics are maintained by the cgraph_mark_inline. */
node->global.time = inline_summary (node)->self_time; info->time = info->self_time;
node->global.size = inline_summary (node)->self_size; 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 ...@@ -390,10 +429,12 @@ static inline int
estimate_edge_time (struct cgraph_edge *edge) estimate_edge_time (struct cgraph_edge *edge)
{ {
int call_stmt_time; int call_stmt_time;
struct inline_summary *info = inline_summary (edge->callee);
call_stmt_time = edge->call_stmt_time; call_stmt_time = edge->call_stmt_time;
gcc_checking_assert (call_stmt_time); gcc_checking_assert (call_stmt_time);
return (((gcov_type)edge->callee->global.time return (((gcov_type)info->time
- inline_summary (edge->callee)->time_inlining_benefit - info->time_inlining_benefit
- call_stmt_time) * edge->frequency - call_stmt_time) * edge->frequency
+ CGRAPH_FREQ_BASE / 2) / CGRAPH_FREQ_BASE; + CGRAPH_FREQ_BASE / 2) / CGRAPH_FREQ_BASE;
} }
...@@ -405,7 +446,7 @@ int ...@@ -405,7 +446,7 @@ int
estimate_time_after_inlining (struct cgraph_node *node, estimate_time_after_inlining (struct cgraph_node *node,
struct cgraph_edge *edge) 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) if (time < 0)
time = 0; time = 0;
if (time > MAX_TIME) if (time > MAX_TIME)
...@@ -421,7 +462,7 @@ int ...@@ -421,7 +462,7 @@ int
estimate_size_after_inlining (struct cgraph_node *node, estimate_size_after_inlining (struct cgraph_node *node,
struct cgraph_edge *edge) 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); gcc_assert (size >= 0);
return size; return size;
} }
...@@ -435,9 +476,10 @@ estimate_growth (struct cgraph_node *node) ...@@ -435,9 +476,10 @@ estimate_growth (struct cgraph_node *node)
int growth = 0; int growth = 0;
struct cgraph_edge *e; struct cgraph_edge *e;
bool self_recursive = false; bool self_recursive = false;
struct inline_summary *info = inline_summary (node);
if (node->global.estimated_growth != INT_MIN) if (info->estimated_growth != INT_MIN)
return node->global.estimated_growth; return info->estimated_growth;
for (e = node->callers; e; e = e->next_caller) for (e = node->callers; e; e = e->next_caller)
{ {
...@@ -453,15 +495,15 @@ estimate_growth (struct cgraph_node *node) ...@@ -453,15 +495,15 @@ estimate_growth (struct cgraph_node *node)
some inlining. */ some inlining. */
if (cgraph_will_be_removed_from_program_if_no_direct_calls (node) if (cgraph_will_be_removed_from_program_if_no_direct_calls (node)
&& !DECL_EXTERNAL (node->decl) && !self_recursive) && !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 /* COMDAT functions are very often not shared across multiple units since they
come from various template instantiations. Take this into account. */ come from various template instantiations. Take this into account. */
else if (DECL_COMDAT (node->decl) && !self_recursive else if (DECL_COMDAT (node->decl) && !self_recursive
&& cgraph_can_remove_if_no_direct_calls_p (node)) && 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; * (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY)) + 50) / 100;
node->global.estimated_growth = growth; info->estimated_growth = growth;
return growth; return growth;
} }
...@@ -561,19 +603,25 @@ inline_read_summary (void) ...@@ -561,19 +603,25 @@ inline_read_summary (void)
struct cgraph_node *node; struct cgraph_node *node;
struct inline_summary *info; struct inline_summary *info;
lto_cgraph_encoder_t encoder; lto_cgraph_encoder_t encoder;
struct bitpack_d bp;
index = lto_input_uleb128 (ib); index = lto_input_uleb128 (ib);
encoder = file_data->cgraph_node_encoder; encoder = file_data->cgraph_node_encoder;
node = lto_cgraph_encoder_deref (encoder, index); node = lto_cgraph_encoder_deref (encoder, index);
info = inline_summary (node); info = inline_summary (node);
node->global.estimated_stack_size info->estimated_stack_size
= info->estimated_self_stack_size = lto_input_uleb128 (ib); = 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); 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); 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, lto_destroy_simple_input_block (file_data,
...@@ -623,6 +671,8 @@ inline_write_summary (cgraph_node_set set, ...@@ -623,6 +671,8 @@ inline_write_summary (cgraph_node_set set,
if (node->analyzed) if (node->analyzed)
{ {
struct inline_summary *info = inline_summary (node); struct inline_summary *info = inline_summary (node);
struct bitpack_d bp;
lto_output_uleb128_stream (ob->main_stream, lto_output_uleb128_stream (ob->main_stream,
lto_cgraph_encoder_encode (encoder, node)); lto_cgraph_encoder_encode (encoder, node));
lto_output_sleb128_stream (ob->main_stream, lto_output_sleb128_stream (ob->main_stream,
...@@ -635,6 +685,11 @@ inline_write_summary (cgraph_node_set set, ...@@ -635,6 +685,11 @@ inline_write_summary (cgraph_node_set set,
info->self_time); info->self_time);
lto_output_sleb128_stream (ob->main_stream, lto_output_sleb128_stream (ob->main_stream,
info->time_inlining_benefit); 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); lto_destroy_simple_output_block (ob);
......
...@@ -23,9 +23,10 @@ along with GCC; see the file COPYING3. If not see ...@@ -23,9 +23,10 @@ along with GCC; see the file COPYING3. If not see
struct inline_summary struct inline_summary
{ {
/* Information about the function body itself. */
/* Estimated stack frame consumption by the function. */ /* Estimated stack frame consumption by the function. */
HOST_WIDE_INT estimated_self_stack_size; HOST_WIDE_INT estimated_self_stack_size;
/* Size of the function body. */ /* Size of the function body. */
int self_size; int self_size;
/* How many instructions are likely going to disappear after inlining. */ /* How many instructions are likely going to disappear after inlining. */
...@@ -34,6 +35,29 @@ struct inline_summary ...@@ -34,6 +35,29 @@ struct inline_summary
int self_time; int self_time;
/* How much time is going to be saved by inlining. */ /* How much time is going to be saved by inlining. */
int time_inlining_benefit; int time_inlining_benefit;
/* False when there something makes inlining impossible (such as va_arg). */
unsigned inlinable : 1;
/* False when there something makes versioning impossible.
Currently computed and used only by ipa-cp. */
unsigned versionable : 1;
/* True when function should be inlined independently on its size. */
unsigned disregard_inline_limits : 1;
/* Information about function that will result after applying all the
inline decisions present in the callgraph. Generally kept up to
date only for functions that are not inline clones. */
/* Estimated stack frame consumption by the function. */
HOST_WIDE_INT estimated_stack_size;
/* Expected offset of the stack frame of inlined function. */
HOST_WIDE_INT stack_frame_offset;
/* Estimated size of the function after inlining. */
int time;
int size;
/* Cached estimated growth after inlining.
INT_MIN if not computed. */
int estimated_growth;
}; };
typedef struct inline_summary inline_summary_t; typedef struct inline_summary inline_summary_t;
...@@ -47,6 +71,7 @@ void inline_generate_summary (void); ...@@ -47,6 +71,7 @@ void inline_generate_summary (void);
void inline_read_summary (void); void inline_read_summary (void);
void inline_write_summary (cgraph_node_set, varpool_node_set); void inline_write_summary (cgraph_node_set, varpool_node_set);
void inline_free_summary (void); void inline_free_summary (void);
void initialize_inline_failed (struct cgraph_edge *);
int estimate_time_after_inlining (struct cgraph_node *, struct cgraph_edge *); int estimate_time_after_inlining (struct cgraph_node *, struct cgraph_edge *);
int estimate_size_after_inlining (struct cgraph_node *, struct cgraph_edge *); int estimate_size_after_inlining (struct cgraph_node *, struct cgraph_edge *);
int estimate_growth (struct cgraph_node *); int estimate_growth (struct cgraph_node *);
...@@ -63,10 +88,10 @@ static inline int ...@@ -63,10 +88,10 @@ static inline int
estimate_edge_growth (struct cgraph_edge *edge) estimate_edge_growth (struct cgraph_edge *edge)
{ {
int call_stmt_size; int call_stmt_size;
struct inline_summary *info = inline_summary (edge->callee);
call_stmt_size = edge->call_stmt_size; call_stmt_size = edge->call_stmt_size;
gcc_checking_assert (call_stmt_size); gcc_checking_assert (call_stmt_size);
return (edge->callee->global.size return (info->size
- inline_summary (edge->callee)->size_inlining_benefit - info->size_inlining_benefit
- call_stmt_size); - call_stmt_size);
} }
...@@ -92,6 +92,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -92,6 +92,7 @@ along with GCC; see the file COPYING3. If not see
#include "fibheap.h" #include "fibheap.h"
#include "params.h" #include "params.h"
#include "gimple-pretty-print.h" #include "gimple-pretty-print.h"
#include "ipa-inline.h"
/* Per basic block info. */ /* Per basic block info. */
...@@ -1281,13 +1282,13 @@ execute_split_functions (void) ...@@ -1281,13 +1282,13 @@ execute_split_functions (void)
} }
/* This can be relaxed; function might become inlinable after splitting /* This can be relaxed; function might become inlinable after splitting
away the uninlinable part. */ away the uninlinable part. */
if (!node->local.inlinable) if (!inline_summary (node)->inlinable)
{ {
if (dump_file) if (dump_file)
fprintf (dump_file, "Not splitting: not inlinable.\n"); fprintf (dump_file, "Not splitting: not inlinable.\n");
return 0; return 0;
} }
if (node->local.disregard_inline_limits) if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
{ {
if (dump_file) if (dump_file)
fprintf (dump_file, "Not splitting: disregarding inline limits.\n"); fprintf (dump_file, "Not splitting: disregarding inline limits.\n");
......
...@@ -78,8 +78,8 @@ cgraph_postorder (struct cgraph_node **order) ...@@ -78,8 +78,8 @@ cgraph_postorder (struct cgraph_node **order)
/* Break possible cycles involving always-inline /* Break possible cycles involving always-inline
functions by ignoring edges from always-inline functions by ignoring edges from always-inline
functions to non-always-inline functions. */ functions to non-always-inline functions. */
if (edge->caller->local.disregard_inline_limits if (DECL_DISREGARD_INLINE_LIMITS (edge->caller->decl)
&& !edge->callee->local.disregard_inline_limits) && !DECL_DISREGARD_INLINE_LIMITS (edge->callee->decl))
continue; continue;
if (!edge->caller->aux) if (!edge->caller->aux)
{ {
...@@ -380,7 +380,6 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -380,7 +380,6 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
cgraph_node_remove_callees (node); cgraph_node_remove_callees (node);
ipa_remove_all_references (&node->ref_list); ipa_remove_all_references (&node->ref_list);
node->analyzed = false; node->analyzed = false;
node->local.inlinable = false;
} }
if (!node->aux) if (!node->aux)
{ {
...@@ -421,7 +420,6 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) ...@@ -421,7 +420,6 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
if (!clone) if (!clone)
{ {
cgraph_release_function_body (node); cgraph_release_function_body (node);
node->local.inlinable = false;
if (node->prev_sibling_clone) if (node->prev_sibling_clone)
node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone; node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
else if (node->clone_of) else if (node->clone_of)
...@@ -1629,7 +1627,7 @@ record_cdtor_fn (struct cgraph_node *node) ...@@ -1629,7 +1627,7 @@ record_cdtor_fn (struct cgraph_node *node)
if (DECL_STATIC_DESTRUCTOR (node->decl)) if (DECL_STATIC_DESTRUCTOR (node->decl))
VEC_safe_push (tree, heap, static_dtors, node->decl); VEC_safe_push (tree, heap, static_dtors, node->decl);
node = cgraph_get_node (node->decl); node = cgraph_get_node (node->decl);
node->local.disregard_inline_limits = 1; DECL_DISREGARD_INLINE_LIMITS (node->decl) = 1;
} }
/* Define global constructors/destructor functions for the CDTORS, of /* Define global constructors/destructor functions for the CDTORS, of
......
...@@ -489,10 +489,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, ...@@ -489,10 +489,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
bp_pack_value (&bp, node->local.local, 1); bp_pack_value (&bp, node->local.local, 1);
bp_pack_value (&bp, node->local.externally_visible, 1); bp_pack_value (&bp, node->local.externally_visible, 1);
bp_pack_value (&bp, node->local.finalized, 1); bp_pack_value (&bp, node->local.finalized, 1);
bp_pack_value (&bp, node->local.inlinable, 1);
bp_pack_value (&bp, node->local.versionable, 1);
bp_pack_value (&bp, node->local.can_change_signature, 1); bp_pack_value (&bp, node->local.can_change_signature, 1);
bp_pack_value (&bp, node->local.disregard_inline_limits, 1);
bp_pack_value (&bp, node->local.redefined_extern_inline, 1); bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
bp_pack_value (&bp, node->local.vtable_method, 1); bp_pack_value (&bp, node->local.vtable_method, 1);
bp_pack_value (&bp, node->needed, 1); bp_pack_value (&bp, node->needed, 1);
...@@ -928,10 +925,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data, ...@@ -928,10 +925,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->local.local = bp_unpack_value (bp, 1); node->local.local = bp_unpack_value (bp, 1);
node->local.externally_visible = bp_unpack_value (bp, 1); node->local.externally_visible = bp_unpack_value (bp, 1);
node->local.finalized = bp_unpack_value (bp, 1); node->local.finalized = bp_unpack_value (bp, 1);
node->local.inlinable = bp_unpack_value (bp, 1);
node->local.versionable = bp_unpack_value (bp, 1);
node->local.can_change_signature = bp_unpack_value (bp, 1); node->local.can_change_signature = bp_unpack_value (bp, 1);
node->local.disregard_inline_limits = bp_unpack_value (bp, 1);
node->local.redefined_extern_inline = bp_unpack_value (bp, 1); node->local.redefined_extern_inline = bp_unpack_value (bp, 1);
node->local.vtable_method = bp_unpack_value (bp, 1); node->local.vtable_method = bp_unpack_value (bp, 1);
node->needed = bp_unpack_value (bp, 1); node->needed = bp_unpack_value (bp, 1);
......
2011-04-16 Jan Hubicka <jh@suse.cz>
* lto.c (lto_balanced_map): Update.
2011-04-14 Jan Hubicka <jh@suse.cz> 2011-04-14 Jan Hubicka <jh@suse.cz>
* lto.c: Include ipa-inline.h * lto.c: Include ipa-inline.h
......
...@@ -1030,7 +1030,7 @@ lto_balanced_map (void) ...@@ -1030,7 +1030,7 @@ lto_balanced_map (void)
if (partition_cgraph_node_p (node)) if (partition_cgraph_node_p (node))
{ {
order[n_nodes++] = node; order[n_nodes++] = node;
total_size += node->global.size; total_size += inline_summary (node)->size;
} }
} }
free (postorder); free (postorder);
...@@ -1049,7 +1049,7 @@ lto_balanced_map (void) ...@@ -1049,7 +1049,7 @@ lto_balanced_map (void)
{ {
if (!order[i]->aux) if (!order[i]->aux)
add_cgraph_node_to_partition (partition, order[i]); add_cgraph_node_to_partition (partition, order[i]);
total_size -= order[i]->global.size; total_size -= inline_summary (order[i])->size;
/* Once we added a new node to the partition, we also want to add /* Once we added a new node to the partition, we also want to add
all referenced variables unless they was already added into some all referenced variables unless they was already added into some
......
...@@ -91,6 +91,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -91,6 +91,7 @@ along with GCC; see the file COPYING3. If not see
#include "dbgcnt.h" #include "dbgcnt.h"
#include "tree-inline.h" #include "tree-inline.h"
#include "gimple-pretty-print.h" #include "gimple-pretty-print.h"
#include "ipa-inline.h"
/* Enumeration of all aggregate reductions we can do. */ /* Enumeration of all aggregate reductions we can do. */
enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */ enum sra_mode { SRA_MODE_EARLY_IPA, /* early call regularization */
...@@ -4469,7 +4470,7 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node) ...@@ -4469,7 +4470,7 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node)
} }
if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl)) if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))
&& node->global.size >= MAX_INLINE_INSNS_AUTO) && inline_summary(node)->size >= MAX_INLINE_INSNS_AUTO)
{ {
if (dump_file) if (dump_file)
fprintf (dump_file, "Function too big to be made truly local.\n"); fprintf (dump_file, "Function too big to be made truly local.\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment