Commit e18412fc by Jan Hubicka Committed by Jan Hubicka

cgraphunit.c (walk_polymorphic_call_targets): Break out from ...

	* cgraphunit.c (walk_polymorphic_call_targets): Break out from ...
	(analyze_functions): ... here.

From-SVN: r202299
parent d352b245
2013-09-04 Jan Hubicka <jh@suse.cz> 2013-09-04 Jan Hubicka <jh@suse.cz>
* cgraphunit.c (walk_polymorphic_call_targets): Break out from ...
(analyze_functions): ... here.
2013-09-04 Jan Hubicka <jh@suse.cz>
PR middle-end/58201 PR middle-end/58201
* cgraphunit.c (analyze_functions): Clear AUX fields * cgraphunit.c (analyze_functions): Clear AUX fields
after processing; initialize assembler name has. after processing; initialize assembler name has.
......
...@@ -821,6 +821,76 @@ varpool_finalize_decl (tree decl) ...@@ -821,6 +821,76 @@ varpool_finalize_decl (tree decl)
varpool_assemble_decl (node); varpool_assemble_decl (node);
} }
/* EDGE is an polymorphic call. Mark all possible targets as reachable
and if there is only one target, perform trivial devirtualization.
REACHABLE_CALL_TARGETS collects target lists we already walked to
avoid udplicate work. */
static void
walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets,
struct cgraph_edge *edge)
{
unsigned int i;
void *cache_token;
bool final;
vec <cgraph_node *>targets
= possible_polymorphic_call_targets
(edge, &final, &cache_token);
if (!pointer_set_insert (reachable_call_targets,
cache_token))
{
if (cgraph_dump_file)
dump_possible_polymorphic_call_targets
(cgraph_dump_file, edge);
for (i = 0; i < targets.length(); i++)
{
/* Do not bother to mark virtual methods in anonymous namespace;
either we will find use of virtual table defining it, or it is
unused. */
if (targets[i]->symbol.definition
&& TREE_CODE
(TREE_TYPE (targets[i]->symbol.decl))
== METHOD_TYPE
&& !type_in_anonymous_namespace_p
(method_class_type
(TREE_TYPE (targets[i]->symbol.decl))))
enqueue_node ((symtab_node) targets[i]);
}
}
/* Very trivial devirtualization; when the type is
final or anonymous (so we know all its derivation)
and there is only one possible virtual call target,
make the edge direct. */
if (final)
{
gcc_assert (targets.length());
if (targets.length() == 1)
{
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file,
"Devirtualizing call: ");
print_gimple_stmt (cgraph_dump_file,
edge->call_stmt, 0,
TDF_SLIM);
}
cgraph_make_edge_direct (edge, targets[0]);
cgraph_redirect_edge_call_stmt_to_callee (edge);
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file,
"Devirtualized as: ");
print_gimple_stmt (cgraph_dump_file,
edge->call_stmt, 0,
TDF_SLIM);
}
}
}
}
/* Discover all functions and variables that are trivially needed, analyze /* Discover all functions and variables that are trivially needed, analyze
them as well as all functions and variables referred by them */ them as well as all functions and variables referred by them */
...@@ -923,71 +993,13 @@ analyze_functions (void) ...@@ -923,71 +993,13 @@ analyze_functions (void)
if (optimize && flag_devirtualize) if (optimize && flag_devirtualize)
{ {
struct cgraph_edge *next; struct cgraph_edge *next;
for (edge = cnode->indirect_calls; edge; edge = next)
for (edge = cnode->indirect_calls; edge; edge = next)
{ {
next = edge->next_callee; next = edge->next_callee;
if (edge->indirect_info->polymorphic) if (edge->indirect_info->polymorphic)
{ walk_polymorphic_call_targets (reachable_call_targets,
unsigned int i; edge);
void *cache_token;
bool final;
vec <cgraph_node *>targets
= possible_polymorphic_call_targets
(edge, &final, &cache_token);
if (!pointer_set_insert (reachable_call_targets,
cache_token))
{
if (cgraph_dump_file)
dump_possible_polymorphic_call_targets
(cgraph_dump_file, edge);
for (i = 0; i < targets.length(); i++)
{
/* Do not bother to mark virtual methods in anonymous namespace;
either we will find use of virtual table defining it, or it is
unused. */
if (targets[i]->symbol.definition
&& TREE_CODE
(TREE_TYPE (targets[i]->symbol.decl))
== METHOD_TYPE
&& !type_in_anonymous_namespace_p
(method_class_type
(TREE_TYPE (targets[i]->symbol.decl))))
enqueue_node ((symtab_node) targets[i]);
}
}
/* Very trivial devirtualization; when the type is
final or anonymous (so we know all its derivation)
and there is only one possible virtual call target,
make the edge direct. */
if (final)
{
gcc_assert (targets.length());
if (targets.length() == 1)
{
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file,
"Devirtualizing call: ");
print_gimple_stmt (cgraph_dump_file,
edge->call_stmt, 0,
TDF_SLIM);
}
cgraph_make_edge_direct (edge, targets[0]);
cgraph_redirect_edge_call_stmt_to_callee (edge);
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file,
"Devirtualized as: ");
print_gimple_stmt (cgraph_dump_file,
edge->call_stmt, 0,
TDF_SLIM);
}
}
}
}
} }
} }
......
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