1 /* Basic IPA optimizations and utilities.
2 Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
23 #include "coretypes.h"
26 #include "tree-pass.h"
29 /* Fill array order with all nodes with output flag set in the reverse
33 cgraph_postorder (struct cgraph_node
**order
)
35 struct cgraph_node
*node
, *node2
;
38 struct cgraph_edge
*edge
, last
;
40 struct cgraph_node
**stack
=
41 XCNEWVEC (struct cgraph_node
*, cgraph_n_nodes
);
43 /* We have to deal with cycles nicely, so use a depth first traversal
44 output algorithm. Ignore the fact that some functions won't need
45 to be output and put them into order as well, so we get dependencies
46 right through intline functions. */
47 for (node
= cgraph_nodes
; node
; node
= node
->next
)
49 for (node
= cgraph_nodes
; node
; node
= node
->next
)
56 node
->aux
= node
->callers
;
59 while (node2
->aux
!= &last
)
62 if (edge
->next_caller
)
63 node2
->aux
= edge
->next_caller
;
66 if (!edge
->caller
->aux
)
68 if (!edge
->caller
->callers
)
69 edge
->caller
->aux
= &last
;
71 edge
->caller
->aux
= edge
->caller
->callers
;
72 stack
[stack_size
++] = node2
;
77 if (node2
->aux
== &last
)
79 order
[order_pos
++] = node2
;
81 node2
= stack
[--stack_size
];
88 for (node
= cgraph_nodes
; node
; node
= node
->next
)
93 /* Perform reachability analysis and reclaim all unreachable nodes.
94 If BEFORE_INLINING_P is true this function is called before inlining
95 decisions has been made. If BEFORE_INLINING_P is false this function also
96 removes unneeded bodies of extern inline functions. */
99 cgraph_remove_unreachable_nodes (bool before_inlining_p
, FILE *file
)
101 struct cgraph_node
*first
= (void *) 1;
102 struct cgraph_node
*node
, *next
;
103 bool changed
= false;
106 #ifdef ENABLE_CHECKING
110 fprintf (file
, "\nReclaiming functions:");
111 #ifdef ENABLE_CHECKING
112 for (node
= cgraph_nodes
; node
; node
= node
->next
)
113 gcc_assert (!node
->aux
);
115 for (node
= cgraph_nodes
; node
; node
= node
->next
)
116 if (node
->needed
&& !node
->global
.inlined_to
117 && ((!DECL_EXTERNAL (node
->decl
))
119 || before_inlining_p
))
125 gcc_assert (!node
->aux
);
127 /* Perform reachability analysis. As a special case do not consider
128 extern inline functions not inlined as live because we won't output
130 while (first
!= (void *) 1)
132 struct cgraph_edge
*e
;
136 for (e
= node
->callees
; e
; e
= e
->next_callee
)
139 && (!e
->inline_failed
|| !e
->callee
->analyzed
140 || (!DECL_EXTERNAL (e
->callee
->decl
))
141 || before_inlining_p
))
143 e
->callee
->aux
= first
;
148 /* Remove unreachable nodes. Extern inline functions need special care;
149 Unreachable extern inline functions shall be removed.
150 Reachable extern inline functions we never inlined shall get their bodies
152 Reachable extern inline functions we sometimes inlined will be turned into
153 unanalyzed nodes so they look like for true extern functions to the rest
154 of code. Body of such functions is released via remove_node once the
155 inline clones are eliminated. */
156 for (node
= cgraph_nodes
; node
; node
= next
)
162 tree decl
= node
->decl
;
164 node
->global
.inlined_to
= NULL
;
165 if (DECL_STRUCT_FUNCTION (decl
))
166 local_insns
= node
->local
.self_insns
;
170 fprintf (file
, " %s", cgraph_node_name (node
));
171 if (!node
->analyzed
|| !DECL_EXTERNAL (node
->decl
)
172 || before_inlining_p
)
173 cgraph_remove_node (node
);
176 struct cgraph_edge
*e
;
178 for (e
= node
->callers
; e
; e
= e
->next_caller
)
181 if (e
|| node
->needed
)
183 struct cgraph_node
*clone
;
185 for (clone
= node
->next_clone
; clone
;
186 clone
= clone
->next_clone
)
191 cgraph_release_function_body (node
);
192 node
->analyzed
= false;
194 cgraph_node_remove_callees (node
);
195 node
->analyzed
= false;
198 cgraph_remove_node (node
);
200 if (!DECL_SAVED_TREE (decl
))
201 insns
+= local_insns
;
205 for (node
= cgraph_nodes
; node
; node
= node
->next
)
208 fprintf (file
, "\nReclaimed %i insns", insns
);
209 #ifdef ENABLE_CHECKING
215 /* Mark visibility of all functions.
217 A local function is one whose calls can occur only in the current
218 compilation unit and all its calls are explicit, so we can change
219 its calling convention. We simply mark all static functions whose
220 address is not taken as local.
222 We also change the TREE_PUBLIC flag of all declarations that are public
223 in language point of view but we want to overwrite this default
224 via visibilities for the backend point of view. */
227 function_and_variable_visibility (void)
229 struct cgraph_node
*node
;
230 struct varpool_node
*vnode
;
232 for (node
= cgraph_nodes
; node
; node
= node
->next
)
235 && (DECL_COMDAT (node
->decl
)
236 || (!flag_whole_program
237 && TREE_PUBLIC (node
->decl
) && !DECL_EXTERNAL (node
->decl
))))
238 node
->local
.externally_visible
= true;
239 if (!node
->local
.externally_visible
&& node
->analyzed
240 && !DECL_EXTERNAL (node
->decl
))
242 gcc_assert (flag_whole_program
|| !TREE_PUBLIC (node
->decl
));
243 TREE_PUBLIC (node
->decl
) = 0;
245 node
->local
.local
= (!node
->needed
247 && !DECL_EXTERNAL (node
->decl
)
248 && !node
->local
.externally_visible
);
250 for (vnode
= varpool_nodes_queue
; vnode
; vnode
= vnode
->next_needed
)
253 && !flag_whole_program
254 && (DECL_COMDAT (vnode
->decl
) || TREE_PUBLIC (vnode
->decl
)))
255 vnode
->externally_visible
= 1;
256 if (!vnode
->externally_visible
)
258 gcc_assert (flag_whole_program
|| !TREE_PUBLIC (vnode
->decl
));
259 TREE_PUBLIC (vnode
->decl
) = 0;
261 gcc_assert (TREE_STATIC (vnode
->decl
));
266 fprintf (dump_file
, "\nMarking local functions:");
267 for (node
= cgraph_nodes
; node
; node
= node
->next
)
268 if (node
->local
.local
)
269 fprintf (dump_file
, " %s", cgraph_node_name (node
));
270 fprintf (dump_file
, "\n\n");
271 fprintf (dump_file
, "\nMarking externally visible functions:");
272 for (node
= cgraph_nodes
; node
; node
= node
->next
)
273 if (node
->local
.externally_visible
)
274 fprintf (dump_file
, " %s", cgraph_node_name (node
));
275 fprintf (dump_file
, "\n\n");
277 cgraph_function_flags_ready
= true;
281 struct tree_opt_pass pass_ipa_function_and_variable_visibility
=
283 "visibility", /* name */
285 function_and_variable_visibility
, /* execute */
288 0, /* static_pass_number */
289 TV_CGRAPHOPT
, /* tv_id */
290 0, /* properties_required */
291 0, /* properties_provided */
292 0, /* properties_destroyed */
293 0, /* todo_flags_start */
294 TODO_remove_functions
| TODO_dump_cgraph
,/* todo_flags_finish */