Commit 9b0436b7 by Jan Hubicka Committed by Jan Hubicka

cgraph.c (cgraph_remove_node): Fix removal from linked list.


	* cgraph.c (cgraph_remove_node): Fix removal from linked list.
	* cgraphunit.c (cgraph_finalize_compilation_unit): Clear next_needed
	list.
	(cgraph_remove_unreachable_nodes): New function
	(cgraph_decide_inlining_of_small_function): Fix pasto.
	(cgraph_decide_inlining_incrementally): Fix pasto.
	(cgrpah_decide_inlining): Likewise; remove unreachable nodes.

From-SVN: r76142
parent 954b12d2
2004-01-19 Jan Hubicka <jh@suse.cz>
* cgraph.c (cgraph_remove_node): Fix removal from linked list.
* cgraphunit.c (cgraph_finalize_compilation_unit): Clear next_needed
list.
(cgraph_remove_unreachable_nodes): New function
(cgraph_decide_inlining_of_small_function): Fix pasto.
(cgraph_decide_inlining_incrementally): Fix pasto.
(cgrpah_decide_inlining): Likewise; remove unreachable nodes.
2004-01-19 Steven Bosscher <stevenb@suse.de>
* gengtype.c (header_file): Make it static.
......
......@@ -231,7 +231,7 @@ cgraph_remove_node (struct cgraph_node *node)
if (node->previous)
node->previous->next = node->next;
else
cgraph_nodes = node;
cgraph_nodes = node->next;
if (node->next)
node->next->previous = node->previous;
DECL_SAVED_TREE (node->decl) = NULL;
......
......@@ -436,6 +436,8 @@ cgraph_finalize_compilation_unit (void)
if (cgraph_dump_file)
fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
}
else
node->next_needed = NULL;
}
if (cgraph_dump_file)
{
......@@ -792,6 +794,105 @@ cgraph_inlined_callees (struct cgraph_node *node, struct cgraph_node **array)
return nfound;
}
/* Perform reachability analysis and reclaim all unreachable nodes.
This function also remove unneeded bodies of extern inline functions
and thus needs to be done only after inlining decisions has been made. */
static bool
cgraph_remove_unreachable_nodes (void)
{
struct cgraph_node *first = (void *) 1;
struct cgraph_node *node;
bool changed = false;
int insns = 0;
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "\nReclaiming functions:");
#ifdef ENABLE_CHECKING
for (node = cgraph_nodes; node; node = node->next)
if (node->aux)
abort ();
#endif
for (node = cgraph_nodes; node; node = node->next)
if (node->needed && (!DECL_EXTERNAL (node->decl) || !node->analyzed))
{
node->aux = first;
first = node;
}
else if (node->aux)
abort ();
/* Perform reachability analysis. As a special case do not consider
extern inline functions not inlined as live because we won't output
them at all. */
while (first != (void *) 1)
{
struct cgraph_edge *e;
node = first;
first = first->aux;
for (e = node->callees; e; e = e->next_callee)
if (!e->callee->aux
&& node->analyzed
&& (!e->inline_failed || !e->callee->analyzed
|| !DECL_EXTERNAL (e->callee->decl)))
{
e->callee->aux = first;
first = e->callee;
}
}
/* Remove unreachable nodes. Extern inline functions need special care;
Unreachable extern inline functions shall be removed.
Reachable extern inline functions we never inlined shall get their bodies
elliminated
Reachable extern inline functions we sometimes inlined will be turned into
unanalyzed nodes so they look like for true extern functions to the rest
of code. */
for (node = cgraph_nodes; node; node = node->next)
{
if (!node->aux)
{
int local_insns;
tree decl = node->decl;
if (DECL_SAVED_INSNS (decl))
local_insns = node->local.self_insns;
else
local_insns = 0;
if (cgraph_dump_file)
fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
if (!node->analyzed || !DECL_EXTERNAL (node->decl))
cgraph_remove_node (node);
else
{
struct cgraph_edge *e;
for (e = node->callers; e; e = e->next_caller)
if (e->caller->aux)
break;
if (e || node->needed)
{
DECL_SAVED_TREE (node->decl) = NULL_TREE;
while (node->callees)
cgraph_remove_edge (node, node->callees->callee);
node->analyzed = false;
}
else
cgraph_remove_node (node);
}
if (!DECL_SAVED_TREE (decl))
insns += local_insns;
changed = true;
}
}
for (node = cgraph_nodes; node; node = node->next)
node->aux = NULL;
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "\nReclaimed %i insns", insns);
return changed;
}
/* Estimate size of the function after inlining WHAT into TO. */
static int
......@@ -1055,7 +1156,7 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
ninlined, &e->inline_failed))
{
for (i = 0; i < ninlined; i++)
inlined[i]->output = 0, node->aux = 0;
inlined[i]->output = 0, inlined[i]->aux = 0;
if (cgraph_dump_file)
fprintf (cgraph_dump_file, " Not inlining into %s.\n",
cgraph_node_name (e->caller));
......@@ -1071,17 +1172,16 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
the keys. */
for (i = 0; i < ninlined; i++)
{
inlined[i]->output = 0, node->aux = 0;
inlined[i]->output = 0, inlined[i]->aux = 0;
if (heap_node[inlined[i]->uid])
fibheap_replace_key (heap, heap_node[inlined[i]->uid],
cgraph_estimate_growth (inlined[i]));
}
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
" Inlined into %s which now has %i insns.\n",
cgraph_node_name (e->caller),
e->caller->global.insns);
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
" Inlined into %s which now has %i insns.\n",
cgraph_node_name (e->caller),
e->caller->global.insns);
}
/* Similarly all functions called by the function we just inlined
......@@ -1101,7 +1201,8 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
fibheap_replace_key (heap, heap_node[e->callee->uid],
cgraph_estimate_growth (e->callee));
inlined_callees[i]->output = 0, node->aux = 0;
inlined_callees[i]->output = 0;
inlined_callees[i]->aux = 0;
}
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
......@@ -1150,6 +1251,11 @@ cgraph_decide_inlining (void)
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "\nInlining always_inline functions:\n");
#ifdef ENABLE_CHECKING
for (node = cgraph_nodes; node; node = node->next)
if (node->aux || node->output)
abort ();
#endif
/* In the first pass mark all always_inline edges. Do this with a priority
so none of our later choices will make this impossible. */
......@@ -1185,7 +1291,7 @@ cgraph_decide_inlining (void)
cgraph_mark_inline (node, e->callee, inlined, ninlined,
inlined_callees, ninlined_callees);
for (y = 0; y < ninlined_callees; y++)
inlined_callees[y]->output = 0, node->aux = 0;
inlined_callees[y]->output = 0, inlined_callees[y]->aux = 0;
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
" Inlined into %s which now has %i insns.\n",
......@@ -1197,12 +1303,22 @@ cgraph_decide_inlining (void)
" Inlined %i times for a net change of %+i insns.\n",
node->global.cloned_times, overall_insns - old_insns);
for (y = 0; y < ninlined; y++)
inlined[y]->output = 0, node->aux = 0;
inlined[y]->output = 0, inlined[y]->aux = 0;
}
#ifdef ENABLE_CHECKING
for (node = cgraph_nodes; node; node = node->next)
if (node->aux || node->output)
abort ();
#endif
if (!flag_really_no_inline)
{
cgraph_decide_inlining_of_small_functions (inlined, inlined_callees);
#ifdef ENABLE_CHECKING
for (node = cgraph_nodes; node; node = node->next)
if (node->aux || node->output)
abort ();
#endif
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "\nDeciding on functions called once:\n");
......@@ -1251,7 +1367,7 @@ cgraph_decide_inlining (void)
ninlined, inlined_callees,
ninlined_callees);
for (y = 0; y < ninlined_callees; y++)
inlined_callees[y]->output = 0, node->aux = 0;
inlined_callees[y]->output = 0, inlined_callees[y]->aux = 0;
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
" Inlined into %s which now has %i insns"
......@@ -1267,11 +1383,12 @@ cgraph_decide_inlining (void)
" Inline limit reached, not inlined.\n");
}
for (y = 0; y < ninlined; y++)
inlined[y]->output = 0, node->aux = 0;
inlined[y]->output = 0, inlined[y]->aux = 0;
}
}
}
}
cgraph_remove_unreachable_nodes ();
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
......@@ -1317,7 +1434,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
cgraph_mark_inline (node, e->callee, inlined, ninlined,
inlined_callees, ninlined_callees);
for (y = 0; y < ninlined_callees; y++)
inlined_callees[y]->output = 0, node->aux = 0;
inlined_callees[y]->output = 0, inlined_callees[y]->aux = 0;
}
if (!flag_really_no_inline)
......@@ -1342,13 +1459,13 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node)
cgraph_mark_inline (node, e->callee, inlined, ninlined,
inlined_callees, ninlined_callees);
for (y = 0; y < ninlined_callees; y++)
inlined_callees[y]->output = 0, node->aux = 0;
inlined_callees[y]->output = 0, inlined_callees[y]->aux = 0;
}
}
/* Clear the flags set by cgraph_inlined_into. */
for (y = 0; y < ninlined; y++)
inlined[y]->output = 0, node->aux = 0;
inlined[y]->output = 0, inlined[y]->aux = 0;
free (inlined);
free (inlined_callees);
......
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