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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159699
138bc75d-0d04-0410-961f-
82ee72b054a4
+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>
* rtl.h (union rtunion_def): Remove rt_bit member.
/* For normal nodes a pointer to the first extra name alias. For alias
nodes a pointer to the normal node. */
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;
PTR GTY ((skip)) aux;
/* Ordering of all cgraph nodes. */
+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>
* cxx-pretty-print.c: Correct merge error.
tree vtbl;
tree primary_vtbl;
int needed = 0;
+ struct varpool_node *current = NULL, *last = NULL, *first = NULL;
/* If the vtables for this class have already been emitted there is
nothing more to do. */
actually marking the variable as written. */
if (flag_syntax_only)
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
info. */
note_debug_info_needed (ctype);
cgraph_mark_address_taken_node (cgraph_node (BASELINK_FUNCTIONS (t)));
break;
case VAR_DECL:
- if (DECL_VTABLE_OR_VTT_P (t))
- {
- /* The ABI requires that all virtual tables be emitted
- 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 (DECL_CONTEXT (t)
+ && flag_use_repository
+ && TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL)
/* If we need a static variable in a function, then we
need the containing function. */
mark_decl_referenced (DECL_CONTEXT (t));
first_varpool = (struct varpool_node *)first_varpool->aux;
vnode->aux = NULL;
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);
+ }
+ }
}
}
static void
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)
{
bool boundary_p = !varpool_node_in_set_p (node, vset) && node->analyzed;
struct bitpack_d *bp;
struct varpool_node *alias;
int count = 0;
+ int ref;
lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl);
bp = bitpack_create ();
bp_pack_value (bp, count != 0, 1);
lto_output_bitpack (ob->main_stream, 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)
{
for (i = 0; i < len; i++)
{
lto_output_varpool_node (ob, lto_varpool_encoder_deref (varpool_encoder, i),
+ varpool_encoder,
set, vset);
}
struct bitpack_d *bp;
bool aliases_p;
int count;
+ int ref = LCC_NOT_FOUND;
decl_index = lto_input_uleb128 (ib);
var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index);
if (node->finalized)
varpool_mark_needed_node (node);
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)
{
count = lto_input_uleb128 (ib);
{
unsigned HOST_WIDE_INT len;
VEC(varpool_node_ptr, heap) *varpool = NULL;
+ int i;
+ struct varpool_node *node;
len = lto_input_uleb128 (ib);
while (len)
input_varpool_node (file_data, ib));
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;
}
gcc_assert (varpool_nodes_queue == node);
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_refering (&node->ref_list);
ggc_free (node);
timevar_push (TV_VARPOOL);
while (varpool_first_unanalyzed_node)
{
- tree decl = varpool_first_unanalyzed_node->decl;
- bool analyzed = varpool_first_unanalyzed_node->analyzed;
+ struct varpool_node *node = varpool_first_unanalyzed_node, *next;
+ tree decl = node->decl;
+ bool analyzed = node->analyzed;
varpool_first_unanalyzed_node->analyzed = true;
}
if (DECL_INITIAL (decl))
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;
}
timevar_pop (TV_VARPOOL);