mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
8c944c97a2
commit
12485662c0
|
|
@ -1,3 +1,17 @@
|
|||
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>
|
||||
|
||||
* tree-vect-stmts.c (vectorizable_condition): Do not get
|
||||
|
|
|
|||
|
|
@ -3563,10 +3563,7 @@ public:
|
|||
virtual unsigned int execute (function *)
|
||||
{
|
||||
ipa_free_fn_summary ();
|
||||
/* Early optimizations may make function unreachable. We can not
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
59
gcc/ipa.c
59
gcc/ipa.c
|
|
@ -101,12 +101,32 @@ enqueue_node (symtab_node *node, symtab_node **first,
|
|||
*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. */
|
||||
|
||||
static void
|
||||
process_references (symtab_node *snode,
|
||||
symtab_node **first,
|
||||
bool before_inlining_p,
|
||||
hash_set<symtab_node *> *reachable)
|
||||
{
|
||||
int i;
|
||||
|
|
@ -118,14 +138,7 @@ process_references (symtab_node *snode,
|
|||
|
||||
if (node->definition && !node->in_other_partition
|
||||
&& ((!DECL_EXTERNAL (node->decl) || node->alias)
|
||||
|| (((before_inlining_p
|
||||
&& (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))))))
|
||||
|| (possible_inline_candidate_p (node)
|
||||
/* We use variable constructors during late compilation for
|
||||
constant folding. Keep references alive so partitioning
|
||||
knows about potential references. */
|
||||
|
|
@ -140,7 +153,7 @@ process_references (symtab_node *snode,
|
|||
body. */
|
||||
if (DECL_EXTERNAL (node->decl)
|
||||
&& node->alias
|
||||
&& before_inlining_p)
|
||||
&& symtab->state < IPA_SSA_AFTER_INLINING)
|
||||
reachable->add (body);
|
||||
reachable->add (node);
|
||||
}
|
||||
|
|
@ -160,8 +173,7 @@ static void
|
|||
walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
|
||||
struct cgraph_edge *edge,
|
||||
symtab_node **first,
|
||||
hash_set<symtab_node *> *reachable,
|
||||
bool before_inlining_p)
|
||||
hash_set<symtab_node *> *reachable)
|
||||
{
|
||||
unsigned int i;
|
||||
void *cache_token;
|
||||
|
|
@ -190,15 +202,14 @@ walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
|
|||
/* Prior inlining, keep alive bodies of possible targets for
|
||||
devirtualization. */
|
||||
if (n->definition
|
||||
&& (before_inlining_p
|
||||
&& opt_for_fn (body->decl, optimize)
|
||||
&& (possible_inline_candidate_p (body)
|
||||
&& opt_for_fn (body->decl, flag_devirtualize)))
|
||||
{
|
||||
/* Be sure that we will not optimize out alias target
|
||||
body. */
|
||||
if (DECL_EXTERNAL (n->decl)
|
||||
&& n->alias
|
||||
&& before_inlining_p)
|
||||
&& symtab->state < IPA_SSA_AFTER_INLINING)
|
||||
reachable->add (body);
|
||||
reachable->add (n);
|
||||
}
|
||||
|
|
@ -303,8 +314,6 @@ symbol_table::remove_unreachable_nodes (FILE *file)
|
|||
hash_set<symtab_node *> reachable;
|
||||
hash_set<tree> body_needed_for_clonning;
|
||||
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);
|
||||
build_type_inheritance_graph ();
|
||||
|
|
@ -396,7 +405,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
|
|||
enqueue_node (next, &first, &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))
|
||||
|
|
@ -416,8 +425,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
|
|||
next = e->next_callee;
|
||||
if (e->indirect_info->polymorphic)
|
||||
walk_polymorphic_call_targets (&reachable_call_targets,
|
||||
e, &first, &reachable,
|
||||
before_inlining_p);
|
||||
e, &first, &reachable);
|
||||
}
|
||||
}
|
||||
for (e = cnode->callees; e; e = e->next_callee)
|
||||
|
|
@ -428,18 +436,13 @@ symbol_table::remove_unreachable_nodes (FILE *file)
|
|||
&& (!e->inline_failed
|
||||
|| !DECL_EXTERNAL (e->callee->decl)
|
||||
|| e->callee->alias
|
||||
|| (before_inlining_p
|
||||
&& (opt_for_fn (body->decl, optimize)
|
||||
|| (symtab->state < IPA_SSA
|
||||
&& lookup_attribute
|
||||
("always_inline",
|
||||
DECL_ATTRIBUTES (body->decl)))))))
|
||||
|| possible_inline_candidate_p (e->callee)))
|
||||
{
|
||||
/* Be sure that we will not optimize out alias target
|
||||
body. */
|
||||
if (DECL_EXTERNAL (e->callee->decl)
|
||||
&& e->callee->alias
|
||||
&& before_inlining_p)
|
||||
&& symtab->state < IPA_SSA_AFTER_INLINING)
|
||||
reachable.add (body);
|
||||
reachable.add (e->callee);
|
||||
}
|
||||
|
|
@ -654,7 +657,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
|
|||
of possible later devirtualization. Do not mark them as
|
||||
local too early so we won't optimize them out before
|
||||
we are done with polymorphic call analysis. */
|
||||
&& (!before_inlining_p
|
||||
&& (symtab->state >= IPA_SSA_AFTER_INLINING
|
||||
|| !node->call_for_symbol_and_aliases
|
||||
(is_indirect_call_target_p, NULL, true)))
|
||||
{
|
||||
|
|
|
|||
35
gcc/passes.c
35
gcc/passes.c
|
|
@ -459,6 +459,35 @@ public:
|
|||
|
||||
}; // 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
|
||||
|
||||
simple_ipa_opt_pass *
|
||||
|
|
@ -473,6 +502,12 @@ make_pass_local_optimization_passes (gcc::context *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 {
|
||||
|
||||
const pass_data pass_data_all_early_optimizations =
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
NEXT_PASS (pass_local_fn_summary);
|
||||
POP_INSERT_PASSES ()
|
||||
|
||||
NEXT_PASS (pass_ipa_remove_symbols);
|
||||
NEXT_PASS (pass_ipa_oacc);
|
||||
PUSH_INSERT_PASSES_WITHIN (pass_ipa_oacc)
|
||||
NEXT_PASS (pass_ipa_pta);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
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>
|
||||
|
||||
PR tree-optimization/88074
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O3 -c -fdump-ipa-free-fnsummary1" } */
|
||||
/* { dg-options "-O3 -c -fdump-ipa-remove_symbols" } */
|
||||
static __attribute__((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" } } */
|
||||
|
|
|
|||
Loading…
Reference in New Issue