cgraph.c (assembler_name_hash): New static var.
authorJan Hubicka <jh@suse.cz>
Sun, 13 Jul 2008 10:06:19 +0000 (12:06 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sun, 13 Jul 2008 10:06:19 +0000 (10:06 +0000)
* cgraph.c (assembler_name_hash): New static var.
(hash_node_by_assembler_name, eq_assembler_name): New.
(cgraph_node_for_asm): Use hashtable.
(cgraph_remove_node): Maintain hashtable.
(change_decl_assembler_name): Sanity check that names are not changing
after aliasing was processed.
* cgraph.h (varpoon_node): Add next GGC marker.
* tree.c (decl_assembler_name_equal): Constify.
(decl_assembler_name_hash): New.
* tree.h (decl_assembler_name_equal): Constify.
(decl_assembler_name_hash): Update.

From-SVN: r137753

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/tree.c
gcc/tree.h
gcc/varasm.c

index 0f9971d1c4f28533ad27530bf2f4218bd3bc30cc..d38611b8fb28d337eed1d0b3ca321c14b0e0c72b 100644 (file)
@@ -1,3 +1,17 @@
+2008-07-12  Jan Hubicka  <jh@suse.cz>
+
+       * cgraph.c (assembler_name_hash): New static var.
+       (hash_node_by_assembler_name, eq_assembler_name): New.
+       (cgraph_node_for_asm): Use hashtable.
+       (cgraph_remove_node): Maintain hashtable.
+       (change_decl_assembler_name): Sanity check that names are not changing
+       after aliasing was processed.
+       * cgraph.h (varpoon_node): Add next GGC marker.
+       * tree.c (decl_assembler_name_equal): Constify.
+       (decl_assembler_name_hash): New.
+       * tree.h (decl_assembler_name_equal): Constify.
+       (decl_assembler_name_hash): Update.
+
 2008-07-12  David Daney  <ddaney@avtrex.com>
 
        * config/mips/driver-native.c (host_detect_local_cpu): Handle
index 6a80bbed0950702e081aaaacde7ba027ef24844e..881bc42dfe195f38dd48bca57dffcaf49c39022d 100644 (file)
@@ -91,6 +91,8 @@ static inline void cgraph_edge_remove_callee (struct cgraph_edge *e);
 
 /* Hash table used to convert declarations into nodes.  */
 static GTY((param_is (struct cgraph_node))) htab_t cgraph_hash;
+/* Hash table used to convert assembler names into nodes.  */
+static GTY((param_is (struct cgraph_node))) htab_t assembler_name_hash;
 
 /* The linked list of cgraph nodes.  */
 struct cgraph_node *cgraph_nodes;
@@ -409,6 +411,18 @@ cgraph_node (tree decl)
       node->origin->nested = node;
       node->master_clone = node;
     }
+
+  /* This code can go away once flag_unit_at_a_mode is removed.  */
+  if (assembler_name_hash)
+    {
+      tree name = DECL_ASSEMBLER_NAME (node->decl);
+      slot = ((struct cgraph_node **)
+              htab_find_slot_with_hash (assembler_name_hash, name,
+                                       decl_assembler_name_hash (name),
+                                       INSERT));
+      if (!*slot)
+        *slot = node;
+    }
   return node;
 }
 
@@ -425,6 +439,24 @@ cgraph_insert_node_to_hashtable (struct cgraph_node *node)
   *slot = node;
 }
 
+/* Returns a hash code for P.  */
+
+static hashval_t
+hash_node_by_assembler_name (const void *p)
+{
+  const struct cgraph_node *n = (const struct cgraph_node *) p;
+  return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->decl));
+}
+
+/* Returns nonzero if P1 and P2 are equal.  */
+
+static int
+eq_assembler_name (const void *p1, const void *p2)
+{
+  const struct cgraph_node *n1 = (const struct cgraph_node *) p1;
+  const_tree name = (const_tree)p2;
+  return (decl_assembler_name_equal (n1->decl, name));
+}
 
 /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
    Return NULL if there's no such node.  */
@@ -433,11 +465,36 @@ struct cgraph_node *
 cgraph_node_for_asm (tree asmname)
 {
   struct cgraph_node *node;
+  void **slot;
 
-  for (node = cgraph_nodes; node ; node = node->next)
-    if (decl_assembler_name_equal (node->decl, asmname))
-      return node;
+  if (!assembler_name_hash)
+    {
+      assembler_name_hash =
+       htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name,
+                        NULL);
+      for (node = cgraph_nodes; node; node = node->next)
+        if (!node->global.inlined_to)
+         {
+           tree name = DECL_ASSEMBLER_NAME (node->decl);
+           slot = htab_find_slot_with_hash (assembler_name_hash, name,
+                                            decl_assembler_name_hash (name),
+                                            INSERT);
+           /* We can have multiple declarations with same assembler name. For C++
+              it is __builtin_strlen and strlen, for instance.  Do we need to
+              record them all?  Original implementation marked just first one
+              so lets hope for the best.  */
+           if (*slot)
+             continue;
+           *slot = node;
+         }
+    }
+
+  slot = htab_find_slot_with_hash (assembler_name_hash, asmname,
+                                  decl_assembler_name_hash (asmname),
+                                  NO_INSERT);
 
