cgraph.c (cgraph_nodes_queue): Declare.

* cgraph.c (cgraph_nodes_queue): Declare.
	(eq_node): Take identifier as p2.
	(cgraph_node): Update htab_find_slot_with_hash call.
	(cgraph_node_for_identifier): New.
	(cgraph_mark_needed_node): Move here from cgraphunit.c.
	* cgraph.h (cgraph_nodes_queue): Declare.
	(cgraph_node_for_identifier): Declare.
	* cgraphunit.c (cgraph_finalize_function): Collect entry points here
	instead of in cgraph_finalize_compilation_unit; constructors and
	destructors are entry points.
	(cgraph_finalize_compilation_unit): Reorganize debug outout;
	examine nested functions after lowerng; call collect_functions hook.
	(cgraph_mark_local_functions): DECL_COMDAT functions are not local.
	(cgraph_finalize_compilation_unit): Do not collect entry points.
	* varasm.c: Include cgraph.h
	(assemble_name): Mark referenced identifier as needed.

	* cgraphunit.c (record_call_1): Use get_callee_fndecl.

From-SVN: r68390
This commit is contained in:
Jan Hubicka 2003-06-23 23:11:44 +02:00 committed by Jan Hubicka
parent 89ce1c8f76
commit 1668aabc22
5 changed files with 136 additions and 66 deletions

View File

@ -1,3 +1,24 @@
Mon Jun 23 23:07:35 CEST 2003 Jan Hubicka <jh@suse.cz>
* cgraph.c (cgraph_nodes_queue): Declare.
(eq_node): Take identifier as p2.
(cgraph_node): Update htab_find_slot_with_hash call.
(cgraph_node_for_identifier): New.
(cgraph_mark_needed_node): Move here from cgraphunit.c.
* cgraph.h (cgraph_nodes_queue): Declare.
(cgraph_node_for_identifier): Declare.
* cgraphunit.c (cgraph_finalize_function): Collect entry points here
instead of in cgraph_finalize_compilation_unit; constructors and
destructors are entry points.
(cgraph_finalize_compilation_unit): Reorganize debug outout;
examine nested functions after lowerng; call collect_functions hook.
(cgraph_mark_local_functions): DECL_COMDAT functions are not local.
(cgraph_finalize_compilation_unit): Do not collect entry points.
* varasm.c: Include cgraph.h
(assemble_name): Mark referenced identifier as needed.
* cgraphunit.c (record_call_1): Use get_callee_fndecl.
2003-06-23 Jakub Jelinek <jakub@redhat.com>
* config/i386/i386.c (x86_output_mi_thunk): Don't pass MEM to %P0,

View File

@ -48,6 +48,9 @@ static htab_t cgraph_hash = 0;
/* The linked list of cgraph nodes. */
struct cgraph_node *cgraph_nodes;
/* Queue of cgraph nodes scheduled to be lowered. */
struct cgraph_node *cgraph_nodes_queue;
/* Number of nodes in existence. */
int cgraph_n_nodes;
@ -79,7 +82,7 @@ eq_node (p1, p2)
const void *p2;
{
return ((DECL_ASSEMBLER_NAME (((struct cgraph_node *) p1)->decl)) ==
DECL_ASSEMBLER_NAME ((tree) p2));
(tree) p2);
}
/* Return cgraph node assigned to DECL. Create new one when needed. */
@ -100,7 +103,8 @@ cgraph_node (decl)
}
slot =
(struct cgraph_node **) htab_find_slot_with_hash (cgraph_hash, decl,
(struct cgraph_node **) htab_find_slot_with_hash (cgraph_hash,
DECL_ASSEMBLER_NAME (decl),
htab_hash_pointer
(DECL_ASSEMBLER_NAME
(decl)), 1);
@ -125,6 +129,30 @@ cgraph_node (decl)
return node;
}
/* Try to find existing function for identifier ID. */
struct cgraph_node *
cgraph_node_for_identifier (id)
tree id;
{
struct cgraph_node **slot;
if (TREE_CODE (id) != IDENTIFIER_NODE)
abort ();
if (!cgraph_hash)
{
cgraph_hash = htab_create (10, hash_node, eq_node, NULL);
VARRAY_TREE_INIT (known_fns, 32, "known_fns");
}
slot =
(struct cgraph_node **) htab_find_slot_with_hash (cgraph_hash, id,
htab_hash_pointer (id), 0);
if (!slot)
return NULL;
return *slot;
}
/* Create edge from CALLER to CALLEE in the cgraph. */
static struct cgraph_edge *
@ -194,6 +222,28 @@ cgraph_remove_node (node)
/* Do not free the structure itself so the walk over chain can continue. */
}
/* Notify finalize_compilation_unit that given node is reachable
or needed. */
void
cgraph_mark_needed_node (node, needed)
struct cgraph_node *node;
int needed;
{
if (needed)
{
node->needed = 1;
}
if (!node->reachable)
{
node->reachable = 1;
if (DECL_SAVED_TREE (node->decl))
{
node->aux = cgraph_nodes_queue;
cgraph_nodes_queue = node;
}
}
}
/* Record call from CALLER to CALLEE */

