From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32619 invoked by alias); 18 Jun 2011 08:32:57 -0000 Received: (qmail 32602 invoked by uid 22791); 18 Jun 2011 08:32:53 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from nikam.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 18 Jun 2011 08:32:35 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id 30A2B9AC786; Sat, 18 Jun 2011 10:32:33 +0200 (CEST) Date: Sat, 18 Jun 2011 09:11:00 -0000 From: Jan Hubicka To: gcc-patches@gcc.gnu.org Subject: varpool alias reorg Message-ID: <20110618083233.GA22220@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-06/txt/msg01381.txt.bz2 Hi, this patch makes symetric changes to varpool as did the prevoius series to cgraph. Basically the aliases are now represented as separate varpool nodes with alias reference to the variable they refer to, with some infrastructure to walk the alias references as needed. Bootstrapped/regtested x86_64-linux, comitted. Honza * lto-symtab.c (lto_varpool_replace_node): Remove code handling extra name aliases. (lto_symtab_resolve_can_prevail_p): Likewise. (lto_symtab_merge_cgraph_nodes): Update alias_of pointers. * cgraphbuild.c (record_reference): Remove extra body alias code. (mark_load): Likewise. (mark_store): Likewise. * cgraph.h (varpool_node): Remove extra_name filed; add alias_of and extraname_alias. (varpool_create_variable_alias, varpool_for_node_and_aliases): Declare. (varpool_alias_aliased_node): New inline function. (varpool_variable_node): New function. * cgraphunit.c (handle_alias_pairs): Handle also variable aliases. * ipa-ref.c (ipa_record_reference): Allow aliases on variables. * lto-cgraph.c (lto_output_varpool_node): Update streaming. (input_varpool_node): Likewise. * lto-streamer-out.c (produce_symtab): Remove extra name aliases. (varpool_externally_visible_p): Remove extra body alias code. (function_and_variable_visibility): Likewise. * tree-ssa-structalias.c (associate_varinfo_to_alias_1): New function. (ipa_pta_execute): Use it. * varpool.c (varpool_remove_node): Remove extra name alias code. (varpool_mark_needed_node): Likewise. (varpool_analyze_pending_decls): Analyze aliases. (assemble_aliases): New functoin. (varpool_assemble_decl): Use it. (varpool_create_variable_alias): New function. (varpool_extra_name_alias): Rewrite. (varpool_for_node_and_aliases): New function. Index: lto-symtab.c =================================================================== *** lto-symtab.c (revision 175079) --- lto-symtab.c (working copy) *************** lto_varpool_replace_node (struct varpool *** 268,299 **** gcc_assert (!vnode->analyzed || prevailing_node->analyzed); varpool_mark_needed_node (prevailing_node); } - /* Relink aliases. */ - if (vnode->extra_name && !vnode->alias) - { - struct varpool_node *alias, *last; - for (alias = vnode->extra_name; - alias; alias = alias->next) - { - last = alias; - alias->extra_name = prevailing_node; - } - - if (prevailing_node->extra_name) - { - last->next = prevailing_node->extra_name; - prevailing_node->extra_name->prev = last; - } - prevailing_node->extra_name = vnode->extra_name; - vnode->extra_name = NULL; - } gcc_assert (!vnode->finalized || prevailing_node->finalized); gcc_assert (!vnode->analyzed || prevailing_node->analyzed); - /* When replacing by an alias, the references goes to the original - variable. */ - if (prevailing_node->alias && prevailing_node->extra_name) - prevailing_node = prevailing_node->extra_name; ipa_clone_refering (NULL, prevailing_node, &vnode->ref_list); /* Be sure we can garbage collect the initializer. */ --- 268,276 ---- *************** lto_symtab_resolve_can_prevail_p (lto_sy *** 445,451 **** return false; if (e->vnode->finalized) return true; - return e->vnode->alias && e->vnode->extra_name->finalized; } gcc_unreachable (); *************** void *** 779,784 **** --- 755,761 ---- lto_symtab_merge_cgraph_nodes (void) { struct cgraph_node *node; + struct varpool_node *vnode; lto_symtab_maybe_init_hash_table (); htab_traverse (lto_symtab_identifiers, lto_symtab_merge_cgraph_nodes_1, NULL); *************** lto_symtab_merge_cgraph_nodes (void) *** 786,791 **** --- 763,771 ---- if ((node->thunk.thunk_p || node->alias) && node->thunk.alias) node->thunk.alias = lto_symtab_prevailing_decl (node->thunk.alias); + for (vnode = varpool_nodes; vnode; vnode = vnode->next) + if (vnode->alias_of) + vnode->alias_of = lto_symtab_prevailing_decl (vnode->alias_of); } /* Given the decl DECL, return the prevailing decl with the same name. */ Index: cgraphbuild.c =================================================================== *** cgraphbuild.c (revision 175079) --- cgraphbuild.c (working copy) *************** record_reference (tree *tp, int *walk_su *** 87,94 **** if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&decl, walk_subtrees); varpool_mark_needed_node (vnode); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; ipa_record_reference (NULL, ctx->varpool_node, NULL, vnode, IPA_REF_ADDR, NULL); --- 87,92 ---- *************** mark_address (gimple stmt, tree addr, vo *** 261,268 **** if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&addr, &walk_subtrees); varpool_mark_needed_node (vnode); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; ipa_record_reference ((struct cgraph_node *)data, NULL, NULL, vnode, IPA_REF_ADDR, stmt); --- 259,264 ---- *************** mark_load (gimple stmt, tree t, void *da *** 296,303 **** if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); varpool_mark_needed_node (vnode); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; ipa_record_reference ((struct cgraph_node *)data, NULL, NULL, vnode, IPA_REF_LOAD, stmt); --- 292,297 ---- *************** mark_store (gimple stmt, tree t, void *d *** 320,327 **** if (lang_hooks.callgraph.analyze_expr) lang_hooks.callgraph.analyze_expr (&t, &walk_subtrees); varpool_mark_needed_node (vnode); - if (vnode->alias && vnode->extra_name) - vnode = vnode->extra_name; ipa_record_reference ((struct cgraph_node *)data, NULL, NULL, vnode, IPA_REF_STORE, stmt); --- 314,319 ---- Index: cgraph.h =================================================================== *** cgraph.h (revision 175079) --- cgraph.h (working copy) *************** DEF_VEC_ALLOC_P(cgraph_edge_p,heap); *** 380,392 **** struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node { tree decl; /* Pointer to the next function in varpool_nodes. */ struct varpool_node *next, *prev; /* Pointer to the next function in varpool_nodes_queue. */ struct varpool_node *next_needed, *prev_needed; - /* 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; --- 380,391 ---- struct GTY((chain_next ("%h.next"), chain_prev ("%h.prev"))) varpool_node { tree decl; + /* For aliases points to declaration DECL is alias of. */ + tree alias_of; /* Pointer to the next function in varpool_nodes. */ struct varpool_node *next, *prev; /* Pointer to the next function in varpool_nodes_queue. */ struct varpool_node *next_needed, *prev_needed; /* 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 GTY((chain_next ("%h.next"), chai *** 415,420 **** --- 414,420 ---- /* Set for aliases once they got through assemble_alias. Also set for extra name aliases in varpool_extra_name_alias. */ unsigned alias : 1; + unsigned extra_name_alias : 1; /* Set when variable is used from other LTRANS partition. */ unsigned used_from_other_partition : 1; /* Set when variable is available in the other LTRANS partition. *************** bool varpool_analyze_pending_decls (void *** 665,673 **** --- 665,677 ---- void varpool_remove_unreferenced_decls (void); void varpool_empty_needed_queue (void); struct varpool_node * varpool_extra_name_alias (tree, tree); + struct varpool_node * varpool_create_variable_alias (tree, tree); const char * varpool_node_name (struct varpool_node *node); void varpool_reset_queue (void); bool const_value_known_p (tree); + bool varpool_for_node_and_aliases (struct varpool_node *, + bool (*) (struct varpool_node *, void *), + void *, bool); /* Walk all reachable static variables. */ #define FOR_EACH_STATIC_VARIABLE(node) \ *************** cgraph_alias_aliased_node (struct cgraph *** 968,973 **** --- 972,991 ---- return NULL; } + /* Return node that alias N is aliasing. */ + + static inline struct varpool_node * + varpool_alias_aliased_node (struct varpool_node *n) + { + struct ipa_ref *ref; + + ipa_ref_list_reference_iterate (&n->ref_list, 0, ref); + gcc_checking_assert (ref->use == IPA_REF_ALIAS); + if (ref->refered_type == IPA_REF_CGRAPH) + return ipa_ref_varpool_node (ref); + return NULL; + } + /* Given NODE, walk the alias chain to return the function NODE is alias of. Walk through thunk, too. When AVAILABILITY is non-NULL, get minimal availablity in the chain. */ *************** cgraph_function_or_thunk_node (struct cg *** 1020,1025 **** --- 1038,1071 ---- if (a < *availability) *availability = a; } + } + if (*availability) + *availability = AVAIL_NOT_AVAILABLE; + return NULL; + } + + /* Given NODE, walk the alias chain to return the function NODE is alias of. + Do not walk through thunks. + When AVAILABILITY is non-NULL, get minimal availablity in the chain. */ + + static inline struct varpool_node * + varpool_variable_node (struct varpool_node *node, enum availability *availability) + { + if (availability) + *availability = cgraph_variable_initializer_availability (node); + while (node) + { + if (node->alias && node->analyzed) + node = varpool_alias_aliased_node (node); + else + return node; + if (node && availability) + { + enum availability a; + a = cgraph_variable_initializer_availability (node); + if (a < *availability) + *availability = a; + } } if (*availability) *availability = AVAIL_NOT_AVAILABLE; Index: cgraphunit.c =================================================================== *** cgraphunit.c (revision 175079) --- cgraphunit.c (working copy) *************** handle_alias_pairs (void) *** 1186,1191 **** --- 1186,1192 ---- unsigned i; struct cgraph_node *target_node; struct cgraph_node *src_node; + struct varpool_node *target_vnode; for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p);) { *************** handle_alias_pairs (void) *** 1206,1211 **** --- 1207,1226 ---- cgraph_create_function_alias (p->decl, target_node->decl); VEC_unordered_remove (alias_pair, alias_pairs, i); } + else if (TREE_CODE (p->decl) == VAR_DECL + && !lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) + && (target_vnode = varpool_node_for_asm (p->target)) != NULL) + { + /* Normally EXTERNAL flag is used to mark external inlines, + however for aliases it seems to be allowed to use it w/o + any meaning. See gcc.dg/attr-alias-3.c + However for weakref we insist on EXTERNAL flag being set. + See gcc.dg/attr-alias-5.c */ + if (DECL_EXTERNAL (p->decl)) + DECL_EXTERNAL (p->decl) = 0; + varpool_create_variable_alias (p->decl, target_vnode->decl); + VEC_unordered_remove (alias_pair, alias_pairs, i); + } else { if (dump_file) Index: ipa-ref.c =================================================================== *** ipa-ref.c (revision 175079) --- ipa-ref.c (working copy) *************** ipa_record_reference (struct cgraph_node *** 68,74 **** { ref->refering.varpool_node = refering_varpool_node; ref->refering_type = IPA_REF_VARPOOL; ! gcc_assert (use_type == IPA_REF_ADDR); } if (refered_node) { --- 68,74 ---- { ref->refering.varpool_node = refering_varpool_node; ref->refering_type = IPA_REF_VARPOOL; ! gcc_assert (use_type == IPA_REF_ADDR || use_type == IPA_REF_ALIAS); } if (refered_node) { Index: lto-cgraph.c =================================================================== *** lto-cgraph.c (revision 175079) --- lto-cgraph.c (working copy) *************** lto_output_varpool_node (struct lto_simp *** 544,551 **** { 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); --- 544,549 ---- *************** lto_output_varpool_node (struct lto_simp *** 554,560 **** bp_pack_value (&bp, node->force_output, 1); bp_pack_value (&bp, node->finalized, 1); bp_pack_value (&bp, node->alias, 1); ! gcc_assert (!node->alias || !node->extra_name); gcc_assert (node->finalized || !node->analyzed); gcc_assert (node->needed); /* Constant pool initializers can be de-unified into individual ltrans units. --- 552,558 ---- bp_pack_value (&bp, node->force_output, 1); bp_pack_value (&bp, node->finalized, 1); bp_pack_value (&bp, node->alias, 1); ! bp_pack_value (&bp, node->alias_of != NULL, 1); gcc_assert (node->finalized || !node->analyzed); gcc_assert (node->needed); /* Constant pool initializers can be de-unified into individual ltrans units. *************** lto_output_varpool_node (struct lto_simp *** 573,583 **** set, vset), 1); bp_pack_value (&bp, boundary_p, 1); /* in_other_partition. */ } - /* Also emit any extra name aliases. */ - for (alias = node->extra_name; alias; alias = alias->next) - count++; - bp_pack_value (&bp, count != 0, 1); lto_output_bitpack (&bp); if (node->same_comdat_group && !boundary_p) { ref = lto_varpool_encoder_lookup (varpool_encoder, node->same_comdat_group); --- 571,579 ---- set, vset), 1); bp_pack_value (&bp, boundary_p, 1); /* in_other_partition. */ } lto_output_bitpack (&bp); + if (node->alias_of) + lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->alias_of); if (node->same_comdat_group && !boundary_p) { ref = lto_varpool_encoder_lookup (varpool_encoder, node->same_comdat_group); *************** lto_output_varpool_node (struct lto_simp *** 588,604 **** lto_output_sleb128_stream (ob->main_stream, ref); lto_output_enum (ob->main_stream, ld_plugin_symbol_resolution, LDPR_NUM_KNOWN, node->resolution); - - if (count) - { - lto_output_uleb128_stream (ob->main_stream, count); - for (alias = node->extra_name; alias; alias = alias->next) - { - lto_output_var_decl_index (ob->decl_state, ob->main_stream, alias->decl); - lto_output_enum (ob->main_stream, ld_plugin_symbol_resolution, - LDPR_NUM_KNOWN, alias->resolution); - } - } } /* Output the varpool NODE to OB. --- 584,589 ---- *************** input_varpool_node (struct lto_file_decl *** 1054,1062 **** tree var_decl; struct varpool_node *node; 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); --- 1039,1046 ---- tree var_decl; struct varpool_node *node; struct bitpack_d bp; int ref = LCC_NOT_FOUND; + bool non_null_aliasof; decl_index = lto_input_uleb128 (ib); var_decl = lto_file_decl_data_get_var_decl (file_data, decl_index); *************** input_varpool_node (struct lto_file_decl *** 1068,1073 **** --- 1052,1058 ---- node->force_output = bp_unpack_value (&bp, 1); node->finalized = bp_unpack_value (&bp, 1); node->alias = bp_unpack_value (&bp, 1); + non_null_aliasof = bp_unpack_value (&bp, 1); node->analyzed = node->finalized; node->used_from_other_partition = bp_unpack_value (&bp, 1); node->in_other_partition = bp_unpack_value (&bp, 1); *************** input_varpool_node (struct lto_file_decl *** 1076,1082 **** DECL_EXTERNAL (node->decl) = 1; TREE_STATIC (node->decl) = 0; } - aliases_p = bp_unpack_value (&bp, 1); if (node->finalized) varpool_mark_needed_node (node); ref = lto_input_sleb128 (ib); --- 1061,1066 ---- *************** input_varpool_node (struct lto_file_decl *** 1084,1101 **** node->same_comdat_group = (struct varpool_node *) (intptr_t) ref; node->resolution = lto_input_enum (ib, ld_plugin_symbol_resolution, LDPR_NUM_KNOWN); ! if (aliases_p) { ! count = lto_input_uleb128 (ib); ! for (; count > 0; count --) ! { ! tree decl = lto_file_decl_data_get_var_decl (file_data, ! lto_input_uleb128 (ib)); ! struct varpool_node *alias; ! alias = varpool_extra_name_alias (decl, var_decl); ! alias->resolution = lto_input_enum (ib, ld_plugin_symbol_resolution, ! LDPR_NUM_KNOWN); ! } } return node; } --- 1068,1078 ---- node->same_comdat_group = (struct varpool_node *) (intptr_t) ref; node->resolution = lto_input_enum (ib, ld_plugin_symbol_resolution, LDPR_NUM_KNOWN); ! ! if (non_null_aliasof) { ! decl_index = lto_input_uleb128 (ib); ! node->alias_of = lto_file_decl_data_get_var_decl (file_data, decl_index); } return node; } Index: lto-streamer-out.c =================================================================== *** lto-streamer-out.c (revision 175079) --- lto-streamer-out.c (working copy) *************** produce_symtab (struct output_block *ob, *** 2557,2563 **** char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL); struct pointer_set_t *seen; struct cgraph_node *node; ! struct varpool_node *vnode, *valias; struct lto_output_stream stream; lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder; lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder; --- 2557,2563 ---- char *section_name = lto_get_section_name (LTO_section_symtab, NULL, NULL); struct pointer_set_t *seen; struct cgraph_node *node; ! struct varpool_node *vnode; struct lto_output_stream stream; lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder; lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder; *************** produce_symtab (struct output_block *ob, *** 2617,2627 **** && vnode->finalized && DECL_VIRTUAL_P (vnode->decl)) continue; ! if (vnode->alias) continue; write_symbol (cache, &stream, vnode->decl, seen, false); - for (valias = vnode->extra_name; valias; valias = valias->next) - write_symbol (cache, &stream, valias->decl, seen, true); } for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++) { --- 2617,2625 ---- && vnode->finalized && DECL_VIRTUAL_P (vnode->decl)) continue; ! if (vnode->alias && !vnode->alias_of) continue; write_symbol (cache, &stream, vnode->decl, seen, false); } for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++) { *************** produce_symtab (struct output_block *ob, *** 2633,2643 **** && vnode->finalized && DECL_VIRTUAL_P (vnode->decl)) continue; ! if (vnode->alias) continue; write_symbol (cache, &stream, vnode->decl, seen, false); - for (valias = vnode->extra_name; valias; valias = valias->next) - write_symbol (cache, &stream, valias->decl, seen, true); } /* Write all aliases. */ --- 2631,2639 ---- && vnode->finalized && DECL_VIRTUAL_P (vnode->decl)) continue; ! if (vnode->alias && !vnode->alias_of) continue; write_symbol (cache, &stream, vnode->decl, seen, false); } /* Write all aliases. */ Index: ipa.c =================================================================== *** ipa.c (revision 175079) --- ipa.c (working copy) *************** cgraph_externally_visible_p (struct cgra *** 655,661 **** static bool varpool_externally_visible_p (struct varpool_node *vnode, bool aliased) { - struct varpool_node *alias; if (!DECL_COMDAT (vnode->decl) && !TREE_PUBLIC (vnode->decl)) return false; --- 648,653 ---- *************** varpool_externally_visible_p (struct var *** 694,704 **** This is needed for i.e. references from asm statements. */ if (varpool_used_from_object_file_p (vnode)) return true; - for (alias = vnode->extra_name; alias; alias = alias->next) - if (alias->resolution != LDPR_PREVAILING_DEF_IRONLY) - break; - if (!alias && vnode->resolution == LDPR_PREVAILING_DEF_IRONLY) - return false; /* As a special case, the COMDAT virutal tables can be unshared. In LTO mode turn vtables into static variables. The variable is readonly, --- 686,691 ---- *************** function_and_variable_visibility (bool w *** 782,794 **** { if (!node->analyzed) continue; ! /* Weakrefs alias symbols from other compilation unit. In the case ! the destination of weakref became available because of LTO, we must ! mark it as needed. */ ! if (in_lto_p ! && lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) ! && !node->needed) ! cgraph_mark_needed_node (node); gcc_assert (node->needed); pointer_set_insert (aliased_nodes, node); if (dump_file) --- 769,775 ---- { if (!node->analyzed) continue; ! cgraph_mark_needed_node (node); gcc_assert (node->needed); pointer_set_insert (aliased_nodes, node); if (dump_file) *************** function_and_variable_visibility (bool w *** 798,810 **** else if ((vnode = varpool_node_for_asm (p->target)) != NULL && !DECL_EXTERNAL (vnode->decl)) { ! /* Weakrefs alias symbols from other compilation unit. In the case ! the destination of weakref became available because of LTO, we must ! mark it as needed. */ ! if (in_lto_p ! && lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) ! && !vnode->needed) ! varpool_mark_needed_node (vnode); gcc_assert (vnode->needed); pointer_set_insert (aliased_vnodes, vnode); if (dump_file) --- 779,785 ---- else if ((vnode = varpool_node_for_asm (p->target)) != NULL && !DECL_EXTERNAL (vnode->decl)) { ! varpool_mark_needed_node (vnode); gcc_assert (vnode->needed); pointer_set_insert (aliased_vnodes, vnode); if (dump_file) Index: tree-ssa-structalias.c =================================================================== *** tree-ssa-structalias.c (revision 175079) --- tree-ssa-structalias.c (working copy) *************** associate_varinfo_to_alias (struct cgrap *** 6685,6690 **** --- 6685,6700 ---- return false; } + /* Associate node with varinfo DATA. Worker for + varpool_for_node_and_aliases. */ + static bool + associate_varinfo_to_alias_1 (struct varpool_node *node, void *data) + { + if (node->alias) + insert_vi_for_tree (node->decl, (varinfo_t)data); + return false; + } + /* Execute the driver for IPA PTA. */ static unsigned int ipa_pta_execute (void) *************** ipa_pta_execute (void) *** 6716,6729 **** /* Create constraints for global variables and their initializers. */ for (var = varpool_nodes; var; var = var->next) { - struct varpool_node *alias; varinfo_t vi; vi = get_vi_for_tree (var->decl); ! ! /* Associate the varinfo node with all aliases. */ ! for (alias = var->extra_name; alias; alias = alias->next) ! insert_vi_for_tree (alias->decl, vi); } if (dump_file) --- 6726,6737 ---- /* Create constraints for global variables and their initializers. */ for (var = varpool_nodes; var; var = var->next) { varinfo_t vi; + if (var->alias) + continue; vi = get_vi_for_tree (var->decl); ! varpool_for_node_and_aliases (var, associate_varinfo_to_alias_1, vi, true); } if (dump_file) Index: varpool.c =================================================================== *** varpool.c (revision 175079) --- varpool.c (working copy) *************** varpool_remove_node (struct varpool_node *** 162,186 **** gcc_assert (*slot == node); htab_clear_slot (varpool_hash, slot); gcc_assert (!varpool_assembled_nodes_queue); - if (!node->alias) - while (node->extra_name) - varpool_remove_node (node->extra_name); if (node->next) node->next->prev = node->prev; if (node->prev) node->prev->next = node->next; else { ! if (node->alias && node->extra_name) ! { ! gcc_assert (node->extra_name->extra_name == node); ! node->extra_name->extra_name = node->next; ! } ! else ! { ! gcc_assert (varpool_nodes == node); ! varpool_nodes = node->next; ! } } if (varpool_first_unanalyzed_node == node) varpool_first_unanalyzed_node = node->next_needed; --- 162,175 ---- gcc_assert (*slot == node); htab_clear_slot (varpool_hash, slot); gcc_assert (!varpool_assembled_nodes_queue); if (node->next) node->next->prev = node->prev; if (node->prev) node->prev->next = node->next; else { ! gcc_assert (varpool_nodes == node); ! varpool_nodes = node->next; } if (varpool_first_unanalyzed_node == node) varpool_first_unanalyzed_node = node->next_needed; *************** varpool_enqueue_needed_node (struct varp *** 311,318 **** void varpool_mark_needed_node (struct varpool_node *node) { - if (node->alias && node->extra_name) - node = node->extra_name; if (!node->needed && node->finalized && !TREE_ASM_WRITTEN (node->decl)) varpool_enqueue_needed_node (node); --- 300,305 ---- *************** varpool_analyze_pending_decls (void) *** 473,479 **** already informed about increased alignment. */ align_variable (decl, 0); } ! if (DECL_INITIAL (decl)) record_references_in_initializer (decl, analyzed); if (node->same_comdat_group) { --- 460,499 ---- already informed about increased alignment. */ align_variable (decl, 0); } ! if (node->alias && node->alias_of) ! { ! struct varpool_node *tgt = varpool_node (node->alias_of); ! if (!VEC_length (ipa_ref_t, node->ref_list.references)) ! ipa_record_reference (NULL, node, NULL, tgt, IPA_REF_ALIAS, NULL); ! /* C++ FE sometimes change linkage flags after producing same body aliases. */ ! if (node->extra_name_alias) ! { ! DECL_WEAK (node->decl) = DECL_WEAK (node->alias_of); ! TREE_PUBLIC (node->decl) = TREE_PUBLIC (node->alias_of); ! DECL_VISIBILITY (node->decl) = DECL_VISIBILITY (node->alias_of); ! if (TREE_PUBLIC (node->decl)) ! { ! DECL_COMDAT (node->decl) = DECL_COMDAT (node->alias_of); ! DECL_COMDAT_GROUP (node->decl) = DECL_COMDAT_GROUP (node->alias_of); ! if (DECL_ONE_ONLY (node->alias_of) && !node->same_comdat_group) ! { ! node->same_comdat_group = tgt; ! if (!tgt->same_comdat_group) ! tgt->same_comdat_group = node; ! else ! { ! struct varpool_node *n; ! for (n = tgt->same_comdat_group; ! n->same_comdat_group != tgt; ! n = n->same_comdat_group) ! ; ! n->same_comdat_group = node; ! } ! } ! } ! } ! } ! else if (DECL_INITIAL (decl)) record_references_in_initializer (decl, analyzed); if (node->same_comdat_group) { *************** varpool_analyze_pending_decls (void) *** 488,493 **** --- 508,530 ---- return changed; } + /* Assemble thunks and aliases asociated to NODE. */ + + static void + assemble_aliases (struct varpool_node *node) + { + int i; + struct ipa_ref *ref; + for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++) + if (ref->use == IPA_REF_ALIAS) + { + struct varpool_node *alias = ipa_ref_refering_varpool_node (ref); + assemble_alias (alias->decl, + DECL_ASSEMBLER_NAME (alias->alias_of)); + assemble_aliases (alias); + } + } + /* Output one variable, if necessary. Return whether we output it. */ bool varpool_assemble_decl (struct varpool_node *node) *************** varpool_assemble_decl (struct varpool_no *** 503,527 **** assemble_variable (decl, 0, 1, 0); if (TREE_ASM_WRITTEN (decl)) { - struct varpool_node *alias; - node->next_needed = varpool_assembled_nodes_queue; node->prev_needed = NULL; if (varpool_assembled_nodes_queue) varpool_assembled_nodes_queue->prev_needed = node; varpool_assembled_nodes_queue = node; node->finalized = 1; ! ! /* Also emit any extra name aliases. */ ! for (alias = node->extra_name; alias; alias = alias->next) ! { ! /* Update linkage fields in case they've changed. */ ! DECL_WEAK (alias->decl) = DECL_WEAK (decl); ! TREE_PUBLIC (alias->decl) = TREE_PUBLIC (decl); ! DECL_VISIBILITY (alias->decl) = DECL_VISIBILITY (decl); ! assemble_alias (alias->decl, DECL_ASSEMBLER_NAME (decl)); ! } ! return true; } } --- 540,552 ---- assemble_variable (decl, 0, 1, 0); if (TREE_ASM_WRITTEN (decl)) { node->next_needed = varpool_assembled_nodes_queue; node->prev_needed = NULL; if (varpool_assembled_nodes_queue) varpool_assembled_nodes_queue->prev_needed = node; varpool_assembled_nodes_queue = node; node->finalized = 1; ! assemble_aliases (node); return true; } } *************** add_new_static_var (tree type) *** 670,707 **** Extra name aliases are output whenever DECL is output. */ struct varpool_node * varpool_extra_name_alias (tree alias, tree decl) { ! struct varpool_node key, *alias_node, *decl_node, **slot; #ifndef ASM_OUTPUT_DEF /* If aliases aren't supported by the assembler, fail. */ return NULL; #endif ! gcc_assert (TREE_CODE (decl) == VAR_DECL); gcc_assert (TREE_CODE (alias) == VAR_DECL); ! /* Make sure the hash table has been created. */ ! decl_node = varpool_node (decl); ! ! key.decl = alias; ! ! slot = (struct varpool_node **) htab_find_slot (varpool_hash, &key, INSERT); ! ! /* If the varpool_node has been already created, fail. */ ! if (*slot) ! return NULL; ! ! alias_node = ggc_alloc_cleared_varpool_node (); ! alias_node->decl = alias; alias_node->alias = 1; ! alias_node->extra_name = decl_node; ! alias_node->next = decl_node->extra_name; ! ipa_empty_ref_list (&alias_node->ref_list); ! if (decl_node->extra_name) ! decl_node->extra_name->prev = alias_node; ! decl_node->extra_name = alias_node; ! *slot = alias_node; return alias_node; } --- 695,739 ---- Extra name aliases are output whenever DECL is output. */ struct varpool_node * + varpool_create_variable_alias (tree alias, tree decl) + { + struct varpool_node *alias_node; + + gcc_assert (TREE_CODE (decl) == VAR_DECL); + gcc_assert (TREE_CODE (alias) == VAR_DECL); + alias_node = varpool_node (alias); + alias_node->alias = 1; + alias_node->finalized = 1; + alias_node->alias_of = decl; + if (decide_is_variable_needed (alias_node, alias) + || alias_node->needed) + varpool_mark_needed_node (alias_node); + return alias_node; + } + + /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. + Extra name aliases are output whenever DECL is output. */ + + struct varpool_node * varpool_extra_name_alias (tree alias, tree decl) { ! struct varpool_node *alias_node; #ifndef ASM_OUTPUT_DEF /* If aliases aren't supported by the assembler, fail. */ return NULL; #endif ! alias_node = varpool_create_variable_alias (alias, decl); ! alias_node->extra_name_alias = true; gcc_assert (TREE_CODE (decl) == VAR_DECL); gcc_assert (TREE_CODE (alias) == VAR_DECL); ! alias_node = varpool_node (alias); alias_node->alias = 1; ! alias_node->finalized = 1; ! alias_node->alias_of = decl; ! if (decide_is_variable_needed (alias_node, alias) ! || alias_node->needed) ! varpool_mark_needed_node (alias_node); return alias_node; } *************** varpool_extra_name_alias (tree alias, tr *** 711,727 **** bool varpool_used_from_object_file_p (struct varpool_node *node) { - struct varpool_node *alias; - if (!TREE_PUBLIC (node->decl)) return false; if (resolution_used_from_other_file_p (node->resolution)) return true; - for (alias = node->extra_name; alias; alias = alias->next) - if (TREE_PUBLIC (alias->decl) - && resolution_used_from_other_file_p (alias->resolution)) - return true; return false; } #include "gt-varpool.h" --- 743,780 ---- bool varpool_used_from_object_file_p (struct varpool_node *node) { if (!TREE_PUBLIC (node->decl)) return false; if (resolution_used_from_other_file_p (node->resolution)) return true; return false; } + /* Call calback on NODE and aliases asociated to NODE. + When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are + skipped. */ + + bool + varpool_for_node_and_aliases (struct varpool_node *node, + bool (*callback) (struct varpool_node *, void *), + void *data, + bool include_overwritable) + { + int i; + struct ipa_ref *ref; + + if (callback (node, data)) + return true; + for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref); i++) + if (ref->use == IPA_REF_ALIAS) + { + struct varpool_node *alias = ipa_ref_refering_varpool_node (ref); + if (include_overwritable + || cgraph_variable_initializer_availability (alias) > AVAIL_OVERWRITABLE) + if (varpool_for_node_and_aliases (alias, callback, data, + include_overwritable)) + return true; + } + return false; + } #include "gt-varpool.h"