+  if (slot)
+    return (struct cgraph_node *) *slot;
   return NULL;
 }
 
@@ -763,6 +820,7 @@ cgraph_remove_node (struct cgraph_node *node)
   cgraph_call_node_removal_hooks (node);
   cgraph_node_remove_callers (node);
   cgraph_node_remove_callees (node);
+
   /* Incremental inlining access removed nodes stored in the postorder list.
      */
   node->needed = node->reachable = false;
@@ -824,6 +882,16 @@ cgraph_remove_node (struct cgraph_node *node)
              && (TREE_ASM_WRITTEN (n->decl) || DECL_EXTERNAL (n->decl))))
        kill_body = true;
     }
+  if (assembler_name_hash)
+    {
+      tree name = DECL_ASSEMBLER_NAME (node->decl);
+      slot = htab_find_slot_with_hash (assembler_name_hash, name,
+                                      decl_assembler_name_hash (name),
+                                      NO_INSERT);
+      /* Inline clones are not hashed.  */
+      if (slot && *slot == node)
+        htab_clear_slot (assembler_name_hash, slot);
+    }
 
   if (kill_body && flag_unit_at_a_time)
     cgraph_release_function_body (node);
@@ -1038,6 +1106,7 @@ debug_cgraph (void)
 void
 change_decl_assembler_name (tree decl, tree name)
 {
+  gcc_assert (!assembler_name_hash);
   if (!DECL_ASSEMBLER_NAME_SET_P (decl))
     {
       SET_DECL_ASSEMBLER_NAME (decl, name);
index ee79c9200f1a0e599bd7085036a10e4bc8a85391..070bd77dcdc06f91bd5c03542d8e94ed547bd831 100644 (file)
@@ -224,7 +224,7 @@ DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
 /* The varpool data structure.
    Each static variable decl has assigned varpool_node.  */
 
-struct varpool_node GTY(())
+struct varpool_node GTY((chain_next ("%h.next")))
 {
   tree decl;
   /* Pointer to the next function in varpool_nodes.  */
index 14ecf383f9357bc9f274ed08818d34c7b1d077c4..81c471b706731e79edabd5093ad982d8d14c30c4 100644 (file)
@@ -347,7 +347,7 @@ decl_assembler_name (tree decl)
 /* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL.  */
 
 bool
-decl_assembler_name_equal (tree decl, tree asmname)
+decl_assembler_name_equal (tree decl, const_tree asmname)
 {
   tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
 
@@ -378,6 +378,27 @@ decl_assembler_name_equal (tree decl, tree asmname)
   return false;
 }
 
+/* Hash asmnames ignoring the user specified marks.  */
+
+hashval_t
+decl_assembler_name_hash (const_tree asmname)
+{
+  if (IDENTIFIER_POINTER (asmname)[0] == '*')
+    {
+      const char *decl_str = IDENTIFIER_POINTER (asmname) + 1;
+      size_t ulp_len = strlen (user_label_prefix);
+
+      if (ulp_len == 0)
+       ;
+      else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
+       decl_str += ulp_len;
+
+      return htab_hash_string (decl_str);
+    }
+
+  return htab_hash_string (IDENTIFIER_POINTER (asmname));
+}
+
 /* 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, PHI_NODE, STRING_CST, and CALL_EXPR.  */
index f5b2f66f65c4690381cd62436e1d5a0013ebf9f7..103f802c80649a81166c30b1777bbf5c05457fd3 100644 (file)
@@ -3923,7 +3923,8 @@ enum ptrmemfunc_vbit_where_t
 #define NULL_TREE (tree) NULL
 
 extern tree decl_assembler_name (tree);
-extern bool decl_assembler_name_equal (tree decl, tree asmname);
+extern bool decl_assembler_name_equal (tree decl, const_tree asmname);
+extern hashval_t decl_assembler_name_hash (const_tree asmname);
 
 /* 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 d8c611444d350c1a5f74a9c8650ebf91277d938a..49cdda4c9a5619db0096eb3a60618b18a7f6667f 100644 (file)
@@ -5380,7 +5380,10 @@ assemble_alias (tree decl, tree target)
 
   /* If the target has already been emitted, we don't have to queue the
      alias.  This saves a tad of memory.  */
-  target_decl = find_decl_and_mark_needed (decl, target);
+  if (!flag_unit_at_a_time || cgraph_global_info_ready)
+    target_decl = find_decl_and_mark_needed (decl, target);
+  else
+    target_decl= NULL;
   if (target_decl && TREE_ASM_WRITTEN (target_decl))
     do_assemble_alias (decl, target);
   else