lto-symtab.c (lto_cgraph_replace_node): When call statement is present, also set gimple_call_set_cannot_inline.

* lto-symtab.c (lto_cgraph_replace_node): When call statement is
	present, also set gimple_call_set_cannot_inline.
	* ipa-inline.c: Update toplevel comment.
	(MAX_TIME): Remove.
	(cgraph_clone_inlined_nodes): Fix linebreaks.
	(cgraph_check_inline_limits): Restructure to ...
	(caller_growth_limits): ... this one; be more tolerant
	on growth in nested inline chains; add explanatory comment;
	fix stack accounting thinko introduced by previous patch.
	(cgraph_default_inline_p): Remove.
	(report_inline_failed_reason): New function.
	(can_inline_edge_p): New function.
	(can_early_inline_edge_p): New function.
	(leaf_node_p): Move upwards in file.
	(want_early_inline_function_p): New function.
	(want_inline_small_function_p): New function.
	(want_inline_self_recursive_call_p): New function.
	(cgraph_edge_badness): Rename to ...
	(edge_badness) ... this one; fix linebreaks.
	(update_edge_key): Update call of edge_baddness; add
	detailed dump about queue updates.
	(update_caller_keys): Use can_inline_edge_p and
	want_inline_small_function_p.
	(cgraph_decide_recursive_inlining): Rename to...
	(recursive_inlining): Use can_inline_edge_p and
	want_inline_self_recursive_call_p; simplify and
	remove no longer valid FIXME.
	(cgraph_set_inline_failed): Remove.
	(add_new_edges_to_heap): Use can_inline_edge_p and
	want_inline_small_function_p.
	(cgraph_decide_inlining_of_small_functions): Rename to ...
	(inline_small_functions): ... this one; cleanup; use
	can/want predicates; cleanup debug ouput; work edges
	till fibheap is exhausted and do not stop once unit
	growth is reached; remove later loop processing remaining
	edges.
	(cgraph_flatten): Rename to ...
	(flatten_function): ... this one; use can_inline_edge_p
	and can_early_inline_edge_p predicates.
	(cgraph_decide_inlining): Rename to ...
	(ipa_inline): ... this one; remove unreachable nodes before
	inlining functions called once; simplify the pass.
	(cgraph_perform_always_inlining): Rename to ...
	(inline_always_inline_functions): ... this one; use
	DECL_DISREGARD_INLINE_LIMITS; use can_inline_edge_p
	predicate
	(cgraph_decide_inlining_incrementally): Rename to ...
	(early_inline_small_functions): ... this one; simplify
	using new predicates; cleanup; make dumps prettier.
	(cgraph_early_inlining): Rename to ...
	(early_inliner): newer inline regular functions into always-inlines;
	fix updating of call stmt summaries.
	(pass_early_inline): Update for new names.
	(inline_transform): Fix formating.
	(gate_cgraph_decide_inlining): Rename to ...
	(pass_ipa_inline): ... this one.
	* ipa-inline.h (inline_summary): Remove disregard_inline_limits.
	* ipa-inline-analysis.c (dump_inline_summary): Update.
	(compute_inline_parameters): Do not compute disregard_inline_limits;
	look for mismatching arguments.
	(estimate_growth): Fix handlig of non-trivial self recursion.
	(inline_read_summary): Do not read info->disregard_inline_limits.
	(inline_write_summary): Do not write info->disregard_inline_limits.
	* tree-inline.c (inline_forbidden_into_p, tree_can_inline_p): Remove and
	move all checks into can_inline_edge_p predicate; re-enable code comparing
	optimization levels.
	(expand_call_inline): Do not test inline_forbidden_into_p.
	* Makefile.in (ipa-inline.o): Update arguments.

	* gcc.dg/winline-5.c: Update testcase.

From-SVN: r172609
This commit is contained in:
Jan Hubicka 2011-04-17 16:22:20 +02:00 committed by Jan Hubicka
parent 51c5169c60
commit 4c0f767939
10 changed files with 830 additions and 672 deletions

View File

@ -1,3 +1,74 @@
2011-04-17 Jan Hubicka <jh@suse.cz>
* lto-symtab.c (lto_cgraph_replace_node): When call statement is
present, also set gimple_call_set_cannot_inline.
* ipa-inline.c: Update toplevel comment.
(MAX_TIME): Remove.
(cgraph_clone_inlined_nodes): Fix linebreaks.
(cgraph_check_inline_limits): Restructure to ...
(caller_growth_limits): ... this one; be more tolerant
on growth in nested inline chains; add explanatory comment;
fix stack accounting thinko introduced by previous patch.
(cgraph_default_inline_p): Remove.
(report_inline_failed_reason): New function.
(can_inline_edge_p): New function.
(can_early_inline_edge_p): New function.
(leaf_node_p): Move upwards in file.
(want_early_inline_function_p): New function.
(want_inline_small_function_p): New function.
(want_inline_self_recursive_call_p): New function.
(cgraph_edge_badness): Rename to ...
(edge_badness) ... this one; fix linebreaks.
(update_edge_key): Update call of edge_baddness; add
detailed dump about queue updates.
(update_caller_keys): Use can_inline_edge_p and
want_inline_small_function_p.
(cgraph_decide_recursive_inlining): Rename to...
(recursive_inlining): Use can_inline_edge_p and
want_inline_self_recursive_call_p; simplify and
remove no longer valid FIXME.
(cgraph_set_inline_failed): Remove.
(add_new_edges_to_heap): Use can_inline_edge_p and
want_inline_small_function_p.
(cgraph_decide_inlining_of_small_functions): Rename to ...
(inline_small_functions): ... this one; cleanup; use
can/want predicates; cleanup debug ouput; work edges
till fibheap is exhausted and do not stop once unit
growth is reached; remove later loop processing remaining
edges.
(cgraph_flatten): Rename to ...
(flatten_function): ... this one; use can_inline_edge_p
and can_early_inline_edge_p predicates.
(cgraph_decide_inlining): Rename to ...
(ipa_inline): ... this one; remove unreachable nodes before
inlining functions called once; simplify the pass.
(cgraph_perform_always_inlining): Rename to ...
(inline_always_inline_functions): ... this one; use
DECL_DISREGARD_INLINE_LIMITS; use can_inline_edge_p
predicate
(cgraph_decide_inlining_incrementally): Rename to ...
(early_inline_small_functions): ... this one; simplify
using new predicates; cleanup; make dumps prettier.
(cgraph_early_inlining): Rename to ...
(early_inliner): newer inline regular functions into always-inlines;
fix updating of call stmt summaries.
(pass_early_inline): Update for new names.
(inline_transform): Fix formating.
(gate_cgraph_decide_inlining): Rename to ...
(pass_ipa_inline): ... this one.
* ipa-inline.h (inline_summary): Remove disregard_inline_limits.
* ipa-inline-analysis.c (dump_inline_summary): Update.
(compute_inline_parameters): Do not compute disregard_inline_limits;
look for mismatching arguments.
(estimate_growth): Fix handlig of non-trivial self recursion.
(inline_read_summary): Do not read info->disregard_inline_limits.
(inline_write_summary): Do not write info->disregard_inline_limits.
* tree-inline.c (inline_forbidden_into_p, tree_can_inline_p): Remove and
move all checks into can_inline_edge_p predicate; re-enable code comparing
optimization levels.
(expand_call_inline): Do not test inline_forbidden_into_p.
* Makefile.in (ipa-inline.o): Update arguments.
2011-04-17 Revital Eres <revital.eres@linaro.org>
* ddg.c (free_ddg_all_sccs): Free sccs field in struct ddg_all_sccs.

View File

@ -3028,8 +3028,8 @@ matrix-reorg.o : matrix-reorg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
ipa-inline.o : ipa-inline.c gt-ipa-inline.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
$(DIAGNOSTIC_H) $(FIBHEAP_H) $(PARAMS_H) $(TIMEVAR_H) $(TREE_PASS_H) \
$(HASHTAB_H) $(COVERAGE_H) $(GGC_H) $(TREE_FLOW_H) $(RTL_H) $(IPA_PROP_H) \
$(EXCEPT_H) gimple-pretty-print.h ipa-inline.h
$(COVERAGE_H) $(GGC_H) $(TREE_FLOW_H) $(RTL_H) $(IPA_PROP_H) \
$(EXCEPT_H) gimple-pretty-print.h ipa-inline.h $(TARGET_H)
ipa-inline-analysis.o : ipa-inline-analysis.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \
$(DIAGNOSTIC_H) $(PARAMS_H) $(TIMEVAR_H) $(TREE_PASS_H) \

View File

@ -79,6 +79,8 @@ DEFCIFCODE(OPTIMIZING_FOR_SIZE,
/* Inlining failed because of mismatched options or arguments. */
DEFCIFCODE(TARGET_OPTION_MISMATCH, N_("target specific option mismatch"))
DEFCIFCODE(TARGET_OPTIMIZATION_MISMATCH,
N_("optimization level attribute mismatch"))
DEFCIFCODE(MISMATCHED_ARGUMENTS, N_("mismatched arguments"))
/* Call was originally indirect. */
@ -89,4 +91,18 @@ DEFCIFCODE(ORIGINALLY_INDIRECT_CALL,
DEFCIFCODE(INDIRECT_UNKNOWN_CALL,
N_("indirect function call with a yet undetermined callee"))
/* We can't inline different EH personalities together. */
DEFCIFCODE(EH_PERSONALITY,
N_("excepion handling personality mismatch"))
/* Don't inline if the callee can throw non-call exceptions but the
caller cannot. */
DEFCIFCODE(NON_CALL_EXCEPTIONS,
N_("excepion handling personality mismatch"))
/* Don't inline if the callee can throw non-call exceptions but the
caller cannot. */
DEFCIFCODE(OPTIMIZATION_MISMATCH,
N_("optimization mode mismatch"))
DEFCIFCODE(OVERWRITABLE, N_("function body can be overwriten at linktime"))

View File

@ -131,7 +131,7 @@ dump_inline_summary (FILE *f, struct cgraph_node *node)
struct inline_summary *s = inline_summary (node);
fprintf (f, "Inline summary for %s/%i", cgraph_node_name (node),
node->uid);
if (s->disregard_inline_limits)
if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
fprintf (f, " always_inline");
if (s->inlinable)
fprintf (f, " inlinable");
@ -142,7 +142,7 @@ dump_inline_summary (FILE *f, struct cgraph_node *node)
fprintf (f, " global time: %i\n", s->time);
fprintf (f, " self size: %i, benefit: %i\n",
s->self_size, s->size_inlining_benefit);
fprintf (f, " global size: %i", s->size);
fprintf (f, " global size: %i\n", s->size);
fprintf (f, " self stack: %i\n",
(int)s->estimated_self_stack_size);
fprintf (f, " global stack: %i\n\n",
@ -303,6 +303,17 @@ estimate_function_body_sizes (struct cgraph_node *node)
struct cgraph_edge *edge = cgraph_edge (node, stmt);
edge->call_stmt_size = this_size;
edge->call_stmt_time = this_time;
/* Do not inline calls where we cannot triviall work around mismatches
in argument or return types. */
if (edge->callee
&& !gimple_check_call_matching_types (stmt, edge->callee->decl))
{
edge->call_stmt_cannot_inline_p = true;
gimple_call_set_cannot_inline (stmt, true);
}
else
gcc_assert (!gimple_call_cannot_inline_p (stmt));
}
this_time *= freq;
@ -364,8 +375,6 @@ compute_inline_parameters (struct cgraph_node *node)
/* Can this function be inlined at all? */
info->inlinable = tree_inlinable_function_p (node->decl);
if (!info->inlinable)
info->disregard_inline_limits = 0;
/* Inlinable functions always can change signature. */
if (info->inlinable)
@ -388,8 +397,6 @@ compute_inline_parameters (struct cgraph_node *node)
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);
}
@ -483,25 +490,34 @@ estimate_growth (struct cgraph_node *node)
for (e = node->callers; e; e = e->next_caller)
{
if (e->caller == node)
self_recursive = true;
if (e->inline_failed)
growth += estimate_edge_growth (e);
}
gcc_checking_assert (e->inline_failed);
/* ??? Wrong for non-trivially self recursive functions or cases where
we decide to not inline for different reasons, but it is not big deal
as in that case we will keep the body around, but we will also avoid
some inlining. */
if (cgraph_will_be_removed_from_program_if_no_direct_calls (node)
&& !DECL_EXTERNAL (node->decl) && !self_recursive)
growth -= info->size;
/* COMDAT functions are very often not shared across multiple units since they
come from various template instantiations. Take this into account. */
else if (DECL_COMDAT (node->decl) && !self_recursive
&& cgraph_can_remove_if_no_direct_calls_p (node))
growth -= (info->size
* (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY)) + 50) / 100;
if (e->caller == node
|| (e->caller->global.inlined_to
&& e->caller->global.inlined_to == node))
self_recursive = true;
growth += estimate_edge_growth (e);
}
/* For self recursive functions the growth estimation really should be
infinity. We don't want to return very large values because the growth
plays various roles in badness computation fractions. Be sure to not
return zero or negative growths. */
if (self_recursive)
growth = growth < info->size ? info->size : growth;
else
{
if (cgraph_will_be_removed_from_program_if_no_direct_calls (node)
&& !DECL_EXTERNAL (node->decl))
growth -= info->size;
/* COMDAT functions are very often not shared across multiple units since they
come from various template instantiations. Take this into account. */
else if (DECL_COMDAT (node->decl)
&& cgraph_can_remove_if_no_direct_calls_p (node))
growth -= (info->size
* (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY)) + 50) / 100;
}
info->estimated_growth = growth;
return growth;
@ -621,7 +637,6 @@ inline_read_summary (void)
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,
@ -688,7 +703,6 @@ inline_write_summary (cgraph_node_set set,
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);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -41,8 +41,6 @@ struct inline_summary
/* 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

View File

@ -1,3 +1,7 @@
2011-04-17 Jan Hubicka <jh@suse.cz>
* gcc.dg/winline-5.c: Update testcase.
2011-04-17 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/discr27.ad[sb]: Move dg directive.

View File

@ -15,15 +15,7 @@ inline int q(void) /* { dg-warning "inline-unit-growth" } */
big();
big();
}
inline int q1(void)
{
big();
big();
big();
}
int t (void)
{
/* We allow one inlining over limit. */
q1();
return q (); /* { dg-warning "called from here" } */
}

