Commit c4be6568 by Jan Hubicka Committed by Jan Hubicka

devirt-13.C: New testcase.



	* g++.dg/ipa/devirt-13.C: New testcase.
	* g++.dg/ipa/devirt-14.C: New testcase.
	* cgraphunit.c (analyze_functions): Do basic devirtualization;
	do not walk base classes of anonymous types.

From-SVN: r201942
parent 97aba8e9
2013-08-23 Jan Hubicka <jh@suse.cz>
* cgraphunit.c (analyze_functions): Do basic devirtualization;
do not walk base classes of anonymous types.
2013-08-23 Kaz Kojima <kkojima@gcc.gnu.org> 2013-08-23 Kaz Kojima <kkojima@gcc.gnu.org>
PR rtl-optimization/58220 PR rtl-optimization/58220
......
...@@ -922,26 +922,73 @@ analyze_functions (void) ...@@ -922,26 +922,73 @@ analyze_functions (void)
enqueue_node ((symtab_node)edge->callee); enqueue_node ((symtab_node)edge->callee);
if (optimize && flag_devirtualize) if (optimize && flag_devirtualize)
{ {
for (edge = cnode->indirect_calls; edge; edge = edge->next_callee) struct cgraph_edge *next;
if (edge->indirect_info->polymorphic) for (edge = cnode->indirect_calls; edge; edge = next)
{ {
unsigned int i; next = edge->next_callee;
void *cache_token; if (edge->indirect_info->polymorphic)
vec <cgraph_node *>targets {
= possible_polymorphic_call_targets unsigned int i;
(edge, NULL, &cache_token); void *cache_token;
bool final;
if (!pointer_set_insert (reachable_call_targets, vec <cgraph_node *>targets
cache_token)) = possible_polymorphic_call_targets
{ (edge, &final, &cache_token);
if (cgraph_dump_file)
dump_possible_polymorphic_call_targets if (!pointer_set_insert (reachable_call_targets,
(cgraph_dump_file, edge); cache_token))
{
for (i = 0; i < targets.length(); i++) if (cgraph_dump_file)
enqueue_node ((symtab_node) targets[i]); 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);
}
}
}
}
}
} }
/* If decl is a clone of an abstract function, /* If decl is a clone of an abstract function,
......
2013-08-23 Jan Hubicka <jh@suse.cz>
* g++.dg/ipa/devirt-13.C: New testcase.
* g++.dg/ipa/devirt-14.C: New testcase.
2013-08-23 Jakub Jelinek <jakub@redhat.com> 2013-08-23 Jakub Jelinek <jakub@redhat.com>
PR target/58218 PR target/58218
......
/* { dg-do run } */
/* Call to foo should be devirtualized because there are no derived types of A. */
/* { dg-options "-O2 -fdump-ipa-cgraph -fdump-tree-ssa" } */
namespace {
class A {
public:
virtual int foo(void)
{
return 0;
}
};
}
class A a, *b=&a;
main()
{
return b->foo();
}
/* { dg-final { scan-ipa-dump "Devirtualizing call" "cgraph" } } */
/* { dg-final { scan-tree-dump-times "OBJ_TYPE_REF" 0 "ssa"} } */
/* { dg-final { cleanup-ipa-dump "cgraph" } } */
/* { dg-final { cleanup-tree-dump "ssa" } } */
/* No devirtualization happens here, but A::foo should not end up as reachable
because the constructor of A is unreachable and therefore the virtual
method table referring to A::foo is optimized out. */
/* { dg-do run } */
/* { dg-options "-O2 -fdump-tree-ssa" } */
class B {
public:
virtual int foo(void)
{
return 0;
}
};
namespace {
class A : public B {
public:
virtual int foo(void)
{
return 1;
}
};
}
class B a, *b=&a;
main()
{
if (0)
{
class A a;
a.foo();
}
return b->foo();
}
/* { dg-final { scan-tree-dump-nop "A::foo" 0 "ssa"} } */
/* { dg-final { cleanup-tree-dump "ssa" } } */
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