diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 2841b4f5a77..366fbf2a28a 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -2845,7 +2845,7 @@ merge_decls (tree newdecl, tree olddecl, tree
newtype, tree oldtype)
            || TREE_PUBLIC (olddecl)
            || TREE_STATIC (olddecl))
           && DECL_SECTION_NAME (newdecl) != NULL)
-        set_decl_section_name (olddecl, DECL_SECTION_NAME (newdecl));
+        set_decl_section_name (olddecl, newdecl);

       /* This isn't quite correct for something like
         int __thread x attribute ((tls_model ("local-exec")));
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 0abde3d8f91..3b07258b31d 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -246,7 +246,7 @@ public:
     }

   /* Return section as string.  */
-  const char * get_section ()
+  const char * get_section () const
     {
       if (!x_section)
     return NULL;
@@ -305,6 +305,9 @@ public:
   /* Set section for symbol and its aliases.  */
   void set_section (const char *section);

+  /* Like set_section, but copying the section name from another node.  */
+  void set_section (const symtab_node &other);
+
   /* Set section, do not recurse into aliases.
      When one wants to change section of symbol and its aliases,
      use set_section.  */
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 41a600e64a5..0b1c93534f2 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -572,7 +572,7 @@ cgraph_node::create_virtual_clone (vec<cgraph_edge
*> redirect_callers,
   set_new_clone_decl_and_node_flags (new_node);
   new_node->clone.tree_map = tree_map;
   if (!implicit_section)
-    new_node->set_section (get_section ());
+    new_node->set_section (*this);

   /* Clones of global symbols or symbols with unique names are unique.  */
   if ((TREE_PUBLIC (old_decl)
@@ -996,7 +996,7 @@ cgraph_node::create_version_clone_with_body
   new_version_node->local = 1;
   new_version_node->lowered = true;
   if (!implicit_section)
-    new_version_node->set_section (get_section ());
+    new_version_node->set_section (*this);
   /* Clones of global symbols or symbols with unique names are unique.  */
   if ((TREE_PUBLIC (old_decl)
        && !DECL_EXTERNAL (old_decl)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 5c5a85e3221..ed4034f8e9d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2830,7 +2830,7 @@ duplicate_decls (tree newdecl, tree olddecl,
bool newdecl_is_friend)
          done later in decl_attributes since we are called before attributes
          are assigned.  */
       if (DECL_SECTION_NAME (newdecl) != NULL)
-        set_decl_section_name (olddecl, DECL_SECTION_NAME (newdecl));
+        set_decl_section_name (olddecl, newdecl);

       if (DECL_ONE_ONLY (newdecl))
         {
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 47441c10c52..d111792af5b 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -351,7 +351,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
       resolve_unique_section (thunk_fndecl, 0, flag_function_sections);

       /* Output the thunk into the same section as function.  */
-      set_decl_section_name (thunk_fndecl, DECL_SECTION_NAME (fn));
+      set_decl_section_name (thunk_fndecl, fn);
       symtab_node::get (thunk_fndecl)->implicit_section
         = symtab_node::get (fn)->implicit_section;
     }
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index 994ee9148c0..707ccdafcdb 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -518,7 +518,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));
+      set_decl_section_name (clone, fn);

       /* Adjust the parameter names and locations.  */
       parm = DECL_ARGUMENTS (fn);
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index bcce245e59c..d6c934b1163 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -1677,7 +1677,7 @@ finish_thunk (tree thunk, tree function)
       resolve_unique_section (thunk, 0, flag_function_sections);

       /* Output the thunk into the same section as function.  */
-      set_decl_section_name (thunk, DECL_SECTION_NAME (fn));
+      set_decl_section_name (thunk, fn);
       symtab_node::get (thunk)->implicit_section
         = symtab_node::get (fn)->implicit_section;
     }
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 3e634e22c86..84d17c36189 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -1418,8 +1418,7 @@ symtab_node::copy_visibility_from (symtab_node *n)
   DECL_DLLIMPORT_P (decl) = DECL_DLLIMPORT_P (n->decl);
   resolution = n->resolution;
   set_comdat_group (n->get_comdat_group ());
-  call_for_symbol_and_aliases (symtab_node::set_section,
-                 const_cast<char *>(n->get_section ()), true);
+  set_section (*n);
   externally_visible = n->externally_visible;
   if (!DECL_RTL_SET_P (decl))
     return;
@@ -1605,6 +1604,14 @@ symtab_node::set_section (const char *section)
     (symtab_node::set_section, const_cast<char *>(section), true);
 }

+void
+symtab_node::set_section (const symtab_node &other)
+{
+  const char *section = other.get_section ();
+  call_for_symbol_and_aliases
+    (symtab_node::set_section, const_cast<char *>(section), true);
+}
+
 /* Return the initialization priority.  */

 priority_type
@@ -1748,8 +1755,7 @@ symtab_node::resolve_alias (symtab_node *target,
bool transparent)
     {
       error ("section of alias %q+D must match section of its target", decl);
     }
-  call_for_symbol_and_aliases (symtab_node::set_section,
-                 const_cast<char *>(target->get_section ()), true);
+  set_section (*target);
   if (target->implicit_section)
     call_for_symbol_and_aliases (set_implicit_section, NULL, true);

diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 2e775286540..a2023d60ea0 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -4994,7 +4994,7 @@ ipa_tm_create_version (struct cgraph_node *old_node)
   new_node->lowered = true;
   new_node->tm_clone = 1;
   if (!old_node->implicit_section)
-    new_node->set_section (old_node->get_section ());
+    new_node->set_section (*old_node);
   get_cg_data (&old_node, true)->clone = new_node;

   if (old_node->get_availability () >= AVAIL_INTERPOSABLE)
diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c
index 6fc8370f42c..b7b0a57bde4 100644
--- a/gcc/tree-emutls.c
+++ b/gcc/tree-emutls.c
@@ -259,7 +259,7 @@ get_emutls_init_templ_addr (tree decl)
   if (targetm.emutls.tmpl_section)
     set_decl_section_name (to, targetm.emutls.tmpl_section);
   else
-    set_decl_section_name (to, DECL_SECTION_NAME (decl));
+    set_decl_section_name (to, decl);

   /* Create varpool node for the new variable and finalize it if it is
      not external one.  */
diff --git a/gcc/tree.c b/gcc/tree.c
index d2c9fe35995..0c5b88302b7 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -774,6 +774,33 @@ set_decl_section_name (tree node, const char *value)
   snode->set_section (value);
 }

+/* Set section name of NODE to match the section name of OTHER.
+
+   set_decl_section_name (decl, other) is equivalent to
+   set_decl_section_name (decl, DECL_SECTION_NAME (other)), but possibly more
+   efficient.  */
+void
+set_decl_section_name (tree decl, const_tree other)
+{
+  struct symtab_node *other_node = symtab_node::get (other);
+  if (other_node)
+    {
+      struct symtab_node *decl_node;
+      if (VAR_P (decl))
+    decl_node = varpool_node::get_create (decl);
+      else
+    decl_node = cgraph_node::get_create (decl);
+      decl_node->set_section (*other_node);
+    }
+  else
+    {
+      struct symtab_node *decl_node = symtab_node::get (decl);
+      if (!decl_node)
+    return;
+      decl_node->set_section (NULL);
+    }
+}
+
 /* Return TLS model of a variable NODE.  */
 enum tls_model
 decl_tls_model (const_tree node)
diff --git a/gcc/tree.h b/gcc/tree.h
index a7d39c3a74d..91e519cdb83 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4241,6 +4241,7 @@ extern tree decl_comdat_group (const_tree);
 extern tree decl_comdat_group_id (const_tree);
 extern const char *decl_section_name (const_tree);
 extern void set_decl_section_name (tree, const char *);
+extern void set_decl_section_name (tree, const_tree);
 extern enum tls_model decl_tls_model (const_tree);
 extern void set_decl_tls_model (tree, enum tls_model);

