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