This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Symbol table 6/many: Symbol table hashes


Hi,
this patch moves cgraph/varpool hashes into symbol table hashes, so the
symbol table is actually almost a symbol table ;)
Work done.

Bootstrapped/regtested x86_64-linux. Will commit it after bit of more
testing - the assembler name handling is slipperly wrt aliases.

Honza

	* cgraph.c (cgraph_hash, assembler_name_hash): Remove.
	(hash_node, eq_node): Remove.
	(cgraph_create_node): Do not handle hashtable.
	(cgraph_get_node): Remove.
	(cgraph_insert_node_to_hashtable): Remove.
	(hash_node_by_assembler_name): Remove.
	(eq_assembler_name): Remove.
	(cgraph_node_for_asm): Rewrite.
	(cgraph_find_replacement_node): Break out from ...
	(cgraph_remove_node): ... here; do not maintain hashtables.
	(change_decl_assembler_name): Remove.
	(cgraph_clone_node): Do not maintain hashtables.
	* cgraph.h (const_symtab_node): New typedef.
	(cgraph_insert_node_to_hashtable): Remove.
	(symtab_get_node, symtab_node_for_asm,
	symtab_insert_node_to_hashtable): Declare.
	(cgraph_find_replacement_node): Declare.
	(cgraph_get_node, varpool_get_node): Turn into inlines.
	(cgraph, varpool): Work sanely on NULL pointers.
	(FOR_EACH_SYMBOL): New walker.
	* ipa-inline-transform.c (save_inline_function_body): Use
	symtab_insert_node_to_hashtable.
	* symtab.c: Include ggc.h and diagnostics.h
	(symtab_hash, assembler_name_hash): New static vars;
	(hash_node, eq_node, hash_node_by_assembler_name,
	eq_assembler_name): New.
	(symtab_register_node): Update hashtables.
	(symtab_insert_node_to_hashtable): New.
	(symtab_unregister_node): Update hashtables.
	(symtab_get_node): New.
	(symtab_node_for_asm): New.
	(change_decl_assembler_name): New.
	* Makefile.in (symtab.o): Needs GTY.
	* varpool.c (varpool_hash): Remove.
	(hash_varpool_node, eq_varpool_node, varpool_get_node): Remove.
	(varpool_node): Rewrite using varpool_get_node.
	(varpool_remove_node): DO not maintain hashtables.
	(varpool_node_for_asm); Rewrite.
Index: cgraph.c
===================================================================
*** cgraph.c	(revision 186496)
--- cgraph.c	(working copy)
*************** static void cgraph_node_remove_callers (
*** 119,129 ****
  static inline void cgraph_edge_remove_caller (struct cgraph_edge *e);
  static inline void cgraph_edge_remove_callee (struct cgraph_edge *e);
  
- /* Hash table used to convert declarations into nodes.  */
- static GTY((param_is (union symtab_node_def))) htab_t cgraph_hash;
- /* Hash table used to convert assembler names into nodes.  */
- static GTY((param_is (union symtab_node_def))) htab_t assembler_name_hash;
- 
  /* Queue of cgraph nodes scheduled to be lowered.  */
  symtab_node x_cgraph_nodes_queue;
  #define cgraph_nodes_queue ((struct cgraph_node *)x_cgraph_nodes_queue)
--- 119,124 ----
*************** cgraph_call_node_duplication_hooks (stru
*** 419,444 ****
    }
  }
  
- /* Returns a hash code for P.  */
- 
- static hashval_t
- hash_node (const void *p)
- {
-   const struct cgraph_node *n = (const struct cgraph_node *) p;
-   return (hashval_t) DECL_UID (n->symbol.decl);
- }
- 
- 
- /* Returns nonzero if P1 and P2 are equal.  */
- 
- static int
- eq_node (const void *p1, const void *p2)
- {
-   const struct cgraph_node *n1 = (const struct cgraph_node *) p1;
-   const struct cgraph_node *n2 = (const struct cgraph_node *) p2;
-   return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl);
- }
- 
  /* Allocate new callgraph node.  */
  
  static inline struct cgraph_node *
--- 414,419 ----
*************** cgraph_create_node_1 (void)
*** 479,520 ****
  struct cgraph_node *
  cgraph_create_node (tree decl)
  {
!   struct cgraph_node key, *node, **slot;
! 
    gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
  
-   if (!cgraph_hash)
-     cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
- 
-   key.symbol.decl = decl;
-   slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT);
-   gcc_assert (!*slot);
- 
-   node = cgraph_create_node_1 ();
    node->symbol.decl = decl;
!   symtab_register_node ((symtab_node)node);
!   *slot = node;
    if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
      {
        node->origin = cgraph_get_create_node (DECL_CONTEXT (decl));
        node->next_nested = node->origin->nested;
        node->origin->nested = node;
      }
-   if (assembler_name_hash)
-     {
-       void **aslot;
-       tree name = DECL_ASSEMBLER_NAME (decl);
- 
-       aslot = 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 (*aslot == NULL)
- 	*aslot = node;
-     }
    return node;
  }
  
--- 454,471 ----
  struct cgraph_node *
  cgraph_create_node (tree decl)
  {
!   struct cgraph_node *node = cgraph_create_node_1 ();
    gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
  
    node->symbol.decl = decl;
!   symtab_register_node ((symtab_node) node);
! 
    if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
      {
        node->origin = cgraph_get_create_node (DECL_CONTEXT (decl));
        node->next_nested = node->origin->nested;
        node->origin->nested = node;
      }
    return node;
  }
  
*************** cgraph_add_thunk (struct cgraph_node *de
*** 629,728 ****
    return node;
  }
  
- /* Returns the cgraph node assigned to DECL or NULL if no cgraph node
-    is assigned.  */
- 
- struct cgraph_node *
- cgraph_get_node (const_tree decl)
- {
-   struct cgraph_node key, *node = NULL, **slot;
- 
-   gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
- 
-   if (!cgraph_hash)
-     return NULL;
- 
-   key.symbol.decl = CONST_CAST2 (tree, const_tree, decl);
- 
-   slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key,
- 						 NO_INSERT);
- 
-   if (slot && *slot)
-     node = *slot;
-   return node;
- }
- 
- /* Insert already constructed node into hashtable.  */
- 
- void
- cgraph_insert_node_to_hashtable (struct cgraph_node *node)
- {
-   struct cgraph_node **slot;
- 
-   slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, node, INSERT);
- 
-   gcc_assert (!*slot);
-   *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->symbol.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->symbol.decl, name));
- }
- 
  /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
     Return NULL if there's no such node.  */
  
  struct cgraph_node *
  cgraph_node_for_asm (tree asmname)
  {
!   struct cgraph_node *node;
!   void **slot;
  
!   if (!assembler_name_hash)
!     {
!       assembler_name_hash =
! 	htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name,
! 			 NULL);
!       FOR_EACH_FUNCTION (node)
!         if (!node->global.inlined_to)
! 	  {
! 	    tree name = DECL_ASSEMBLER_NAME (node->symbol.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)
! 	      *slot = node;
! 	  }
!     }
! 
!   slot = htab_find_slot_with_hash (assembler_name_hash, asmname,
! 				   decl_assembler_name_hash (asmname),
! 				   NO_INSERT);
! 
!   if (slot)
!     {
!       node = (struct cgraph_node *) *slot;
!       return node;
!     }
    return NULL;
  }
  
--- 580,595 ----
    return node;
  }
  
  /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
     Return NULL if there's no such node.  */
  
  struct cgraph_node *
  cgraph_node_for_asm (tree asmname)
  {
!   symtab_node node = symtab_node_for_asm (asmname);
  
!   if (node && symtab_function_p (node))
!     return cgraph (node);
    return NULL;
  }
  
*************** cgraph_release_function_body (struct cgr
*** 1392,1404 ****
      DECL_INITIAL (node->symbol.decl) = error_mark_node;
  }
  
  /* Remove the node from cgraph.  */
  
  void
  cgraph_remove_node (struct cgraph_node *node)
  {
-   void **slot;
-   bool kill_body = false;
    struct cgraph_node *n;
    int uid = node->uid;
  
--- 1259,1354 ----
      DECL_INITIAL (node->symbol.decl) = error_mark_node;
  }
  
+ /* NODE is being removed from symbol table; see if its entry can be replaced by
+    other inline clone.  */
+ struct cgraph_node *
+ cgraph_find_replacement_node (struct cgraph_node *node)
+ {
+   struct cgraph_node *next_inline_clone, *replacement;
+ 
+   for (next_inline_clone = node->clones;
+        next_inline_clone
+        && next_inline_clone->symbol.decl != node->symbol.decl;
+        next_inline_clone = next_inline_clone->next_sibling_clone)
+     ;
+ 
+   /* If there is inline clone of the node being removed, we need
+      to put it into the position of removed node and reorganize all
+      other clones to be based on it.  */
+   if (next_inline_clone)
+     {
+       struct cgraph_node *n;
+       struct cgraph_node *new_clones;
+ 
+       replacement = next_inline_clone;
+ 
+       /* Unlink inline clone from the list of clones of removed node.  */
+       if (next_inline_clone->next_sibling_clone)
+ 	next_inline_clone->next_sibling_clone->prev_sibling_clone
+ 	  = next_inline_clone->prev_sibling_clone;
+       if (next_inline_clone->prev_sibling_clone)
+ 	{
+ 	  gcc_assert (node->clones != next_inline_clone);
+ 	  next_inline_clone->prev_sibling_clone->next_sibling_clone
+ 	    = next_inline_clone->next_sibling_clone;
+ 	}
+       else
+ 	{
+ 	  gcc_assert (node->clones == next_inline_clone);
+ 	  node->clones = next_inline_clone->next_sibling_clone;
+ 	}
+ 
+       new_clones = node->clones;
+       node->clones = NULL;
+ 
+       /* Copy clone info.  */
+       next_inline_clone->clone = node->clone;
+ 
+       /* Now place it into clone tree at same level at NODE.  */
+       next_inline_clone->clone_of = node->clone_of;
+       next_inline_clone->prev_sibling_clone = NULL;
+       next_inline_clone->next_sibling_clone = NULL;
+       if (node->clone_of)
+ 	{
+ 	  if (node->clone_of->clones)
+ 	    node->clone_of->clones->prev_sibling_clone = next_inline_clone;
+ 	  next_inline_clone->next_sibling_clone = node->clone_of->clones;
+ 	  node->clone_of->clones = next_inline_clone;
+ 	}
+ 
+       /* Merge the clone list.  */
+       if (new_clones)
+ 	{
+ 	  if (!next_inline_clone->clones)
+ 	    next_inline_clone->clones = new_clones;
+ 	  else
+ 	    {
+ 	      n = next_inline_clone->clones;
+ 	      while (n->next_sibling_clone)
+ 		n =  n->next_sibling_clone;
+ 	      n->next_sibling_clone = new_clones;
+ 	      new_clones->prev_sibling_clone = n;
+ 	    }
+ 	}
+ 
+       /* Update clone_of pointers.  */
+       n = new_clones;
+       while (n)
+ 	{
+ 	  n->clone_of = next_inline_clone;
+ 	  n = n->next_sibling_clone;
+ 	}
+       return replacement;
+     }
+   else
+     return NULL;
+ }
+ 
  /* Remove the node from cgraph.  */
  
  void
  cgraph_remove_node (struct cgraph_node *node)
  {
    struct cgraph_node *n;
    int uid = node->uid;
  
*************** cgraph_remove_node (struct cgraph_node *
*** 1423,1513 ****
        *node2 = node->next_nested;
      }
    symtab_unregister_node ((symtab_node)node);
-   slot = htab_find_slot (cgraph_hash, node, NO_INSERT);
-   if (*slot == node)
-     {
-       struct cgraph_node *next_inline_clone;
- 
-       for (next_inline_clone = node->clones;
-       	   next_inline_clone
- 	   && next_inline_clone->symbol.decl != node->symbol.decl;
- 	   next_inline_clone = next_inline_clone->next_sibling_clone)
- 	;
- 
-       /* If there is inline clone of the node being removed, we need
-          to put it into the position of removed node and reorganize all
- 	 other clones to be based on it.  */
-       if (next_inline_clone)
- 	{
- 	  struct cgraph_node *n;
- 	  struct cgraph_node *new_clones;
- 
- 	  *slot = next_inline_clone;
- 
- 	  /* Unlink inline clone from the list of clones of removed node.  */
- 	  if (next_inline_clone->next_sibling_clone)
- 	    next_inline_clone->next_sibling_clone->prev_sibling_clone
- 	      = next_inline_clone->prev_sibling_clone;
- 	  if (next_inline_clone->prev_sibling_clone)
- 	    {
- 	      gcc_assert (node->clones != next_inline_clone);
- 	      next_inline_clone->prev_sibling_clone->next_sibling_clone
- 	        = next_inline_clone->next_sibling_clone;
- 	    }
- 	  else
- 	    {
- 	      gcc_assert (node->clones == next_inline_clone);
- 	      node->clones = next_inline_clone->next_sibling_clone;
- 	    }
- 
- 	  new_clones = node->clones;
- 	  node->clones = NULL;
- 
- 	  /* Copy clone info.  */
- 	  next_inline_clone->clone = node->clone;
- 
- 	  /* Now place it into clone tree at same level at NODE.  */
- 	  next_inline_clone->clone_of = node->clone_of;
- 	  next_inline_clone->prev_sibling_clone = NULL;
- 	  next_inline_clone->next_sibling_clone = NULL;
- 	  if (node->clone_of)
- 	    {
- 	      if (node->clone_of->clones)
- 	        node->clone_of->clones->prev_sibling_clone = next_inline_clone;
- 	      next_inline_clone->next_sibling_clone = node->clone_of->clones;
- 	      node->clone_of->clones = next_inline_clone;
- 	    }
- 
- 	  /* Merge the clone list.  */
- 	  if (new_clones)
- 	    {
- 	      if (!next_inline_clone->clones)
- 		next_inline_clone->clones = new_clones;
- 	      else
- 		{
- 		  n = next_inline_clone->clones;
- 		  while (n->next_sibling_clone)
- 		    n =  n->next_sibling_clone;
- 		  n->next_sibling_clone = new_clones;
- 		  new_clones->prev_sibling_clone = n;
- 		}
- 	    }
- 
- 	  /* Update clone_of pointers.  */
- 	  n = new_clones;
- 	  while (n)
- 	    {
- 	      n->clone_of = next_inline_clone;
- 	      n = n->next_sibling_clone;
- 	    }
- 	}
-       else
- 	{
- 	  htab_clear_slot (cgraph_hash, slot);
- 	  kill_body = true;
- 	}
- 
-     }
    if (node->prev_sibling_clone)
      node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
    else if (node->clone_of)
--- 1373,1378 ----
*************** cgraph_remove_node (struct cgraph_node *
*** 1549,1577 ****
       itself is kept in the cgraph even after it is compiled.  Check whether
       we are done with this body and reclaim it proactively if this is the case.
       */
!   if (!kill_body && *slot)
!     {
!       struct cgraph_node *n = (struct cgraph_node *) *slot;
!       if (!n->clones && !n->clone_of && !n->global.inlined_to
  	  && (cgraph_global_info_ready
  	      && (TREE_ASM_WRITTEN (n->symbol.decl)
  		  || DECL_EXTERNAL (n->symbol.decl)
! 		  || n->symbol.in_other_partition)))
! 	kill_body = true;
!     }
!   if (assembler_name_hash)
!     {
!       tree name = DECL_ASSEMBLER_NAME (node->symbol.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)
      cgraph_release_function_body (node);
    node->symbol.decl = NULL;
    if (node->call_site_hash)
      {
--- 1414,1428 ----
       itself is kept in the cgraph even after it is compiled.  Check whether
       we are done with this body and reclaim it proactively if this is the case.
       */
!   n = cgraph_get_node (node->symbol.decl);
!   if (!n
!       || (!n->clones && !n->clone_of && !n->global.inlined_to
  	  && (cgraph_global_info_ready
  	      && (TREE_ASM_WRITTEN (n->symbol.decl)
  		  || DECL_EXTERNAL (n->symbol.decl)
! 		  || n->symbol.in_other_partition))))
      cgraph_release_function_body (node);
+ 
    node->symbol.decl = NULL;
    if (node->call_site_hash)
      {
*************** debug_cgraph (void)
*** 1939,1989 ****
    dump_cgraph (stderr);
  }
  
- 
- /* Set the DECL_ASSEMBLER_NAME and update cgraph hashtables.  */
- 
- void
- change_decl_assembler_name (tree decl, tree name)
- {
-   struct cgraph_node *node;
-   void **slot;
-   if (!DECL_ASSEMBLER_NAME_SET_P (decl))
-     SET_DECL_ASSEMBLER_NAME (decl, name);
-   else
-     {
-       if (name == DECL_ASSEMBLER_NAME (decl))
- 	return;
- 
-       if (assembler_name_hash
- 	  && TREE_CODE (decl) == FUNCTION_DECL
- 	  && (node = cgraph_get_node (decl)) != NULL)
- 	{
- 	  tree old_name = DECL_ASSEMBLER_NAME (decl);
- 	  slot = htab_find_slot_with_hash (assembler_name_hash, old_name,
- 					   decl_assembler_name_hash (old_name),
- 					   NO_INSERT);
- 	  /* Inline clones are not hashed.  */
- 	  if (slot && *slot == node)
- 	    htab_clear_slot (assembler_name_hash, slot);
- 	}
-       if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
- 	  && DECL_RTL_SET_P (decl))
- 	warning (0, "%D renamed after being referenced in assembly", decl);
- 
-       SET_DECL_ASSEMBLER_NAME (decl, name);
-     }
-   if (assembler_name_hash
-       && TREE_CODE (decl) == FUNCTION_DECL
-       && (node = cgraph_get_node (decl)) != NULL)
-     {
-       slot = htab_find_slot_with_hash (assembler_name_hash, name,
- 				       decl_assembler_name_hash (name),
- 				       INSERT);
-       gcc_assert (!*slot);
-       *slot = node;
-     }
- }
- 
  /* Add a top-level asm statement to the list.  */
  
  struct cgraph_asm_node *
--- 1790,1795 ----
*************** cgraph_clone_node (struct cgraph_node *n
*** 2154,2178 ****
    n->clones = new_node;
    new_node->clone_of = n;
  
-   if (n->symbol.decl != decl)
-     {
-       struct cgraph_node **slot;
-       slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, new_node, INSERT);
-       gcc_assert (!*slot);
-       *slot = new_node;
-       if (assembler_name_hash)
- 	{
- 	  void **aslot;
- 	  tree name = DECL_ASSEMBLER_NAME (decl);
- 
- 	  aslot = htab_find_slot_with_hash (assembler_name_hash, name,
- 					    decl_assembler_name_hash (name),
- 					    INSERT);
- 	  gcc_assert (!*aslot);
- 	  *aslot = new_node;
- 	}
-     }
- 
    if (call_duplication_hook)
      cgraph_call_node_duplication_hooks (n, new_node);
    return new_node;
--- 1960,1965 ----
Index: cgraph.h
===================================================================
*** cgraph.h	(revision 186496)
--- cgraph.h	(working copy)
*************** enum symtab_type
*** 40,45 ****
--- 40,46 ----
  
  union symtab_node_def;
  typedef union symtab_node_def *symtab_node;
+ typedef const union symtab_node_def *const_symtab_node;
  
  /* Base of all entries in the symbol table.
     The symtab_node is inherited by cgraph and varpol nodes.  */
*************** extern bool same_body_aliases_done;
*** 499,513 ****
  void symtab_register_node (symtab_node);
  void symtab_unregister_node (symtab_node);
  void symtab_remove_node (symtab_node);
  
  /* In cgraph.c  */
  void dump_cgraph (FILE *);
  void debug_cgraph (void);
  void dump_cgraph_node (FILE *, struct cgraph_node *);
  void debug_cgraph_node (struct cgraph_node *);
- void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
  void cgraph_remove_edge (struct cgraph_edge *);
  void cgraph_remove_node (struct cgraph_node *);
  void cgraph_add_to_same_comdat_group (struct cgraph_node *, struct cgraph_node *);
  bool cgraph_remove_node_and_inline_clones (struct cgraph_node *, struct cgraph_node *);
  void cgraph_release_function_body (struct cgraph_node *);
--- 500,517 ----
  void symtab_register_node (symtab_node);
  void symtab_unregister_node (symtab_node);
  void symtab_remove_node (symtab_node);
+ symtab_node symtab_get_node (const_tree);
+ symtab_node symtab_node_for_asm (const_tree asmname);
+ void symtab_insert_node_to_hashtable (symtab_node);
  
  /* In cgraph.c  */
  void dump_cgraph (FILE *);
  void debug_cgraph (void);
  void dump_cgraph_node (FILE *, struct cgraph_node *);
  void debug_cgraph_node (struct cgraph_node *);
  void cgraph_remove_edge (struct cgraph_edge *);
  void cgraph_remove_node (struct cgraph_node *);
+ struct cgraph_node *cgraph_find_replacement_node (struct cgraph_node *);
  void cgraph_add_to_same_comdat_group (struct cgraph_node *, struct cgraph_node *);
  bool cgraph_remove_node_and_inline_clones (struct cgraph_node *, struct cgraph_node *);
  void cgraph_release_function_body (struct cgraph_node *);
*************** struct cgraph_edge *cgraph_create_edge (
*** 518,524 ****
  struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple,
  						 int, gcov_type, int);
  struct cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void);
- struct cgraph_node * cgraph_get_node (const_tree);
  struct cgraph_node * cgraph_create_node (tree);
  struct cgraph_node * cgraph_get_create_node (tree);
  struct cgraph_node * cgraph_same_body_alias (struct cgraph_node *, tree, tree);
--- 522,527 ----
*************** void cgraph_make_node_local (struct cgra
*** 697,703 ****
  bool cgraph_node_can_be_local_p (struct cgraph_node *);
  
  
- struct varpool_node * varpool_get_node (const_tree decl);
  void varpool_remove_node (struct varpool_node *node);
  void varpool_finalize_named_section_flags (struct varpool_node *node);
  bool varpool_assemble_pending_decls (void);
--- 700,705 ----
*************** static inline struct cgraph_node *
*** 734,740 ****
  cgraph (symtab_node node)
  {
    gcc_checking_assert (!node || node->symbol.type == SYMTAB_FUNCTION);
!   return &node->x_function;
  }
  
  /* Return varpool node for given symbol and check it is a variable.  */
--- 736,742 ----
  cgraph (symtab_node node)
  {
    gcc_checking_assert (!node || node->symbol.type == SYMTAB_FUNCTION);
!   return (struct cgraph_node *)node;
  }
  
  /* Return varpool node for given symbol and check it is a variable.  */
*************** static inline struct varpool_node *
*** 742,750 ****
  varpool (symtab_node node)
  {
    gcc_checking_assert (!node || node->symbol.type == SYMTAB_VARIABLE);
!   return &node->x_variable;
  }
  
  
  /* Return first reachable static variable with initializer.  */
  static inline struct varpool_node *
--- 744,771 ----
  varpool (symtab_node node)
  {
    gcc_checking_assert (!node || node->symbol.type == SYMTAB_VARIABLE);
!   return (struct varpool_node *)node;
  }
  
+ /* Return callgraph node for given symbol and check it is a function. */
+ static inline struct cgraph_node *
+ cgraph_get_node (const_tree decl)
+ {
+   gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL);
+   return cgraph (symtab_get_node (decl));
+ }
+ 
+ /* Return varpool node for given symbol and check it is a function. */
+ static inline struct varpool_node *
+ varpool_get_node (const_tree decl)
+ {
+   gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
+   return varpool (symtab_get_node (decl));
+ }
+ 
+ /* Walk all symbols.  */
+ #define FOR_EACH_SYMBOL(node) \
+    for ((node) = symtab_nodes; (node); (node) = (node)->symbol.next)
  
  /* Return first reachable static variable with initializer.  */
  static inline struct varpool_node *
Index: ipa-inline-transform.c
===================================================================
*** ipa-inline-transform.c	(revision 186491)
--- ipa-inline-transform.c	(working copy)
*************** save_inline_function_body (struct cgraph
*** 278,284 ****
    /* first_clone will be turned into real function.  */
    first_clone = node->clones;
    first_clone->symbol.decl = copy_node (node->symbol.decl);
!   cgraph_insert_node_to_hashtable (first_clone);
    gcc_assert (first_clone == cgraph_get_node (first_clone->symbol.decl));
  
    /* Now reshape the clone tree, so all other clones descends from
--- 278,284 ----
    /* first_clone will be turned into real function.  */
    first_clone = node->clones;
    first_clone->symbol.decl = copy_node (node->symbol.decl);
!   symtab_insert_node_to_hashtable ((symtab_node) first_clone);
    gcc_assert (first_clone == cgraph_get_node (first_clone->symbol.decl));
  
    /* Now reshape the clone tree, so all other clones descends from
Index: symtab.c
===================================================================
*** symtab.c	(revision 186496)
--- symtab.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 25,31 ****
--- 25,38 ----
  #include "tree.h"
  #include "tree-inline.h"
  #include "hashtab.h"
+ #include "ggc.h"
  #include "cgraph.h"
+ #include "diagnostic.h"
+ 
+ /* Hash table used to convert declarations into nodes.  */
+ static GTY((param_is (union symtab_node_def))) htab_t symtab_hash;
+ /* Hash table used to convert assembler names into nodes.  */
+ static GTY((param_is (union symtab_node_def))) htab_t assembler_name_hash;
  
  /* Linked list of symbol table nodes.  */
  symtab_node symtab_nodes;
*************** symtab_node symtab_nodes;
*** 35,65 ****
--- 42,166 ----
     them, to support -fno-toplevel-reorder.  */
  int symtab_order;
  
+ /* Returns a hash code for P.  */
+ 
+ static hashval_t
+ hash_node (const void *p)
+ {
+   const_symtab_node n = (const_symtab_node ) p;
+   return (hashval_t) DECL_UID (n->symbol.decl);
+ }
+ 
+ 
+ /* Returns nonzero if P1 and P2 are equal.  */
+ 
+ static int
+ eq_node (const void *p1, const void *p2)
+ {
+   const_symtab_node n1 = (const_symtab_node) p1;
+   const_symtab_node n2 = (const_symtab_node) p2;
+   return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl);
+ }
+ 
+ /* Returns a hash code for P.  */
+ 
+ static hashval_t
+ hash_node_by_assembler_name (const void *p)
+ {
+   const_symtab_node n = (const_symtab_node) p;
+   return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->symbol.decl));
+ }
+ 
+ /* Returns nonzero if P1 and P2 are equal.  */
+ 
+ static int
+ eq_assembler_name (const void *p1, const void *p2)
+ {
+   const_symtab_node n1 = (const_symtab_node) p1;
+   const_tree name = (const_tree)p2;
+   return (decl_assembler_name_equal (n1->symbol.decl, name));
+ }
+ 
+ 
  /* Add node into symbol table.  This function is not used directly, but via
     cgraph/varpool node creation routines.  */
  
  void
  symtab_register_node (symtab_node node)
  {
+   struct symtab_node_base key;
+   symtab_node *slot;
+ 
    node->symbol.next = symtab_nodes;
    node->symbol.previous = NULL;
    if (symtab_nodes)
      symtab_nodes->symbol.previous = node;
    symtab_nodes = node;
  
+   if (!symtab_hash)
+     symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
+   key.decl = node->symbol.decl;
+   slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT);
+   if (*slot == NULL)
+     *slot = node;
+ 
+   if (assembler_name_hash)
+     {
+       void **aslot;
+       tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
+ 
+       aslot = 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 (*aslot == NULL)
+ 	*aslot = node;
+     }
+ 
    node->symbol.order = symtab_order++;
  
    ipa_empty_ref_list (&node->symbol.ref_list);
  }
  
+ /* Make NODE to be the one symtab hash is pointing to.  Used when reshaping tree
+    of inline clones.  */
+ void
+ symtab_insert_node_to_hashtable (symtab_node node)
+ {
+   struct symtab_node_base key;
+   symtab_node *slot;
+ 
+   if (!symtab_hash)
+     symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
+   key.decl = node->symbol.decl;
+   slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT);
+   *slot = node;
+ 
+   if (assembler_name_hash)
+     {
+       void **aslot;
+       tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
+ 
+       aslot = htab_find_slot_with_hash (assembler_name_hash, name,
+ 					decl_assembler_name_hash (name),
+ 					INSERT);
+       *aslot = node;
+     }
+ }
+ 
  /* Remove node from symbol table.  This function is not used directly, but via
     cgraph/varpool node removal routines.  */
  
  void
  symtab_unregister_node (symtab_node node)
  {
+   void **slot;
    ipa_remove_all_references (&node->symbol.ref_list);
    ipa_remove_all_refering (&node->symbol.ref_list);
+   symtab_node replacement_node = NULL;
  
    if (node->symbol.same_comdat_group)
      {
*************** symtab_unregister_node (symtab_node node
*** 83,88 ****
--- 184,243 ----
      node->symbol.next->symbol.previous = node->symbol.previous;
    node->symbol.next = NULL;
    node->symbol.previous = NULL;
+ 
+   slot = htab_find_slot (symtab_hash, node, NO_INSERT);
+   if (*slot == node)
+     {
+       if (symtab_function_p (node))
+ 	replacement_node = (symtab_node)cgraph_find_replacement_node (cgraph (node));
+       if (!replacement_node)
+ 	htab_clear_slot (symtab_hash, slot);
+       else
+ 	*slot = replacement_node;
+     }
+ 
+   if (assembler_name_hash)
+     {
+       tree name = DECL_ASSEMBLER_NAME (node->symbol.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)
+ 	{
+ 	  if (!replacement_node)
+ 	    htab_clear_slot (assembler_name_hash, slot);
+ 	  else
+ 	    *slot = replacement_node;
+ 	}
+     }
+ }
+ 
+ /* Return symbol table node associated with DECL, if any,
+    and NULL otherwise.  */
+ 
+ symtab_node
+ symtab_get_node (const_tree decl)
+ {
+   symtab_node *slot;
+   struct symtab_node_base key;
+ 
+   gcc_checking_assert (TREE_CODE (decl) == FUNCTION_DECL
+ 		       || (TREE_CODE (decl) == VAR_DECL
+ 			   && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)
+ 			       || in_lto_p)));
+ 
+   if (!symtab_hash)
+     return NULL;
+ 
+   key.decl = CONST_CAST2 (tree, const_tree, decl);
+ 
+   slot = (symtab_node *) htab_find_slot (symtab_hash, &key,
+ 					 NO_INSERT);
+ 
+   if (slot)
+     return *slot;
+   return NULL;
  }
  
  /* Remove symtab NODE from the symbol table.  */
*************** symtab_remove_node (symtab_node node)
*** 95,97 ****
--- 250,341 ----
    else if (symtab_variable_p (node))
      varpool_remove_node (varpool (node));
  }
+ 
+ /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
+    Return NULL if there's no such node.  */
+ 
+ symtab_node
+ symtab_node_for_asm (const_tree asmname)
+ {
+   symtab_node node;
+   void **slot;
+ 
+   if (!assembler_name_hash)
+     {
+       assembler_name_hash =
+ 	htab_create_ggc (10, hash_node_by_assembler_name, eq_assembler_name,
+ 			 NULL);
+       FOR_EACH_SYMBOL (node)
+         if (!symtab_function_p (node) || !cgraph (node)->global.inlined_to)
+ 	  {
+ 	    tree name = DECL_ASSEMBLER_NAME (node->symbol.decl);
+ 	    slot = htab_find_slot_with_hash (assembler_name_hash, name,
+ 					     decl_assembler_name_hash (name),
+ 					     INSERT);
+ 	    gcc_checking_assert (node == symtab_get_node (node->symbol.decl));
+ 	    /* 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)
+ 	      *slot = node;
+ 	  }
+     }
+ 
+   slot = htab_find_slot_with_hash (assembler_name_hash, asmname,
+ 				   decl_assembler_name_hash (asmname),
+ 				   NO_INSERT);
+ 
+   if (slot)
+     {
+       node = (symtab_node) *slot;
+       return node;
+     }
+   return NULL;
+ }
+ 
+ /* Set the DECL_ASSEMBLER_NAME and update symtab hashtables.  */
+ 
+ void
+ change_decl_assembler_name (tree decl, tree name)
+ {
+   symtab_node node;
+   void **slot;
+   if (!DECL_ASSEMBLER_NAME_SET_P (decl))
+     SET_DECL_ASSEMBLER_NAME (decl, name);
+   else
+     {
+       if (name == DECL_ASSEMBLER_NAME (decl))
+ 	return;
+ 
+       if (assembler_name_hash
+ 	  && TREE_CODE (decl) == FUNCTION_DECL
+ 	  && (node = symtab_get_node (decl)) != NULL)
+ 	{
+ 	  tree old_name = DECL_ASSEMBLER_NAME (decl);
+ 	  slot = htab_find_slot_with_hash (assembler_name_hash, old_name,
+ 					   decl_assembler_name_hash (old_name),
+ 					   NO_INSERT);
+ 	  /* Inline clones are not hashed.  */
+ 	  if (slot && *slot == node)
+ 	    htab_clear_slot (assembler_name_hash, slot);
+ 	}
+       if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
+ 	  && DECL_RTL_SET_P (decl))
+ 	warning (0, "%D renamed after being referenced in assembly", decl);
+ 
+       SET_DECL_ASSEMBLER_NAME (decl, name);
+     }
+   if (assembler_name_hash
+       && TREE_CODE (decl) == FUNCTION_DECL
+       && (node = symtab_get_node (decl)) != NULL)
+     {
+       slot = htab_find_slot_with_hash (assembler_name_hash, name,
+ 				       decl_assembler_name_hash (name),
+ 				       INSERT);
+       gcc_checking_assert (!*slot);
+       *slot = node;
+     }
+ }
+ 
+ #include "gt-symtab.h"
Index: Makefile.in
===================================================================
*** Makefile.in	(revision 186496)
--- Makefile.in	(working copy)
*************** simplify-rtx.o : simplify-rtx.c $(CONFIG
*** 2912,2918 ****
     $(TREE_H) $(TARGET_H)
  symtab.o : symtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
!    $(HASHTAB_H) 
  cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
     gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
--- 2912,2918 ----
     $(TREE_H) $(TARGET_H)
  symtab.o : symtab.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
!    $(HASHTAB_H) gt-symtab.h
  cgraph.o : cgraph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
     langhooks.h toplev.h $(DIAGNOSTIC_CORE_H) $(FLAGS_H) $(GGC_H) $(TARGET_H) $(CGRAPH_H) \
     gt-cgraph.h output.h intl.h $(BASIC_BLOCK_H) debug.h $(HASHTAB_H) \
*************** GTFILES = $(CPP_ID_DATA_H) $(srcdir)/inp
*** 3690,3696 ****
    $(srcdir)/fixed-value.h \
    $(srcdir)/output.h $(srcdir)/cfgloop.h \
    $(srcdir)/cselib.h $(srcdir)/basic-block.h  $(srcdir)/ipa-ref.h $(srcdir)/cgraph.h \
!   $(srcdir)/reload.h $(srcdir)/caller-save.c \
    $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
    $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/matrix-reorg.c \
    $(srcdir)/dbxout.c \
--- 3690,3696 ----
    $(srcdir)/fixed-value.h \
    $(srcdir)/output.h $(srcdir)/cfgloop.h \
    $(srcdir)/cselib.h $(srcdir)/basic-block.h  $(srcdir)/ipa-ref.h $(srcdir)/cgraph.h \
!   $(srcdir)/reload.h $(srcdir)/caller-save.c $(srcdir)/symtab.c \
    $(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
    $(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/matrix-reorg.c \
    $(srcdir)/dbxout.c \
Index: varpool.c
===================================================================
*** varpool.c	(revision 186496)
--- varpool.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 48,56 ****
      All variables supposed to be output into final file needs to be
      explicitly marked by frontend via VARPOOL_FINALIZE_DECL function.  */
  
- /* Hash table used to convert declarations into nodes.  */
- static GTY((param_is (union symtab_node_def))) htab_t varpool_hash;
- 
  /* Queue of cgraph nodes scheduled to be lowered and output.
     The queue is maintained via mark_needed_node, linked via node->next_needed
     pointer.
--- 48,53 ----
*************** varpool_node_name (struct varpool_node *
*** 84,149 ****
    return lang_hooks.decl_printable_name (node->symbol.decl, 2);
  }
  
- /* Returns a hash code for P.  */
- static hashval_t
- hash_varpool_node (const void *p)
- {
-   const struct varpool_node *n = (const struct varpool_node *) p;
-   return (hashval_t) DECL_UID (n->symbol.decl);
- }
- 
- /* Returns nonzero if P1 and P2 are equal.  */
- static int
- eq_varpool_node (const void *p1, const void *p2)
- {
-   const struct varpool_node *n1 =
-     (const struct varpool_node *) p1;
-   const struct varpool_node *n2 =
-     (const struct varpool_node *) p2;
-   return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl);
- }
- 
- /* Return varpool node assigned to DECL without creating new one.  */
- struct varpool_node *
- varpool_get_node (const_tree decl)
- {
-   struct varpool_node key, **slot;
- 
-   gcc_assert (TREE_CODE (decl) == VAR_DECL
- 	      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
- 
-   if (!varpool_hash)
-     return NULL;
-   key.symbol.decl = CONST_CAST2 (tree, const_tree, decl);
-   slot = (struct varpool_node **)
-     htab_find_slot (varpool_hash, &key, NO_INSERT);
-   if (!slot)
-     return NULL;
-   return *slot;
- }
- 
  /* Return varpool node assigned to DECL.  Create new one when needed.  */
  struct varpool_node *
  varpool_node (tree decl)
  {
!   struct varpool_node key, *node, **slot;
! 
    gcc_assert (TREE_CODE (decl) == VAR_DECL
  	      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || in_lto_p));
  
-   if (!varpool_hash)
-     varpool_hash = htab_create_ggc (10, hash_varpool_node,
- 					   eq_varpool_node, NULL);
-   key.symbol.decl = decl;
-   slot = (struct varpool_node **)
-     htab_find_slot (varpool_hash, &key, INSERT);
-   if (*slot)
-     return *slot;
    node = ggc_alloc_cleared_varpool_node ();
    node->symbol.type = SYMTAB_VARIABLE;
    node->symbol.decl = decl;
    symtab_register_node ((symtab_node)node);
-   *slot = node;
    return node;
  }
  
--- 81,100 ----
    return lang_hooks.decl_printable_name (node->symbol.decl, 2);
  }
  
  /* Return varpool node assigned to DECL.  Create new one when needed.  */
  struct varpool_node *
  varpool_node (tree decl)
  {
!   struct varpool_node *node = varpool_get_node (decl);
    gcc_assert (TREE_CODE (decl) == VAR_DECL
  	      && (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || in_lto_p));
+   if (node)
+     return node;
  
    node = ggc_alloc_cleared_varpool_node ();
    node->symbol.type = SYMTAB_VARIABLE;
    node->symbol.decl = decl;
    symtab_register_node ((symtab_node)node);
    return node;
  }
  
*************** varpool_node (tree decl)
*** 151,160 ****
  void
  varpool_remove_node (struct varpool_node *node)
  {
-   void **slot;
-   slot = htab_find_slot (varpool_hash, node, NO_INSERT);
-   gcc_assert (*slot == node);
-   htab_clear_slot (varpool_hash, slot);
    gcc_assert (!varpool_assembled_nodes_queue);
    symtab_unregister_node ((symtab_node)node);
    if (varpool_first_unanalyzed_node == node)
--- 102,107 ----
*************** debug_varpool (void)
*** 238,249 ****
  struct varpool_node *
  varpool_node_for_asm (tree asmname)
  {
!   struct varpool_node *node;
! 
!   FOR_EACH_VARIABLE (node)
!     if (decl_assembler_name_equal (node->symbol.decl, asmname))
!       return node;
! 
    return NULL;
  }
  
--- 185,193 ----
  struct varpool_node *
  varpool_node_for_asm (tree asmname)
  {
!   symtab_node node = symtab_node_for_asm (asmname);
!   if (node && symtab_variable_p (node))
!     return varpool (node);
    return NULL;
  }
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]