diff mbox

Move DECL_SECTION_NAME into symtab

Message ID 20140609023437.GA10726@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka June 9, 2014, 2:34 a.m. UTC
Hi,
this patch follows the change to move DECL_COMDAT_GROUP by moving DECL_SECTION_NAME
into symtab nodes instead of keeping it in decl_with_vis. (I pla to proceed with
other symbol table related fields).

It follows exactly same path as the previous patch. Notable change is adding
of node removal into duplicate_decl in c-decl.c.

Memory usage wise the patch is small win for non-WPA, at WPA we actually
consume bit more memory (about 800K on Firefox).  We have more symtab nodes
than declarations because of inline clonning.  This will be solved by fixing
memory representation of symbol nodes (I plan to move rare items into on side
hashtables).  With accessors API it should be easy.

Bootstrapped/regtested x86_64-linux, slightly earlier version of patch was
tested also at PPC (linux/AIX)

Honza

	* symtab.c (dump_symtab_base): Update dumping.
	(symtab_make_decl_local): Clear only DECL_COMDAT.
	* tree-vect-data-refs.c (Check that variable is static before
	tampering with sections.
	* cgraphclones.c (duplicate_thunk_for_node): Do not clear section name.
	(cgraph_create_virtual_clone): Likewise.
	* tree.c (decl_comdat_group, decl_comdat_group_id): Constify argument.
	(decl_section_name, set_decl_section_name): New accessors.
	(find_decls_types_r): Do not walk section name
	* tree.h (DECL_SECTION_NAME): Implement using
	decl_section_name.
	(decl_comdat_group, decl_comdat_group_id): Constify.
	(decl_section_name, set_decl_section_name): Update.
	* varpool.c (varpool_finalize_named_section_flags): Use
	get_section.
	* cgraph.c (cgraph_add_thunk): Reset node instead of rebuilding.
	(cgraph_make_node_local_1): Clear section and comdat group.
	* cgraph.h (set_comdat_group): Sanity check.
	(get_section, set_section): New.
	* ipa-comdats.c (ipa_comdats): Use get_section.
	* ipa.c (ipa_discover_readonly_nonaddressable_var): Likewise.
	* lto-streamer-out.c: Do not follow section names.
	* c-family/c-common.c (handle_section_attribute):
	Update.
	* lto-cgraph.c (lto_output_node): Output section.
	(lto_output_varpool_node): Likewise.
	(read_comdat_group): Rename to ...
	(read_identifier): ... this one.
	(read_string_cst): New function.
	(input_node, input_varpool_node): Input section names.
	* tree-emutls.c (get_emutls_init_templ_addr): Update.
	(new_emutls_decl): Update.
	(secname_for_decl): Check section names only of static
	vars.
	* config/mep/mep.c (mep_unique_section): Use set_decl_section_name.
	* config/i386/winnt.c (i386_pe_unique_section): Likewise.
	* config/i386/i386.c (x86_64_elf_unique_section): Likewise.
	* config/c6x/c6x.c (c6x_elf_unique_section): Likewise.
	* config/rs6000/rs6000.c (rs6000_xcoff_unique_section): Likewise.
	* config/mcore/mcore.c (mcore_unique_section): Likewise.
	* config/mips/mips.c (mips16_build_function_stub): Likewise.
	* config/v850/v850.c (v850_insert_attributes): Likewise.
	* config/h8300/h8300.c: (h8300_handle_eightbit_data_attribute):
	Likewise.
	(h8300_handle_tiny_data_attribute): Likewise.
	* config/bfin/bfin.c (bfin_handle_l1_text_attribute): Likewise.
	(bfin_handle_l2_attribute): Likewise.

	* lto.c (mentions_vars_p_decl_with_vis, compare_tree_sccs_1,
	lto_fixup_prevailing_decls): Skip section names.

	* go/go-gcc.cc (global_variable_set_init): Use
	set_decl_section_name.
	* tree-streamer-in.c (lto_input_ts_decl_with_vis_tree_pointers): Do not read section name.

	* gcc-interface/utils.c (process_attributes): Use it.

	* c-decl.c (merge_decls): Use set_decl_section_name.
	(duplicate_decls): Remove node if it exists.

	* class.c (build_utf8_ref): Use set_decl_section_name.
	(emit_register_classes_in_jcr_section): Likewise.
	(emit_register_classes_in_jcr_section): Likewise.

	* method.c (use_thunk): Use set_decl_section_name.
	* optimize.c (maybe_clone_body): Use set_decl_section_name.
	* decl.c (duplicate_decls): Likewise.
	* vtable-class-hierarchy.c: Likewise.

Comments

Richard Biener June 10, 2014, 8:56 a.m. UTC | #1
On Mon, Jun 9, 2014 at 4:34 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
> Hi,
> this patch follows the change to move DECL_COMDAT_GROUP by moving DECL_SECTION_NAME
> into symtab nodes instead of keeping it in decl_with_vis. (I pla to proceed with
> other symbol table related fields).
>
> It follows exactly same path as the previous patch. Notable change is adding
> of node removal into duplicate_decl in c-decl.c.
>
> Memory usage wise the patch is small win for non-WPA, at WPA we actually
> consume bit more memory (about 800K on Firefox).  We have more symtab nodes
> than declarations because of inline clonning.  This will be solved by fixing
> memory representation of symbol nodes (I plan to move rare items into on side
> hashtables).  With accessors API it should be easy.

What I wondered about for some time is why 'clones' need to use the
same structs as their origins.  They share some bits with their origin
and they apply some changes.  Thus I think it would be nice to change
the inheritance of a symtab entry to sth like

  symbol - cgraph-node-base - cgraph-node
     |                                      \
     |                                       cgraph-clone
     varpool-node-base - varpool-node
                                 \
                                  varpool-clone (do we have those?)

Richard.

> Bootstrapped/regtested x86_64-linux, slightly earlier version of patch was
> tested also at PPC (linux/AIX)
>
> Honza
>
>         * symtab.c (dump_symtab_base): Update dumping.
>         (symtab_make_decl_local): Clear only DECL_COMDAT.
>         * tree-vect-data-refs.c (Check that variable is static before
>         tampering with sections.
>         * cgraphclones.c (duplicate_thunk_for_node): Do not clear section name.
>         (cgraph_create_virtual_clone): Likewise.
>         * tree.c (decl_comdat_group, decl_comdat_group_id): Constify argument.
>         (decl_section_name, set_decl_section_name): New accessors.
>         (find_decls_types_r): Do not walk section name
>         * tree.h (DECL_SECTION_NAME): Implement using
>         decl_section_name.
>         (decl_comdat_group, decl_comdat_group_id): Constify.
>         (decl_section_name, set_decl_section_name): Update.
>         * varpool.c (varpool_finalize_named_section_flags): Use
>         get_section.
>         * cgraph.c (cgraph_add_thunk): Reset node instead of rebuilding.
>         (cgraph_make_node_local_1): Clear section and comdat group.
>         * cgraph.h (set_comdat_group): Sanity check.
>         (get_section, set_section): New.
>         * ipa-comdats.c (ipa_comdats): Use get_section.
>         * ipa.c (ipa_discover_readonly_nonaddressable_var): Likewise.
>         * lto-streamer-out.c: Do not follow section names.
>         * c-family/c-common.c (handle_section_attribute):
>         Update.
>         * lto-cgraph.c (lto_output_node): Output section.
>         (lto_output_varpool_node): Likewise.
>         (read_comdat_group): Rename to ...
>         (read_identifier): ... this one.
>         (read_string_cst): New function.
>         (input_node, input_varpool_node): Input section names.
>         * tree-emutls.c (get_emutls_init_templ_addr): Update.
>         (new_emutls_decl): Update.
>         (secname_for_decl): Check section names only of static
>         vars.
>         * config/mep/mep.c (mep_unique_section): Use set_decl_section_name.
>         * config/i386/winnt.c (i386_pe_unique_section): Likewise.
>         * config/i386/i386.c (x86_64_elf_unique_section): Likewise.
>         * config/c6x/c6x.c (c6x_elf_unique_section): Likewise.
>         * config/rs6000/rs6000.c (rs6000_xcoff_unique_section): Likewise.
>         * config/mcore/mcore.c (mcore_unique_section): Likewise.
>         * config/mips/mips.c (mips16_build_function_stub): Likewise.
>         * config/v850/v850.c (v850_insert_attributes): Likewise.
>         * config/h8300/h8300.c: (h8300_handle_eightbit_data_attribute):
>         Likewise.
>         (h8300_handle_tiny_data_attribute): Likewise.
>         * config/bfin/bfin.c (bfin_handle_l1_text_attribute): Likewise.
>         (bfin_handle_l2_attribute): Likewise.
>
>         * lto.c (mentions_vars_p_decl_with_vis, compare_tree_sccs_1,
>         lto_fixup_prevailing_decls): Skip section names.
>
>         * go/go-gcc.cc (global_variable_set_init): Use
>         set_decl_section_name.
>         * tree-streamer-in.c (lto_input_ts_decl_with_vis_tree_pointers): Do not read section name.
>
>         * gcc-interface/utils.c (process_attributes): Use it.
>
>         * c-decl.c (merge_decls): Use set_decl_section_name.
>         (duplicate_decls): Remove node if it exists.
>
>         * class.c (build_utf8_ref): Use set_decl_section_name.
>         (emit_register_classes_in_jcr_section): Likewise.
>         (emit_register_classes_in_jcr_section): Likewise.
>
>         * method.c (use_thunk): Use set_decl_section_name.
>         * optimize.c (maybe_clone_body): Use set_decl_section_name.
>         * decl.c (duplicate_decls): Likewise.
>         * vtable-class-hierarchy.c: Likewise.
> Index: ipa-visibility.c
> ===================================================================
> --- ipa-visibility.c    (revision 211362)
> +++ ipa-visibility.c    (working copy)
> @@ -512,6 +512,7 @@ function_and_variable_visibility (bool w
>                      next = next->same_comdat_group)
>                 {
>                   next->set_comdat_group (NULL);
> +                 next->set_section (NULL);
>                   symtab_make_decl_local (next->decl);
>                   next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
>                                         || next->unique_name
> @@ -526,6 +527,8 @@ function_and_variable_visibility (bool w
>             }
>           if (TREE_PUBLIC (node->decl))
>             node->set_comdat_group (NULL);
> +         if (DECL_COMDAT (node->decl))
> +           node->set_section (NULL);
>           symtab_make_decl_local (node->decl);
>         }
>
> @@ -643,6 +646,7 @@ function_and_variable_visibility (bool w
>                      next = next->same_comdat_group)
>                 {
>                   next->set_comdat_group (NULL);
> +                 next->set_section (NULL);
>                   symtab_make_decl_local (next->decl);
>                   next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
>                                         || next->unique_name
> @@ -653,6 +657,8 @@ function_and_variable_visibility (bool w
>             }
>           if (TREE_PUBLIC (vnode->decl))
>             vnode->set_comdat_group (NULL);
> +         if (DECL_COMDAT (vnode->decl))
> +           vnode->set_section (NULL);
>           symtab_make_decl_local (vnode->decl);
>           vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
>         }
> Index: c-family/c-common.c
> ===================================================================
> --- c-family/c-common.c (revision 211362)
> +++ c-family/c-common.c (working copy)
> @@ -7442,7 +7442,7 @@ handle_section_attribute (tree *node, tr
>               *no_add_attrs = true;
>             }
>           else
> -           DECL_SECTION_NAME (decl) = TREE_VALUE (args);
> +           set_decl_section_name (decl, TREE_VALUE (args));
>         }
>        else
>         {
> Index: java/class.c
> ===================================================================
> --- java/class.c        (revision 211362)
> +++ java/class.c        (working copy)
> @@ -991,7 +991,7 @@ build_utf8_ref (tree name)
>                        | SECTION_MERGE | (SECTION_ENTSIZE & decl_size));
>           sprintf (buf, ".rodata.jutf8.%d", decl_size);
>           switch_to_section (get_section (buf, flags, NULL));
> -         DECL_SECTION_NAME (decl) = build_string (strlen (buf), buf);
> +         set_decl_section_name (decl, build_string (strlen (buf), buf));
>         }
>      }
>
> @@ -2805,8 +2805,6 @@ emit_register_classes_in_jcr_section (vo
>    cdecl = build_decl (UNKNOWN_LOCATION,
>                       VAR_DECL, get_identifier ("_Jv_JCR_SECTION_data"),
>                       class_array_type);
> -  DECL_SECTION_NAME (cdecl) = build_string (strlen (JCR_SECTION_NAME),
> -                                           JCR_SECTION_NAME);
>    DECL_ALIGN (cdecl) = POINTER_SIZE;
>    DECL_USER_ALIGN (cdecl) = 1;
>    DECL_INITIAL (cdecl) = build_constructor (class_array_type, init);
> @@ -2817,6 +2815,8 @@ emit_register_classes_in_jcr_section (vo
>    DECL_ARTIFICIAL (cdecl) = 1;
>    DECL_IGNORED_P (cdecl) = 1;
>    DECL_PRESERVE_P (cdecl) = 1;
> +  set_decl_section_name (cdecl, build_string (strlen (JCR_SECTION_NAME),
> +                                             JCR_SECTION_NAME));
>    pushdecl_top_level (cdecl);
>    relayout_decl (cdecl);
>    rest_of_decl_compilation (cdecl, 1, 0);
> Index: c/c-decl.c
> ===================================================================
> --- c/c-decl.c  (revision 211362)
> +++ c/c-decl.c  (working copy)
> @@ -2304,8 +2304,10 @@ merge_decls (tree newdecl, tree olddecl,
>          We want to issue an error if the sections conflict but that
>          must be done later in decl_attributes since we are called
>          before attributes are assigned.  */
> -      if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
> -       DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
> +      if ((DECL_EXTERNAL (olddecl) || TREE_PUBLIC (olddecl) || TREE_STATIC (olddecl))
> +         && DECL_SECTION_NAME (newdecl) == NULL_TREE
> +         && DECL_SECTION_NAME (olddecl))
> +       set_decl_section_name (newdecl, DECL_SECTION_NAME (olddecl));
>
>        /* Copy the assembler name.
>          Currently, it can only be defined in the prototype.  */
> @@ -2574,6 +2576,13 @@ duplicate_decls (tree newdecl, tree oldd
>    merge_decls (newdecl, olddecl, newtype, oldtype);
>
>    /* The NEWDECL will no longer be needed.  */
> +  if (TREE_CODE (newdecl) == FUNCTION_DECL
> +      || TREE_CODE (newdecl) == VAR_DECL)
> +    {
> +      struct symtab_node *snode = symtab_get_node (newdecl);
> +      if (snode)
> +       symtab_remove_node (snode);
> +    }
>    ggc_free (newdecl);
>    return true;
>  }
> Index: cgraph.c
> ===================================================================
> --- cgraph.c    (revision 211362)
> +++ cgraph.c    (working copy)
> @@ -641,14 +641,9 @@ cgraph_add_thunk (struct cgraph_node *de
>
>    node = cgraph_get_node (alias);
>    if (node)
> -    {
> -      gcc_assert (node->definition);
> -      gcc_assert (!node->alias);
> -      gcc_assert (!node->thunk.thunk_p);
> -      cgraph_remove_node (node);
> -    }
> -
> -  node = cgraph_create_node (alias);
> +    cgraph_reset_node (node);
> +  else
> +    node = cgraph_create_node (alias);
>    gcc_checking_assert (!virtual_offset
>                        || wi::eq_p (virtual_offset, virtual_value));
>    node->thunk.fixed_offset = fixed_offset;
> @@ -2264,6 +2259,8 @@ cgraph_make_node_local_1 (struct cgraph_
>      {
>        symtab_make_decl_local (node->decl);
>
> +      node->set_section (NULL);
> +      node->set_comdat_group (NULL);
>        node->externally_visible = false;
>        node->forced_by_abi = false;
>        node->local.local = true;
> Index: cgraph.h
> ===================================================================
> --- cgraph.h    (revision 211362)
> +++ cgraph.h    (working copy)
> @@ -157,9 +157,24 @@ public:
>    /* Set comdat group.  */
>    void set_comdat_group (tree group)
>      {
> +      gcc_checking_assert (!group || TREE_CODE (group) == IDENTIFIER_NODE
> +                          || DECL_P (group));
>        comdat_group_ = group;
>      }
>
> +  /* Return section.  */
> +  tree get_section ()
> +    {
> +      return section_;
> +    }
> +
> +  /* Set section.  */
> +  void set_section (tree section)
> +    {
> +      gcc_checking_assert (!section || TREE_CODE (section) == STRING_CST);
> +      section_ = section;
> +    }
> +
>    /* Vectors of referring and referenced entities.  */
>    struct ipa_ref_list ref_list;
>
> @@ -175,6 +190,9 @@ public:
>
>    /* Comdat group the symbol is in.  Can be private if GGC allowed that.  */
>    tree comdat_group_;
> +
> +  /* Section name. Again can be private, if allowed.  */
> +  tree section_;
>  };
>
>  enum availability
> Index: tree.c
> ===================================================================
> --- tree.c      (revision 211362)
> +++ tree.c      (working copy)
> @@ -608,7 +608,7 @@ decl_assembler_name (tree decl)
>     DECL is associated with.  This can be either an IDENTIFIER_NODE or a
>     decl, in which case its DECL_ASSEMBLER_NAME identifies the group.  */
>  tree
> -decl_comdat_group (tree node)
> +decl_comdat_group (const_tree node)
>  {
>    struct symtab_node *snode = symtab_get_node (node);
>    if (!snode)
> @@ -618,7 +618,7 @@ decl_comdat_group (tree node)
>
>  /* Likewise, but make sure it's been reduced to an IDENTIFIER_NODE.  */
>  tree
> -decl_comdat_group_id (tree node)
> +decl_comdat_group_id (const_tree node)
>  {
>    struct symtab_node *snode = symtab_get_node (node);
>    if (!snode)
> @@ -626,6 +626,37 @@ decl_comdat_group_id (tree node)
>    return snode->get_comdat_group_id ();
>  }
>
> +/* When the target supports named section, return its name as IDENTIFIER_NODE
> +   or NULL if it is in no section.  */
> +tree
> +decl_section_name (const_tree node)
> +{
> +  struct symtab_node *snode = symtab_get_node (node);
> +  if (!snode)
> +    return NULL;
> +  return snode->get_section ();
> +}
> +
> +/* Set section section name of NODE to VALUE (that is expected to
> +   be identifier node)  */
> +void
> +set_decl_section_name (tree node, tree value)
> +{
> +  struct symtab_node *snode;
> +
> +  if (value == NULL)
> +    {
> +      snode = symtab_get_node (node);
> +      if (!snode)
> +       return;
> +    }
> +  else if (TREE_CODE (node) == VAR_DECL)
> +    snode = varpool_node_for_decl (node);
> +  else
> +    snode = cgraph_get_create_node (node);
> +  snode->set_section (value);
> +}
> +
>  /* Compute the number of bytes occupied by a tree with code CODE.
>     This function cannot be used for nodes that have variable sizes,
>     including TREE_VEC, INTEGER_CST, STRING_CST, and CALL_EXPR.  */
> @@ -5264,10 +5295,6 @@ find_decls_types_r (tree *tp, int *ws, v
>           fld_worklist_push (DECL_FIELD_BIT_OFFSET (t), fld);
>           fld_worklist_push (DECL_FCONTEXT (t), fld);
>         }
> -      else if (TREE_CODE (t) == VAR_DECL)
> -       {
> -         fld_worklist_push (DECL_SECTION_NAME (t), fld);
> -       }
>
>        if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
>           && DECL_HAS_VALUE_EXPR_P (t))
> Index: tree.h
> ===================================================================
> --- tree.h      (revision 211362)
> +++ tree.h      (working copy)
> @@ -2368,8 +2368,7 @@ extern void decl_value_expr_insert (tree
>
>  /* Records the section name in a section attribute.  Used to pass
>     the name from decl_attributes to make_function_rtl and make_decl_rtl.  */
> -#define DECL_SECTION_NAME(NODE) \
> -  (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.section_name)
> +#define DECL_SECTION_NAME(NODE) decl_section_name (NODE)
>
>  /* Nonzero in a decl means that the gimplifier has seen (or placed)
>     this variable in a BIND_EXPR.  */
> @@ -3431,8 +3430,10 @@ tree_operand_check_code (const_tree __t,
>     || ((NODE) && TREE_TYPE ((NODE)) == error_mark_node))
>
>  extern tree decl_assembler_name (tree);
> -extern tree decl_comdat_group (tree);
> -extern tree decl_comdat_group_id (tree);
> +extern tree decl_comdat_group (const_tree);
> +extern tree decl_comdat_group_id (const_tree);
> +extern tree decl_section_name (const_tree);
> +extern void set_decl_section_name (tree, tree);
>
>  /* Compute the number of bytes occupied by 'node'.  This routine only
>     looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH.  */
> Index: tree-emutls.c
> ===================================================================
> --- tree-emutls.c       (revision 211362)
> +++ tree-emutls.c       (working copy)
> @@ -245,7 +245,6 @@ get_emutls_init_templ_addr (tree decl)
>    TREE_READONLY (to) = 1;
>    DECL_IGNORED_P (to) = 1;
>    DECL_CONTEXT (to) = DECL_CONTEXT (decl);
> -  DECL_SECTION_NAME (to) = DECL_SECTION_NAME (decl);
>    DECL_PRESERVE_P (to) = DECL_PRESERVE_P (decl);
>
>    DECL_WEAK (to) = DECL_WEAK (decl);
> @@ -265,10 +264,13 @@ get_emutls_init_templ_addr (tree decl)
>
>    if (targetm.emutls.tmpl_section)
>      {
> -      DECL_SECTION_NAME (to)
> -        = build_string (strlen (targetm.emutls.tmpl_section),
> -                       targetm.emutls.tmpl_section);
> +      set_decl_section_name
> +       (to,
> +         build_string (strlen (targetm.emutls.tmpl_section),
> +                      targetm.emutls.tmpl_section));
>      }
> +  else
> +    set_decl_section_name (to, DECL_SECTION_NAME (decl));
>
>    /* Create varpool node for the new variable and finalize it if it is
>       not external one.  */
> @@ -323,9 +325,10 @@ new_emutls_decl (tree decl, tree alias_o
>    /* If the target wants the control variables grouped, do so.  */
>    if (!DECL_COMMON (to) && targetm.emutls.var_section)
>      {
> -      DECL_SECTION_NAME (to)
> -        = build_string (strlen (targetm.emutls.var_section),
> -                       targetm.emutls.var_section);
> +      set_decl_section_name
> +        (to,
> +         build_string (strlen (targetm.emutls.var_section),
> +                      targetm.emutls.var_section));
>      }
>
>    /* If this variable is defined locally, then we need to initialize the
> Index: cp/optimize.c
> ===================================================================
> --- cp/optimize.c       (revision 211362)
> +++ cp/optimize.c       (working copy)
> @@ -476,7 +476,6 @@ maybe_clone_body (tree fn)
>          to it. By doing so, it also corrupted the comdat group. */
>        if (DECL_ONE_ONLY (fn))
>         cgraph_get_create_node (clone)->set_comdat_group (cxx_comdat_group (clone));
> -      DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
>        DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
>        DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
>        DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
> @@ -487,6 +486,7 @@ maybe_clone_body (tree fn)
>        DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
>        DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
>        DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
> +      set_decl_section_name (clone, DECL_SECTION_NAME (fn));
>
>        /* Adjust the parameter names and locations.  */
>        parm = DECL_ARGUMENTS (fn);
> Index: cp/decl.c
> ===================================================================
> --- cp/decl.c   (revision 211362)
> +++ cp/decl.c   (working copy)
> @@ -2019,8 +2019,10 @@ duplicate_decls (tree newdecl, tree oldd
>          We want to issue an error if the sections conflict but that must be
>          done later in decl_attributes since we are called before attributes
>          are assigned.  */
> -      if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
> -       DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
> +      if ((DECL_EXTERNAL (olddecl) || TREE_PUBLIC (olddecl) || TREE_STATIC (olddecl))
> +         && DECL_SECTION_NAME (newdecl) == NULL_TREE
> +         && DECL_SECTION_NAME (olddecl) != NULL_TREE)
> +       set_decl_section_name (newdecl, DECL_SECTION_NAME (olddecl));
>
>        if (TREE_CODE (newdecl) == FUNCTION_DECL)
>         {
> Index: cp/method.c
> ===================================================================
> --- cp/method.c (revision 211362)
> +++ cp/method.c (working copy)
> @@ -363,7 +363,7 @@ use_thunk (tree thunk_fndecl, bool emit_
>           resolve_unique_section (thunk_fndecl, 0, flag_function_sections);
>
>           /* Output the thunk into the same section as function.  */
> -         DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function);
> +         set_decl_section_name (thunk_fndecl, DECL_SECTION_NAME (function));
>         }
>      }
>
> Index: cp/vtable-class-hierarchy.c
> ===================================================================
> --- cp/vtable-class-hierarchy.c (revision 211362)
> +++ cp/vtable-class-hierarchy.c (working copy)
> @@ -1247,8 +1247,8 @@ vtable_find_or_create_map_decl (tree bas
>        /* Put these mmap variables in thr .vtable_map_vars section, so
>           we can find and protect them.  */
>
> -      DECL_SECTION_NAME (var_decl) = build_string (strlen (".vtable_map_vars"),
> -                                                   ".vtable_map_vars");
> +      set_decl_section_name (var_decl, build_string (strlen (".vtable_map_vars"),
> +                                                     ".vtable_map_vars"));
>        DECL_HAS_IMPLICIT_SECTION_NAME_P (var_decl) = true;
>        DECL_INITIAL (var_decl) = initial_value;
>
> Index: lto-cgraph.c
> ===================================================================
> --- lto-cgraph.c        (revision 211362)
> +++ lto-cgraph.c        (working copy)
> @@ -396,6 +396,7 @@ lto_output_node (struct lto_simple_outpu
>    int i;
>    bool alias_p;
>    const char *comdat;
> +  const char *section;
>    tree group;
>
>    boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
> @@ -486,6 +487,7 @@ lto_output_node (struct lto_simple_outpu
>    else
>      comdat = "";
>    lto_output_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
> +
>    if (group)
>      {
>        if (node->same_comdat_group && !boundary_p)
> @@ -499,6 +501,13 @@ lto_output_node (struct lto_simple_outpu
>        streamer_write_hwi_stream (ob->main_stream, ref);
>      }
>
> +  group = node->get_section ();
> +  if (group)
> +    section = TREE_STRING_POINTER (group);
> +  else
> +    section = "";
> +  lto_output_data_stream (ob->main_stream, section, strlen (section) + 1);
> +
>    streamer_write_hwi_stream (ob->main_stream, node->tp_first_run);
>
>    bp = bitpack_create (ob->main_stream);
> @@ -563,6 +572,7 @@ lto_output_varpool_node (struct lto_simp
>    int ref;
>    bool alias_p;
>    const char *comdat;
> +  const char *section;
>    tree group;
>
>    streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
> @@ -600,12 +610,14 @@ lto_output_varpool_node (struct lto_simp
>           /* in_other_partition.  */
>      }
>    streamer_write_bitpack (&bp);
> +
>    group = node->get_comdat_group ();
>    if (group)
>      comdat = IDENTIFIER_POINTER (group);
>    else
>      comdat = "";
>    lto_output_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
> +
>    if (group)
>      {
>        if (node->same_comdat_group && !boundary_p)
> @@ -618,6 +630,14 @@ lto_output_varpool_node (struct lto_simp
>         ref = LCC_NOT_FOUND;
>        streamer_write_hwi_stream (ob->main_stream, ref);
>      }
> +
> +  group = node->get_section ();
> +  if (group)
> +    section = TREE_STRING_POINTER (group);
> +  else
> +    section = "";
> +  lto_output_data_stream (ob->main_stream, section, strlen (section) + 1);
> +
>    streamer_write_enum (ob->main_stream, ld_plugin_symbol_resolution,
>                        LDPR_NUM_KNOWN, node->resolution);
>  }
> @@ -968,13 +988,33 @@ output_symtab (void)
>    output_refs (encoder);
>  }
>
> -/* Return COMDAT_GROUP encoded in IB as a plain string.  */
> +/* Return identifier encoded in IB as a plain string.  */
>
>  static tree
> -read_comdat_group (struct lto_input_block *ib)
> +read_identifier (struct lto_input_block *ib)
>  {
>    unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1);
> -  tree group;
> +  tree id;
> +
> +  if (ib->data[ib->p + len])
> +    lto_section_overrun (ib);
> +  if (!len)
> +    {
> +      ib->p++;
> +      return NULL;
> +    }
> +  id = get_identifier (ib->data + ib->p);
> +  ib->p += len + 1;
> +  return id;
> +}
> +
> +/* Return identifier encoded in IB as a plain string.  */
> +
> +static tree
> +read_string_cst (struct lto_input_block *ib)
> +{
> +  unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1);
> +  tree id;
>
>    if (ib->data[ib->p + len])
>      lto_section_overrun (ib);
> @@ -983,9 +1023,9 @@ read_comdat_group (struct lto_input_bloc
>        ib->p++;
>        return NULL;
>      }
> -  group = get_identifier (ib->data + ib->p);
> +  id = build_string (len, ib->data + ib->p);
>    ib->p += len + 1;
> -  return group;
> +  return id;
>  }
>
>  /* Overwrite the information in NODE based on FILE_DATA, TAG, FLAGS,
> @@ -1077,6 +1117,7 @@ input_node (struct lto_file_decl_data *f
>    int order;
>    int i, count;
>    tree group;
> +  tree section;
>
>    order = streamer_read_hwi (ib) + order_base;
>    clone_ref = streamer_read_hwi (ib);
> @@ -1122,9 +1163,10 @@ input_node (struct lto_file_decl_data *f
>    if (tag == LTO_symtab_analyzed_node)
>      ref = streamer_read_hwi (ib);
>
> -  group = read_comdat_group (ib);
> +  group = read_identifier (ib);
>    if (group)
>      ref2 = streamer_read_hwi (ib);
> +  section = read_string_cst (ib);
>
>    /* Make sure that we have not read this node before.  Nodes that
>       have already been read will have their tag stored in the 'aux'
> @@ -1151,6 +1193,8 @@ input_node (struct lto_file_decl_data *f
>      }
>    else
>      node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
> +  if (section)
> +    node->set_section (section);
>
>    if (node->thunk.thunk_p)
>      {
> @@ -1183,6 +1227,7 @@ input_varpool_node (struct lto_file_decl
>    int ref = LCC_NOT_FOUND;
>    int order;
>    tree group;
> +  tree section;
>
>    order = streamer_read_hwi (ib) + order_base;
>    decl_index = streamer_read_uhwi (ib);
> @@ -1220,7 +1265,7 @@ input_varpool_node (struct lto_file_decl
>      }
>    if (node->alias && !node->analyzed && node->weakref)
>      node->alias_target = get_alias_symbol (node->decl);
> -  group = read_comdat_group (ib);
> +  group = read_identifier (ib);
>    if (group)
>      {
>        node->set_comdat_group (group);
> @@ -1230,6 +1275,9 @@ input_varpool_node (struct lto_file_decl
>      }
>    else
>      node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
> +  section = read_string_cst (ib);
> +  if (section)
> +    node->set_section (section);
>    node->resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
>                                                 LDPR_NUM_KNOWN);
>    gcc_assert (flag_ltrans
> Index: cgraphclones.c
> ===================================================================
> --- cgraphclones.c      (revision 211362)
> +++ cgraphclones.c      (working copy)
> @@ -340,7 +340,6 @@ duplicate_thunk_for_node (cgraph_node *t
>
>    DECL_NAME (new_decl) = clone_function_name (thunk->decl, "artificial_thunk");
>    SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
> -  DECL_SECTION_NAME (new_decl) = NULL;
>
>    new_thunk = cgraph_create_node (new_decl);
>    set_new_clone_decl_and_node_flags (new_thunk);
> @@ -557,8 +556,6 @@ cgraph_create_virtual_clone (struct cgra
>       that is not weak also.
>       ??? We cannot use COMDAT linkage because there is no
>       ABI support for this.  */
> -  if (old_node->get_comdat_group ())
> -    DECL_SECTION_NAME (new_node->decl) = NULL;
>    set_new_clone_decl_and_node_flags (new_node);
>    new_node->clone.tree_map = tree_map;
>    new_node->clone.args_to_skip = args_to_skip;
> Index: lto-streamer-out.c
> ===================================================================
> --- lto-streamer-out.c  (revision 211362)
> +++ lto-streamer-out.c  (working copy)
> @@ -535,7 +535,6 @@ DFS_write_tree_body (struct output_block
>        /* Make sure we don't inadvertently set the assembler name.  */
>        if (DECL_ASSEMBLER_NAME_SET_P (expr))
>         DFS_follow_tree_edge (DECL_ASSEMBLER_NAME (expr));
> -      DFS_follow_tree_edge (DECL_SECTION_NAME (expr));
>      }
>
>    if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
> @@ -973,7 +972,6 @@ hash_tree (struct streamer_tree_cache_d
>      {
>        if (DECL_ASSEMBLER_NAME_SET_P (t))
>         visit (DECL_ASSEMBLER_NAME (t));
> -      visit (DECL_SECTION_NAME (t));
>      }
>
>    if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
> Index: dwarf2out.c
> ===================================================================
> --- dwarf2out.c (revision 211362)
> +++ dwarf2out.c (working copy)
> @@ -13611,7 +13611,9 @@ secname_for_decl (const_tree decl)
>  {
>    const char *secname;
>
> -  if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_SECTION_NAME (decl))
> +  if (VAR_OR_FUNCTION_DECL_P (decl)
> +      && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl) || TREE_STATIC (decl))
> +      && DECL_SECTION_NAME (decl))
>      {
>        tree sectree = DECL_SECTION_NAME (decl);
>        secname = TREE_STRING_POINTER (sectree);
> Index: go/go-gcc.cc
> ===================================================================
> --- go/go-gcc.cc        (revision 211362)
> +++ go/go-gcc.cc        (working copy)
> @@ -2376,7 +2376,7 @@ Gcc_backend::global_variable_set_init(Bv
>    // a different one now that DECL_INITIAL is set.
>    if (DECL_HAS_IMPLICIT_SECTION_NAME_P (var_decl))
>      {
> -      DECL_SECTION_NAME (var_decl) = NULL_TREE;
> +      set_decl_section_name (var_decl, NULL);
>        resolve_unique_section (var_decl,
>                               compute_reloc_for_constant (expr_tree),
>                               1);
> Index: ada/gcc-interface/utils.c
> ===================================================================
> --- ada/gcc-interface/utils.c   (revision 211362)
> +++ ada/gcc-interface/utils.c   (working copy)
> @@ -2476,9 +2476,9 @@ process_attributes (tree *node, struct a
>        case ATTR_LINK_SECTION:
>         if (targetm_common.have_named_sections)
>           {
> -           DECL_SECTION_NAME (*node)
> -             = build_string (IDENTIFIER_LENGTH (attr->name),
> -                             IDENTIFIER_POINTER (attr->name));
> +           set_decl_section_name (*node,
> +                                  build_string (IDENTIFIER_LENGTH (attr->name),
> +                                                IDENTIFIER_POINTER (attr->name)));
>             DECL_COMMON (*node) = 0;
>           }
>         else
> Index: ipa.c
> ===================================================================
> --- ipa.c       (revision 211362)
> +++ ipa.c       (working copy)
> @@ -714,7 +714,7 @@ ipa_discover_readonly_nonaddressable_var
>             /* Making variable in explicit section readonly can cause section
>                type conflict.
>                See e.g. gcc.c-torture/compile/pr23237.c */
> -           && DECL_SECTION_NAME (vnode->decl) == NULL)
> +           && vnode->get_section () == NULL)
>           {
>             if (!TREE_READONLY (vnode->decl) && dump_file)
>               fprintf (dump_file, " %s (read-only)", vnode->name ());
> Index: tree-vect-data-refs.c
> ===================================================================
> --- tree-vect-data-refs.c       (revision 211362)
> +++ tree-vect-data-refs.c       (working copy)
> @@ -5213,7 +5213,8 @@ vect_can_force_dr_alignment_p (const_tre
>    /* Do not override explicit alignment set by the user when an explicit
>       section name is also used.  This is a common idiom used by many
>       software projects.  */
> -  if (DECL_SECTION_NAME (decl) != NULL_TREE
> +  if (TREE_STATIC (decl)
> +      && DECL_SECTION_NAME (decl) != NULL_TREE
>        && !DECL_HAS_IMPLICIT_SECTION_NAME_P (decl))
>      return false;
>
> Index: lto/lto.c
> ===================================================================
> --- lto/lto.c   (revision 211362)
> +++ lto/lto.c   (working copy)
> @@ -767,7 +767,6 @@ mentions_vars_p_decl_with_vis (tree t)
>
>    /* Accessor macro has side-effects, use field-name here. */
>    CHECK_NO_VAR (t->decl_with_vis.assembler_name);
> -  CHECK_NO_VAR (DECL_SECTION_NAME (t));
>    return false;
>  }
>
> @@ -1529,7 +1528,6 @@ compare_tree_sccs_1 (tree t1, tree t2, t
>        if (DECL_ASSEMBLER_NAME_SET_P (t1))
>         compare_tree_edges (DECL_ASSEMBLER_NAME (t1),
>                             DECL_ASSEMBLER_NAME (t2));
> -      compare_tree_edges (DECL_SECTION_NAME (t1), DECL_SECTION_NAME (t2));
>      }
>
>    if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
> @@ -2718,7 +2716,6 @@ lto_fixup_prevailing_decls (tree t)
>        if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
>         {
>           LTO_NO_PREVAIL (t->decl_with_vis.assembler_name);
> -         LTO_NO_PREVAIL (DECL_SECTION_NAME (t));
>         }
>        if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
>         {
> Index: tree-streamer-out.c
> ===================================================================
> --- tree-streamer-out.c (revision 211362)
> +++ tree-streamer-out.c (working copy)
> @@ -660,8 +660,6 @@ write_ts_decl_with_vis_tree_pointers (st
>      stream_write_tree (ob, DECL_ASSEMBLER_NAME (expr), ref_p);
>    else
>      stream_write_tree (ob, NULL_TREE, false);
> -
> -  stream_write_tree (ob, DECL_SECTION_NAME (expr), ref_p);
>  }
>
>
> Index: varasm.c
> ===================================================================
> --- varasm.c    (revision 211362)
> +++ varasm.c    (working copy)
> @@ -1369,6 +1369,7 @@ make_decl_rtl (tree decl)
>       is called early and it needs to make DECL_RTL to get the name.
>       we take care of recomputing the DECL_RTL after visibility is changed.  */
>    if (TREE_CODE (decl) == VAR_DECL
> +      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
>        && DECL_SECTION_NAME (decl) != NULL_TREE
>        && DECL_INITIAL (decl) == NULL_TREE
>        && DECL_COMMON (decl))
> @@ -6460,7 +6461,7 @@ default_unique_section (tree decl, int r
>
>    string = ACONCAT ((linkonce, prefix, ".", name, NULL));
>
> -  DECL_SECTION_NAME (decl) = build_string (strlen (string), string);
> +  set_decl_section_name (decl, build_string (strlen (string), string));
>  }
>
>  /* Like compute_reloc_for_constant, except for an RTX.  The return value
> Index: ipa-comdats.c
> ===================================================================
> --- ipa-comdats.c       (revision 211362)
> +++ ipa-comdats.c       (working copy)
> @@ -243,7 +243,7 @@ ipa_comdats (void)
>              || symbol->force_output
>              || symbol->used_from_other_partition
>              || TREE_THIS_VOLATILE (symbol->decl)
> -            || DECL_SECTION_NAME (symbol->decl)
> +            || symbol->get_section ()
>              || (TREE_CODE (symbol->decl) == FUNCTION_DECL
>                  && (DECL_STATIC_CONSTRUCTOR (symbol->decl)
>                      || DECL_STATIC_DESTRUCTOR (symbol->decl))))
> Index: tree-streamer-in.c
> ===================================================================
> --- tree-streamer-in.c  (revision 211362)
> +++ tree-streamer-in.c  (working copy)
> @@ -759,8 +759,6 @@ lto_input_ts_decl_with_vis_tree_pointers
>        gcc_assert (TREE_CODE (id) == IDENTIFIER_NODE);
>        SET_DECL_ASSEMBLER_NAME (expr, id);
>      }
> -
> -  DECL_SECTION_NAME (expr) = stream_read_tree (ib, data_in);
>  }
>
>
> Index: symtab.c
> ===================================================================
> --- symtab.c    (revision 211362)
> +++ symtab.c    (working copy)
> @@ -563,9 +563,9 @@ dump_symtab_base (FILE *f, symtab_node *
>              IDENTIFIER_POINTER (node->get_comdat_group_id ()));
>    if (DECL_ONE_ONLY (node->decl))
>      fprintf (f, " one_only");
> -  if (DECL_SECTION_NAME (node->decl))
> -    fprintf (f, " section_name:%s",
> -            TREE_STRING_POINTER (DECL_SECTION_NAME (node->decl)));
> +  if (node->get_section ())
> +    fprintf (f, " section:%s",
> +            TREE_STRING_POINTER (node->get_section ()));
>    if (DECL_VISIBILITY_SPECIFIED (node->decl))
>      fprintf (f, " visibility_specified");
>    if (DECL_VISIBILITY (node->decl))
> @@ -877,11 +877,7 @@ symtab_make_decl_local (tree decl)
>      DECL_COMMON (decl) = 0;
>    else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
>
> -  if (DECL_COMDAT (decl))
> -    {
> -      DECL_SECTION_NAME (decl) = 0;
> -      DECL_COMDAT (decl) = 0;
> -    }
> +  DECL_COMDAT (decl) = 0;
>    DECL_WEAK (decl) = 0;
>    DECL_EXTERNAL (decl) = 0;
>    DECL_VISIBILITY_SPECIFIED (decl) = 0;
> Index: config/mep/mep.c
> ===================================================================
> --- config/mep/mep.c    (revision 211362)
> +++ config/mep/mep.c    (working copy)
> @@ -4658,7 +4658,7 @@ mep_unique_section (tree decl, int reloc
>
>    sprintf (string, "%s%s", prefix, name);
>
> -  DECL_SECTION_NAME (decl) = build_string (len, string);
> +  set_decl_section_name (decl, build_string (len, string));
>  }
>
>  /* Given a decl, a section name, and whether the decl initializer
> Index: config/i386/winnt.c
> ===================================================================
> --- config/i386/winnt.c (revision 211362)
> +++ config/i386/winnt.c (working copy)
> @@ -438,7 +438,7 @@ i386_pe_unique_section (tree decl, int r
>    string = XALLOCAVEC (char, len + 1);
>    sprintf (string, "%s%s", prefix, name);
>
> -  DECL_SECTION_NAME (decl) = build_string (len, string);
> +  set_decl_section_name (decl, build_string (len, string));
>  }
>
>  /* Local and global relocs can be placed always into readonly memory for
> Index: config/i386/i386.c
> ===================================================================
> --- config/i386/i386.c  (revision 211362)
> +++ config/i386/i386.c  (working copy)
> @@ -5193,7 +5193,7 @@ x86_64_elf_unique_section (tree decl, in
>
>           string = ACONCAT ((linkonce, prefix, ".", name, NULL));
>
> -         DECL_SECTION_NAME (decl) = build_string (strlen (string), string);
> +         set_decl_section_name (decl, build_string (strlen (string), string));
>           return;
>         }
>      }
> Index: config/c6x/c6x.c
> ===================================================================
> --- config/c6x/c6x.c    (revision 211362)
> +++ config/c6x/c6x.c    (working copy)
> @@ -1060,7 +1060,7 @@ c6x_elf_unique_section (tree decl, int r
>
>        string = ACONCAT ((linkonce, prefix, ".", name, NULL));
>
> -      DECL_SECTION_NAME (decl) = build_string (strlen (string), string);
> +      set_decl_section_name (decl, build_string (strlen (string), string));
>        return;
>      }
>    default_unique_section (decl, reloc);
> Index: config/rs6000/rs6000.c
> ===================================================================
> --- config/rs6000/rs6000.c      (revision 211362)
> +++ config/rs6000/rs6000.c      (working copy)
> @@ -29342,7 +29342,7 @@ rs6000_xcoff_unique_section (tree decl,
>
>    name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
>    name = (*targetm.strip_name_encoding) (name);
> -  DECL_SECTION_NAME (decl) = build_string (strlen (name), name);
> +  set_decl_section_name (decl, build_string (strlen (name), name));
>  }
>
>  /* Select section for constant in constant pool.
> Index: config/mcore/mcore.c
> ===================================================================
> --- config/mcore/mcore.c        (revision 211362)
> +++ config/mcore/mcore.c        (working copy)
> @@ -3089,7 +3089,7 @@ mcore_unique_section (tree decl, int rel
>
>    sprintf (string, "%s%s", prefix, name);
>
> -  DECL_SECTION_NAME (decl) = build_string (len, string);
> +  set_decl_section_name (decl, build_string (len, string));
>  }
>
>  int
> Index: config/mips/mips.c
> ===================================================================
> --- config/mips/mips.c  (revision 211362)
> +++ config/mips/mips.c  (working copy)
> @@ -6618,7 +6618,7 @@ mips16_build_function_stub (void)
>    stubdecl = build_decl (BUILTINS_LOCATION,
>                          FUNCTION_DECL, get_identifier (stubname),
>                          build_function_type_list (void_type_node, NULL_TREE));
> -  DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
> +  set_decl_section_name (stubdecl, build_string (strlen (secname), secname));
>    DECL_RESULT (stubdecl) = build_decl (BUILTINS_LOCATION,
>                                        RESULT_DECL, NULL_TREE, void_type_node);
>
> @@ -6872,7 +6872,7 @@ mips16_build_call_stub (rtx retval, rtx
>                              FUNCTION_DECL, stubid,
>                              build_function_type_list (void_type_node,
>                                                        NULL_TREE));
> -      DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
> +      set_decl_section_name (stubdecl, build_string (strlen (secname), secname));
>        DECL_RESULT (stubdecl) = build_decl (BUILTINS_LOCATION,
>                                            RESULT_DECL, NULL_TREE,
>                                            void_type_node);
> Index: config/v850/v850.c
> ===================================================================
> --- config/v850/v850.c  (revision 211362)
> +++ config/v850/v850.c  (working copy)
> @@ -2644,7 +2644,7 @@ v850_insert_attributes (tree decl, tree
>           /* Only set the section name if specified by a pragma, because
>              otherwise it will force those variables to get allocated storage
>              in this module, rather than by the linker.  */
> -         DECL_SECTION_NAME (decl) = chosen_section;
> +         set_decl_section_name (decl, chosen_section);
>         }
>      }
>  }
> Index: config/h8300/h8300.c
> ===================================================================
> --- config/h8300/h8300.c        (revision 211362)
> +++ config/h8300/h8300.c        (working copy)
> @@ -5461,7 +5461,7 @@ h8300_handle_eightbit_data_attribute (tr
>
>    if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
>      {
> -      DECL_SECTION_NAME (decl) = build_string (7, ".eight");
> +      set_decl_section_name (decl, build_string (7, ".eight"));
>      }
>    else
>      {
> @@ -5485,7 +5485,7 @@ h8300_handle_tiny_data_attribute (tree *
>
>    if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
>      {
> -      DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
> +      set_decl_section_name (decl, build_string (6, ".tiny"));
>      }
>    else
>      {
> Index: config/bfin/bfin.c
> ===================================================================
> --- config/bfin/bfin.c  (revision 211362)
> +++ config/bfin/bfin.c  (working copy)
> @@ -4769,7 +4769,7 @@ bfin_handle_l1_text_attribute (tree *nod
>        *no_add_attrs = true;
>      }
>    else
> -    DECL_SECTION_NAME (decl) = build_string (9, ".l1.text");
> +    set_decl_section_name (decl, build_string (9, ".l1.text"));
>
>    return NULL_TREE;
>  }
> @@ -4847,7 +4847,7 @@ bfin_handle_l2_attribute (tree *node, tr
>           *no_add_attrs = true;
>         }
>        else
> -       DECL_SECTION_NAME (decl) = build_string (9, ".l2.text");
> +       set_decl_section_name (decl, build_string (9, ".l2.text"));
>      }
>    else if (TREE_CODE (decl) == VAR_DECL)
>      {
> @@ -4860,7 +4860,7 @@ bfin_handle_l2_attribute (tree *node, tr
>           *no_add_attrs = true;
>         }
>        else
> -       DECL_SECTION_NAME (decl) = build_string (9, ".l2.data");
> +       set_decl_section_name (decl, build_string (9, ".l2.data"));
>      }
>
>    return NULL_TREE;
> Index: varpool.c
> ===================================================================
> --- varpool.c   (revision 211362)
> +++ varpool.c   (working copy)
> @@ -582,7 +582,7 @@ varpool_finalize_named_section_flags (va
>        && !DECL_EXTERNAL (node->decl)
>        && TREE_CODE (node->decl) == VAR_DECL
>        && !DECL_HAS_VALUE_EXPR_P (node->decl)
> -      && DECL_SECTION_NAME (node->decl))
> +      && node->get_section ())
>      get_variable_section (node->decl, false);
>  }
>
Jan Hubicka June 10, 2014, 5:58 p.m. UTC | #2
> On Mon, Jun 9, 2014 at 4:34 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
> > Hi,
> > this patch follows the change to move DECL_COMDAT_GROUP by moving DECL_SECTION_NAME
> > into symtab nodes instead of keeping it in decl_with_vis. (I pla to proceed with
> > other symbol table related fields).
> >
> > It follows exactly same path as the previous patch. Notable change is adding
> > of node removal into duplicate_decl in c-decl.c.
> >
> > Memory usage wise the patch is small win for non-WPA, at WPA we actually
> > consume bit more memory (about 800K on Firefox).  We have more symtab nodes
> > than declarations because of inline clonning.  This will be solved by fixing
> > memory representation of symbol nodes (I plan to move rare items into on side
> > hashtables).  With accessors API it should be easy.
> 
> What I wondered about for some time is why 'clones' need to use the
> same structs as their origins.  They share some bits with their origin
> and they apply some changes.  Thus I think it would be nice to change
> the inheritance of a symtab entry to sth like
> 
>   symbol - cgraph-node-base - cgraph-node
>      |                                      \
>      |                                       cgraph-clone
>      varpool-node-base - varpool-node
>                                  \
>                                   varpool-clone (do we have those?)

Yep, revisiting hiearchy of symbol is on my TODO list. I want to clear APIs first
to make it easier.

We can also make difference in between external declarations, definitions,
thunks and aliases so we do not share data for all of them.

One problem is that we change one type of symbol into another.  We would need tool
for that - allocating duplicate node and redirecting datastructures.  Not a big deal,
but not that pretty either (I think we do not really dangle pointers to nodes, but
I am not 100% sure)

Still those rare data (i.e. things that are not set for most of nodes) probably should
sit in on side hashtable.

Honza
diff mbox

Patch

Index: ipa-visibility.c
===================================================================
--- ipa-visibility.c	(revision 211362)
+++ ipa-visibility.c	(working copy)
@@ -512,6 +512,7 @@  function_and_variable_visibility (bool w
 		     next = next->same_comdat_group)
 		{
 		  next->set_comdat_group (NULL);
+		  next->set_section (NULL);
 		  symtab_make_decl_local (next->decl);
 		  next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
 					|| next->unique_name
@@ -526,6 +527,8 @@  function_and_variable_visibility (bool w
 	    }
 	  if (TREE_PUBLIC (node->decl))
 	    node->set_comdat_group (NULL);
+	  if (DECL_COMDAT (node->decl))
+	    node->set_section (NULL);
 	  symtab_make_decl_local (node->decl);
 	}
 
@@ -643,6 +646,7 @@  function_and_variable_visibility (bool w
 		     next = next->same_comdat_group)
 		{
 		  next->set_comdat_group (NULL);
+		  next->set_section (NULL);
 		  symtab_make_decl_local (next->decl);
 		  next->unique_name = ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
 					|| next->unique_name
@@ -653,6 +657,8 @@  function_and_variable_visibility (bool w
 	    }
 	  if (TREE_PUBLIC (vnode->decl))
 	    vnode->set_comdat_group (NULL);
+	  if (DECL_COMDAT (vnode->decl))
+	    vnode->set_section (NULL);
 	  symtab_make_decl_local (vnode->decl);
 	  vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
 	}
Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 211362)
+++ c-family/c-common.c	(working copy)
@@ -7442,7 +7442,7 @@  handle_section_attribute (tree *node, tr
 	      *no_add_attrs = true;
 	    }
 	  else
-	    DECL_SECTION_NAME (decl) = TREE_VALUE (args);
+	    set_decl_section_name (decl, TREE_VALUE (args));
 	}
       else
 	{
Index: java/class.c
===================================================================
--- java/class.c	(revision 211362)
+++ java/class.c	(working copy)
@@ -991,7 +991,7 @@  build_utf8_ref (tree name)
 		       | SECTION_MERGE | (SECTION_ENTSIZE & decl_size));
 	  sprintf (buf, ".rodata.jutf8.%d", decl_size);
 	  switch_to_section (get_section (buf, flags, NULL));
-	  DECL_SECTION_NAME (decl) = build_string (strlen (buf), buf);
+	  set_decl_section_name (decl, build_string (strlen (buf), buf));
 	}
     }
 
@@ -2805,8 +2805,6 @@  emit_register_classes_in_jcr_section (vo
   cdecl = build_decl (UNKNOWN_LOCATION,
 		      VAR_DECL, get_identifier ("_Jv_JCR_SECTION_data"),
 		      class_array_type);
-  DECL_SECTION_NAME (cdecl) = build_string (strlen (JCR_SECTION_NAME),
-					    JCR_SECTION_NAME);
   DECL_ALIGN (cdecl) = POINTER_SIZE;
   DECL_USER_ALIGN (cdecl) = 1;
   DECL_INITIAL (cdecl) = build_constructor (class_array_type, init);
@@ -2817,6 +2815,8 @@  emit_register_classes_in_jcr_section (vo
   DECL_ARTIFICIAL (cdecl) = 1;
   DECL_IGNORED_P (cdecl) = 1;
   DECL_PRESERVE_P (cdecl) = 1;
+  set_decl_section_name (cdecl, build_string (strlen (JCR_SECTION_NAME),
+					      JCR_SECTION_NAME));
   pushdecl_top_level (cdecl);
   relayout_decl (cdecl);
   rest_of_decl_compilation (cdecl, 1, 0);
Index: c/c-decl.c
===================================================================
--- c/c-decl.c	(revision 211362)
+++ c/c-decl.c	(working copy)
@@ -2304,8 +2304,10 @@  merge_decls (tree newdecl, tree olddecl,
 	 We want to issue an error if the sections conflict but that
 	 must be done later in decl_attributes since we are called
 	 before attributes are assigned.  */
-      if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
-	DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
+      if ((DECL_EXTERNAL (olddecl) || TREE_PUBLIC (olddecl) || TREE_STATIC (olddecl))
+	  && DECL_SECTION_NAME (newdecl) == NULL_TREE
+	  && DECL_SECTION_NAME (olddecl))
+	set_decl_section_name (newdecl, DECL_SECTION_NAME (olddecl));
 
       /* Copy the assembler name.
 	 Currently, it can only be defined in the prototype.  */
@@ -2574,6 +2576,13 @@  duplicate_decls (tree newdecl, tree oldd
   merge_decls (newdecl, olddecl, newtype, oldtype);
 
   /* The NEWDECL will no longer be needed.  */
+  if (TREE_CODE (newdecl) == FUNCTION_DECL
+      || TREE_CODE (newdecl) == VAR_DECL)
+    {
+      struct symtab_node *snode = symtab_get_node (newdecl);
+      if (snode)
+	symtab_remove_node (snode);
+    }
   ggc_free (newdecl);
   return true;
 }
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 211362)
+++ cgraph.c	(working copy)
@@ -641,14 +641,9 @@  cgraph_add_thunk (struct cgraph_node *de
 
   node = cgraph_get_node (alias);
   if (node)
-    {
-      gcc_assert (node->definition);
-      gcc_assert (!node->alias);
-      gcc_assert (!node->thunk.thunk_p);
-      cgraph_remove_node (node);
-    }
-  
-  node = cgraph_create_node (alias);
+    cgraph_reset_node (node);
+  else
+    node = cgraph_create_node (alias);
   gcc_checking_assert (!virtual_offset
 		       || wi::eq_p (virtual_offset, virtual_value));
   node->thunk.fixed_offset = fixed_offset;
@@ -2264,6 +2259,8 @@  cgraph_make_node_local_1 (struct cgraph_
     {
       symtab_make_decl_local (node->decl);
 
+      node->set_section (NULL);
+      node->set_comdat_group (NULL);
       node->externally_visible = false;
       node->forced_by_abi = false;
       node->local.local = true;
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 211362)
+++ cgraph.h	(working copy)
@@ -157,9 +157,24 @@  public:
   /* Set comdat group.  */
   void set_comdat_group (tree group)
     {
+      gcc_checking_assert (!group || TREE_CODE (group) == IDENTIFIER_NODE
+			   || DECL_P (group));
       comdat_group_ = group;
     }
 
+  /* Return section.  */
+  tree get_section ()
+    {
+      return section_;
+    }
+
+  /* Set section.  */
+  void set_section (tree section)
+    {
+      gcc_checking_assert (!section || TREE_CODE (section) == STRING_CST);
+      section_ = section;
+    }
+
   /* Vectors of referring and referenced entities.  */
   struct ipa_ref_list ref_list;
 
@@ -175,6 +190,9 @@  public:
 
   /* Comdat group the symbol is in.  Can be private if GGC allowed that.  */
   tree comdat_group_;
+
+  /* Section name. Again can be private, if allowed.  */
+  tree section_;
 };
 
 enum availability
Index: tree.c
===================================================================
--- tree.c	(revision 211362)
+++ tree.c	(working copy)
@@ -608,7 +608,7 @@  decl_assembler_name (tree decl)
    DECL is associated with.  This can be either an IDENTIFIER_NODE or a
    decl, in which case its DECL_ASSEMBLER_NAME identifies the group.  */
 tree
-decl_comdat_group (tree node)
+decl_comdat_group (const_tree node)
 {
   struct symtab_node *snode = symtab_get_node (node);
   if (!snode)
@@ -618,7 +618,7 @@  decl_comdat_group (tree node)
 
 /* Likewise, but make sure it's been reduced to an IDENTIFIER_NODE.  */
 tree
-decl_comdat_group_id (tree node)
+decl_comdat_group_id (const_tree node)
 {
   struct symtab_node *snode = symtab_get_node (node);
   if (!snode)
@@ -626,6 +626,37 @@  decl_comdat_group_id (tree node)
   return snode->get_comdat_group_id ();
 }
 
+/* When the target supports named section, return its name as IDENTIFIER_NODE
+   or NULL if it is in no section.  */
+tree
+decl_section_name (const_tree node)
+{
+  struct symtab_node *snode = symtab_get_node (node);
+  if (!snode)
+    return NULL;
+  return snode->get_section ();
+}
+
+/* Set section section name of NODE to VALUE (that is expected to
+   be identifier node)  */
+void
+set_decl_section_name (tree node, tree value)
+{
+  struct symtab_node *snode;
+
+  if (value == NULL)
+    {
+      snode = symtab_get_node (node);
+      if (!snode)
+	return;
+    }
+  else if (TREE_CODE (node) == VAR_DECL)
+    snode = varpool_node_for_decl (node);
+  else
+    snode = cgraph_get_create_node (node);
+  snode->set_section (value);
+}
+
 /* Compute the number of bytes occupied by a tree with code CODE.
    This function cannot be used for nodes that have variable sizes,
    including TREE_VEC, INTEGER_CST, STRING_CST, and CALL_EXPR.  */
@@ -5264,10 +5295,6 @@  find_decls_types_r (tree *tp, int *ws, v
 	  fld_worklist_push (DECL_FIELD_BIT_OFFSET (t), fld);
 	  fld_worklist_push (DECL_FCONTEXT (t), fld);
 	}
-      else if (TREE_CODE (t) == VAR_DECL)
-	{
-	  fld_worklist_push (DECL_SECTION_NAME (t), fld);
-	}
 
       if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
 	  && DECL_HAS_VALUE_EXPR_P (t))
Index: tree.h
===================================================================
--- tree.h	(revision 211362)
+++ tree.h	(working copy)
@@ -2368,8 +2368,7 @@  extern void decl_value_expr_insert (tree
 
 /* Records the section name in a section attribute.  Used to pass
    the name from decl_attributes to make_function_rtl and make_decl_rtl.  */
-#define DECL_SECTION_NAME(NODE) \
-  (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.section_name)
+#define DECL_SECTION_NAME(NODE) decl_section_name (NODE)
 
 /* Nonzero in a decl means that the gimplifier has seen (or placed)
    this variable in a BIND_EXPR.  */
@@ -3431,8 +3430,10 @@  tree_operand_check_code (const_tree __t,
    || ((NODE) && TREE_TYPE ((NODE)) == error_mark_node))
 
 extern tree decl_assembler_name (tree);
-extern tree decl_comdat_group (tree);
-extern tree decl_comdat_group_id (tree);
+extern tree decl_comdat_group (const_tree);
+extern tree decl_comdat_group_id (const_tree);
+extern tree decl_section_name (const_tree);
+extern void set_decl_section_name (tree, tree);
 
 /* Compute the number of bytes occupied by 'node'.  This routine only
    looks at TREE_CODE and, if the code is TREE_VEC, TREE_VEC_LENGTH.  */
Index: tree-emutls.c
===================================================================
--- tree-emutls.c	(revision 211362)
+++ tree-emutls.c	(working copy)
@@ -245,7 +245,6 @@  get_emutls_init_templ_addr (tree decl)
   TREE_READONLY (to) = 1;
   DECL_IGNORED_P (to) = 1;
   DECL_CONTEXT (to) = DECL_CONTEXT (decl);
-  DECL_SECTION_NAME (to) = DECL_SECTION_NAME (decl);
   DECL_PRESERVE_P (to) = DECL_PRESERVE_P (decl);
 
   DECL_WEAK (to) = DECL_WEAK (decl);
@@ -265,10 +264,13 @@  get_emutls_init_templ_addr (tree decl)
 
   if (targetm.emutls.tmpl_section)
     {
-      DECL_SECTION_NAME (to)
-        = build_string (strlen (targetm.emutls.tmpl_section),
-			targetm.emutls.tmpl_section);
+      set_decl_section_name
+	(to,
+         build_string (strlen (targetm.emutls.tmpl_section),
+		       targetm.emutls.tmpl_section));
     }
+  else
+    set_decl_section_name (to, DECL_SECTION_NAME (decl));
 
   /* Create varpool node for the new variable and finalize it if it is
      not external one.  */
@@ -323,9 +325,10 @@  new_emutls_decl (tree decl, tree alias_o
   /* If the target wants the control variables grouped, do so.  */
   if (!DECL_COMMON (to) && targetm.emutls.var_section)
     {
-      DECL_SECTION_NAME (to)
-        = build_string (strlen (targetm.emutls.var_section),
-			targetm.emutls.var_section);
+      set_decl_section_name 
+        (to,
+         build_string (strlen (targetm.emutls.var_section),
+		       targetm.emutls.var_section));
     }
 
   /* If this variable is defined locally, then we need to initialize the
Index: cp/optimize.c
===================================================================
--- cp/optimize.c	(revision 211362)
+++ cp/optimize.c	(working copy)
@@ -476,7 +476,6 @@  maybe_clone_body (tree fn)
 	 to it. By doing so, it also corrupted the comdat group. */
       if (DECL_ONE_ONLY (fn))
 	cgraph_get_create_node (clone)->set_comdat_group (cxx_comdat_group (clone));
-      DECL_SECTION_NAME (clone) = DECL_SECTION_NAME (fn);
       DECL_USE_TEMPLATE (clone) = DECL_USE_TEMPLATE (fn);
       DECL_EXTERNAL (clone) = DECL_EXTERNAL (fn);
       DECL_INTERFACE_KNOWN (clone) = DECL_INTERFACE_KNOWN (fn);
@@ -487,6 +486,7 @@  maybe_clone_body (tree fn)
       DECL_DLLIMPORT_P (clone) = DECL_DLLIMPORT_P (fn);
       DECL_ATTRIBUTES (clone) = copy_list (DECL_ATTRIBUTES (fn));
       DECL_DISREGARD_INLINE_LIMITS (clone) = DECL_DISREGARD_INLINE_LIMITS (fn);
+      set_decl_section_name (clone, DECL_SECTION_NAME (fn));
 
       /* Adjust the parameter names and locations.  */
       parm = DECL_ARGUMENTS (fn);
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 211362)
+++ cp/decl.c	(working copy)
@@ -2019,8 +2019,10 @@  duplicate_decls (tree newdecl, tree oldd
 	 We want to issue an error if the sections conflict but that must be
 	 done later in decl_attributes since we are called before attributes
 	 are assigned.  */
-      if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
-	DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
+      if ((DECL_EXTERNAL (olddecl) || TREE_PUBLIC (olddecl) || TREE_STATIC (olddecl))
+	  && DECL_SECTION_NAME (newdecl) == NULL_TREE
+	  && DECL_SECTION_NAME (olddecl) != NULL_TREE)
+	set_decl_section_name (newdecl, DECL_SECTION_NAME (olddecl));
 
       if (TREE_CODE (newdecl) == FUNCTION_DECL)
 	{
Index: cp/method.c
===================================================================
--- cp/method.c	(revision 211362)
+++ cp/method.c	(working copy)
@@ -363,7 +363,7 @@  use_thunk (tree thunk_fndecl, bool emit_
 	  resolve_unique_section (thunk_fndecl, 0, flag_function_sections);
 
 	  /* Output the thunk into the same section as function.  */
-	  DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function);
+	  set_decl_section_name (thunk_fndecl, DECL_SECTION_NAME (function));
 	}
     }
 
Index: cp/vtable-class-hierarchy.c
===================================================================
--- cp/vtable-class-hierarchy.c	(revision 211362)
+++ cp/vtable-class-hierarchy.c	(working copy)
@@ -1247,8 +1247,8 @@  vtable_find_or_create_map_decl (tree bas
       /* Put these mmap variables in thr .vtable_map_vars section, so
          we can find and protect them.  */
 
-      DECL_SECTION_NAME (var_decl) = build_string (strlen (".vtable_map_vars"),
-                                                   ".vtable_map_vars");
+      set_decl_section_name (var_decl, build_string (strlen (".vtable_map_vars"),
+                                                     ".vtable_map_vars"));
       DECL_HAS_IMPLICIT_SECTION_NAME_P (var_decl) = true;
       DECL_INITIAL (var_decl) = initial_value;
 
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c	(revision 211362)
+++ lto-cgraph.c	(working copy)
@@ -396,6 +396,7 @@  lto_output_node (struct lto_simple_outpu
   int i;
   bool alias_p;
   const char *comdat;
+  const char *section;
   tree group;
 
   boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
@@ -486,6 +487,7 @@  lto_output_node (struct lto_simple_outpu
   else
     comdat = "";
   lto_output_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
+
   if (group)
     {
       if (node->same_comdat_group && !boundary_p)
@@ -499,6 +501,13 @@  lto_output_node (struct lto_simple_outpu
       streamer_write_hwi_stream (ob->main_stream, ref);
     }
 
+  group = node->get_section ();
+  if (group)
+    section = TREE_STRING_POINTER (group);
+  else
+    section = "";
+  lto_output_data_stream (ob->main_stream, section, strlen (section) + 1);
+
   streamer_write_hwi_stream (ob->main_stream, node->tp_first_run);
 
   bp = bitpack_create (ob->main_stream);
@@ -563,6 +572,7 @@  lto_output_varpool_node (struct lto_simp
   int ref;
   bool alias_p;
   const char *comdat;
+  const char *section;
   tree group;
 
   streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
@@ -600,12 +610,14 @@  lto_output_varpool_node (struct lto_simp
 	  /* in_other_partition.  */
     }
   streamer_write_bitpack (&bp);
+
   group = node->get_comdat_group ();
   if (group)
     comdat = IDENTIFIER_POINTER (group);
   else
     comdat = "";
   lto_output_data_stream (ob->main_stream, comdat, strlen (comdat) + 1);
+
   if (group)
     {
       if (node->same_comdat_group && !boundary_p)
@@ -618,6 +630,14 @@  lto_output_varpool_node (struct lto_simp
 	ref = LCC_NOT_FOUND;
       streamer_write_hwi_stream (ob->main_stream, ref);
     }
+
+  group = node->get_section ();
+  if (group)
+    section = TREE_STRING_POINTER (group);
+  else
+    section = "";
+  lto_output_data_stream (ob->main_stream, section, strlen (section) + 1);
+
   streamer_write_enum (ob->main_stream, ld_plugin_symbol_resolution,
 		       LDPR_NUM_KNOWN, node->resolution);
 }
@@ -968,13 +988,33 @@  output_symtab (void)
   output_refs (encoder);
 }
 
-/* Return COMDAT_GROUP encoded in IB as a plain string.  */
+/* Return identifier encoded in IB as a plain string.  */
 
 static tree
-read_comdat_group (struct lto_input_block *ib)
+read_identifier (struct lto_input_block *ib)
 {
   unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1);
-  tree group;
+  tree id;
+
+  if (ib->data[ib->p + len])
+    lto_section_overrun (ib);
+  if (!len)
+    {
+      ib->p++;
+      return NULL;
+    }
+  id = get_identifier (ib->data + ib->p);
+  ib->p += len + 1;
+  return id;
+}
+
+/* Return identifier encoded in IB as a plain string.  */
+
+static tree
+read_string_cst (struct lto_input_block *ib)
+{
+  unsigned int len = strnlen (ib->data + ib->p, ib->len - ib->p - 1);
+  tree id;
 
   if (ib->data[ib->p + len])
     lto_section_overrun (ib);
@@ -983,9 +1023,9 @@  read_comdat_group (struct lto_input_bloc
       ib->p++;
       return NULL;
     }
-  group = get_identifier (ib->data + ib->p);
+  id = build_string (len, ib->data + ib->p);
   ib->p += len + 1;
-  return group;
+  return id;
 }
 
 /* Overwrite the information in NODE based on FILE_DATA, TAG, FLAGS,
@@ -1077,6 +1117,7 @@  input_node (struct lto_file_decl_data *f
   int order;
   int i, count;
   tree group;
+  tree section;
 
   order = streamer_read_hwi (ib) + order_base;
   clone_ref = streamer_read_hwi (ib);
@@ -1122,9 +1163,10 @@  input_node (struct lto_file_decl_data *f
   if (tag == LTO_symtab_analyzed_node)
     ref = streamer_read_hwi (ib);
 
-  group = read_comdat_group (ib);
+  group = read_identifier (ib);
   if (group)
     ref2 = streamer_read_hwi (ib);
+  section = read_string_cst (ib);
 
   /* Make sure that we have not read this node before.  Nodes that
      have already been read will have their tag stored in the 'aux'
@@ -1151,6 +1193,8 @@  input_node (struct lto_file_decl_data *f
     }
   else
     node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
+  if (section)
+    node->set_section (section);
 
   if (node->thunk.thunk_p)
     {
@@ -1183,6 +1227,7 @@  input_varpool_node (struct lto_file_decl
   int ref = LCC_NOT_FOUND;
   int order;
   tree group;
+  tree section;
 
   order = streamer_read_hwi (ib) + order_base;
   decl_index = streamer_read_uhwi (ib);
@@ -1220,7 +1265,7 @@  input_varpool_node (struct lto_file_decl
     }
   if (node->alias && !node->analyzed && node->weakref)
     node->alias_target = get_alias_symbol (node->decl);
-  group = read_comdat_group (ib);
+  group = read_identifier (ib);
   if (group)
     {
       node->set_comdat_group (group);
@@ -1230,6 +1275,9 @@  input_varpool_node (struct lto_file_decl
     }
   else
     node->same_comdat_group = (symtab_node *) (intptr_t) LCC_NOT_FOUND;
+  section = read_string_cst (ib);
+  if (section)
+    node->set_section (section);
   node->resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution,
 					        LDPR_NUM_KNOWN);
   gcc_assert (flag_ltrans
Index: cgraphclones.c
===================================================================
--- cgraphclones.c	(revision 211362)
+++ cgraphclones.c	(working copy)
@@ -340,7 +340,6 @@  duplicate_thunk_for_node (cgraph_node *t
 
   DECL_NAME (new_decl) = clone_function_name (thunk->decl, "artificial_thunk");
   SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
-  DECL_SECTION_NAME (new_decl) = NULL;
 
   new_thunk = cgraph_create_node (new_decl);
   set_new_clone_decl_and_node_flags (new_thunk);
@@ -557,8 +556,6 @@  cgraph_create_virtual_clone (struct cgra
      that is not weak also.
      ??? We cannot use COMDAT linkage because there is no
      ABI support for this.  */
-  if (old_node->get_comdat_group ())
-    DECL_SECTION_NAME (new_node->decl) = NULL;
   set_new_clone_decl_and_node_flags (new_node);
   new_node->clone.tree_map = tree_map;
   new_node->clone.args_to_skip = args_to_skip;
Index: lto-streamer-out.c
===================================================================
--- lto-streamer-out.c	(revision 211362)
+++ lto-streamer-out.c	(working copy)
@@ -535,7 +535,6 @@  DFS_write_tree_body (struct output_block
       /* Make sure we don't inadvertently set the assembler name.  */
       if (DECL_ASSEMBLER_NAME_SET_P (expr))
 	DFS_follow_tree_edge (DECL_ASSEMBLER_NAME (expr));
-      DFS_follow_tree_edge (DECL_SECTION_NAME (expr));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
@@ -973,7 +972,6 @@  hash_tree (struct streamer_tree_cache_d
     {
       if (DECL_ASSEMBLER_NAME_SET_P (t))
 	visit (DECL_ASSEMBLER_NAME (t));
-      visit (DECL_SECTION_NAME (t));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 211362)
+++ dwarf2out.c	(working copy)
@@ -13611,7 +13611,9 @@  secname_for_decl (const_tree decl)
 {
   const char *secname;
 
-  if (VAR_OR_FUNCTION_DECL_P (decl) && DECL_SECTION_NAME (decl))
+  if (VAR_OR_FUNCTION_DECL_P (decl)
+      && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl) || TREE_STATIC (decl))
+      && DECL_SECTION_NAME (decl))
     {
       tree sectree = DECL_SECTION_NAME (decl);
       secname = TREE_STRING_POINTER (sectree);
Index: go/go-gcc.cc
===================================================================
--- go/go-gcc.cc	(revision 211362)
+++ go/go-gcc.cc	(working copy)
@@ -2376,7 +2376,7 @@  Gcc_backend::global_variable_set_init(Bv
   // a different one now that DECL_INITIAL is set.
   if (DECL_HAS_IMPLICIT_SECTION_NAME_P (var_decl))
     {
-      DECL_SECTION_NAME (var_decl) = NULL_TREE;
+      set_decl_section_name (var_decl, NULL);
       resolve_unique_section (var_decl,
 			      compute_reloc_for_constant (expr_tree),
 			      1);
Index: ada/gcc-interface/utils.c
===================================================================
--- ada/gcc-interface/utils.c	(revision 211362)
+++ ada/gcc-interface/utils.c	(working copy)
@@ -2476,9 +2476,9 @@  process_attributes (tree *node, struct a
       case ATTR_LINK_SECTION:
 	if (targetm_common.have_named_sections)
 	  {
-	    DECL_SECTION_NAME (*node)
-	      = build_string (IDENTIFIER_LENGTH (attr->name),
-			      IDENTIFIER_POINTER (attr->name));
+	    set_decl_section_name (*node,
+				   build_string (IDENTIFIER_LENGTH (attr->name),
+						 IDENTIFIER_POINTER (attr->name)));
 	    DECL_COMMON (*node) = 0;
 	  }
 	else
Index: ipa.c
===================================================================
--- ipa.c	(revision 211362)
+++ ipa.c	(working copy)
@@ -714,7 +714,7 @@  ipa_discover_readonly_nonaddressable_var
 	    /* Making variable in explicit section readonly can cause section
 	       type conflict. 
 	       See e.g. gcc.c-torture/compile/pr23237.c */
-	    && DECL_SECTION_NAME (vnode->decl) == NULL)
+	    && vnode->get_section () == NULL)
 	  {
 	    if (!TREE_READONLY (vnode->decl) && dump_file)
 	      fprintf (dump_file, " %s (read-only)", vnode->name ());
Index: tree-vect-data-refs.c
===================================================================
--- tree-vect-data-refs.c	(revision 211362)
+++ tree-vect-data-refs.c	(working copy)
@@ -5213,7 +5213,8 @@  vect_can_force_dr_alignment_p (const_tre
   /* Do not override explicit alignment set by the user when an explicit
      section name is also used.  This is a common idiom used by many
      software projects.  */
-  if (DECL_SECTION_NAME (decl) != NULL_TREE
+  if (TREE_STATIC (decl) 
+      && DECL_SECTION_NAME (decl) != NULL_TREE
       && !DECL_HAS_IMPLICIT_SECTION_NAME_P (decl))
     return false;
 
Index: lto/lto.c
===================================================================
--- lto/lto.c	(revision 211362)
+++ lto/lto.c	(working copy)
@@ -767,7 +767,6 @@  mentions_vars_p_decl_with_vis (tree t)
 
   /* Accessor macro has side-effects, use field-name here. */
   CHECK_NO_VAR (t->decl_with_vis.assembler_name);
-  CHECK_NO_VAR (DECL_SECTION_NAME (t));
   return false;
 }
 
@@ -1529,7 +1528,6 @@  compare_tree_sccs_1 (tree t1, tree t2, t
       if (DECL_ASSEMBLER_NAME_SET_P (t1))
 	compare_tree_edges (DECL_ASSEMBLER_NAME (t1),
 			    DECL_ASSEMBLER_NAME (t2));
-      compare_tree_edges (DECL_SECTION_NAME (t1), DECL_SECTION_NAME (t2));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL))
@@ -2718,7 +2716,6 @@  lto_fixup_prevailing_decls (tree t)
       if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
 	{
 	  LTO_NO_PREVAIL (t->decl_with_vis.assembler_name);
-	  LTO_NO_PREVAIL (DECL_SECTION_NAME (t));
 	}
       if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
 	{
Index: tree-streamer-out.c
===================================================================
--- tree-streamer-out.c	(revision 211362)
+++ tree-streamer-out.c	(working copy)
@@ -660,8 +660,6 @@  write_ts_decl_with_vis_tree_pointers (st
     stream_write_tree (ob, DECL_ASSEMBLER_NAME (expr), ref_p);
   else
     stream_write_tree (ob, NULL_TREE, false);
-
-  stream_write_tree (ob, DECL_SECTION_NAME (expr), ref_p);
 }
 
 
Index: varasm.c
===================================================================
--- varasm.c	(revision 211362)
+++ varasm.c	(working copy)
@@ -1369,6 +1369,7 @@  make_decl_rtl (tree decl)
      is called early and it needs to make DECL_RTL to get the name.
      we take care of recomputing the DECL_RTL after visibility is changed.  */
   if (TREE_CODE (decl) == VAR_DECL
+      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
       && DECL_SECTION_NAME (decl) != NULL_TREE
       && DECL_INITIAL (decl) == NULL_TREE
       && DECL_COMMON (decl))
@@ -6460,7 +6461,7 @@  default_unique_section (tree decl, int r
 
   string = ACONCAT ((linkonce, prefix, ".", name, NULL));
 
-  DECL_SECTION_NAME (decl) = build_string (strlen (string), string);
+  set_decl_section_name (decl, build_string (strlen (string), string));
 }
 
 /* Like compute_reloc_for_constant, except for an RTX.  The return value
Index: ipa-comdats.c
===================================================================
--- ipa-comdats.c	(revision 211362)
+++ ipa-comdats.c	(working copy)
@@ -243,7 +243,7 @@  ipa_comdats (void)
 	     || symbol->force_output
 	     || symbol->used_from_other_partition
 	     || TREE_THIS_VOLATILE (symbol->decl)
-	     || DECL_SECTION_NAME (symbol->decl)
+	     || symbol->get_section ()
 	     || (TREE_CODE (symbol->decl) == FUNCTION_DECL
 		 && (DECL_STATIC_CONSTRUCTOR (symbol->decl)
 		     || DECL_STATIC_DESTRUCTOR (symbol->decl))))
Index: tree-streamer-in.c
===================================================================
--- tree-streamer-in.c	(revision 211362)
+++ tree-streamer-in.c	(working copy)
@@ -759,8 +759,6 @@  lto_input_ts_decl_with_vis_tree_pointers
       gcc_assert (TREE_CODE (id) == IDENTIFIER_NODE);
       SET_DECL_ASSEMBLER_NAME (expr, id);
     }
-
-  DECL_SECTION_NAME (expr) = stream_read_tree (ib, data_in);
 }
 
 
Index: symtab.c
===================================================================
--- symtab.c	(revision 211362)
+++ symtab.c	(working copy)
@@ -563,9 +563,9 @@  dump_symtab_base (FILE *f, symtab_node *
 	     IDENTIFIER_POINTER (node->get_comdat_group_id ()));
   if (DECL_ONE_ONLY (node->decl))
     fprintf (f, " one_only");
-  if (DECL_SECTION_NAME (node->decl))
-    fprintf (f, " section_name:%s",
-	     TREE_STRING_POINTER (DECL_SECTION_NAME (node->decl)));
+  if (node->get_section ())
+    fprintf (f, " section:%s",
+	     TREE_STRING_POINTER (node->get_section ()));
   if (DECL_VISIBILITY_SPECIFIED (node->decl))
     fprintf (f, " visibility_specified");
   if (DECL_VISIBILITY (node->decl))
@@ -877,11 +877,7 @@  symtab_make_decl_local (tree decl)
     DECL_COMMON (decl) = 0;
   else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
 
-  if (DECL_COMDAT (decl))
-    {
-      DECL_SECTION_NAME (decl) = 0;
-      DECL_COMDAT (decl) = 0;
-    }
+  DECL_COMDAT (decl) = 0;
   DECL_WEAK (decl) = 0;
   DECL_EXTERNAL (decl) = 0;
   DECL_VISIBILITY_SPECIFIED (decl) = 0;
Index: config/mep/mep.c
===================================================================
--- config/mep/mep.c	(revision 211362)
+++ config/mep/mep.c	(working copy)
@@ -4658,7 +4658,7 @@  mep_unique_section (tree decl, int reloc
 
   sprintf (string, "%s%s", prefix, name);
 
-  DECL_SECTION_NAME (decl) = build_string (len, string);
+  set_decl_section_name (decl, build_string (len, string));
 }
 
 /* Given a decl, a section name, and whether the decl initializer
Index: config/i386/winnt.c
===================================================================
--- config/i386/winnt.c	(revision 211362)
+++ config/i386/winnt.c	(working copy)
@@ -438,7 +438,7 @@  i386_pe_unique_section (tree decl, int r
   string = XALLOCAVEC (char, len + 1);
   sprintf (string, "%s%s", prefix, name);
 
-  DECL_SECTION_NAME (decl) = build_string (len, string);
+  set_decl_section_name (decl, build_string (len, string));
 }
 
 /* Local and global relocs can be placed always into readonly memory for
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 211362)
+++ config/i386/i386.c	(working copy)
@@ -5193,7 +5193,7 @@  x86_64_elf_unique_section (tree decl, in
 
 	  string = ACONCAT ((linkonce, prefix, ".", name, NULL));
 
-	  DECL_SECTION_NAME (decl) = build_string (strlen (string), string);
+	  set_decl_section_name (decl, build_string (strlen (string), string));
 	  return;
 	}
     }
Index: config/c6x/c6x.c
===================================================================
--- config/c6x/c6x.c	(revision 211362)
+++ config/c6x/c6x.c	(working copy)
@@ -1060,7 +1060,7 @@  c6x_elf_unique_section (tree decl, int r
 
       string = ACONCAT ((linkonce, prefix, ".", name, NULL));
 
-      DECL_SECTION_NAME (decl) = build_string (strlen (string), string);
+      set_decl_section_name (decl, build_string (strlen (string), string));
       return;
     }
   default_unique_section (decl, reloc);
Index: config/rs6000/rs6000.c
===================================================================
--- config/rs6000/rs6000.c	(revision 211362)
+++ config/rs6000/rs6000.c	(working copy)
@@ -29342,7 +29342,7 @@  rs6000_xcoff_unique_section (tree decl,
 
   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
   name = (*targetm.strip_name_encoding) (name);
-  DECL_SECTION_NAME (decl) = build_string (strlen (name), name);
+  set_decl_section_name (decl, build_string (strlen (name), name));
 }
 
 /* Select section for constant in constant pool.
Index: config/mcore/mcore.c
===================================================================
--- config/mcore/mcore.c	(revision 211362)
+++ config/mcore/mcore.c	(working copy)
@@ -3089,7 +3089,7 @@  mcore_unique_section (tree decl, int rel
   
   sprintf (string, "%s%s", prefix, name);
 
-  DECL_SECTION_NAME (decl) = build_string (len, string);
+  set_decl_section_name (decl, build_string (len, string));
 }
 
 int
Index: config/mips/mips.c
===================================================================
--- config/mips/mips.c	(revision 211362)
+++ config/mips/mips.c	(working copy)
@@ -6618,7 +6618,7 @@  mips16_build_function_stub (void)
   stubdecl = build_decl (BUILTINS_LOCATION,
 			 FUNCTION_DECL, get_identifier (stubname),
 			 build_function_type_list (void_type_node, NULL_TREE));
-  DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
+  set_decl_section_name (stubdecl, build_string (strlen (secname), secname));
   DECL_RESULT (stubdecl) = build_decl (BUILTINS_LOCATION,
 				       RESULT_DECL, NULL_TREE, void_type_node);
 
@@ -6872,7 +6872,7 @@  mips16_build_call_stub (rtx retval, rtx
 			     FUNCTION_DECL, stubid,
 			     build_function_type_list (void_type_node,
 						       NULL_TREE));
-      DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
+      set_decl_section_name (stubdecl, build_string (strlen (secname), secname));
       DECL_RESULT (stubdecl) = build_decl (BUILTINS_LOCATION,
 					   RESULT_DECL, NULL_TREE,
 					   void_type_node);
Index: config/v850/v850.c
===================================================================
--- config/v850/v850.c	(revision 211362)
+++ config/v850/v850.c	(working copy)
@@ -2644,7 +2644,7 @@  v850_insert_attributes (tree decl, tree
 	  /* Only set the section name if specified by a pragma, because
 	     otherwise it will force those variables to get allocated storage
 	     in this module, rather than by the linker.  */
-	  DECL_SECTION_NAME (decl) = chosen_section;
+	  set_decl_section_name (decl, chosen_section);
 	}
     }
 }
Index: config/h8300/h8300.c
===================================================================
--- config/h8300/h8300.c	(revision 211362)
+++ config/h8300/h8300.c	(working copy)
@@ -5461,7 +5461,7 @@  h8300_handle_eightbit_data_attribute (tr
 
   if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
     {
-      DECL_SECTION_NAME (decl) = build_string (7, ".eight");
+      set_decl_section_name (decl, build_string (7, ".eight"));
     }
   else
     {
@@ -5485,7 +5485,7 @@  h8300_handle_tiny_data_attribute (tree *
 
   if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
     {
-      DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
+      set_decl_section_name (decl, build_string (6, ".tiny"));
     }
   else
     {
Index: config/bfin/bfin.c
===================================================================
--- config/bfin/bfin.c	(revision 211362)
+++ config/bfin/bfin.c	(working copy)
@@ -4769,7 +4769,7 @@  bfin_handle_l1_text_attribute (tree *nod
       *no_add_attrs = true;
     }
   else
-    DECL_SECTION_NAME (decl) = build_string (9, ".l1.text");
+    set_decl_section_name (decl, build_string (9, ".l1.text"));
 
   return NULL_TREE;
 }
@@ -4847,7 +4847,7 @@  bfin_handle_l2_attribute (tree *node, tr
 	  *no_add_attrs = true;
 	}
       else
-	DECL_SECTION_NAME (decl) = build_string (9, ".l2.text");
+	set_decl_section_name (decl, build_string (9, ".l2.text"));
     }
   else if (TREE_CODE (decl) == VAR_DECL)
     {
@@ -4860,7 +4860,7 @@  bfin_handle_l2_attribute (tree *node, tr
 	  *no_add_attrs = true;
 	}
       else
-	DECL_SECTION_NAME (decl) = build_string (9, ".l2.data");
+	set_decl_section_name (decl, build_string (9, ".l2.data"));
     }
 
   return NULL_TREE;
Index: varpool.c
===================================================================
--- varpool.c	(revision 211362)
+++ varpool.c	(working copy)
@@ -582,7 +582,7 @@  varpool_finalize_named_section_flags (va
       && !DECL_EXTERNAL (node->decl)
       && TREE_CODE (node->decl) == VAR_DECL
       && !DECL_HAS_VALUE_EXPR_P (node->decl)
-      && DECL_SECTION_NAME (node->decl))
+      && node->get_section ())
     get_variable_section (node->decl, false);
 }