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"
36 #include "diagnostic.h"
38 static void cgraph_expand_functions
PARAMS ((void));
39 static void cgraph_mark_functions_to_output
PARAMS ((void));
40 static void cgraph_expand_function
PARAMS ((struct cgraph_node
*));
41 static tree record_call_1
PARAMS ((tree
*, int *, void *));
42 static void cgraph_mark_local_functions
PARAMS ((void));
44 /* Analyze function once it is parsed. Set up the local information
45 available - create cgraph edges for function calles via BODY. */
48 cgraph_finalize_function (decl
, body
)
50 tree body ATTRIBUTE_UNUSED
;
52 struct cgraph_node
*node
= cgraph_node (decl
);
56 if (flag_inline_trees
)
57 node
->local
.inline_many
= tree_inlinable_function_p (decl
);
59 node
->local
.inline_many
= 0;
61 (*debug_hooks
->deferred_inline_function
) (decl
);
64 static struct cgraph_node
*queue
= NULL
;
66 /* Notify finalize_compilation_unit that given node is reachable
69 cgraph_mark_needed_node (node
, needed
)
70 struct cgraph_node
*node
;
75 if (DECL_SAVED_TREE (node
->decl
))
76 announce_function (node
->decl
);
82 if (DECL_SAVED_TREE (node
->decl
))
90 /* Walk tree and record all calls. Called via walk_tree. */
92 record_call_1 (tp
, walk_subtrees
, data
)
97 /* Record dereferences to the functions. This makes the functions
98 reachable unconditionally. */
99 if (TREE_CODE (*tp
) == ADDR_EXPR
)
101 tree decl
= TREE_OPERAND (*tp
, 0);
102 if (TREE_CODE (decl
) == FUNCTION_DECL
)
103 cgraph_mark_needed_node (cgraph_node (decl
), 1);
105 else if (TREE_CODE (*tp
) == CALL_EXPR
)
107 tree decl
= TREE_OPERAND (*tp
, 0);
108 if (TREE_CODE (decl
) == ADDR_EXPR
)
109 decl
= TREE_OPERAND (decl
, 0);
110 if (TREE_CODE (decl
) == FUNCTION_DECL
)
112 if (DECL_BUILT_IN (decl
))
114 cgraph_record_call (data
, decl
);
115 walk_tree (&TREE_OPERAND (*tp
, 1), record_call_1
, data
, NULL
);
122 /* Create cgraph edges for function calles via BODY. */
125 cgraph_create_edges (decl
, body
)
129 walk_tree (&body
, record_call_1
, decl
, NULL
);
132 /* Analyze the whole compilation unit once it is parsed completely. */
135 cgraph_finalize_compilation_unit ()
137 struct cgraph_node
*node
;
138 struct cgraph_edge
*edge
;
140 /* Collect entry points to the unit. */
143 fprintf (stderr
, "\n\nUnit entry points:");
145 for (node
= cgraph_nodes
; node
; node
= node
->next
)
147 tree decl
= node
->decl
;
149 if (!DECL_SAVED_TREE (decl
))
151 if ((TREE_PUBLIC (decl
) && !DECL_COMDAT (decl
) && !DECL_EXTERNAL (decl
))
152 || (DECL_ASSEMBLER_NAME_SET_P (decl
)
153 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl
))))
155 cgraph_mark_needed_node (node
, 1);
159 /* Propagate reachability flag and lower representation of all reachable
160 functions. In the future, lowering will introduce new functions and
161 new entry points on the way (by template instantiation and virtual
162 method table generation for instance). */
165 tree decl
= queue
->decl
;
169 if (node
->lowered
|| !node
->reachable
|| !DECL_SAVED_TREE (decl
))
172 /* At the moment frontend automatically emits all nested functions. */
175 struct cgraph_node
*node2
;
177 for (node2
= node
->nested
; node2
; node2
= node2
->next_nested
)
178 if (!node2
->reachable
)
179 cgraph_mark_needed_node (node2
, 0);
182 if (lang_hooks
.callgraph
.lower_function
)
183 (*lang_hooks
.callgraph
.lower_function
) (decl
);
184 /* First kill forward declaration so reverse inling works properly. */
185 cgraph_create_edges (decl
, DECL_SAVED_TREE (decl
));
187 for (edge
= node
->callees
; edge
; edge
= edge
->next_callee
)
189 if (!edge
->callee
->reachable
)
190 cgraph_mark_needed_node (edge
->callee
, 0);
192 node
->lowered
= true;
195 fprintf (stderr
, "\n\nReclaiming functions:");
197 for (node
= cgraph_nodes
; node
; node
= node
->next
)
199 tree decl
= node
->decl
;
201 if (!node
->reachable
&& DECL_SAVED_TREE (decl
))
203 DECL_SAVED_TREE (decl
) = NULL
;
204 announce_function (decl
);
210 /* Figure out what functions we want to assemble. */
213 cgraph_mark_functions_to_output ()
215 struct cgraph_node
*node
;
217 /* Figure out functions we want to assemble. */
218 for (node
= cgraph_nodes
; node
; node
= node
->next
)
220 tree decl
= node
->decl
;
222 if (DECL_SAVED_TREE (decl
)
224 || (!node
->local
.inline_many
&& node
->reachable
)
225 || TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl
)))
226 && !TREE_ASM_WRITTEN (decl
) && !node
->origin
227 && !DECL_EXTERNAL (decl
))
232 /* Expand function specified by NODE. */
234 cgraph_expand_function (node
)
235 struct cgraph_node
*node
;
237 tree decl
= node
->decl
;
239 announce_function (decl
);
240 if (flag_inline_trees
)
241 optimize_inline_calls (decl
);
243 /* Avoid RTL inlining from taking place. */
244 (*lang_hooks
.callgraph
.expand_function
) (decl
);
245 if (DECL_UNINLINABLE (decl
))
246 DECL_SAVED_TREE (decl
) = NULL
;
247 current_function_decl
= NULL
;
251 /* Expand all functions that must be output.
253 Attempt to topologically sort the nodes so function is output when
254 all called functions are already assembled to allow data to be propagated
255 accross the callgraph. Use stack to get smaller distance between function
256 and it's callees (later we may use more sophisticated algorithm for
257 function reordering, we will likely want to use subsections to make output
258 functions to appear in top-down order, not bottom-up they are assembled). */
261 cgraph_expand_functions ()
263 struct cgraph_node
*node
, *node2
;
264 struct cgraph_node
**stack
=
265 xcalloc (sizeof (struct cgraph_node
*), cgraph_n_nodes
);
266 struct cgraph_node
**order
=
267 xcalloc (sizeof (struct cgraph_node
*), cgraph_n_nodes
);
270 struct cgraph_edge
*edge
, last
;
273 cgraph_mark_functions_to_output ();
275 /* We have to deal with cycles nicely, so use depth first traversal
276 algorithm. Ignore the fact that some functions won't need to be output
277 and put them into order as well, so we get dependencies right trought inlined
279 for (node
= cgraph_nodes
; node
; node
= node
->next
)
281 for (node
= cgraph_nodes
; node
; node
= node
->next
)
282 if (node
->output
&& !node
->aux
)
288 node
->aux
= node
->callers
;
291 while (node2
->aux
!= &last
)
294 if (edge
->next_caller
)
295 node2
->aux
= edge
->next_caller
;
298 if (!edge
->caller
->aux
)
300 if (!edge
->caller
->callers
)
301 edge
->caller
->aux
= &last
;
303 edge
->caller
->aux
= edge
->caller
->callers
;
304 stack
[stack_size
++] = node2
;
305 node2
= edge
->caller
;
309 if (node2
->aux
== &last
)
311 order
[order_pos
++] = node2
;
313 node2
= stack
[--stack_size
];
319 for (i
= order_pos
- 1; i
>=0; i
--)
324 if (!node
->reachable
)
327 cgraph_expand_function (node
);
334 /* Mark all local functions.
335 We can not use node->needed directly as it is modified during
336 execution of cgraph_optimize. */
339 cgraph_mark_local_functions ()
341 struct cgraph_node
*node
;
344 fprintf (stderr
, "\n\nMarking local functions:");
346 /* Figure out functions we want to assemble. */
347 for (node
= cgraph_nodes
; node
; node
= node
->next
)
349 node
->local
.local
= (!node
->needed
350 && DECL_SAVED_TREE (node
->decl
)
351 && !TREE_PUBLIC (node
->decl
));
352 if (node
->local
.local
)
353 announce_function (node
->decl
);
358 /* Perform simple optimizations based on callgraph. */
363 struct cgraph_node
*node
;
366 cgraph_mark_local_functions ();
368 cgraph_global_info_ready
= true;
370 fprintf (stderr
, "\n\nAssembling functions:");
372 /* Output everything.
373 ??? Our inline heuristic may decide to not inline functions previously
374 marked as inlinable thus adding new function bodies that must be output.
375 Later we should move all inlining decisions to callgraph code to make
377 cgraph_expand_functions ();
379 fprintf (stderr
, "\n\nAssembling functions that failed to inline:");
380 while (changed
&& !errorcount
&& !sorrycount
)
383 for (node
= cgraph_nodes
; node
; node
= node
->next
)
385 tree decl
= node
->decl
;
387 && !TREE_ASM_WRITTEN (decl
)
388 && DECL_SAVED_TREE (decl
)
389 && !DECL_EXTERNAL (decl
))
391 struct cgraph_edge
*edge
;
393 for (edge
= node
->callers
; edge
; edge
= edge
->next_caller
)
394 if (TREE_ASM_WRITTEN (edge
->caller
->decl
))
397 cgraph_expand_function (node
);