Commit 7660e67e by Steven Bosscher

cgraphunit.c (cgraph_create_edges): Drop walk_tree in favor of walk_tree_without_duplicates.

2003-05-10  Steven Bosscher  <steven@gcc.gnu.org>

	* cgraphunit.c (cgraph_create_edges): Drop walk_tree in
	favor of walk_tree_without_duplicates.  Add comments.

From-SVN: r66712
parent 76abd4c6
2003-05-10 Steven Bosscher <steven@gcc.gnu.org>
* cgraphunit.c (cgraph_create_edges): Drop walk_tree in
favor of walk_tree_without_duplicates. Add comments.
2003-05-12 Josef Zlomek <zlomekj@suse.cz> 2003-05-12 Josef Zlomek <zlomekj@suse.cz>
* alloc-pool.h (ALLOC_POOL_ID_TYPE): New type. * alloc-pool.h (ALLOC_POOL_ID_TYPE): New type.
......
...@@ -68,6 +68,7 @@ static struct cgraph_node *queue = NULL; ...@@ -68,6 +68,7 @@ static struct cgraph_node *queue = NULL;
/* Notify finalize_compilation_unit that given node is reachable /* Notify finalize_compilation_unit that given node is reachable
or needed. */ or needed. */
void void
cgraph_mark_needed_node (node, needed) cgraph_mark_needed_node (node, needed)
struct cgraph_node *node; struct cgraph_node *node;
...@@ -107,6 +108,11 @@ record_call_1 (tp, walk_subtrees, data) ...@@ -107,6 +108,11 @@ record_call_1 (tp, walk_subtrees, data)
} }
else if (TREE_CODE (*tp) == CALL_EXPR) else if (TREE_CODE (*tp) == CALL_EXPR)
{ {
/* We cannot use get_callee_fndecl here because it actually tries
too hard to get the function declaration, looking for indirect
references and stripping NOPS. As a result, get_callee_fndecl
finds calls that shouldn't be in the call graph. */
tree decl = TREE_OPERAND (*tp, 0); tree decl = TREE_OPERAND (*tp, 0);
if (TREE_CODE (decl) == ADDR_EXPR) if (TREE_CODE (decl) == ADDR_EXPR)
decl = TREE_OPERAND (decl, 0); decl = TREE_OPERAND (decl, 0);
...@@ -115,6 +121,14 @@ record_call_1 (tp, walk_subtrees, data) ...@@ -115,6 +121,14 @@ record_call_1 (tp, walk_subtrees, data)
if (DECL_BUILT_IN (decl)) if (DECL_BUILT_IN (decl))
return NULL; return NULL;
cgraph_record_call (data, decl); cgraph_record_call (data, decl);
/* When we see a function call, we don't want to look at the
function reference in the ADDR_EXPR that is hanging from
the CALL_EXPR we're examining here, because we would
conclude incorrectly that the function's address could be
taken by something that is not a function call. So only
walk the function parameter list, skip the other subtrees. */
walk_tree (&TREE_OPERAND (*tp, 1), record_call_1, data, NULL); walk_tree (&TREE_OPERAND (*tp, 1), record_call_1, data, NULL);
*walk_subtrees = 0; *walk_subtrees = 0;
} }
...@@ -122,14 +136,16 @@ record_call_1 (tp, walk_subtrees, data) ...@@ -122,14 +136,16 @@ record_call_1 (tp, walk_subtrees, data)
return NULL; return NULL;
} }
/* Create cgraph edges for function calles via BODY. */ /* Create cgraph edges for function calls inside BODY from DECL. */
void void
cgraph_create_edges (decl, body) cgraph_create_edges (decl, body)
tree decl; tree decl;
tree body; tree body;
{ {
walk_tree (&body, record_call_1, decl, NULL); /* The nodes we're interested in are never shared, so walk
the tree ignoring duplicates. */
walk_tree_without_duplicates (&body, record_call_1, decl);
} }
/* Analyze the whole compilation unit once it is parsed completely. */ /* Analyze the whole compilation unit once it is parsed completely. */
...@@ -155,14 +171,16 @@ cgraph_finalize_compilation_unit () ...@@ -155,14 +171,16 @@ cgraph_finalize_compilation_unit ()
|| (DECL_ASSEMBLER_NAME_SET_P (decl) || (DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))) && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
{ {
cgraph_mark_needed_node (node, 1); /* This function can be called from outside this compliation
unit, so it most definitely is needed. */
cgraph_mark_needed_node (node, 1);
} }
} }
/* Propagate reachability flag and lower representation of all reachable /* Propagate reachability flag and lower representation of all reachable
functions. In the future, lowering will introduce new functions and functions. In the future, lowering will introduce new functions and
new entry points on the way (by template instantiation and virtual new entry points on the way (by template instantiation and virtual
method table generation for instance). */ method table generation for instance). */
while (queue) while (queue)
{ {
tree decl = queue->decl; tree decl = queue->decl;
...@@ -184,6 +202,7 @@ cgraph_finalize_compilation_unit () ...@@ -184,6 +202,7 @@ cgraph_finalize_compilation_unit ()
if (lang_hooks.callgraph.lower_function) if (lang_hooks.callgraph.lower_function)
(*lang_hooks.callgraph.lower_function) (decl); (*lang_hooks.callgraph.lower_function) (decl);
/* First kill forward declaration so reverse inling works properly. */ /* First kill forward declaration so reverse inling works properly. */
cgraph_create_edges (decl, DECL_SAVED_TREE (decl)); cgraph_create_edges (decl, DECL_SAVED_TREE (decl));
...@@ -194,6 +213,7 @@ cgraph_finalize_compilation_unit () ...@@ -194,6 +213,7 @@ cgraph_finalize_compilation_unit ()
} }
node->lowered = true; node->lowered = true;
} }
if (!quiet_flag) if (!quiet_flag)
fprintf (stderr, "\n\nReclaiming functions:"); fprintf (stderr, "\n\nReclaiming functions:");
...@@ -217,11 +237,13 @@ cgraph_mark_functions_to_output () ...@@ -217,11 +237,13 @@ cgraph_mark_functions_to_output ()
{ {
struct cgraph_node *node; struct cgraph_node *node;
/* Figure out functions we want to assemble. */
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
{ {
tree decl = node->decl; tree decl = node->decl;
/* We need to output all local functions that are used and not
always inlined, as well as those that are reachable from
outside the current compilation unit. */
if (DECL_SAVED_TREE (decl) if (DECL_SAVED_TREE (decl)
&& (node->needed && (node->needed
|| (!node->local.inline_many && !node->global.inline_once || (!node->local.inline_many && !node->global.inline_once
...@@ -234,6 +256,7 @@ cgraph_mark_functions_to_output () ...@@ -234,6 +256,7 @@ cgraph_mark_functions_to_output ()
} }
/* Optimize the function before expansion. */ /* Optimize the function before expansion. */
static void static void
cgraph_optimize_function (node) cgraph_optimize_function (node)
struct cgraph_node *node; struct cgraph_node *node;
...@@ -250,6 +273,7 @@ cgraph_optimize_function (node) ...@@ -250,6 +273,7 @@ cgraph_optimize_function (node)
} }
/* Expand function specified by NODE. */ /* Expand function specified by NODE. */
static void static void
cgraph_expand_function (node) cgraph_expand_function (node)
struct cgraph_node *node; struct cgraph_node *node;
...@@ -260,11 +284,12 @@ cgraph_expand_function (node) ...@@ -260,11 +284,12 @@ cgraph_expand_function (node)
cgraph_optimize_function (node); cgraph_optimize_function (node);
/* Avoid RTL inlining from taking place. */ /* Generate RTL for the body of DECL. Nested functions are expanded
via lang_expand_decl_stmt. */
(*lang_hooks.callgraph.expand_function) (decl); (*lang_hooks.callgraph.expand_function) (decl);
/* When we decided to inline the function once, we never ever should need to /* When we decided to inline the function once, we never ever should
output it separately. */ need to output it separately. */
if (node->global.inline_once) if (node->global.inline_once)
abort (); abort ();
if (!node->local.inline_many if (!node->local.inline_many
...@@ -277,11 +302,12 @@ cgraph_expand_function (node) ...@@ -277,11 +302,12 @@ cgraph_expand_function (node)
/* Expand all functions that must be output. /* Expand all functions that must be output.
Attempt to topologically sort the nodes so function is output when Attempt to topologically sort the nodes so function is output when
all called functions are already assembled to allow data to be propagated all called functions are already assembled to allow data to be
accross the callgraph. Use stack to get smaller distance between function propagated accross the callgraph. Use a stack to get smaller distance
and it's callees (later we may use more sophisticated algorithm for between a function and it's callees (later we may choose to use a more
function reordering, we will likely want to use subsections to make output sophisticated algorithm for function reordering; we will likely want
functions to appear in top-down order, not bottom-up they are assembled). */ to use subsections to make the output functions appear in top-down
order. */
static void static void
cgraph_expand_functions () cgraph_expand_functions ()
...@@ -298,10 +324,10 @@ cgraph_expand_functions () ...@@ -298,10 +324,10 @@ cgraph_expand_functions ()
cgraph_mark_functions_to_output (); cgraph_mark_functions_to_output ();
/* We have to deal with cycles nicely, so use depth first traversal /* We have to deal with cycles nicely, so use a depth first traversal
algorithm. Ignore the fact that some functions won't need to be output output algorithm. Ignore the fact that some functions won't need
and put them into order as well, so we get dependencies right trought inlined to be output and put them into order as well, so we get dependencies
functions. */ right through intline functions. */
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
node->aux = NULL; node->aux = NULL;
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
...@@ -380,8 +406,8 @@ cgraph_mark_local_functions () ...@@ -380,8 +406,8 @@ cgraph_mark_local_functions ()
} }
} }
/* Decide what function should be inlined because they are invoked once /* Decide what function should be inlined because they are invoked once
(so inlining won't result in duplication of the code). */ (so inlining won't result in duplication of the code). */
static void static void
cgraph_mark_functions_to_inline_once () cgraph_mark_functions_to_inline_once ()
...@@ -391,8 +417,8 @@ cgraph_mark_functions_to_inline_once () ...@@ -391,8 +417,8 @@ cgraph_mark_functions_to_inline_once ()
if (!quiet_flag) if (!quiet_flag)
fprintf (stderr, "\n\nMarking functions to inline once:"); fprintf (stderr, "\n\nMarking functions to inline once:");
/* Now look for function called only once and mark them to inline. From this /* Now look for function called only once and mark them to inline.
point number of calls to given function won't grow. */ From this point number of calls to given function won't grow. */
for (node = cgraph_nodes; node; node = node->next) for (node = cgraph_nodes; node; node = node->next)
{ {
if (node->callers && !node->callers->next_caller && !node->needed if (node->callers && !node->callers->next_caller && !node->needed
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment