diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cgraph.h | 2 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 29 | ||||
-rw-r--r-- | gcc/ipa.c | 15 | ||||
-rw-r--r-- | gcc/lto-cgraph.c | 27 | ||||
-rw-r--r-- | gcc/varpool.c | 25 |
7 files changed, 103 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b924627..e7f0f71 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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> * rtl.h (union rtunion_def): Remove rt_bit member. diff --git a/gcc/cgraph.h b/gcc/cgraph.h index b092301..a9a2962 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -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 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. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5275eca..47f5308 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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> * cxx-pretty-print.c: Correct merge error. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 25c1175..2fd6305 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1808,6 +1808,7 @@ maybe_emit_vtables (tree ctype) 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. */ @@ -1865,8 +1866,20 @@ maybe_emit_vtables (tree ctype) 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); @@ -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))); 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)); @@ -334,6 +334,21 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file) 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); + } + } } } diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 8b0f8e1..f911c3a 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -565,12 +565,14 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, 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 (); @@ -602,6 +604,14 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node 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) { @@ -961,6 +971,7 @@ output_varpool (cgraph_node_set set, varpool_node_set vset) for (i = 0; i < len; i++) { lto_output_varpool_node (ob, lto_varpool_encoder_deref (varpool_encoder, i), + varpool_encoder, set, vset); } @@ -1081,6 +1092,7 @@ input_varpool_node (struct lto_file_decl_data *file_data, 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); @@ -1098,6 +1110,9 @@ input_varpool_node (struct lto_file_decl_data *file_data, 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); @@ -1291,6 +1306,8 @@ input_varpool_1 (struct lto_file_decl_data *file_data, { 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) @@ -1299,6 +1316,16 @@ input_varpool_1 (struct lto_file_decl_data *file_data, 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; } diff --git a/gcc/varpool.c b/gcc/varpool.c index 7185c85..73d39f3 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -194,6 +194,19 @@ varpool_remove_node (struct varpool_node *node) 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); @@ -416,8 +429,9 @@ varpool_analyze_pending_decls (void) 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; @@ -435,6 +449,13 @@ varpool_analyze_pending_decls (void) } 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); |