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
This commit is contained in:
parent
e81b856471
commit
e7f2301855
|
@ -1,3 +1,53 @@
|
||||||
|
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) \
|
||||||
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) \
|
||||||
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) \
|
||||||
|
|
30
gcc/cgraph.c
30
gcc/cgraph.c
|
@ -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)
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
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))
|
||||||
|
|
22
gcc/cgraph.h
22
gcc/cgraph.h
|
@ -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 {
|
||||||
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
|
||||||
#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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
/* 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)
|
||||||
/* 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)
|
||||||
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
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
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
|
||||||
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
|
||||||
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
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
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);
|
||||||
|
|
176
gcc/ipa-inline.c
176
gcc/ipa-inline.c
|
@ -156,6 +156,7 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
|
||||||
bool update_original)
|
bool update_original)
|
||||||
{
|
{
|
||||||
HOST_WIDE_INT peak;
|
HOST_WIDE_INT peak;
|
||||||
|
struct inline_summary *caller_info, *callee_info;
|
||||||
|
|
||||||
if (duplicate)
|
if (duplicate)
|
||||||
{
|
{
|
||||||
|
@ -184,7 +185,7 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
|
||||||
gcc_assert (!e->callee->global.inlined_to);
|
gcc_assert (!e->callee->global.inlined_to);
|
||||||
if (e->callee->analyzed && !DECL_EXTERNAL (e->callee->decl))
|
if (e->callee->analyzed && !DECL_EXTERNAL (e->callee->decl))
|
||||||
{
|
{
|
||||||
overall_size -= e->callee->global.size;
|
overall_size -= inline_summary (e->callee)->size;
|
||||||
nfunctions_inlined++;
|
nfunctions_inlined++;
|
||||||
}
|
}
|
||||||
duplicate = false;
|
duplicate = false;
|
||||||
|
@ -201,17 +202,20 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callee_info = inline_summary (e->callee);
|
||||||
|
caller_info = inline_summary (e->caller);
|
||||||
|
|
||||||
if (e->caller->global.inlined_to)
|
if (e->caller->global.inlined_to)
|
||||||
e->callee->global.inlined_to = e->caller->global.inlined_to;
|
e->callee->global.inlined_to = e->caller->global.inlined_to;
|
||||||
else
|
else
|
||||||
e->callee->global.inlined_to = e->caller;
|
e->callee->global.inlined_to = e->caller;
|
||||||
e->callee->global.stack_frame_offset
|
callee_info->stack_frame_offset
|
||||||
= e->caller->global.stack_frame_offset
|
= caller_info->stack_frame_offset
|
||||||
+ inline_summary (e->caller)->estimated_self_stack_size;
|
+ caller_info->estimated_self_stack_size;
|
||||||
peak = e->callee->global.stack_frame_offset
|
peak = callee_info->stack_frame_offset
|
||||||
+ inline_summary (e->callee)->estimated_self_stack_size;
|
+ callee_info->estimated_self_stack_size;
|
||||||
if (e->callee->global.inlined_to->global.estimated_stack_size < peak)
|
if (inline_summary (e->callee->global.inlined_to)->estimated_stack_size < peak)
|
||||||
e->callee->global.inlined_to->global.estimated_stack_size = peak;
|
inline_summary (e->callee->global.inlined_to)->estimated_stack_size = peak;
|
||||||
cgraph_propagate_frequency (e->callee);
|
cgraph_propagate_frequency (e->callee);
|
||||||
|
|
||||||
/* Recursively clone all bodies. */
|
/* Recursively clone all bodies. */
|
||||||
|
@ -233,6 +237,7 @@ cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original,
|
||||||
int old_size = 0, new_size = 0;
|
int old_size = 0, new_size = 0;
|
||||||
struct cgraph_node *to = NULL;
|
struct cgraph_node *to = NULL;
|
||||||
struct cgraph_edge *curr = e;
|
struct cgraph_edge *curr = e;
|
||||||
|
struct inline_summary *info;
|
||||||
|
|
||||||
/* Don't inline inlined edges. */
|
/* Don't inline inlined edges. */
|
||||||
gcc_assert (e->inline_failed);
|
gcc_assert (e->inline_failed);
|
||||||
|
@ -248,10 +253,11 @@ cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original,
|
||||||
for (;e && !e->inline_failed; e = e->caller->callers)
|
for (;e && !e->inline_failed; e = e->caller->callers)
|
||||||
{
|
{
|
||||||
to = e->caller;
|
to = e->caller;
|
||||||
old_size = e->caller->global.size;
|
info = inline_summary (to);
|
||||||
|
old_size = info->size;
|
||||||
new_size = estimate_size_after_inlining (to, curr);
|
new_size = estimate_size_after_inlining (to, curr);
|
||||||
to->global.size = new_size;
|
info->size = new_size;
|
||||||
to->global.time = estimate_time_after_inlining (to, curr);
|
info->time = estimate_time_after_inlining (to, curr);
|
||||||
}
|
}
|
||||||
gcc_assert (curr->callee->global.inlined_to == to);
|
gcc_assert (curr->callee->global.inlined_to == to);
|
||||||
if (new_size > old_size)
|
if (new_size > old_size)
|
||||||
|
@ -280,23 +286,27 @@ cgraph_check_inline_limits (struct cgraph_edge *e,
|
||||||
int newsize;
|
int newsize;
|
||||||
int limit;
|
int limit;
|
||||||
HOST_WIDE_INT stack_size_limit, inlined_stack;
|
HOST_WIDE_INT stack_size_limit, inlined_stack;
|
||||||
|
struct inline_summary *info, *what_info;
|
||||||
|
|
||||||
if (to->global.inlined_to)
|
if (to->global.inlined_to)
|
||||||
to = to->global.inlined_to;
|
to = to->global.inlined_to;
|
||||||
|
|
||||||
|
info = inline_summary (to);
|
||||||
|
what_info = inline_summary (what);
|
||||||
|
|
||||||
/* When inlining large function body called once into small function,
|
/* When inlining large function body called once into small function,
|
||||||
take the inlined function as base for limiting the growth. */
|
take the inlined function as base for limiting the growth. */
|
||||||
if (inline_summary (to)->self_size > inline_summary(what)->self_size)
|
if (info->self_size > what_info->self_size)
|
||||||
limit = inline_summary (to)->self_size;
|
limit = info->self_size;
|
||||||
else
|
else
|
||||||
limit = inline_summary (what)->self_size;
|
limit = what_info->self_size;
|
||||||
|
|
||||||
limit += limit * PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH) / 100;
|
limit += limit * PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH) / 100;
|
||||||
|
|
||||||
/* Check the size after inlining against the function limits. But allow
|
/* Check the size after inlining against the function limits. But allow
|
||||||
the function to shrink if it went over the limits by forced inlining. */
|
the function to shrink if it went over the limits by forced inlining. */
|
||||||
newsize = estimate_size_after_inlining (to, e);
|
newsize = estimate_size_after_inlining (to, e);
|
||||||
if (newsize >= to->global.size
|
if (newsize >= info->size
|
||||||
&& newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS)
|
&& newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS)
|
||||||
&& newsize > limit)
|
&& newsize > limit)
|
||||||
{
|
{
|
||||||
|
@ -305,13 +315,13 @@ cgraph_check_inline_limits (struct cgraph_edge *e,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack_size_limit = inline_summary (to)->estimated_self_stack_size;
|
stack_size_limit = info->estimated_self_stack_size;
|
||||||
|
|
||||||
stack_size_limit += stack_size_limit * PARAM_VALUE (PARAM_STACK_FRAME_GROWTH) / 100;
|
stack_size_limit += stack_size_limit * PARAM_VALUE (PARAM_STACK_FRAME_GROWTH) / 100;
|
||||||
|
|
||||||
inlined_stack = (to->global.stack_frame_offset
|
inlined_stack = (info->stack_frame_offset
|
||||||
+ inline_summary (to)->estimated_self_stack_size
|
+ info->estimated_self_stack_size
|
||||||
+ what->global.estimated_stack_size);
|
+ what_info->estimated_stack_size);
|
||||||
if (inlined_stack > stack_size_limit
|
if (inlined_stack > stack_size_limit
|
||||||
&& inlined_stack > PARAM_VALUE (PARAM_LARGE_STACK_FRAME))
|
&& inlined_stack > PARAM_VALUE (PARAM_LARGE_STACK_FRAME))
|
||||||
{
|
{
|
||||||
|
@ -328,8 +338,9 @@ static bool
|
||||||
cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason)
|
cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason)
|
||||||
{
|
{
|
||||||
tree decl = n->decl;
|
tree decl = n->decl;
|
||||||
|
struct inline_summary *info = inline_summary (n);
|
||||||
|
|
||||||
if (n->local.disregard_inline_limits)
|
if (info->disregard_inline_limits)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!flag_inline_small_functions && !DECL_DECLARED_INLINE_P (decl))
|
if (!flag_inline_small_functions && !DECL_DECLARED_INLINE_P (decl))
|
||||||
|
@ -354,7 +365,7 @@ cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason)
|
||||||
|
|
||||||
if (DECL_DECLARED_INLINE_P (decl))
|
if (DECL_DECLARED_INLINE_P (decl))
|
||||||
{
|
{
|
||||||
if (n->global.size >= MAX_INLINE_INSNS_SINGLE)
|
if (info->size >= MAX_INLINE_INSNS_SINGLE)
|
||||||
{
|
{
|
||||||
if (reason)
|
if (reason)
|
||||||
*reason = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
|
*reason = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
|
||||||
|
@ -363,7 +374,7 @@ cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (n->global.size >= MAX_INLINE_INSNS_AUTO)
|
if (info->size >= MAX_INLINE_INSNS_AUTO)
|
||||||
{
|
{
|
||||||
if (reason)
|
if (reason)
|
||||||
*reason = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
|
*reason = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
|
||||||
|
@ -385,8 +396,9 @@ cgraph_edge_badness (struct cgraph_edge *edge, bool dump)
|
||||||
{
|
{
|
||||||
gcov_type badness;
|
gcov_type badness;
|
||||||
int growth;
|
int growth;
|
||||||
|
struct inline_summary *callee_info = inline_summary (edge->callee);
|
||||||
|
|
||||||
if (edge->callee->local.disregard_inline_limits)
|
if (callee_info->disregard_inline_limits)
|
||||||
return INT_MIN;
|
return INT_MIN;
|
||||||
|
|
||||||
growth = estimate_edge_growth (edge);
|
growth = estimate_edge_growth (edge);
|
||||||
|
@ -398,11 +410,11 @@ cgraph_edge_badness (struct cgraph_edge *edge, bool dump)
|
||||||
cgraph_node_name (edge->callee));
|
cgraph_node_name (edge->callee));
|
||||||
fprintf (dump_file, " growth %i, time %i-%i, size %i-%i\n",
|
fprintf (dump_file, " growth %i, time %i-%i, size %i-%i\n",
|
||||||
growth,
|
growth,
|
||||||
edge->callee->global.time,
|
callee_info->time,
|
||||||
inline_summary (edge->callee)->time_inlining_benefit
|
callee_info->time_inlining_benefit
|
||||||
+ edge->call_stmt_time,
|
+ edge->call_stmt_time,
|
||||||
edge->callee->global.size,
|
callee_info->size,
|
||||||
inline_summary (edge->callee)->size_inlining_benefit
|
callee_info->size_inlining_benefit
|
||||||
+ edge->call_stmt_size);
|
+ edge->call_stmt_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +434,7 @@ cgraph_edge_badness (struct cgraph_edge *edge, bool dump)
|
||||||
badness =
|
badness =
|
||||||
((int)
|
((int)
|
||||||
((double) edge->count * INT_MIN / max_count / (max_benefit + 1)) *
|
((double) edge->count * INT_MIN / max_count / (max_benefit + 1)) *
|
||||||
(inline_summary (edge->callee)->time_inlining_benefit
|
(callee_info->time_inlining_benefit
|
||||||
+ edge->call_stmt_time + 1)) / growth;
|
+ edge->call_stmt_time + 1)) / growth;
|
||||||
if (dump)
|
if (dump)
|
||||||
{
|
{
|
||||||
|
@ -453,9 +465,9 @@ cgraph_edge_badness (struct cgraph_edge *edge, bool dump)
|
||||||
int growth_for_all;
|
int growth_for_all;
|
||||||
badness = growth * 10000;
|
badness = growth * 10000;
|
||||||
benefitperc =
|
benefitperc =
|
||||||
100 * (inline_summary (edge->callee)->time_inlining_benefit
|
100 * (callee_info->time_inlining_benefit
|
||||||
+ edge->call_stmt_time)
|
+ edge->call_stmt_time)
|
||||||
/ (edge->callee->global.time + 1) + 1;
|
/ (callee_info->time + 1) + 1;
|
||||||
benefitperc = MIN (benefitperc, 100);
|
benefitperc = MIN (benefitperc, 100);
|
||||||
div *= benefitperc;
|
div *= benefitperc;
|
||||||
|
|
||||||
|
@ -543,13 +555,13 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node,
|
||||||
struct cgraph_edge *edge;
|
struct cgraph_edge *edge;
|
||||||
cgraph_inline_failed_t failed_reason;
|
cgraph_inline_failed_t failed_reason;
|
||||||
|
|
||||||
if (!node->local.inlinable
|
if (!inline_summary (node)->inlinable
|
||||||
|| cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE
|
|| cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE
|
||||||
|| node->global.inlined_to)
|
|| node->global.inlined_to)
|
||||||
return;
|
return;
|
||||||
if (!bitmap_set_bit (updated_nodes, node->uid))
|
if (!bitmap_set_bit (updated_nodes, node->uid))
|
||||||
return;
|
return;
|
||||||
node->global.estimated_growth = INT_MIN;
|
inline_summary (node)->estimated_growth = INT_MIN;
|
||||||
|
|
||||||
/* See if there is something to do. */
|
/* See if there is something to do. */
|
||||||
for (edge = node->callers; edge; edge = edge->next_caller)
|
for (edge = node->callers; edge; edge = edge->next_caller)
|
||||||
|
@ -586,7 +598,7 @@ update_callee_keys (fibheap_t heap, struct cgraph_node *node,
|
||||||
bitmap updated_nodes)
|
bitmap updated_nodes)
|
||||||
{
|
{
|
||||||
struct cgraph_edge *e = node->callees;
|
struct cgraph_edge *e = node->callees;
|
||||||
node->global.estimated_growth = INT_MIN;
|
inline_summary (node)->estimated_growth = INT_MIN;
|
||||||
|
|
||||||
if (!e)
|
if (!e)
|
||||||
return;
|
return;
|
||||||
|
@ -596,11 +608,11 @@ update_callee_keys (fibheap_t heap, struct cgraph_node *node,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (e->inline_failed
|
if (e->inline_failed
|
||||||
&& e->callee->local.inlinable
|
&& inline_summary (e->callee)->inlinable
|
||||||
&& cgraph_function_body_availability (e->callee) >= AVAIL_AVAILABLE
|
&& cgraph_function_body_availability (e->callee) >= AVAIL_AVAILABLE
|
||||||
&& !bitmap_bit_p (updated_nodes, e->callee->uid))
|
&& !bitmap_bit_p (updated_nodes, e->callee->uid))
|
||||||
{
|
{
|
||||||
node->global.estimated_growth = INT_MIN;
|
inline_summary (node)->estimated_growth = INT_MIN;
|
||||||
/* If function becomes uninlinable, we need to remove it from the heap. */
|
/* If function becomes uninlinable, we need to remove it from the heap. */
|
||||||
if (!cgraph_default_inline_p (e->callee, &e->inline_failed))
|
if (!cgraph_default_inline_p (e->callee, &e->inline_failed))
|
||||||
update_caller_keys (heap, e->callee, updated_nodes);
|
update_caller_keys (heap, e->callee, updated_nodes);
|
||||||
|
@ -632,7 +644,7 @@ update_all_callee_keys (fibheap_t heap, struct cgraph_node *node,
|
||||||
bitmap updated_nodes)
|
bitmap updated_nodes)
|
||||||
{
|
{
|
||||||
struct cgraph_edge *e = node->callees;
|
struct cgraph_edge *e = node->callees;
|
||||||
node->global.estimated_growth = INT_MIN;
|
inline_summary (node)->estimated_growth = INT_MIN;
|
||||||
|
|
||||||
if (!e)
|
if (!e)
|
||||||
return;
|
return;
|
||||||
|
@ -709,7 +721,7 @@ cgraph_decide_recursive_inlining (struct cgraph_edge *edge,
|
||||||
|
|
||||||
/* It does not make sense to recursively inline always-inline functions
|
/* It does not make sense to recursively inline always-inline functions
|
||||||
as we are going to sorry() on the remaining calls anyway. */
|
as we are going to sorry() on the remaining calls anyway. */
|
||||||
if (node->local.disregard_inline_limits
|
if (inline_summary (node)->disregard_inline_limits
|
||||||
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl)))
|
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -811,8 +823,8 @@ cgraph_decide_recursive_inlining (struct cgraph_edge *edge,
|
||||||
if (dump_file)
|
if (dump_file)
|
||||||
fprintf (dump_file,
|
fprintf (dump_file,
|
||||||
"\n Inlined %i times, body grown from size %i to %i, time %i to %i\n", n,
|
"\n Inlined %i times, body grown from size %i to %i, time %i to %i\n", n,
|
||||||
master_clone->global.size, node->global.size,
|
inline_summary (master_clone)->size, inline_summary (node)->size,
|
||||||
master_clone->global.time, node->global.time);
|
inline_summary (master_clone)->time, inline_summary (node)->time);
|
||||||
|
|
||||||
/* Remove master clone we used for inlining. We rely that clones inlined
|
/* Remove master clone we used for inlining. We rely that clones inlined
|
||||||
into master clone gets queued just before master clone so we don't
|
into master clone gets queued just before master clone so we don't
|
||||||
|
@ -870,7 +882,7 @@ add_new_edges_to_heap (fibheap_t heap, VEC (cgraph_edge_p, heap) *new_edges)
|
||||||
struct cgraph_edge *edge = VEC_pop (cgraph_edge_p, new_edges);
|
struct cgraph_edge *edge = VEC_pop (cgraph_edge_p, new_edges);
|
||||||
|
|
||||||
gcc_assert (!edge->aux);
|
gcc_assert (!edge->aux);
|
||||||
if (edge->callee->local.inlinable
|
if (inline_summary (edge->callee)->inlinable
|
||||||
&& edge->inline_failed
|
&& edge->inline_failed
|
||||||
&& cgraph_default_inline_p (edge->callee, &edge->inline_failed))
|
&& cgraph_default_inline_p (edge->callee, &edge->inline_failed))
|
||||||
edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge, false), edge);
|
edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge, false), edge);
|
||||||
|
@ -905,26 +917,37 @@ cgraph_decide_inlining_of_small_functions (void)
|
||||||
/* Put all inline candidates into the heap. */
|
/* Put all inline candidates into the heap. */
|
||||||
|
|
||||||
for (node = cgraph_nodes; node; node = node->next)
|
for (node = cgraph_nodes; node; node = node->next)
|
||||||
{
|
if (node->analyzed)
|
||||||
if (!node->local.inlinable || !node->callers)
|
{
|
||||||
continue;
|
struct inline_summary *info = inline_summary (node);
|
||||||
if (dump_file)
|
|
||||||
fprintf (dump_file, "Considering inline candidate %s.\n", cgraph_node_name (node));
|
|
||||||
|
|
||||||
node->global.estimated_growth = INT_MIN;
|
if (!info->inlinable || !node->callers)
|
||||||
if (!cgraph_default_inline_p (node, &failed_reason))
|
|
||||||
{
|
|
||||||
cgraph_set_inline_failed (node, failed_reason);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (edge = node->callers; edge; edge = edge->next_caller)
|
|
||||||
if (edge->inline_failed)
|
|
||||||
{
|
{
|
||||||
gcc_assert (!edge->aux);
|
struct cgraph_edge *e;
|
||||||
edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge, false), edge);
|
for (e = node->callers; e; e = e->next_caller)
|
||||||
|
{
|
||||||
|
gcc_assert (e->inline_failed);
|
||||||
|
e->inline_failed = CIF_FUNCTION_NOT_INLINABLE;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
if (dump_file)
|
||||||
|
fprintf (dump_file, "Considering inline candidate %s.\n", cgraph_node_name (node));
|
||||||
|
|
||||||
|
info->estimated_growth = INT_MIN;
|
||||||
|
if (!cgraph_default_inline_p (node, &failed_reason))
|
||||||
|
{
|
||||||
|
cgraph_set_inline_failed (node, failed_reason);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (edge = node->callers; edge; edge = edge->next_caller)
|
||||||
|
if (edge->inline_failed)
|
||||||
|
{
|
||||||
|
gcc_assert (!edge->aux);
|
||||||
|
edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge, false), edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
max_size = compute_max_insns (overall_size);
|
max_size = compute_max_insns (overall_size);
|
||||||
min_size = overall_size;
|
min_size = overall_size;
|
||||||
|
@ -963,7 +986,7 @@ cgraph_decide_inlining_of_small_functions (void)
|
||||||
fprintf (dump_file,
|
fprintf (dump_file,
|
||||||
"\nConsidering %s with %i size\n",
|
"\nConsidering %s with %i size\n",
|
||||||
cgraph_node_name (edge->callee),
|
cgraph_node_name (edge->callee),
|
||||||
edge->callee->global.size);
|
inline_summary (edge->callee)->size);
|
||||||
fprintf (dump_file,
|
fprintf (dump_file,
|
||||||
" to be inlined into %s in %s:%i\n"
|
" to be inlined into %s in %s:%i\n"
|
||||||
" Estimated growth after inlined into all callees is %+i insns.\n"
|
" Estimated growth after inlined into all callees is %+i insns.\n"
|
||||||
|
@ -1007,7 +1030,7 @@ cgraph_decide_inlining_of_small_functions (void)
|
||||||
if (where->global.inlined_to)
|
if (where->global.inlined_to)
|
||||||
{
|
{
|
||||||
edge->inline_failed
|
edge->inline_failed
|
||||||
= (edge->callee->local.disregard_inline_limits
|
= (inline_summary (edge->callee)->disregard_inline_limits
|
||||||
? CIF_RECURSIVE_INLINING : CIF_UNSPECIFIED);
|
? CIF_RECURSIVE_INLINING : CIF_UNSPECIFIED);
|
||||||
if (dump_file)
|
if (dump_file)
|
||||||
fprintf (dump_file, " inline_failed:Recursive inlining performed only for function itself.\n");
|
fprintf (dump_file, " inline_failed:Recursive inlining performed only for function itself.\n");
|
||||||
|
@ -1015,7 +1038,7 @@ cgraph_decide_inlining_of_small_functions (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (edge->callee->local.disregard_inline_limits)
|
if (inline_summary (edge->callee)->disregard_inline_limits)
|
||||||
;
|
;
|
||||||
else if (!cgraph_maybe_hot_edge_p (edge))
|
else if (!cgraph_maybe_hot_edge_p (edge))
|
||||||
not_good = CIF_UNLIKELY_CALL;
|
not_good = CIF_UNLIKELY_CALL;
|
||||||
|
@ -1112,8 +1135,8 @@ cgraph_decide_inlining_of_small_functions (void)
|
||||||
" Inlined into %s which now has time %i and size %i,"
|
" Inlined into %s which now has time %i and size %i,"
|
||||||
"net change of %+i.\n",
|
"net change of %+i.\n",
|
||||||
cgraph_node_name (edge->caller),
|
cgraph_node_name (edge->caller),
|
||||||
edge->caller->global.time,
|
inline_summary (edge->caller)->time,
|
||||||
edge->caller->global.size,
|
inline_summary (edge->caller)->size,
|
||||||
overall_size - old_size);
|
overall_size - old_size);
|
||||||
}
|
}
|
||||||
if (min_size > overall_size)
|
if (min_size > overall_size)
|
||||||
|
@ -1142,7 +1165,7 @@ cgraph_decide_inlining_of_small_functions (void)
|
||||||
fprintf (dump_file,
|
fprintf (dump_file,
|
||||||
"\nSkipping %s with %i size\n",
|
"\nSkipping %s with %i size\n",
|
||||||
cgraph_node_name (edge->callee),
|
cgraph_node_name (edge->callee),
|
||||||
edge->callee->global.size);
|
inline_summary (edge->callee)->size);
|
||||||
fprintf (dump_file,
|
fprintf (dump_file,
|
||||||
" called by %s in %s:%i\n"
|
" called by %s in %s:%i\n"
|
||||||
" Estimated growth after inlined into all callees is %+i insns.\n"
|
" Estimated growth after inlined into all callees is %+i insns.\n"
|
||||||
|
@ -1159,7 +1182,7 @@ cgraph_decide_inlining_of_small_functions (void)
|
||||||
if (dump_flags & TDF_DETAILS)
|
if (dump_flags & TDF_DETAILS)
|
||||||
cgraph_edge_badness (edge, true);
|
cgraph_edge_badness (edge, true);
|
||||||
}
|
}
|
||||||
if (!edge->callee->local.disregard_inline_limits && edge->inline_failed)
|
if (!inline_summary (edge->callee)->disregard_inline_limits && edge->inline_failed)
|
||||||
edge->inline_failed = CIF_INLINE_UNIT_GROWTH_LIMIT;
|
edge->inline_failed = CIF_INLINE_UNIT_GROWTH_LIMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1287,13 +1310,14 @@ cgraph_decide_inlining (void)
|
||||||
if (node->analyzed)
|
if (node->analyzed)
|
||||||
{
|
{
|
||||||
struct cgraph_edge *e;
|
struct cgraph_edge *e;
|
||||||
|
struct inline_summary *info = inline_summary (node);
|
||||||
|
|
||||||
gcc_assert (inline_summary (node)->self_size == node->global.size);
|
gcc_assert (info->self_size == info->size);
|
||||||
if (!DECL_EXTERNAL (node->decl))
|
if (!DECL_EXTERNAL (node->decl))
|
||||||
initial_size += node->global.size;
|
initial_size += info->size;
|
||||||
for (e = node->callees; e; e = e->next_callee)
|
for (e = node->callees; e; e = e->next_callee)
|
||||||
{
|
{
|
||||||
int benefit = (inline_summary (node)->time_inlining_benefit
|
int benefit = (info->time_inlining_benefit
|
||||||
+ e->call_stmt_time);
|
+ e->call_stmt_time);
|
||||||
if (max_count < e->count)
|
if (max_count < e->count)
|
||||||
max_count = e->count;
|
max_count = e->count;
|
||||||
|
@ -1362,7 +1386,7 @@ cgraph_decide_inlining (void)
|
||||||
&& !node->callers->next_caller
|
&& !node->callers->next_caller
|
||||||
&& !node->global.inlined_to
|
&& !node->global.inlined_to
|
||||||
&& cgraph_will_be_removed_from_program_if_no_direct_calls (node)
|
&& cgraph_will_be_removed_from_program_if_no_direct_calls (node)
|
||||||
&& node->local.inlinable
|
&& inline_summary (node)->inlinable
|
||||||
&& cgraph_function_body_availability (node) >= AVAIL_AVAILABLE
|
&& cgraph_function_body_availability (node) >= AVAIL_AVAILABLE
|
||||||
&& node->callers->inline_failed
|
&& node->callers->inline_failed
|
||||||
&& node->callers->caller != node
|
&& node->callers->caller != node
|
||||||
|
@ -1377,11 +1401,11 @@ cgraph_decide_inlining (void)
|
||||||
{
|
{
|
||||||
fprintf (dump_file,
|
fprintf (dump_file,
|
||||||
"\nConsidering %s size %i.\n",
|
"\nConsidering %s size %i.\n",
|
||||||
cgraph_node_name (node), node->global.size);
|
cgraph_node_name (node), inline_summary (node)->size);
|
||||||
fprintf (dump_file,
|
fprintf (dump_file,
|
||||||
" Called once from %s %i insns.\n",
|
" Called once from %s %i insns.\n",
|
||||||
cgraph_node_name (node->callers->caller),
|
cgraph_node_name (node->callers->caller),
|
||||||
node->callers->caller->global.size);
|
inline_summary (node->callers->caller)->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cgraph_check_inline_limits (node->callers, &reason))
|
if (cgraph_check_inline_limits (node->callers, &reason))
|
||||||
|
@ -1393,7 +1417,7 @@ cgraph_decide_inlining (void)
|
||||||
" Inlined into %s which now has %i size"
|
" Inlined into %s which now has %i size"
|
||||||
" for a net change of %+i size.\n",
|
" for a net change of %+i size.\n",
|
||||||
cgraph_node_name (caller),
|
cgraph_node_name (caller),
|
||||||
caller->global.size,
|
inline_summary (caller)->size,
|
||||||
overall_size - old_size);
|
overall_size - old_size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1442,7 +1466,7 @@ leaf_node_p (struct cgraph_node *n)
|
||||||
static bool
|
static bool
|
||||||
cgraph_edge_early_inlinable_p (struct cgraph_edge *e, FILE *file)
|
cgraph_edge_early_inlinable_p (struct cgraph_edge *e, FILE *file)
|
||||||
{
|
{
|
||||||
if (!e->callee->local.inlinable)
|
if (!inline_summary (e->callee)->inlinable)
|
||||||
{
|
{
|
||||||
if (file)
|
if (file)
|
||||||
fprintf (file, "Not inlining: Function not inlinable.\n");
|
fprintf (file, "Not inlining: Function not inlinable.\n");
|
||||||
|
@ -1482,7 +1506,7 @@ cgraph_perform_always_inlining (struct cgraph_node *node)
|
||||||
|
|
||||||
for (e = node->callees; e; e = e->next_callee)
|
for (e = node->callees; e; e = e->next_callee)
|
||||||
{
|
{
|
||||||
if (!e->callee->local.disregard_inline_limits)
|
if (!inline_summary (e->callee)->disregard_inline_limits)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (dump_file)
|
if (dump_file)
|
||||||
|
@ -1524,16 +1548,16 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
|
||||||
|
|
||||||
/* Never inline regular functions into always-inline functions
|
/* Never inline regular functions into always-inline functions
|
||||||
during incremental inlining. */
|
during incremental inlining. */
|
||||||
if (node->local.disregard_inline_limits)
|
if (inline_summary (node)->disregard_inline_limits)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (e = node->callees; e; e = e->next_callee)
|
for (e = node->callees; e; e = e->next_callee)
|
||||||
{
|
{
|
||||||
int allowed_growth = 0;
|
int allowed_growth = 0;
|
||||||
|
|
||||||
if (!e->callee->local.inlinable
|
if (!inline_summary (e->callee)->inlinable
|
||||||
|| !e->inline_failed
|
|| !e->inline_failed
|
||||||
|| e->callee->local.disregard_inline_limits)
|
|| inline_summary (e->callee)->disregard_inline_limits)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Do not consider functions not declared inline. */
|
/* Do not consider functions not declared inline. */
|
||||||
|
|
|
@ -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
|
||||||
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);
|
||||||
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
|
||||||
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
|
||||||
#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)
|
||||||
}
|
}
|
||||||
/* 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)
|
||||||
/* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
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);
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
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)
|
||||||
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)
|
||||||
{
|
{
|
||||||
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
|
||||||
#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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
|
|
Loading…
Reference in New Issue