cgraphunit.c (walk_polymorphic_call_targets): Break out from ...
* cgraphunit.c (walk_polymorphic_call_targets): Break out from ... (analyze_functions): ... here. From-SVN: r202299
This commit is contained in:
parent
d352b2459f
commit
e18412fc01
|
@ -1,3 +1,8 @@
|
|||
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
|
||||
|
|
136
gcc/cgraphunit.c
136
gcc/cgraphunit.c
|
@ -821,6 +821,76 @@ varpool_finalize_decl (tree decl)
|
|||
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
|
||||
them as well as all functions and variables referred by them */
|
||||
|
@ -923,71 +993,13 @@ analyze_functions (void)
|
|||
if (optimize && flag_devirtualize)
|
||||
{
|
||||
struct cgraph_edge *next;
|
||||
for (edge = cnode->indirect_calls; edge; edge = next)
|
||||
|
||||
for (edge = cnode->indirect_calls; edge; edge = next)
|
||||
{
|
||||
next = edge->next_callee;
|
||||
if (edge->indirect_info->polymorphic)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
walk_polymorphic_call_targets (reachable_call_targets,
|
||||
edge);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue