Several parts of GCC need to copy a section name from one tree (or
symtab_node) to another. Currently, this is implemented naively:

1. Query the source's section name
2. Hash the section name string
3. Find the section_hash_entry in the symbol table
4. Increment the section_hash_entry's reference count
5. Assign the destination's section to the section_hash_entry

Since we have the source's section_hash_entry, we can copy the section
name from one symtab_node to another efficiently with the following
algorithm:

1. Query the source's section_hash_entry
2. Increment the section_hash_entry's reference count
3. Assign the destination's section to the section_hash_entry

Implement this algorithm in the overload of symtab_node::set_section
which takes an existing symtab_node.

I did not measure the performance impact of this patch. In
particular, I do not know if this patch actually improves performance.

This patch should not change behavior.

Testing: Bootstrap on x86_64-linux-gnu with --disable-multilib
--enable-checking=release --enable-languages=c,c++. Observe no change in
test results.

2019-11-12  Matthew Glazar <strager....@gmail.com>

* gcc/cgraph.h (symtab_node::set_section_for_node): Declare new
overload.
(symtab_node::set_section_from_string): Rename from set_section.
(symtab_node::set_section_from_node): Declare.
* gcc/symtab.c (symtab_node::set_section_for_node): Define new
overload.
(symtab_node::set_section_from_string): Rename from set_section.
(symtab_node::set_section_from_node): Define.
(symtab_node::set_section): Call renamed set_section_from_string.
(symtab_node::set_section): Call new set_section_from_node.


diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 3b07258b31d..928a8bc2729 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -313,6 +313,10 @@ public:
      use set_section.  */
   void set_section_for_node (const char *section);

+  /* Like set_section_for_node, but copying the section name from another
+     node.  */
+  void set_section_for_node (const symtab_node &other);
+
   /* Set initialization priority to PRIORITY.  */
   void set_init_priority (priority_type priority);

@@ -627,8 +631,9 @@ protected:
                       void *data,
                       bool include_overwrite);
 private:
-  /* Worker for set_section.  */
-  static bool set_section (symtab_node *n, void *s);
+  /* Workers for set_section.  */
+  static bool set_section_from_string (symtab_node *n, void *s);
+  static bool set_section_from_node (symtab_node *n, void *o);

   /* Worker for symtab_resolve_alias.  */
   static bool set_implicit_section (symtab_node *n, void *);
diff --git a/gcc/symtab.c b/gcc/symtab.c
index a2aa519e760..40752addcb6 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -1596,15 +1596,37 @@ symtab_node::set_section_for_node (const char *section)
     }
 }

-/* Worker for set_section.  */
+void
+symtab_node::set_section_for_node (const symtab_node &other)
+{
+  if (x_section == other.x_section)
+    return;
+  if (get_section () && other.get_section ())
+    gcc_checking_assert (strcmp (get_section (), other.get_section ()) != 0);
+  release_section_hash_entry (x_section);
+  if (other.x_section)
+    x_section = retain_section_hash_entry (other.x_section);
+  else
+    x_section = NULL;
+}
+
+/* Workers for set_section.  */

 bool
-symtab_node::set_section (symtab_node *n, void *s)
+symtab_node::set_section_from_string (symtab_node *n, void *s)
 {
   n->set_section_for_node ((char *)s);
   return false;
 }

+bool
+symtab_node::set_section_from_node (symtab_node *n, void *o)
+{
+  const symtab_node &other = *static_cast<const symtab_node *> (o);
+  n->set_section_for_node (other);
+  return false;
+}
+
 /* Set section of symbol and its aliases.  */

 void
@@ -1612,15 +1634,14 @@ symtab_node::set_section (const char *section)
 {
   gcc_assert (!this->alias || !this->analyzed);
   call_for_symbol_and_aliases
-    (symtab_node::set_section, const_cast<char *>(section), true);
+    (symtab_node::set_section_from_string, 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);
+    (symtab_node::set_section_from_node, const_cast<symtab_node
*>(&other), true);
 }

 /* Return the initialization priority.  */

Reply via email to