summaryrefslogtreecommitdiff
path: root/gcc/cgraph.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2006-08-21 01:42:39 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2006-08-21 01:42:39 +0000
commit8df22c5c10b38f208d36041f2918ac6a535d7fe2 (patch)
treea12516abd37107b901b016eeb00d8d3bf4e3660f /gcc/cgraph.c
parentb87494f85672b15fd4a179cc60fcee1cb524d5dd (diff)
downloadgcc-8df22c5c10b38f208d36041f2918ac6a535d7fe2.tar.gz
PR rtl-optimization/28071
* tree-optimize.c (tree_rest_of_compilation): Do not remove edges twice. * tree-inline.c (copy_bb): Use cgraph_set_call_stmt. * ipa-inline.c (cgraph_check_inline_limits): Add one_only argument. (cgraph_decide_inlining, cgraph_decide_inlining_of_small_function, cgraph_decide_inlining_incrementally): Update use of cgraph_check_inline_limits. * cgraph.c (edge_hash, edge_eq): New function. (cgraph_edge, cgraph_set_call_stmt, cgraph_create_edge, cgraph_edge_remove_caller, cgraph_node_remove_callees, cgraph_remove_node): Maintain call site hash. * cgraph.h (struct cgraph_node): Add call_site_hash. (cgraph_set_call_stmt): New function. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116284 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cgraph.c')
-rw-r--r--gcc/cgraph.c92
1 files changed, 89 insertions, 3 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 8d841b46e0d..dc98ccf0958 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -293,11 +293,32 @@ cgraph_node_for_asm (tree asmname)
return NULL;
}
+/* Returns a hash value for X (which really is a die_struct). */
+
+static hashval_t
+edge_hash (const void *x)
+{
+ return htab_hash_pointer (((struct cgraph_edge *) x)->call_stmt);
+}
+
+/* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y. */
+
+static int
+edge_eq (const void *x, const void *y)
+{
+ return ((struct cgraph_edge *) x)->call_stmt == y;
+}
+
/* Return callgraph edge representing CALL_EXPR statement. */
struct cgraph_edge *
cgraph_edge (struct cgraph_node *node, tree call_stmt)
{
- struct cgraph_edge *e;
+ struct cgraph_edge *e, *e2;
+ int n = 0;
+
+ if (node->call_site_hash)
+ return htab_find_with_hash (node->call_site_hash, call_stmt,
+ htab_hash_pointer (call_stmt));
/* This loop may turn out to be performance problem. In such case adding
hashtables into call nodes with very many edges is probably best
@@ -305,11 +326,51 @@ cgraph_edge (struct cgraph_node *node, tree call_stmt)
because we want to make possible having multiple cgraph nodes representing
different clones of the same body before the body is actually cloned. */
for (e = node->callees; e; e= e->next_callee)
- if (e->call_stmt == call_stmt)
- break;
+ {
+ if (e->call_stmt == call_stmt)
+ break;
+ n++;
+ }
+ if (n > 100)
+ {
+ node->call_site_hash = htab_create_ggc (120, edge_hash, edge_eq, NULL);
+ for (e2 = node->callees; e2; e2 = e2->next_callee)
+ {
+ void **slot;
+ slot = htab_find_slot_with_hash (node->call_site_hash,
+ e2->call_stmt,
+ htab_hash_pointer (e2->call_stmt),
+ INSERT);
+ gcc_assert (!*slot);
+ *slot = e2;
+ }
+ }
return e;
}
+/* Change call_smtt of edge E to NEW_STMT. */
+void
+cgraph_set_call_stmt (struct cgraph_edge *e, tree new_stmt)
+{
+ if (e->caller->call_site_hash)
+ {
+ htab_remove_elt_with_hash (e->caller->call_site_hash,
+ e->call_stmt,
+ htab_hash_pointer (e->call_stmt));
+ }
+ e->call_stmt = new_stmt;
+ if (e->caller->call_site_hash)
+ {
+ void **slot;
+ slot = htab_find_slot_with_hash (e->caller->call_site_hash,
+ e->call_stmt,
+ htab_hash_pointer
+ (e->call_stmt), INSERT);
+ gcc_assert (!*slot);
+ *slot = e;
+ }
+}
+
/* Create edge from CALLER to CALLEE in the cgraph. */
struct cgraph_edge *
@@ -353,6 +414,17 @@ cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee,
callee->callers = edge;
edge->count = count;
edge->loop_nest = nest;
+ if (caller->call_site_hash)
+ {
+ void **slot;
+ slot = htab_find_slot_with_hash (caller->call_site_hash,
+ edge->call_stmt,
+ htab_hash_pointer
+ (edge->call_stmt),
+ INSERT);
+ gcc_assert (!*slot);
+ *slot = edge;
+ }
return edge;
}
@@ -380,6 +452,10 @@ cgraph_edge_remove_caller (struct cgraph_edge *e)
e->next_callee->prev_callee = e->prev_callee;
if (!e->prev_callee)
e->caller->callees = e->next_callee;
+ if (e->caller->call_site_hash)
+ htab_remove_elt_with_hash (e->caller->call_site_hash,
+ e->call_stmt,
+ htab_hash_pointer (e->call_stmt));
}
/* Remove the edge E in the cgraph. */
@@ -425,6 +501,11 @@ cgraph_node_remove_callees (struct cgraph_node *node)
for (e = node->callees; e; e = e->next_callee)
cgraph_edge_remove_callee (e);
node->callees = NULL;
+ if (node->call_site_hash)
+ {
+ htab_delete (node->call_site_hash);
+ node->call_site_hash = NULL;
+ }
}
/* Remove all callers from the node. */
@@ -521,6 +602,11 @@ cgraph_remove_node (struct cgraph_node *node)
DECL_INITIAL (node->decl) = error_mark_node;
}
node->decl = NULL;
+ if (node->call_site_hash)
+ {
+ htab_delete (node->call_site_hash);
+ node->call_site_hash = NULL;
+ }
cgraph_n_nodes--;
/* Do not free the structure itself so the walk over chain can continue. */
}