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 <[email protected]>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer