Commit 12485662 by Jan Hubicka Committed by Jan Hubicka

re PR ipa/87706 (Inlined functions trigger invalid -Wmissing-profile warning)


	PR ipa/87706
	* ipa-fnsummary.c (pass_ipa_fnsummary): Do not remove functions
	* ipa.c (possible_inline_candidate_p): Break out from ..
	(process_references): ... here ; drop before_inlining_p;
	cleanup handling of alises.
	(walk_polymorphic_call_targets): Likewise.
	(symbol_table::remove_unreachable_nodes): Likewise.
	* passes.c (pass_data_ipa_remove_symbols): New structure.
	(pass_ipa_remove_symbols): New pass.
	(make_pass_ipa_remove_symbols): New functoin.
	* passes.def (pass_ipa_remove_symbols): Schedule after early passes.

From-SVN: r266315
parent 8c944c97
2018-11-20 Jan Hubicka <hubicka@ucw.cz>
PR ipa/87706
* ipa-fnsummary.c (pass_ipa_fnsummary): Do not remove functions
* ipa.c (possible_inline_candidate_p): Break out from ..
(process_references): ... here ; drop before_inlining_p;
cleanup handling of alises.
(walk_polymorphic_call_targets): Likewise.
(symbol_table::remove_unreachable_nodes): Likewise.
* passes.c (pass_data_ipa_remove_symbols): New structure.
(pass_ipa_remove_symbols): New pass.
(make_pass_ipa_remove_symbols): New functoin.
* passes.def (pass_ipa_remove_symbols): Schedule after early passes.
2018-11-20 Richard Biener <rguenther@suse.de> 2018-11-20 Richard Biener <rguenther@suse.de>
* tree-vect-stmts.c (vectorizable_condition): Do not get * tree-vect-stmts.c (vectorizable_condition): Do not get
...@@ -3563,10 +3563,7 @@ public: ...@@ -3563,10 +3563,7 @@ public:
virtual unsigned int execute (function *) virtual unsigned int execute (function *)
{ {
ipa_free_fn_summary (); ipa_free_fn_summary ();
/* Early optimizations may make function unreachable. We can not return 0;
remove unreachable functions as part of the early opts pass because
TODOs are run before subpasses. Do it here. */
return small_p ? TODO_remove_functions | TODO_dump_symtab : 0;
} }
private: private:
......
...@@ -101,12 +101,32 @@ enqueue_node (symtab_node *node, symtab_node **first, ...@@ -101,12 +101,32 @@ enqueue_node (symtab_node *node, symtab_node **first,
*first = node; *first = node;
} }
/* Return true if NODE may get inlined later.
This is used to keep DECL_EXTERNAL function bodies around long enough
so inliner can proces them. */
static bool
possible_inline_candidate_p (symtab_node *node)
{
if (symtab->state >= IPA_SSA_AFTER_INLINING)
return false;
cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
if (!cnode)
return false;
if (DECL_UNINLINABLE (cnode->decl))
return false;
if (opt_for_fn (cnode->decl, optimize))
return true;
if (symtab->state >= IPA_SSA)
return false;
return lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl));
}
/* Process references. */ /* Process references. */
static void static void
process_references (symtab_node *snode, process_references (symtab_node *snode,
symtab_node **first, symtab_node **first,
bool before_inlining_p,
hash_set<symtab_node *> *reachable) hash_set<symtab_node *> *reachable)
{ {
int i; int i;
...@@ -118,14 +138,7 @@ process_references (symtab_node *snode, ...@@ -118,14 +138,7 @@ process_references (symtab_node *snode,
if (node->definition && !node->in_other_partition if (node->definition && !node->in_other_partition
&& ((!DECL_EXTERNAL (node->decl) || node->alias) && ((!DECL_EXTERNAL (node->decl) || node->alias)
|| (((before_inlining_p || (possible_inline_candidate_p (node)
&& (TREE_CODE (node->decl) != FUNCTION_DECL
|| (TREE_CODE (node->decl) == FUNCTION_DECL
&& opt_for_fn (body->decl, optimize))
|| (symtab->state < IPA_SSA
&& lookup_attribute
("always_inline",
DECL_ATTRIBUTES (body->decl))))))
/* We use variable constructors during late compilation for /* We use variable constructors during late compilation for
constant folding. Keep references alive so partitioning constant folding. Keep references alive so partitioning
knows about potential references. */ knows about potential references. */
...@@ -140,7 +153,7 @@ process_references (symtab_node *snode, ...@@ -140,7 +153,7 @@ process_references (symtab_node *snode,
body. */ body. */
if (DECL_EXTERNAL (node->decl) if (DECL_EXTERNAL (node->decl)
&& node->alias && node->alias
&& before_inlining_p) && symtab->state < IPA_SSA_AFTER_INLINING)
reachable->add (body); reachable->add (body);
reachable->add (node); reachable->add (node);
} }
...@@ -160,8 +173,7 @@ static void ...@@ -160,8 +173,7 @@ static void
walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets, walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
struct cgraph_edge *edge, struct cgraph_edge *edge,
symtab_node **first, symtab_node **first,
hash_set<symtab_node *> *reachable, hash_set<symtab_node *> *reachable)
bool before_inlining_p)
{ {
unsigned int i; unsigned int i;
void *cache_token; void *cache_token;
...@@ -190,15 +202,14 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets, ...@@ -190,15 +202,14 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
/* Prior inlining, keep alive bodies of possible targets for /* Prior inlining, keep alive bodies of possible targets for
devirtualization. */ devirtualization. */
if (n->definition if (n->definition
&& (before_inlining_p && (possible_inline_candidate_p (body)
&& opt_for_fn (body->decl, optimize)
&& opt_for_fn (body->decl, flag_devirtualize))) && opt_for_fn (body->decl, flag_devirtualize)))
{ {
/* Be sure that we will not optimize out alias target /* Be sure that we will not optimize out alias target
body. */ body. */
if (DECL_EXTERNAL (n->decl) if (DECL_EXTERNAL (n->decl)
&& n->alias && n->alias
&& before_inlining_p) && symtab->state < IPA_SSA_AFTER_INLINING)
reachable->add (body); reachable->add (body);
reachable->add (n); reachable->add (n);
} }
...@@ -303,8 +314,6 @@ symbol_table::remove_unreachable_nodes (FILE *file) ...@@ -303,8 +314,6 @@ symbol_table::remove_unreachable_nodes (FILE *file)
hash_set<symtab_node *> reachable; hash_set<symtab_node *> reachable;
hash_set<tree> body_needed_for_clonning; hash_set<tree> body_needed_for_clonning;
hash_set<void *> reachable_call_targets; hash_set<void *> reachable_call_targets;
bool before_inlining_p = symtab->state < (!optimize && !in_lto_p ? IPA_SSA
: IPA_SSA_AFTER_INLINING);
timevar_push (TV_IPA_UNREACHABLE); timevar_push (TV_IPA_UNREACHABLE);
build_type_inheritance_graph (); build_type_inheritance_graph ();
...@@ -396,7 +405,7 @@ symbol_table::remove_unreachable_nodes (FILE *file) ...@@ -396,7 +405,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
enqueue_node (next, &first, &reachable); enqueue_node (next, &first, &reachable);
} }
/* Mark references as reachable. */ /* Mark references as reachable. */
process_references (node, &first, before_inlining_p, &reachable); process_references (node, &first, &reachable);
} }
if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node)) if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
...@@ -416,8 +425,7 @@ symbol_table::remove_unreachable_nodes (FILE *file) ...@@ -416,8 +425,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
next = e->next_callee; next = e->next_callee;
if (e->indirect_info->polymorphic) if (e->indirect_info->polymorphic)
walk_polymorphic_call_targets (&reachable_call_targets, walk_polymorphic_call_targets (&reachable_call_targets,
e, &first, &reachable, e, &first, &reachable);
before_inlining_p);
} }
} }
for (e = cnode->callees; e; e = e->next_callee) for (e = cnode->callees; e; e = e->next_callee)
...@@ -428,18 +436,13 @@ symbol_table::remove_unreachable_nodes (FILE *file) ...@@ -428,18 +436,13 @@ symbol_table::remove_unreachable_nodes (FILE *file)
&& (!e->inline_failed && (!e->inline_failed
|| !DECL_EXTERNAL (e->callee->decl) || !DECL_EXTERNAL (e->callee->decl)
|| e->callee->alias || e->callee->alias
|| (before_inlining_p || possible_inline_candidate_p (e->callee)))
&& (opt_for_fn (body->decl, optimize)
|| (symtab->state < IPA_SSA
&& lookup_attribute
("always_inline",
DECL_ATTRIBUTES (body->decl)))))))
{ {
/* Be sure that we will not optimize out alias target /* Be sure that we will not optimize out alias target
body. */ body. */
if (DECL_EXTERNAL (e->callee->decl) if (DECL_EXTERNAL (e->callee->decl)
&& e->callee->alias && e->callee->alias
&& before_inlining_p) && symtab->state < IPA_SSA_AFTER_INLINING)
reachable.add (body); reachable.add (body);
reachable.add (e->callee); reachable.add (e->callee);
} }
...@@ -654,7 +657,7 @@ symbol_table::remove_unreachable_nodes (FILE *file) ...@@ -654,7 +657,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
of possible later devirtualization. Do not mark them as of possible later devirtualization. Do not mark them as
local too early so we won't optimize them out before local too early so we won't optimize them out before
we are done with polymorphic call analysis. */ we are done with polymorphic call analysis. */
&& (!before_inlining_p && (symtab->state >= IPA_SSA_AFTER_INLINING
|| !node->call_for_symbol_and_aliases || !node->call_for_symbol_and_aliases
(is_indirect_call_target_p, NULL, true))) (is_indirect_call_target_p, NULL, true)))
{ {
......
...@@ -459,6 +459,35 @@ public: ...@@ -459,6 +459,35 @@ public:
}; // class pass_local_optimization_passes }; // class pass_local_optimization_passes
const pass_data pass_data_ipa_remove_symbols =
{
SIMPLE_IPA_PASS, /* type */
"remove_symbols", /* name */
OPTGROUP_NONE, /* optinfo_flags */
TV_NONE, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_remove_functions | TODO_dump_symtab, /* todo_flags_finish */
};
class pass_ipa_remove_symbols : public simple_ipa_opt_pass
{
public:
pass_ipa_remove_symbols (gcc::context *ctxt)
: simple_ipa_opt_pass (pass_data_ipa_remove_symbols, ctxt)
{}
/* opt_pass methods: */
virtual bool gate (function *)
{
/* Don't bother doing anything if the program has errors. */
return (!seen_error () && !in_lto_p);
}
}; // class pass_local_optimization_passes
} // anon namespace } // anon namespace
simple_ipa_opt_pass * simple_ipa_opt_pass *
...@@ -473,6 +502,12 @@ make_pass_local_optimization_passes (gcc::context *ctxt) ...@@ -473,6 +502,12 @@ make_pass_local_optimization_passes (gcc::context *ctxt)
return new pass_local_optimization_passes (ctxt); return new pass_local_optimization_passes (ctxt);
} }
simple_ipa_opt_pass *
make_pass_ipa_remove_symbols (gcc::context *ctxt)
{
return new pass_ipa_remove_symbols (ctxt);
}
namespace { namespace {
const pass_data pass_data_all_early_optimizations = const pass_data pass_data_all_early_optimizations =
......
...@@ -106,6 +106,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -106,6 +106,7 @@ along with GCC; see the file COPYING3. If not see
NEXT_PASS (pass_local_fn_summary); NEXT_PASS (pass_local_fn_summary);
POP_INSERT_PASSES () POP_INSERT_PASSES ()
NEXT_PASS (pass_ipa_remove_symbols);
NEXT_PASS (pass_ipa_oacc); NEXT_PASS (pass_ipa_oacc);
PUSH_INSERT_PASSES_WITHIN (pass_ipa_oacc) PUSH_INSERT_PASSES_WITHIN (pass_ipa_oacc)
NEXT_PASS (pass_ipa_pta); NEXT_PASS (pass_ipa_pta);
......
2018-11-20 Jan Hubicka <hubicka@ucw.cz>
PR ipa/87706
* gcc.dg/ipa/ctor-empty-1.c: Update template.
2018-11-20 Richard Biener <rguenther@suse.de> 2018-11-20 Richard Biener <rguenther@suse.de>
PR tree-optimization/88074 PR tree-optimization/88074
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O3 -c -fdump-ipa-free-fnsummary1" } */ /* { dg-options "-O3 -c -fdump-ipa-remove_symbols" } */
static __attribute__((constructor)) static __attribute__((constructor))
void empty_constructor() void empty_constructor()
{ {
} }
/* { dg-final { scan-ipa-dump "Reclaiming functions: empty_constructor" "free-fnsummary1" } } */ /* { dg-final { scan-ipa-dump "Reclaiming functions: empty_constructor" "remove_symbols" } } */
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