The function inlining information is decided in advance and maintained
in the callgraph as so called inline plan.
For each inlined call, the callee's node is cloned to represent the
- new function copy produced by inlininer.
+ new function copy produced by inliner.
Each inlined call gets a unique corresponding clone node of the callee
and the data structure is updated while inlining is performed, so
the clones are eliminated and their callee edges redirected to the
/* Hash table used to convert declarations into nodes. */
static GTY((param_is (struct cgraph_node))) htab_t cgraph_hash;
-/* We destructively update callgraph during inlining and thus we need to
- keep information on whether inlining happened separately. */
-htab_t cgraph_inline_hash;
-
/* The linked list of cgraph nodes. */
struct cgraph_node *cgraph_nodes;
static hashval_t
hash_node (const void *p)
{
- return ((hashval_t)
- IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
- (((struct cgraph_node *) p)->decl)));
+ const struct cgraph_node *n = p;
+ return (hashval_t) DECL_UID (n->decl);
}
/* Returns nonzero if P1 and P2 are equal. */
static int
eq_node (const void *p1, const void *p2)
{
- return ((DECL_ASSEMBLER_NAME (((struct cgraph_node *) p1)->decl)) ==
- (tree) p2);
+ const struct cgraph_node *n1 = p1, *n2 = p2;
+ return DECL_UID (n1->decl) == DECL_UID (n2->decl);
}
/* Allocate new callgraph node and insert it into basic data structures. */
struct cgraph_node *
cgraph_node (tree decl)
{
- struct cgraph_node *node;
- struct cgraph_node **slot;
+ struct cgraph_node key, *node, **slot;
if (TREE_CODE (decl) != FUNCTION_DECL)
abort ();
if (!cgraph_hash)
cgraph_hash = htab_create_ggc (10, hash_node, eq_node, NULL);
- slot = (struct cgraph_node **)
- htab_find_slot_with_hash (cgraph_hash, DECL_ASSEMBLER_NAME (decl),
- IDENTIFIER_HASH_VALUE
- (DECL_ASSEMBLER_NAME (decl)), INSERT);
+ key.decl = decl;
+
+ slot = (struct cgraph_node **) htab_find_slot (cgraph_hash, &key, INSERT);
+
if (*slot)
return *slot;
return e;
}
-/* Try to find existing function for identifier ID. */
-struct cgraph_node *
-cgraph_node_for_identifier (tree id)
-{
- struct cgraph_node **slot;
-
- if (TREE_CODE (id) != IDENTIFIER_NODE)
- abort ();
-
- if (!cgraph_hash)
- return NULL;
-
- slot = (struct cgraph_node **)
- htab_find_slot_with_hash (cgraph_hash, id,
- IDENTIFIER_HASH_VALUE (id), NO_INSERT);
- if (!slot)
- return NULL;
- return *slot;
-}
-
/* Create edge from CALLER to CALLEE in the cgraph. */
struct cgraph_edge *
cgraph_nodes = node->next;
if (node->next)
node->next->previous = node->previous;
- slot =
- htab_find_slot_with_hash (cgraph_hash, DECL_ASSEMBLER_NAME (node->decl),
- IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
- (node->decl)), NO_INSERT);
+ slot = htab_find_slot (cgraph_hash, node, NO_INSERT);
if (*slot == node)
{
if (node->next_clone)
node->next_needed = cgraph_nodes_queue;
cgraph_nodes_queue = node;
-
- /* At the moment frontend automatically emits all nested functions. */
- if (node->nested)
- {
- struct cgraph_node *node2;
-
- for (node2 = node->nested; node2; node2 = node2->next_nested)
- if (!node2->reachable)
- cgraph_mark_reachable_node (node2);
- }
}
}
/* Returns a hash code for P. */
static hashval_t
-cgraph_varpool_hash_node (const void *p)
+hash_varpool_node (const void *p)
{
- return ((hashval_t)
- IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
- (((struct cgraph_varpool_node *) p)->decl)));
+ const struct cgraph_varpool_node *n = p;
+ return (hashval_t) DECL_UID (n->decl);
}
/* Returns nonzero if P1 and P2 are equal. */
static int
-eq_cgraph_varpool_node (const void *p1, const void *p2)
+eq_varpool_node (const void *p1, const void *p2)
{
- return ((DECL_ASSEMBLER_NAME (((struct cgraph_varpool_node *) p1)->decl)) ==
- (tree) p2);
+ const struct cgraph_varpool_node *n1 = p1, *n2 = p2;
+ return DECL_UID (n1->decl) == DECL_UID (n2->decl);
}
/* Return cgraph_varpool node assigned to DECL. Create new one when needed. */
struct cgraph_varpool_node *
cgraph_varpool_node (tree decl)
{
- struct cgraph_varpool_node *node;
- struct cgraph_varpool_node **slot;
+ struct cgraph_varpool_node key, *node, **slot;
if (!DECL_P (decl) || TREE_CODE (decl) == FUNCTION_DECL)
abort ();
if (!cgraph_varpool_hash)
- cgraph_varpool_hash = htab_create_ggc (10, cgraph_varpool_hash_node,
- eq_cgraph_varpool_node, NULL);
+ cgraph_varpool_hash = htab_create_ggc (10, hash_varpool_node,
+ eq_varpool_node, NULL);
+ key.decl = decl;
slot = (struct cgraph_varpool_node **)
- htab_find_slot_with_hash (cgraph_varpool_hash, DECL_ASSEMBLER_NAME (decl),
- IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME (decl)),
- INSERT);
+ htab_find_slot (cgraph_varpool_hash, &key, INSERT);
if (*slot)
return *slot;
node = ggc_alloc_cleared (sizeof (*node));
void
change_decl_assembler_name (tree decl, tree name)
{
- struct cgraph_node *node = NULL;
- struct cgraph_varpool_node *vnode = NULL;
- void **slot;
-
if (!DECL_ASSEMBLER_NAME_SET_P (decl))
{
SET_DECL_ASSEMBLER_NAME (decl, name);
&& DECL_RTL_SET_P (decl))
warning ("%D renamed after being referenced in assembly", decl);
- if (TREE_CODE (decl) == FUNCTION_DECL && cgraph_hash)
- {
- /* Take a look whether declaration is in the cgraph structure. */
- slot =
- htab_find_slot_with_hash (cgraph_hash, DECL_ASSEMBLER_NAME (decl),
- IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
- (decl)), NO_INSERT);
- if (slot)
- node = *slot;
-
- /* It is, verify that we are the canonical node for this decl. */
- if (node && node->decl == decl)
- {
- node = *slot;
- htab_clear_slot (cgraph_hash, slot);
- }
- else
- node = NULL;
- }
- if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl) && cgraph_varpool_hash)
- {
- /* Take a look whether declaration is in the cgraph structure. */
- slot =
- htab_find_slot_with_hash (cgraph_varpool_hash, DECL_ASSEMBLER_NAME (decl),
- IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
- (decl)), NO_INSERT);
- if (slot)
- vnode = *slot;
-
- /* It is, verify that we are the canonical vnode for this decl. */
- if (vnode && vnode->decl == decl)
- {
- vnode = *slot;
- htab_clear_slot (cgraph_varpool_hash, slot);
- }
- else
- vnode = NULL;
- }
SET_DECL_ASSEMBLER_NAME (decl, name);
- if (node)
- {
- slot =
- htab_find_slot_with_hash (cgraph_hash, name,
- IDENTIFIER_HASH_VALUE (name), INSERT);
- if (*slot)
- abort ();
- *slot = node;
- }
- if (vnode)
- {
- slot =
- htab_find_slot_with_hash (cgraph_varpool_hash, name,
- IDENTIFIER_HASH_VALUE (name), INSERT);
- if (*slot)
- abort ();
- *slot = vnode;
- }
-}
-
-/* Try to find existing function for identifier ID. */
-struct cgraph_varpool_node *
-cgraph_varpool_node_for_identifier (tree id)
-{
- struct cgraph_varpool_node **slot;
-
- if (TREE_CODE (id) != IDENTIFIER_NODE)
- abort ();
-
- if (!cgraph_varpool_hash)
- return NULL;
-
- slot = (struct cgraph_varpool_node **)
- htab_find_slot_with_hash (cgraph_varpool_hash, id,
- IDENTIFIER_HASH_VALUE (id), NO_INSERT);
- if (!slot)
- return NULL;
- return *slot;
}
/* Notify finalize_compilation_unit that given node is reachable
{
if (!cgraph_global_info_ready)
return (DECL_INLINE (decl) && !flag_really_no_inline);
- if (!cgraph_inline_hash)
- return false;
- return (htab_find_slot (cgraph_inline_hash, DECL_ASSEMBLER_NAME (decl),
- NO_INSERT) != NULL);
+ return DECL_POSSIBLY_INLINED (decl);
}
/* Create clone of E in the node N represented by CALL_EXPR the callgraph. */