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?

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

Reply via email to