This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Symbol table 6/many: Symbol table hashes
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 16 Apr 2012 18:09:40 +0200
- Subject: 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;
}