1 /* Callgraph handling code.
2 Copyright (C) 2003 Free Software Foundation, Inc.
3 Contributed by Jan Hubicka
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
24 #include "coretypes.h"
27 #include "tree-inline.h"
28 #include "langhooks.h"
37 static void cgraph_expand_functions
PARAMS ((void));
38 static void cgraph_mark_functions_to_output
PARAMS ((void));
39 static void cgraph_expand_function
PARAMS ((struct cgraph_node
*));
40 static tree record_call_1
PARAMS ((tree
*, int *, void *));
42 /* Analyze function once it is parsed. Set up the local information
43 available - create cgraph edges for function calles via BODY. */
46 cgraph_finalize_function (decl
, body
)
48 tree body ATTRIBUTE_UNUSED
;
50 struct cgraph_node
*node
= cgraph_node (decl
);
54 /* Set TREE_UNINLINABLE flag. */
55 tree_inlinable_function_p (decl
);
57 (*debug_hooks
->deferred_inline_function
) (decl
);
60 static struct cgraph_node
*queue
= NULL
;
62 /* Notify finalize_compilation_unit that given node is reachable
65 cgraph_mark_needed_node (node
, needed
)
66 struct cgraph_node
*node
;
71 if (DECL_SAVED_TREE (node
->decl
))
72 announce_function (node
->decl
);
78 if (DECL_SAVED_TREE (node
->decl
))
86 /* Walk tree and record all calls. Called via walk_tree. */
88 record_call_1 (tp
, walk_subtrees
, data
)
93 /* Record dereferences to the functions. This makes the functions
94 reachable unconditionally. */
95 if (TREE_CODE (*tp
) == ADDR_EXPR
)
97 tree decl
= TREE_OPERAND (*tp
, 0);
98 if (TREE_CODE (decl
) == FUNCTION_DECL
)
99 cgraph_mark_needed_node (cgraph_node (decl
), 1);
101 else if (TREE_CODE (*tp
) == CALL_EXPR
)
103 tree decl
= TREE_OPERAND (*tp
, 0);
104 if (TREE_CODE (decl
) == ADDR_EXPR
)
105 decl
= TREE_OPERAND (decl
, 0);
106 if (TREE_CODE (decl
) == FUNCTION_DECL
)
108 if (DECL_BUILT_IN (decl
))
110 cgraph_record_call (data
, decl
);
111 walk_tree (&TREE_OPERAND (*tp
, 1), record_call_1
, data
, NULL
);
118 /* Create cgraph edges for function calles via BODY. */
121 cgraph_create_edges (decl
, body
)
125 walk_tree (&body
, record_call_1
, decl
, NULL
);
128 /* Analyze the whole compilation unit once it is parsed completely. */
131 cgraph_finalize_compilation_unit ()
133 struct cgraph_node
*node
;
134 struct cgraph_edge
*edge
;
136 /* Collect entry points to the unit. */
139 fprintf (stderr
, "\n\nUnit entry points:");
141 for (node
= cgraph_nodes
; node
; node
= node
->next
)
143 tree decl
= node
->decl
;
145 if (!DECL_SAVED_TREE (decl
))
147 if ((TREE_PUBLIC (decl
) && !DECL_COMDAT (decl
) && !DECL_EXTERNAL (decl
))
148 || (DECL_ASSEMBLER_NAME_SET_P (decl
)
149 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl
))))
151 cgraph_mark_needed_node (node
, 1);
155 /* Propagate reachability flag and lower representation of all reachable
156 functions. In the future, lowering will introduce new functions and
157 new entry points on the way (by template instantiation and virtual
158 method table generation for instance). */
161 tree decl
= queue
->decl
;
165 if (node
->lowered
|| !node
->reachable
|| !DECL_SAVED_TREE (decl
))
168 /* At the moment frontend automatically emits all nested functions. */
171 struct cgraph_node
*node2
;
173 for (node2
= node
->nested
; node2
; node2
= node2
->next_nested
)
174 if (!node2
->reachable
)
175 cgraph_mark_needed_node (node2
, 0);
178 if (lang_hooks
.callgraph
.lower_function
)
179 (*lang_hooks
.callgraph
.lower_function
) (decl
);
180 /* First kill forward declaration so reverse inling works properly. */
181 cgraph_create_edges (decl
, DECL_SAVED_TREE (decl
));
183 for (edge
= node
->callees
; edge
; edge
= edge
->next_callee
)
185 if (!edge
->callee
->reachable
)
186 cgraph_mark_needed_node (edge
->callee
, 0);
188 node
->lowered
= true;
191 fprintf (stderr
, "\n\nReclaiming functions:");
193 for (node
= cgraph_nodes
; node
; node
= node
->next
)
195 tree decl
= node
->decl
;
197 if (!node
->reachable
&& DECL_SAVED_TREE (decl
))
199 DECL_SAVED_TREE (decl
) = NULL
;
200 announce_function (decl
);
206 /* Figure out what functions we want to assemble. */
209 cgraph_mark_functions_to_output ()
211 struct cgraph_node
*node
;
213 /* Figure out functions we want to assemble. */
214 for (node
= cgraph_nodes
; node
; node
= node
->next
)
216 tree decl
= node
->decl
;
218 if (DECL_SAVED_TREE (decl
)
220 || (DECL_UNINLINABLE (decl
) && node
->reachable
)
221 || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl
)))
222 && !TREE_ASM_WRITTEN (decl
) && !node
->origin
223 && !DECL_EXTERNAL (decl
))
228 /* Expand function specified by NODE. */
230 cgraph_expand_function (node
)
231 struct cgraph_node
*node
;
233 tree decl
= node
->decl
;
235 announce_function (decl
);
236 if (flag_inline_trees
)
237 optimize_inline_calls (decl
);
238 (*lang_hooks
.callgraph
.expand_function
) (decl
);
239 if (DECL_UNINLINABLE (decl
))
240 DECL_SAVED_TREE (decl
) = NULL
;
241 current_function_decl
= NULL
;
245 /* Expand all functions that must be output.
247 Attempt to topologically sort the nodes so function is output when
248 all called functions are already assembled to allow data to be propagated
249 accross the callgraph. Use stack to get smaller distance between function
250 and it's callees (later we may use more sophisticated algorithm for
251 function reordering, we will likely want to use subsections to make output
252 functions to appear in top-down order, not bottom-up they are assembled). */
255 cgraph_expand_functions ()
257 struct cgraph_node
*node
, *node2
;
258 struct cgraph_node
**stack
=
259 xcalloc (sizeof (struct cgraph_node
*), cgraph_n_nodes
);
260 struct cgraph_node
**order
=
261 xcalloc (sizeof (struct cgraph_node
*), cgraph_n_nodes
);
264 struct cgraph_edge
*edge
, last
;
267 cgraph_mark_functions_to_output ();
269 /* We have to deal with cycles nicely, so use depth first traversal
270 algorithm. Ignore the fact that some functions won't need to be output
271 and put them into order as well, so we get dependencies right trought inlined
273 for (node
= cgraph_nodes
; node
; node
= node
->next
)
275 for (node
= cgraph_nodes
; node
; node
= node
->next
)
276 if (node
->output
&& !node
->aux
)
282 node
->aux
= node
->callers
;
285 while (node2
->aux
!= &last
)
288 if (edge
->next_caller
)
289 node2
->aux
= edge
->next_caller
;
292 if (!edge
->caller
->aux
)
294 if (!edge
->caller
->callers
)
295 edge
->caller
->aux
= &last
;
297 edge
->caller
->aux
= edge
->caller
->callers
;
298 stack
[stack_size
++] = node2
;
299 node2
= edge
->caller
;
303 if (node2
->aux
== &last
)
305 order
[order_pos
++] = node2
;
307 node2
= stack
[--stack_size
];
313 for (i
= order_pos
- 1; i
>=0; i
--)
318 if (!node
->reachable
)
321 cgraph_expand_function (node
);
328 /* Perform simple optimizations based on callgraph. */
333 struct cgraph_node
*node
;
335 struct cgraph_edge
*edge
;
338 fprintf (stderr
, "\n\nAssembling functions:");
340 /* Output everything.
341 ??? Our inline heuristic may decide to not inline functions previously
342 marked as inlinable thus adding new function bodies that must be output.
343 Later we should move all inlining decisions to callgraph code to make
345 cgraph_expand_functions ();
349 for (node
= cgraph_nodes
; node
; node
= node
->next
)
354 for (edge
= node
->callees
; edge
; edge
= edge
->next_callee
)
355 if (!edge
->callee
->needed
)
356 changed
= edge
->callee
->needed
= true;
359 cgraph_expand_functions ();