Hi, as Michael pointed out, I introduced long lines primarily because of large indentation in cgraph_analyze_function. It makes the code to look better if the polymorphic call logic in broken out.
Bootstrapping/regtesting x86_64-linux, will commit it once testing conlcude. Honza * cgraphunit.c (walk_polymorphic_call_targets): Break out from... (cgraph_analyze_functions): ... here. Index: cgraphunit.c =================================================================== --- cgraphunit.c (revision 202199) +++ cgraphunit.c (working copy) @@ -821,7 +821,77 @@ 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 @@ 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); } }