View File

@ -3138,29 +3138,6 @@ inline_forbidden_p (tree fndecl)
return forbidden_p;
}
/* Return true if CALLEE cannot be inlined into CALLER. */
static bool
inline_forbidden_into_p (tree caller, tree callee)
{
/* Don't inline if the functions have different EH personalities. */
if (DECL_FUNCTION_PERSONALITY (caller)
&& DECL_FUNCTION_PERSONALITY (callee)
&& (DECL_FUNCTION_PERSONALITY (caller)
!= DECL_FUNCTION_PERSONALITY (callee)))
return true;
/* Don't inline if the callee can throw non-call exceptions but the
caller cannot. */
if (DECL_STRUCT_FUNCTION (callee)
&& DECL_STRUCT_FUNCTION (callee)->can_throw_non_call_exceptions
&& !(DECL_STRUCT_FUNCTION (caller)
&& DECL_STRUCT_FUNCTION (caller)->can_throw_non_call_exceptions))
return true;
return false;
}
/* Returns nonzero if FN is a function that does not have any
fundamental inline blocking properties. */
@ -3750,10 +3727,6 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
&& gimple_has_body_p (DECL_ABSTRACT_ORIGIN (fn)))
fn = DECL_ABSTRACT_ORIGIN (fn);
/* First check that inlining isn't simply forbidden in this case. */
if (inline_forbidden_into_p (cg_edge->caller->decl, cg_edge->callee->decl))
goto egress;
/* Don't try to inline functions that are not well-suited to inlining. */
if (!cgraph_inline_p (cg_edge, &reason))
{
@ -5298,75 +5271,3 @@ build_duplicate_type (tree type)
return type;
}
/* Return whether it is safe to inline a function because it used different
target specific options or call site actual types mismatch parameter types.
E is the call edge to be checked. */
bool
tree_can_inline_p (struct cgraph_edge *e)
{
#if 0
/* This causes a regression in SPEC in that it prevents a cold function from
inlining a hot function. Perhaps this should only apply to functions
that the user declares hot/cold/optimize explicitly. */
/* Don't inline a function with a higher optimization level than the
caller, or with different space constraints (hot/cold functions). */
tree caller_tree = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (caller);
tree callee_tree = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (callee);
if (caller_tree != callee_tree)
{
struct cl_optimization *caller_opt
= TREE_OPTIMIZATION ((caller_tree)
? caller_tree
: optimization_default_node);
struct cl_optimization *callee_opt
= TREE_OPTIMIZATION ((callee_tree)
? callee_tree
: optimization_default_node);
if ((caller_opt->optimize > callee_opt->optimize)
|| (caller_opt->optimize_size != callee_opt->optimize_size))
return false;
}
#endif
tree caller, callee;
caller = e->caller->decl;
callee = e->callee->decl;
/* First check that inlining isn't simply forbidden in this case. */
if (inline_forbidden_into_p (caller, callee))
{
e->inline_failed = CIF_UNSPECIFIED;
if (e->call_stmt)
gimple_call_set_cannot_inline (e->call_stmt, true);
return false;
}
/* Allow the backend to decide if inlining is ok. */
if (!targetm.target_option.can_inline_p (caller, callee))
{
e->inline_failed = CIF_TARGET_OPTION_MISMATCH;
if (e->call_stmt)
gimple_call_set_cannot_inline (e->call_stmt, true);
e->call_stmt_cannot_inline_p = true;
return false;
}
/* Do not inline calls where we cannot triviall work around mismatches
in argument or return types. */
if (e->call_stmt
&& !gimple_check_call_matching_types (e->call_stmt, callee))
{
e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
if (e->call_stmt)
gimple_call_set_cannot_inline (e->call_stmt, true);
e->call_stmt_cannot_inline_p = true;
return false;
}
return true;
}

View File

@ -182,7 +182,6 @@ int estimate_num_insns (gimple, eni_weights *);
int estimate_num_insns_fn (tree, eni_weights *);
int count_insns_seq (gimple_seq, eni_weights *);
bool tree_versionable_function_p (tree);
bool tree_can_inline_p (struct cgraph_edge *e);
extern tree remap_decl (tree decl, copy_body_data *id);
extern tree remap_type (tree type, copy_body_data *id);