Intraprocedural information:
Callgraph is place to store data needed for intraprocedural optimization.
- All datastructures are divided into three components: local_info that
+ All data structures are divided into three components: local_info that
is produced while analyzing the function, global_info that is result
- of global walkking of the callgraph on the end of compilation and
+ of global walking of the callgraph on the end of compilation and
rtl_info used by RTL backend to propagate data from already compiled
functions to their callers.
The function inlining information is decided in advance and maintained
in the callgraph as so called inline plan.
- For each inlined call, the calle's node is clonned to represent the
+ For each inlined call, the callee's node is cloned to represent the
new function copy produced by inlininer.
- Each inlined call gets unque corresponding clone node of the callee
- and the datastructure is updated while inlining is performed, so
- the clones are elliminated and their callee edges redirected to the
+ 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
caller.
Each edge has "inline_failed" field. When the field is set to NULL,
- the call will be inlined. When it is non-NULL it contains an reason
- why inlining wasn't performaned.
+ the call will be inlined. When it is non-NULL it contains a reason
+ why inlining wasn't performed.
The varpool data structure:
/* Hash table used to convert declarations into nodes. */
static GTY((param_is (struct cgraph_node))) htab_t cgraph_hash;
-/* We destructivly update callgraph during inlining and thus we need to
- keep information on whether inlining happent separately. */
+/* We destructively update the callgraph during inlining, thus we need to
+ keep a separate table with information on whether inlining happened.
+ ??? Do this with a bit in the DECL instead of a hash table. */
htab_t cgraph_inline_hash;
/* The linked list of cgraph nodes. */
static hashval_t
hash_node (const void *p)
{
- return ((hashval_t)
- IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
- (((struct cgraph_node *) p)->decl)));
+ return htab_hash_pointer (((struct cgraph_node *) p)->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);
+ return (void *)((struct cgraph_node *) p1)->decl == p2;
}
-/* Allocate new callgraph node and insert it into basic datastructures. */
+/* Allocate new callgraph node and insert it into basic data structures. */
static struct cgraph_node *
cgraph_create_node (void)
{
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);
+ htab_find_slot_with_hash (cgraph_hash, decl,
+ htab_hash_pointer (decl), INSERT);
if (*slot)
return *slot;
/* This loop may turn out to be performance problem. In such case adding
hashtables into call nodes with very many edges is probably best
- sollution. It is not good idea to add pointer into CALL_EXPR itself
+ solution. It is not good idea to add pointer into CALL_EXPR itself
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)
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 *
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);
+ htab_find_slot_with_hash (cgraph_hash, node->decl,
+ htab_hash_pointer (node->decl), 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);
- }
}
}
static hashval_t
cgraph_varpool_hash_node (const void *p)
{
- return ((hashval_t)
- IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME
- (((struct cgraph_varpool_node *) p)->decl)));
+ return htab_hash_pointer (((struct cgraph_varpool_node *) p)->decl);
}
/* Returns nonzero if P1 and P2 are equal. */
static int
eq_cgraph_varpool_node (const void *p1, const void *p2)
{
- return ((DECL_ASSEMBLER_NAME (((struct cgraph_varpool_node *) p1)->decl)) ==
- (tree) p2);
+ return (void *)((struct cgraph_varpool_node *) p1)->decl == p2;
}
/* Return cgraph_varpool node assigned to DECL. Create new one when needed. */
cgraph_varpool_hash = htab_create_ggc (10, cgraph_varpool_hash_node,
eq_cgraph_varpool_node, NULL);
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_with_hash (cgraph_varpool_hash, decl,
+ htab_hash_pointer (decl), 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
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 (htab_find_slot (cgraph_inline_hash, decl, NO_INSERT) != NULL);
}
/* Create clone of E in the node N represented by CALL_EXPR the callgraph. */