ipa-visibility.c (can_replace_by_local_alias_in_vtable): New function.

* ipa-visibility.c (can_replace_by_local_alias_in_vtable): New function.
	(update_vtable_references): New function.
	(function_and_variable_visibility): Rewrite also vtable initializers.
	* varpool.c (cgraph_variable_initializer_availability): Remove assert.

From-SVN: r210910
This commit is contained in:
Jan Hubicka 2014-05-25 07:52:49 +02:00 committed by Jan Hubicka
parent 05fc16dde9
commit 07990a5e8e
3 changed files with 65 additions and 1 deletions

View File

@ -1,3 +1,10 @@
2014-05-23 Jan Hubicka <hubicka@ucw.cz>
* ipa-visibility.c (can_replace_by_local_alias_in_vtable): New function.
(update_vtable_references): New function.
(function_and_variable_visibility): Rewrite also vtable initializers.
* varpool.c (cgraph_variable_initializer_availability): Remove assert.
2014-05-23 Jan Hubicka <hubicka@ucw.cz>
* ggc.h (ggc_grow): New function.

View File

@ -343,6 +343,36 @@ can_replace_by_local_alias (symtab_node *node)
&& !symtab_can_be_discarded (node));
}
/* Return true if we can replace refernece to NODE by local alias
within a virtual table. Generally we can replace function pointers
and virtual table pointers. */
bool
can_replace_by_local_alias_in_vtable (symtab_node *node)
{
if (is_a <varpool_node *> (node)
&& !DECL_VIRTUAL_P (node->decl))
return false;
return can_replace_by_local_alias (node);
}
/* walk_tree callback that rewrites initializer references. */
static tree
update_vtable_references (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
{
if (TREE_CODE (*tp) == VAR_DECL
|| TREE_CODE (*tp) == FUNCTION_DECL)
{
if (can_replace_by_local_alias_in_vtable (symtab_get_node (*tp)))
*tp = symtab_nonoverwritable_alias (symtab_get_node (*tp))->decl;
*walk_subtrees = 0;
}
else if (IS_TYPE_OR_DECL_P (*tp))
*walk_subtrees = 0;
return NULL;
}
/* In LTO we can remove COMDAT groups and weak symbols.
Either turn them into normal symbols or external symbol depending on
resolution info. */
@ -625,6 +655,34 @@ function_and_variable_visibility (bool whole_program)
vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
}
update_visibility_by_resolution_info (vnode);
/* Update virutal tables to point to local aliases where possible. */
if (DECL_VIRTUAL_P (vnode->decl)
&& !DECL_EXTERNAL (vnode->decl))
{
int i;
struct ipa_ref *ref;
bool found = false;
/* See if there is something to update. */
for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list,
i, ref); i++)
if (ref->use == IPA_REF_ADDR
&& can_replace_by_local_alias_in_vtable (ref->referred))
{
found = true;
break;
}
if (found)
{
struct pointer_set_t *visited_nodes = pointer_set_create ();
walk_tree (&DECL_INITIAL (vnode->decl),
update_vtable_references, NULL, visited_nodes);
pointer_set_destroy (visited_nodes);
ipa_remove_all_references (&vnode->ref_list);
record_references_in_initializer (vnode->decl, false);
}
}
}
if (dump_file)

View File

@ -355,7 +355,6 @@ varpool_add_new_variable (tree decl)
enum availability
cgraph_variable_initializer_availability (varpool_node *node)
{
gcc_assert (cgraph_function_flags_ready);
if (!node->definition)
return AVAIL_NOT_AVAILABLE;
if (!TREE_PUBLIC (node->decl))