View File

@ -100,6 +100,7 @@ struct cgraph_edge
extern struct cgraph_node *cgraph_nodes;
extern int cgraph_n_nodes;
extern bool cgraph_global_info_ready;
extern struct cgraph_node *cgraph_nodes_queue;
/* In cgraph.c */
void dump_cgraph PARAMS ((FILE *));
@ -107,6 +108,7 @@ void cgraph_remove_call PARAMS ((tree, tree));
void cgraph_remove_node PARAMS ((struct cgraph_node *));
struct cgraph_edge *cgraph_record_call PARAMS ((tree, tree));
struct cgraph_node *cgraph_node PARAMS ((tree decl));
struct cgraph_node *cgraph_node_for_identifier PARAMS ((tree id));
bool cgraph_calls_p PARAMS ((tree, tree));
struct cgraph_local_info *cgraph_local_info PARAMS ((tree));
struct cgraph_global_info *cgraph_global_info PARAMS ((tree));

View File

@ -55,7 +55,29 @@ cgraph_finalize_function (decl, body)
node->decl = decl;
node->local.can_inline_once = tree_inlinable_function_p (decl, 1);
if (/* Externally visible functions must be output. The exception are
COMDAT functions that must be output only when they are needed.
Similarly are handled defered functions and
external functions (GCC extension "extern inline") */
(TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
/* ??? Constructors and destructors not called otherwise can be inlined
into single construction/destruction function per section to save some
resources. For now just mark it as reachable. */
|| DECL_STATIC_CONSTRUCTOR (decl)
|| DECL_STATIC_DESTRUCTOR (decl)
/* Function whose name is output to the assembler file must be produced.
It is possible to assemble the name later after finalizing the function
and the fact is noticed in assemble_name then. */
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
{
cgraph_mark_needed_node (node, 1);
}
if (!node->needed && !DECL_COMDAT (node->decl))
node->local.can_inline_once = tree_inlinable_function_p (decl, 1);
else
node->local.can_inline_once = 0;
if (flag_inline_trees)
node->local.inline_many = tree_inlinable_function_p (decl, 0);
else
@ -64,33 +86,6 @@ cgraph_finalize_function (decl, body)
(*debug_hooks->deferred_inline_function) (decl);
}
static struct cgraph_node *queue = NULL;
/* Notify finalize_compilation_unit that given node is reachable
or needed. */
void
cgraph_mark_needed_node (node, needed)
struct cgraph_node *node;
int needed;
{
if (needed)
{
if (DECL_SAVED_TREE (node->decl))
announce_function (node->decl);
node->needed = 1;
}
if (!node->reachable)
{
node->reachable = 1;
if (DECL_SAVED_TREE (node->decl))
{
node->aux = queue;
queue = node;
}
}
}
/* Walk tree and record all calls. Called via walk_tree. */
static tree
record_call_1 (tp, walk_subtrees, data)
@ -108,15 +103,8 @@ record_call_1 (tp, walk_subtrees, data)
}
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);
if (TREE_CODE (decl) == ADDR_EXPR)
decl = TREE_OPERAND (decl, 0);
if (TREE_CODE (decl) == FUNCTION_DECL)
tree decl = get_callee_fndecl (*tp);
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
{
if (DECL_BUILT_IN (decl))
return NULL;
@ -156,40 +144,31 @@ cgraph_finalize_compilation_unit ()
struct cgraph_node *node;
struct cgraph_edge *edge;
/* Collect entry points to the unit. */
if (!quiet_flag)
fprintf (stderr, "\n\nUnit entry points:");
for (node = cgraph_nodes; node; node = node->next)
{
tree decl = node->decl;
if (!DECL_SAVED_TREE (decl))
continue;
if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
{
/* This function can be called from outside this compliation
unit, so it most definitely is needed. */
cgraph_mark_needed_node (node, 1);
}
fprintf (stderr, "\n\nInitial entry points:");
for (node = cgraph_nodes; node; node = node->next)
if (node->needed && DECL_SAVED_TREE (node->decl))
announce_function (node->decl);
}
/* Propagate reachability flag and lower representation of all reachable
functions. In the future, lowering will introduce new functions and
new entry points on the way (by template instantiation and virtual
method table generation for instance). */
while (queue)
while (cgraph_nodes_queue)
{
tree decl = queue->decl;
tree decl = cgraph_nodes_queue->decl;
node = cgraph_nodes_queue;
cgraph_nodes_queue = cgraph_nodes_queue->aux;
node = queue;
queue = queue->aux;
if (node->lowered || !node->reachable || !DECL_SAVED_TREE (decl))
abort ();
if (lang_hooks.callgraph.lower_function)
(*lang_hooks.callgraph.lower_function) (decl);
/* At the moment frontend automatically emits all nested functions. */
if (node->nested)
{
@ -200,9 +179,6 @@ cgraph_finalize_compilation_unit ()
cgraph_mark_needed_node (node2, 0);
}
if (lang_hooks.callgraph.lower_function)
(*lang_hooks.callgraph.lower_function) (decl);
/* First kill forward declaration so reverse inling works properly. */
cgraph_create_edges (decl, DECL_SAVED_TREE (decl));
@ -213,6 +189,15 @@ cgraph_finalize_compilation_unit ()
}
node->lowered = true;
}
/* Collect entry points to the unit. */
if (!quiet_flag)
{
fprintf (stderr, "\n\nUnit entry points:");
for (node = cgraph_nodes; node; node = node->next)
if (node->needed && DECL_SAVED_TREE (node->decl))
announce_function (node->decl);
}
if (!quiet_flag)
fprintf (stderr, "\n\nReclaiming functions:");
@ -248,7 +233,8 @@ cgraph_mark_functions_to_output ()
&& (node->needed
|| (!node->local.inline_many && !node->global.inline_once
&& node->reachable)
|| TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
&& !TREE_ASM_WRITTEN (decl) && !node->origin
&& !DECL_EXTERNAL (decl))
node->output = 1;
@ -331,7 +317,7 @@ cgraph_expand_functions ()
for (node = cgraph_nodes; node; node = node->next)
node->aux = NULL;
for (node = cgraph_nodes; node; node = node->next)
if (node->output && !node->aux)
if (!node->aux)
{
node2 = node;
if (!node->callers)
@ -400,6 +386,7 @@ cgraph_mark_local_functions ()
{
node->local.local = (!node->needed
&& DECL_SAVED_TREE (node->decl)
&& !DECL_COMDAT (node->decl)
&& !TREE_PUBLIC (node->decl));
if (node->local.local)
announce_function (node->decl);

View File

@ -48,6 +48,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tm_p.h"
#include "debug.h"
#include "target.h"
#include "cgraph.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
@ -1742,7 +1743,16 @@ assemble_name (file, name)
id = maybe_get_identifier (real_name);
if (id)
TREE_SYMBOL_REFERENCED (id) = 1;
{
if (!TREE_SYMBOL_REFERENCED (id)
&& !cgraph_global_info_ready)
{
struct cgraph_node *node = cgraph_node_for_identifier (id);
if (node)
cgraph_mark_needed_node (node, 1);
}
TREE_SYMBOL_REFERENCED (id) = 1;
}
if (name[0] == '*')
fputs (&name[1], file);