decl2.c (maybe_emit_vtables): Produce same comdat group when outputting comdat vtables.
* decl2.c (maybe_emit_vtables): Produce same comdat group when outputting comdat vtables. (cxx_callgraph_analyze_expr): Remove code marking vtables needed. * cgraph.h (struct varpool_node): Add same_comdat_group. * lto-cgrpah.c (lto_output_varpool_node): Output same_comdat_group pointer. (output_varpool): Update call of lto_output_varpool_node. (input_varpool): Read same_comdat_group pointer. (input_varpool_1): Fixup same_comdat_group pointer. * ipa.c (cgraph_remove_unreachable_nodes): WHen one of same comdat group is needed, all are. * varpool.c (varpool_remove_node): Remove node from same comdat group linklist too. (varpool_analyze_pending_decls): Walk same comdat groups. From-SVN: r159699
This commit is contained in:
parent
a2c9fe4253
commit
9f90e80a18
|
@ -1,3 +1,17 @@
|
||||||
|
2010-05-22 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
|
* cgraph.h (struct varpool_node): Add same_comdat_group.
|
||||||
|
* lto-cgrpah.c (lto_output_varpool_node): Output same_comdat_group
|
||||||
|
pointer.
|
||||||
|
(output_varpool): Update call of lto_output_varpool_node.
|
||||||
|
(input_varpool): Read same_comdat_group pointer.
|
||||||
|
(input_varpool_1): Fixup same_comdat_group pointer.
|
||||||
|
* ipa.c (cgraph_remove_unreachable_nodes): WHen one of same comdat
|
||||||
|
group is needed, all are.
|
||||||
|
* varpool.c (varpool_remove_node): Remove node from same comdat group
|
||||||
|
linklist too.
|
||||||
|
(varpool_analyze_pending_decls): Walk same comdat groups.
|
||||||
|
|
||||||
2010-05-22 Steven Bosscher <steven@gcc.gnu.org>
|
2010-05-22 Steven Bosscher <steven@gcc.gnu.org>
|
||||||
|
|
||||||
* rtl.h (union rtunion_def): Remove rt_bit member.
|
* rtl.h (union rtunion_def): Remove rt_bit member.
|
||||||
|
|
|
@ -457,6 +457,8 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node {
|
||||||
/* For normal nodes a pointer to the first extra name alias. For alias
|
/* For normal nodes a pointer to the first extra name alias. For alias
|
||||||
nodes a pointer to the normal node. */
|
nodes a pointer to the normal node. */
|
||||||
struct varpool_node *extra_name;
|
struct varpool_node *extra_name;
|
||||||
|
/* Circular list of nodes in the same comdat group if non-NULL. */
|
||||||
|
struct varpool_node *same_comdat_group;
|
||||||
struct ipa_ref_list ref_list;
|
struct ipa_ref_list ref_list;
|
||||||
PTR GTY ((skip)) aux;
|
PTR GTY ((skip)) aux;
|
||||||
/* Ordering of all cgraph nodes. */
|
/* Ordering of all cgraph nodes. */
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
2010-05-22 Jan Hubicka <jh@suse.cz>
|
||||||
|
|
||||||
|
* decl2.c (maybe_emit_vtables): Produce same comdat group when outputting
|
||||||
|
comdat vtables.
|
||||||
|
(cxx_callgraph_analyze_expr): Remove code marking vtables needed.
|
||||||
|
|
||||||
2010-05-21 Joseph Myers <joseph@codesourcery.com>
|
2010-05-21 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
* cxx-pretty-print.c: Correct merge error.
|
* cxx-pretty-print.c: Correct merge error.
|
||||||
|
|
|
@ -1808,6 +1808,7 @@ maybe_emit_vtables (tree ctype)
|
||||||
tree vtbl;
|
tree vtbl;
|
||||||
tree primary_vtbl;
|
tree primary_vtbl;
|
||||||
int needed = 0;
|
int needed = 0;
|
||||||
|
struct varpool_node *current = NULL, *last = NULL, *first = NULL;
|
||||||
|
|
||||||
/* If the vtables for this class have already been emitted there is
|
/* If the vtables for this class have already been emitted there is
|
||||||
nothing more to do. */
|
nothing more to do. */
|
||||||
|
@ -1865,8 +1866,20 @@ maybe_emit_vtables (tree ctype)
|
||||||
actually marking the variable as written. */
|
actually marking the variable as written. */
|
||||||
if (flag_syntax_only)
|
if (flag_syntax_only)
|
||||||
TREE_ASM_WRITTEN (vtbl) = 1;
|
TREE_ASM_WRITTEN (vtbl) = 1;
|
||||||
|
else if (DECL_COMDAT (vtbl))
|
||||||
|
{
|
||||||
|
current = varpool_node (vtbl);
|
||||||
|
if (last)
|
||||||
|
last->same_comdat_group = current;
|
||||||
|
last = current;
|
||||||
|
if (!first)
|
||||||
|
first = current;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (first != last)
|
||||||
|
last->same_comdat_group = first;
|
||||||
|
|
||||||
/* Since we're writing out the vtable here, also write the debug
|
/* Since we're writing out the vtable here, also write the debug
|
||||||
info. */
|
info. */
|
||||||
note_debug_info_needed (ctype);
|
note_debug_info_needed (ctype);
|
||||||
|
@ -3358,19 +3371,9 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED)
|
||||||
cgraph_mark_address_taken_node (cgraph_node (BASELINK_FUNCTIONS (t)));
|
cgraph_mark_address_taken_node (cgraph_node (BASELINK_FUNCTIONS (t)));
|
||||||
break;
|
break;
|
||||||
case VAR_DECL:
|
case VAR_DECL:
|
||||||
if (DECL_VTABLE_OR_VTT_P (t))
|
if (DECL_CONTEXT (t)
|
||||||
{
|
&& flag_use_repository
|
||||||
/* The ABI requires that all virtual tables be emitted
|
&& TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
|
||||||
whenever one of them is. */
|
|
||||||
tree vtbl;
|
|
||||||
for (vtbl = CLASSTYPE_VTABLES (DECL_CONTEXT (t));
|
|
||||||
vtbl;
|
|
||||||
vtbl = TREE_CHAIN (vtbl))
|
|
||||||
mark_decl_referenced (vtbl);
|
|
||||||
}
|
|
||||||
else if (DECL_CONTEXT (t)
|
|
||||||
&& flag_use_repository
|
|
||||||
&& TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
|
|
||||||
/* If we need a static variable in a function, then we
|
/* If we need a static variable in a function, then we
|
||||||
need the containing function. */
|
need the containing function. */
|
||||||
mark_decl_referenced (DECL_CONTEXT (t));
|
mark_decl_referenced (DECL_CONTEXT (t));
|
||||||
|
|
15
gcc/ipa.c
15
gcc/ipa.c
|
@ -334,6 +334,21 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
|
||||||
first_varpool = (struct varpool_node *)first_varpool->aux;
|
first_varpool = (struct varpool_node *)first_varpool->aux;
|
||||||
vnode->aux = NULL;
|
vnode->aux = NULL;
|
||||||
process_references (&vnode->ref_list, &first, &first_varpool, before_inlining_p);
|
process_references (&vnode->ref_list, &first, &first_varpool, before_inlining_p);
|
||||||
|
/* If any function in a comdat group is reachable, force
|
||||||
|
all other functions in the same comdat group to be
|
||||||
|
also reachable. */
|
||||||
|
if (vnode->same_comdat_group)
|
||||||
|
{
|
||||||
|
struct varpool_node *next;
|
||||||
|
for (next = vnode->same_comdat_group;
|
||||||
|
next != vnode;
|
||||||
|
next = next->same_comdat_group)
|
||||||
|
if (!next->needed)
|
||||||
|
{
|
||||||
|
varpool_mark_needed_node (next);
|
||||||
|
enqueue_varpool_node (next, &first_varpool);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -565,12 +565,14 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
|
lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node,
|
||||||
|
lto_varpool_encoder_t varpool_encoder,
|
||||||
cgraph_node_set set, varpool_node_set vset)
|
cgraph_node_set set, varpool_node_set vset)
|
||||||
{
|
{
|
||||||
bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed;
|
bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed;
|
||||||
struct bitpack_d *bp;
|
struct bitpack_d *bp;
|
||||||
struct varpool_node *alias;
|
struct varpool_node *alias;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
int ref;
|
||||||
|
|
||||||
lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
|
lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
|
||||||
bp = bitpack_create ();
|
bp = bitpack_create ();
|
||||||
|
@ -602,6 +604,14 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node
|
||||||
bp_pack_value (bp, count != 0, 1);
|
bp_pack_value (bp, count != 0, 1);
|
||||||
lto_output_bitpack (ob->main_stream, bp);
|
lto_output_bitpack (ob->main_stream, bp);
|
||||||
bitpack_delete (bp);
|
bitpack_delete (bp);
|
||||||
|
if (node->same_comdat_group && !boundary_p)
|
||||||
|
{
|
||||||
|
ref = lto_varpool_encoder_lookup (varpool_encoder, node->same_comdat_group);
|
||||||
|
gcc_assert (ref != LCC_NOT_FOUND);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ref = LCC_NOT_FOUND;
|
||||||
|
lto_output_sleb128_stream (ob->main_stream, ref);
|
||||||
|
|
||||||
if (count)
|
if (count)
|
||||||
{
|
{
|
||||||
|
@ -961,6 +971,7 @@ output_varpool (cgraph_node_set set, varpool_node_set vset)
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
lto_output_varpool_node (ob, lto_varpool_encoder_deref (varpool_encoder, i),
|
lto_output_varpool_node (ob, lto_varpool_encoder_deref (varpool_encoder, i),
|
||||||
|
varpool_encoder,
|
||||||
set, vset);
|
set, vset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1081,6 +1092,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
|
||||||
struct bitpack_d *bp;
|
struct bitpack_d *bp;
|
||||||
bool aliases_p;
|
bool aliases_p;
|
||||||
int count;
|
int count;
|
||||||
|
int ref = LCC_NOT_FOUND;
|
||||||
|
|
||||||
decl_index = lto_input_uleb128 (ib);
|
decl_index = lto_input_uleb128 (ib);
|
||||||
var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
|
var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
|
||||||
|
@ -1098,6 +1110,9 @@ input_varpool_node (struct lto_file_decl_data *file_data,
|
||||||
if (node->finalized)
|
if (node->finalized)
|
||||||
varpool_mark_needed_node (node);
|
varpool_mark_needed_node (node);
|
||||||
bitpack_delete (bp);
|
bitpack_delete (bp);
|
||||||
|
ref = lto_input_sleb128 (ib);
|
||||||
|
/* Store a reference for now, and fix up later to be a pointer. */
|
||||||
|
node->same_comdat_group = (struct varpool_node *) (intptr_t) ref;
|
||||||
if (aliases_p)
|
if (aliases_p)
|
||||||
{
|
{
|
||||||
count = lto_input_uleb128 (ib);
|
count = lto_input_uleb128 (ib);
|
||||||
|
@ -1291,6 +1306,8 @@ input_varpool_1 (struct lto_file_decl_data *file_data,
|
||||||
{
|
{
|
||||||
unsigned HOST_WIDE_INT len;
|
unsigned HOST_WIDE_INT len;
|
||||||
VEC(varpool_node_ptr, heap) *varpool = NULL;
|
VEC(varpool_node_ptr, heap) *varpool = NULL;
|
||||||
|
int i;
|
||||||
|
struct varpool_node *node;
|
||||||
|
|
||||||
len = lto_input_uleb128 (ib);
|
len = lto_input_uleb128 (ib);
|
||||||
while (len)
|
while (len)
|
||||||
|
@ -1299,6 +1316,16 @@ input_varpool_1 (struct lto_file_decl_data *file_data,
|
||||||
input_varpool_node (file_data, ib));
|
input_varpool_node (file_data, ib));
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
|
for (i = 0; VEC_iterate (varpool_node_ptr, varpool, i, node); i++)
|
||||||
|
{
|
||||||
|
int ref = (int) (intptr_t) node->same_comdat_group;
|
||||||
|
|
||||||
|
/* Fixup same_comdat_group from reference to pointer. */
|
||||||
|
if (ref != LCC_NOT_FOUND)
|
||||||
|
node->same_comdat_group = VEC_index (varpool_node_ptr, varpool, ref);
|
||||||
|
else
|
||||||
|
node->same_comdat_group = NULL;
|
||||||
|
}
|
||||||
return varpool;
|
return varpool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -194,6 +194,19 @@ varpool_remove_node (struct varpool_node *node)
|
||||||
gcc_assert (varpool_nodes_queue == node);
|
gcc_assert (varpool_nodes_queue == node);
|
||||||
varpool_nodes_queue = node->next_needed;
|
varpool_nodes_queue = node->next_needed;
|
||||||
}
|
}
|
||||||
|
if (node->same_comdat_group)
|
||||||
|
{
|
||||||
|
struct varpool_node *prev;
|
||||||
|
for (prev = node->same_comdat_group;
|
||||||
|
prev->same_comdat_group != node;
|
||||||
|
prev = prev->same_comdat_group)
|
||||||
|
;
|
||||||
|
if (node->same_comdat_group == prev)
|
||||||
|
prev->same_comdat_group = NULL;
|
||||||
|
else
|
||||||
|
prev->same_comdat_group = node->same_comdat_group;
|
||||||
|
node->same_comdat_group = NULL;
|
||||||
|
}
|
||||||
ipa_remove_all_references (&node->ref_list);
|
ipa_remove_all_references (&node->ref_list);
|
||||||
ipa_remove_all_refering (&node->ref_list);
|
ipa_remove_all_refering (&node->ref_list);
|
||||||
ggc_free (node);
|
ggc_free (node);
|
||||||
|
@ -416,8 +429,9 @@ varpool_analyze_pending_decls (void)
|
||||||
timevar_push (TV_VARPOOL);
|
timevar_push (TV_VARPOOL);
|
||||||
while (varpool_first_unanalyzed_node)
|
while (varpool_first_unanalyzed_node)
|
||||||
{
|
{
|
||||||
tree decl = varpool_first_unanalyzed_node->decl;
|
struct varpool_node *node = varpool_first_unanalyzed_node, *next;
|
||||||
bool analyzed = varpool_first_unanalyzed_node->analyzed;
|
tree decl = node->decl;
|
||||||
|
bool analyzed = node->analyzed;
|
||||||
|
|
||||||
varpool_first_unanalyzed_node->analyzed = true;
|
varpool_first_unanalyzed_node->analyzed = true;
|
||||||
|
|
||||||
|
@ -435,6 +449,13 @@ varpool_analyze_pending_decls (void)
|
||||||
}
|
}
|
||||||
if (DECL_INITIAL (decl))
|
if (DECL_INITIAL (decl))
|
||||||
record_references_in_initializer (decl, analyzed);
|
record_references_in_initializer (decl, analyzed);
|
||||||
|
if (node->same_comdat_group)
|
||||||
|
{
|
||||||
|
for (next = node->same_comdat_group;
|
||||||
|
next != node;
|
||||||
|
next = next->same_comdat_group)
|
||||||
|
varpool_mark_needed_node (next);
|
||||||
|
}
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
timevar_pop (TV_VARPOOL);
|
timevar_pop (TV_VARPOOL);
|
||||||
|
|
Loading…
Reference in New Issue