aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2013-09-06 01:06:10 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2013-09-05 23:06:10 +0000
commite18412fc019c907bcb59a07f58f55317dd9740a8 (patch)
treee5e3d8cfae6afc78d3c883a7b5b629c65e817437 /gcc
parentd352b2459fa6e4d5bc320af9912769ff3416a3d5 (diff)
downloadgcc-e18412fc019c907bcb59a07f58f55317dd9740a8.zip
gcc-e18412fc019c907bcb59a07f58f55317dd9740a8.tar.gz
gcc-e18412fc019c907bcb59a07f58f55317dd9740a8.tar.bz2
cgraphunit.c (walk_polymorphic_call_targets): Break out from ...
* cgraphunit.c (walk_polymorphic_call_targets): Break out from ... (analyze_functions): ... here. From-SVN: r202299
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/cgraphunit.c136
2 files changed, 79 insertions, 62 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dd93373..9e56b4a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,10 @@
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
* cgraphunit.c (analyze_functions): Clear AUX fields
after processing; initialize assembler name has.
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 125fb3b..08e0ff2 100644
--- a/gcc/cgraphunit.c
+++ b/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);
}
}