diff options
author | Jan Hubicka <jh@suse.cz> | 2012-04-17 12:53:22 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2012-04-17 10:53:22 +0000 |
commit | 1ab24192d5e8e4fcee353bb5c024995e5439f5e3 (patch) | |
tree | 74a135bcf142920c4746545d97004d6d4f499f76 /gcc/cgraph.c | |
parent | 332781bba582208a138ae93c2f20e45d202fc3e5 (diff) | |
download | gcc-1ab24192d5e8e4fcee353bb5c024995e5439f5e3.zip gcc-1ab24192d5e8e4fcee353bb5c024995e5439f5e3.tar.gz gcc-1ab24192d5e8e4fcee353bb5c024995e5439f5e3.tar.bz2 |
cgraph.c (cgraph_hash, [...]): Remove.
* 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, insert_to_assembler_name_hash,
unlink_from_assembler_name_hash): 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.
From-SVN: r186525
Diffstat (limited to 'gcc/cgraph.c')
-rw-r--r-- | gcc/cgraph.c | 407 |
1 files changed, 98 insertions, 309 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 6a54db9..f5f662c 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -119,11 +119,6 @@ static void cgraph_node_remove_callers (struct cgraph_node *node); 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) @@ -419,26 +414,6 @@ cgraph_call_node_duplication_hooks (struct cgraph_node *node1, } } -/* 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 * @@ -479,42 +454,18 @@ cgraph_create_node_1 (void) struct cgraph_node * cgraph_create_node (tree decl) { - struct cgraph_node key, *node, **slot; - + struct cgraph_node *node = cgraph_create_node_1 (); 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; + 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; } - 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; } @@ -629,100 +580,18 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, 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); + symtab_node node = symtab_node_for_asm (asmname); - if (slot) - { - node = (struct cgraph_node *) *slot; - return node; - } + /* We do not want to look at inline clones. */ + for (node = symtab_node_for_asm (asmname); node; node = node->symbol.next_sharing_asm_name) + if (symtab_function_p (node) && !cgraph(node)->global.inlined_to) + return cgraph (node); return NULL; } @@ -1392,13 +1261,96 @@ cgraph_release_function_body (struct cgraph_node *node) 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) { - void **slot; - bool kill_body = false; struct cgraph_node *n; int uid = node->uid; @@ -1423,91 +1375,6 @@ cgraph_remove_node (struct cgraph_node *node) *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) @@ -1549,29 +1416,15 @@ cgraph_remove_node (struct cgraph_node *node) 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 + 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))) - 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) + || n->symbol.in_other_partition)))) cgraph_release_function_body (node); + node->symbol.decl = NULL; if (node->call_site_hash) { @@ -1939,51 +1792,6 @@ debug_cgraph (void) 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 * @@ -2154,25 +1962,6 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq, 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; |