diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 96b437fbcf4..3437a7c34d8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2014-07-08 Jan Hubicka + + * ipa-devirt.c (record_node): Walk through aliases. + 2014-07-08 Jan Hubicka * lto-streamer-out.c (hash_scc): Avoid quadratic hashing loop. diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 1601b6c3037..e7add12bc5b 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -860,7 +860,8 @@ maybe_record_node (vec &nodes, bool can_refer, bool *completep) { - struct cgraph_node *target_node; + struct cgraph_node *target_node, *alias_target; + enum availability avail; /* cxa_pure_virtual and __builtin_unreachable do not need to be added into list of targets; the runtime effect of calling them is undefined. @@ -884,6 +885,17 @@ maybe_record_node (vec &nodes, target_node = cgraph_get_node (target); + /* Preffer alias target over aliases, so we do not get confused by + fake duplicates. */ + if (target_node) + { + alias_target = cgraph_function_or_thunk_node (target_node, &avail); + if (target_node != alias_target + && avail >= AVAIL_AVAILABLE + && cgraph_function_body_availability (target_node)) + target_node = alias_target; + } + /* Method can only be called by polymorphic call if any of vtables refering to it are alive. @@ -910,7 +922,7 @@ maybe_record_node (vec &nodes, { gcc_assert (!target_node->global.inlined_to); gcc_assert (symtab_real_symbol_p (target_node)); - if (!pointer_set_insert (inserted, target)) + if (!pointer_set_insert (inserted, target_node->decl)) { pointer_set_insert (cached_polymorphic_call_targets, target_node);