On Wed, 28 Sep 2011, Jan Hubicka wrote: > Hi, > this patch adds support for V2 plugin API (thanks, Cary) that adds > LDPR_PREVAILING_DEF_IRONLY_EXP. > The reoslution is like LDPR_PREVAILING_DEF_IRONLY but the symbol is exported > out of DSO. It is up to the compiler to optimize it out or keep it based on > the knowledge whether the symbol can be optimized out at all (i.e. most > COMDATs > can, other types can't). > > This solve quite few problems with building C++ APPS, see the PR log. > > I was originally wrong about gold implementation being buggy. The problem > turned > out to be subtle lto-symtab bug that was mostly latent because of the COMDAT > hack > we use. lto_symtab_resolve_symbols is supposed to honor plugin decision when > it is > available but it doesn't when resolution of very first entry in the list is > UNKNOWN. > This can happen because we add into symtab also declarations that are not in > varpool (i.e. they are neither defined or used by the object file), but they > are > used otherwise, i.e. referred from stuff used for debug info or TB > devirtualization. > > To ensure backward compatibility I am keeping the COMDAT hack in place. It > won't help > letting compiler know the plugin API version, since we decide on that at a > time > we output object files and thus we are not called from plugin. I suppose we > could > keep the hack in place for next release and remove it afterwards penalizing > builds > with old binutils? Or perhaps even in GCC 4.7 if GNU LD gets updated in time. > > Bootstrapped/regtested x86_64-linux, built Mozilla and lto-bootstrap in > progress. > OK if it passes?
Ok. Any idea when GNU ld will catch up? Thanks, Richard. > Honza > > PR lto/47247 > * lto-plugin.c (get_symbols_v2): New variable. > (write_resolution): Use V2 API when available. > (onload): Handle LDPT_GET_SYMBOLS_V2. > > * lto-symtab.c (lto_symtab_resolve_symbols): Do not resolve > when resolution is already availbale from plugin. > (lto_symtab_merge_decls_1): Handle LDPR_PREVAILING_DEF_IRONLY_EXP. > * cgraph.c (ld_plugin_symbol_resolution): Add prevailing_def_ironly_exp. > * lto-cgraph.c (LDPR_NUM_KNOWN): Update. > * ipa.c (varpool_externally_visible_p): IRONLY variables are never > externally visible. > * varasm.c (resolution_to_local_definition_p): Add > LDPR_PREVAILING_DEF_IRONLY_EXP. > (resolution_local_p): Likewise. > > * common.c (lto_resolution_str): Add new resolution. > * common.h (lto_resolution_str): Likewise. > Index: lto-plugin/lto-plugin.c > =================================================================== > *** lto-plugin/lto-plugin.c (revision 179274) > --- lto-plugin/lto-plugin.c (working copy) > *************** enum symbol_style > *** 129,135 **** > static char *arguments_file_name; > static ld_plugin_register_claim_file register_claim_file; > static ld_plugin_register_all_symbols_read register_all_symbols_read; > ! static ld_plugin_get_symbols get_symbols; > static ld_plugin_register_cleanup register_cleanup; > static ld_plugin_add_input_file add_input_file; > static ld_plugin_add_input_library add_input_library; > --- 129,135 ---- > static char *arguments_file_name; > static ld_plugin_register_claim_file register_claim_file; > static ld_plugin_register_all_symbols_read register_all_symbols_read; > ! static ld_plugin_get_symbols get_symbols, get_symbols_v2; > static ld_plugin_register_cleanup register_cleanup; > static ld_plugin_add_input_file add_input_file; > static ld_plugin_add_input_library add_input_library; > *************** write_resolution (void) > *** 441,447 **** > struct plugin_symtab *symtab = &info->symtab; > struct ld_plugin_symbol *syms = symtab->syms; > > ! get_symbols (info->handle, symtab->nsyms, syms); > > finish_conflict_resolution (symtab, &info->conflicts); > > --- 441,452 ---- > struct plugin_symtab *symtab = &info->symtab; > struct ld_plugin_symbol *syms = symtab->syms; > > ! /* Version 2 of API supports IRONLY_EXP resolution that is > ! accepted by GCC-4.7 and newer. */ > ! if (get_symbols_v2) > ! get_symbols_v2 (info->handle, symtab->nsyms, syms); > ! else > ! get_symbols (info->handle, symtab->nsyms, syms); > > finish_conflict_resolution (symtab, &info->conflicts); > > *************** onload (struct ld_plugin_tv *tv) > *** 986,991 **** > --- 991,999 ---- > case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: > register_all_symbols_read = p->tv_u.tv_register_all_symbols_read; > break; > + case LDPT_GET_SYMBOLS_V2: > + get_symbols_v2 = p->tv_u.tv_get_symbols; > + break; > case LDPT_GET_SYMBOLS: > get_symbols = p->tv_u.tv_get_symbols; > break; > Index: gcc/lto-symtab.c > =================================================================== > *** gcc/lto-symtab.c (revision 179274) > --- gcc/lto-symtab.c (working copy) > *************** lto_symtab_resolve_symbols (void **slot) > *** 441,452 **** > e->node = cgraph_get_node (e->decl); > else if (TREE_CODE (e->decl) == VAR_DECL) > e->vnode = varpool_get_node (e->decl); > } > > - e = (lto_symtab_entry_t) *slot; > - > /* If the chain is already resolved there is nothing else to do. */ > ! if (e->resolution != LDPR_UNKNOWN) > return; > > /* Find the single non-replaceable prevailing symbol and > --- 444,457 ---- > e->node = cgraph_get_node (e->decl); > else if (TREE_CODE (e->decl) == VAR_DECL) > e->vnode = varpool_get_node (e->decl); > + if (e->resolution == LDPR_PREVAILING_DEF_IRONLY > + || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP > + || e->resolution == LDPR_PREVAILING_DEF) > + prevailing = e; > } > > /* If the chain is already resolved there is nothing else to do. */ > ! if (prevailing) > return; > > /* Find the single non-replaceable prevailing symbol and > *************** lto_symtab_merge_decls_1 (void **slot, v > *** 586,591 **** > --- 591,597 ---- > for (prevailing = (lto_symtab_entry_t) *slot; > prevailing > && prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY > + && prevailing->resolution != LDPR_PREVAILING_DEF_IRONLY_EXP > && prevailing->resolution != LDPR_PREVAILING_DEF; > prevailing = prevailing->next) > ; > *************** lto_symtab_merge_decls_1 (void **slot, v > *** 595,600 **** > --- 601,607 ---- > for (e = prevailing->next; e; e = e->next) > { > if (e->resolution == LDPR_PREVAILING_DEF_IRONLY > + || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP > || e->resolution == LDPR_PREVAILING_DEF) > fatal_error ("multiple prevailing defs for %qE", > DECL_NAME (prevailing->decl)); > *************** lto_symtab_merge_decls_1 (void **slot, v > *** 685,693 **** > to handle UNKNOWN relocation well. > > The problem with storing guessed decision is whether to use > ! PREVAILING_DEF or PREVAILING_DEF_IRONLY. First one would disable > ! some whole program optimizations, while ther second would imply > ! to many whole program assumptions. */ > if (prevailing->node && !flag_ltrans && !prevailing->guessed) > prevailing->node->resolution = prevailing->resolution; > else if (prevailing->vnode && !flag_ltrans && !prevailing->guessed) > --- 692,700 ---- > to handle UNKNOWN relocation well. > > The problem with storing guessed decision is whether to use > ! PREVAILING_DEF, PREVAILING_DEF_IRONLY, PREVAILING_DEF_IRONLY_EXP. > ! First one would disable some whole program optimizations, while > ! ther second would imply to many whole program assumptions. */ > if (prevailing->node && !flag_ltrans && !prevailing->guessed) > prevailing->node->resolution = prevailing->resolution; > else if (prevailing->vnode && !flag_ltrans && !prevailing->guessed) > Index: gcc/cgraph.c > =================================================================== > *** gcc/cgraph.c (revision 179274) > --- gcc/cgraph.c (working copy) > *************** const char * const ld_plugin_symbol_reso > *** 110,116 **** > "preempted_ir", > "resolved_ir", > "resolved_exec", > ! "resolved_dyn" > }; > > static void cgraph_node_remove_callers (struct cgraph_node *node); > --- 110,117 ---- > "preempted_ir", > "resolved_ir", > "resolved_exec", > ! "resolved_dyn", > ! "prevailing_def_ironly_exp" > }; > > static void cgraph_node_remove_callers (struct cgraph_node *node); > Index: gcc/lto-cgraph.c > =================================================================== > *** gcc/lto-cgraph.c (revision 179274) > --- gcc/lto-cgraph.c (working copy) > *************** static void output_cgraph_opt_summary (c > *** 52,58 **** > static void input_cgraph_opt_summary (VEC (cgraph_node_ptr, heap) * nodes); > > /* Number of LDPR values known to GCC. */ > ! #define LDPR_NUM_KNOWN (LDPR_RESOLVED_DYN + 1) > > /* Cgraph streaming is organized as set of record whose type > is indicated by a tag. */ > --- 52,58 ---- > static void input_cgraph_opt_summary (VEC (cgraph_node_ptr, heap) * nodes); > > /* Number of LDPR values known to GCC. */ > ! #define LDPR_NUM_KNOWN (LDPR_PREVAILING_DEF_IRONLY_EXP + 1) > > /* Cgraph streaming is organized as set of record whose type > is indicated by a tag. */ > Index: gcc/ipa.c > =================================================================== > *** gcc/ipa.c (revision 179274) > --- gcc/ipa.c (working copy) > *************** varpool_externally_visible_p (struct var > *** 685,690 **** > --- 688,695 ---- > This is needed for i.e. references from asm statements. */ > if (varpool_used_from_object_file_p (vnode)) > return true; > + if (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, > Index: gcc/lto/common.c > =================================================================== > *** gcc/lto/common.c (revision 179274) > --- gcc/lto/common.c (working copy) > *************** const char *lto_visibility_str[4] __attr > *** 31,37 **** > "INTERNAL", "HIDDEN" > }; > > ! const char *lto_resolution_str[9] __attribute__ ((visibility ("hidden"))) = > { > "UNKNOWN", > "UNDEF", > --- 31,37 ---- > "INTERNAL", "HIDDEN" > }; > > ! const char *lto_resolution_str[10] __attribute__ ((visibility ("hidden"))) = > { > "UNKNOWN", > "UNDEF", > *************** const char *lto_resolution_str[9] __attr > *** 41,46 **** > "PREEMPTED_IR", > "RESOLVED_IR", > "RESOLVED_EXEC", > ! "RESOLVED_DYN" > }; > > --- 41,47 ---- > "PREEMPTED_IR", > "RESOLVED_IR", > "RESOLVED_EXEC", > ! "RESOLVED_DYN", > ! "PREVAILING_DEF_IRONLY_EXP", > }; > > Index: gcc/lto/common.h > =================================================================== > *** gcc/lto/common.h (revision 179274) > --- gcc/lto/common.h (working copy) > *************** along with GCC; see the file COPYING3. > *** 20,26 **** > > > > ! static const char *lto_resolution_str[9] = > { > "UNKNOWN", > "UNDEF", > --- 20,26 ---- > > > > ! static const char *lto_resolution_str[10] = > { > "UNKNOWN", > "UNDEF", > *************** static const char *lto_resolution_str[9] > *** 30,34 **** > "PREEMPTED_IR", > "RESOLVED_IR", > "RESOLVED_EXEC", > ! "RESOLVED_DYN" > }; > --- 30,35 ---- > "PREEMPTED_IR", > "RESOLVED_IR", > "RESOLVED_EXEC", > ! "RESOLVED_DYN", > ! "PREVAILING_DEF_IRONLY_EXP", > }; > Index: gcc/varasm.c > =================================================================== > *** gcc/varasm.c (revision 179274) > --- gcc/varasm.c (working copy) > *************** static bool > *** 6681,6686 **** > --- 6681,6687 ---- > resolution_to_local_definition_p (enum ld_plugin_symbol_resolution > resolution) > { > return (resolution == LDPR_PREVAILING_DEF > + || resolution == LDPR_PREVAILING_DEF_IRONLY_EXP > || resolution == LDPR_PREVAILING_DEF_IRONLY); > } > > *************** resolution_local_p (enum ld_plugin_symbo > *** 6692,6697 **** > --- 6693,6699 ---- > { > return (resolution == LDPR_PREVAILING_DEF > || resolution == LDPR_PREVAILING_DEF_IRONLY > + || resolution == LDPR_PREVAILING_DEF_IRONLY_EXP > || resolution == LDPR_PREEMPTED_REG > || resolution == LDPR_PREEMPTED_IR > || resolution == LDPR_RESOLVED_IR > > -- Richard Guenther <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer