1 /* Basic IPA optimizations and utilities.
2 Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation,
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 3, 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 COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
26 #include "tree-pass.h"
31 /* Fill array order with all nodes with output flag set in the reverse
35 cgraph_postorder (struct cgraph_node **order)
37 struct cgraph_node *node, *node2;
40 struct cgraph_edge *edge, last;
43 struct cgraph_node **stack =
44 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
46 /* We have to deal with cycles nicely, so use a depth first traversal
47 output algorithm. Ignore the fact that some functions won't need
48 to be output and put them into order as well, so we get dependencies
49 right through inline functions. */
50 for (node = cgraph_nodes; node; node = node->next)
52 for (pass = 0; pass < 2; pass++)
53 for (node = cgraph_nodes; node; node = node->next)
56 || (!cgraph_only_called_directly_p (node)
57 && !node->address_taken)))
63 node->aux = node->callers;
66 while (node2->aux != &last)
68 edge = (struct cgraph_edge *) node2->aux;
69 if (edge->next_caller)
70 node2->aux = edge->next_caller;
73 if (!edge->caller->aux)
75 if (!edge->caller->callers)
76 edge->caller->aux = &last;
78 edge->caller->aux = edge->caller->callers;
79 stack[stack_size++] = node2;
84 if (node2->aux == &last)
86 order[order_pos++] = node2;
88 node2 = stack[--stack_size];
95 for (node = cgraph_nodes; node; node = node->next)
100 /* Look for all functions inlined to NODE and update their inlined_to pointers
104 update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
106 struct cgraph_edge *e;
107 for (e = node->callees; e; e = e->next_callee)
108 if (e->callee->global.inlined_to)
110 e->callee->global.inlined_to = inlined_to;
111 update_inlined_to_pointer (e->callee, inlined_to);
115 /* Perform reachability analysis and reclaim all unreachable nodes.
116 If BEFORE_INLINING_P is true this function is called before inlining
117 decisions has been made. If BEFORE_INLINING_P is false this function also
118 removes unneeded bodies of extern inline functions. */
121 cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
123 struct cgraph_node *first = (struct cgraph_node *) (void *) 1;
124 struct cgraph_node *processed = (struct cgraph_node *) (void *) 2;
125 struct cgraph_node *node, *next;
126 bool changed = false;
128 #ifdef ENABLE_CHECKING
132 fprintf (file, "\nReclaiming functions:");
133 #ifdef ENABLE_CHECKING
134 for (node = cgraph_nodes; node; node = node->next)
135 gcc_assert (!node->aux);
137 for (node = cgraph_nodes; node; node = node->next)
138 if (!cgraph_can_remove_if_no_direct_calls_p (node)
139 && ((!DECL_EXTERNAL (node->decl))
141 || before_inlining_p))
143 gcc_assert (!node->global.inlined_to);
146 node->reachable = true;
150 gcc_assert (!node->aux);
151 node->reachable = false;
154 /* Perform reachability analysis. As a special case do not consider
155 extern inline functions not inlined as live because we won't output
157 while (first != (void *) 1)
159 struct cgraph_edge *e;
161 first = (struct cgraph_node *) first->aux;
162 node->aux = processed;
165 for (e = node->callees; e; e = e->next_callee)
166 if (!e->callee->reachable
168 && (!e->inline_failed || !e->callee->analyzed
169 || (!DECL_EXTERNAL (e->callee->decl))
170 || before_inlining_p))
172 bool prev_reachable = e->callee->reachable;
173 e->callee->reachable |= node->reachable;
175 || (e->callee->aux == processed
176 && prev_reachable != e->callee->reachable))
178 e->callee->aux = first;
183 /* If any function in a comdat group is reachable, force
184 all other functions in the same comdat group to be
186 if (node->same_comdat_group
188 && !node->global.inlined_to)
190 for (next = node->same_comdat_group;
192 next = next->same_comdat_group)
193 if (!next->reachable)
197 next->reachable = true;
201 /* We can freely remove inline clones even if they are cloned, however if
202 function is clone of real clone, we must keep it around in order to
203 make materialize_clones produce function body with the changes
205 while (node->clone_of && !node->clone_of->aux && !gimple_has_body_p (node->decl))
207 bool noninline = node->clone_of->decl != node->decl;
208 node = node->clone_of;
218 /* Remove unreachable nodes. Extern inline functions need special care;
219 Unreachable extern inline functions shall be removed.
220 Reachable extern inline functions we never inlined shall get their bodies
222 Reachable extern inline functions we sometimes inlined will be turned into
223 unanalyzed nodes so they look like for true extern functions to the rest
224 of code. Body of such functions is released via remove_node once the
225 inline clones are eliminated. */
226 for (node = cgraph_nodes; node; node = next)
229 if (node->aux && !node->reachable)
231 cgraph_node_remove_callees (node);
232 node->analyzed = false;
233 node->local.inlinable = false;
237 node->global.inlined_to = NULL;
239 fprintf (file, " %s", cgraph_node_name (node));
240 if (!node->analyzed || !DECL_EXTERNAL (node->decl) || before_inlining_p)
241 cgraph_remove_node (node);
244 struct cgraph_edge *e;
246 /* See if there is reachable caller. */
247 for (e = node->callers; e; e = e->next_caller)
251 /* If so, we need to keep node in the callgraph. */
252 if (e || node->needed)
254 struct cgraph_node *clone;
256 /* If there are still clones, we must keep body around.
257 Otherwise we can just remove the body but keep the clone. */
258 for (clone = node->clones; clone;
259 clone = clone->next_sibling_clone)
264 cgraph_release_function_body (node);
265 cgraph_node_remove_callees (node);
266 node->analyzed = false;
267 node->local.inlinable = false;
269 if (node->prev_sibling_clone)
270 node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
271 else if (node->clone_of)
272 node->clone_of->clones = node->next_sibling_clone;
273 if (node->next_sibling_clone)
274 node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
275 node->clone_of = NULL;
276 node->next_sibling_clone = NULL;
277 node->prev_sibling_clone = NULL;
280 cgraph_remove_node (node);
285 for (node = cgraph_nodes; node; node = node->next)
287 /* Inline clones might be kept around so their materializing allows further
288 cloning. If the function the clone is inlined into is removed, we need
289 to turn it into normal cone. */
290 if (node->global.inlined_to
293 gcc_assert (node->clones);
294 node->global.inlined_to = NULL;
295 update_inlined_to_pointer (node, node);
299 #ifdef ENABLE_CHECKING
303 /* Reclaim alias pairs for functions that have disappeared from the
305 remove_unreachable_alias_pairs ();
311 cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program)
313 if (!node->local.finalized)
315 if (!DECL_COMDAT (node->decl)
316 && (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)))
320 /* COMDAT functions must be shared only if they have address taken,
321 otherwise we can produce our own private implementation with
323 if (DECL_COMDAT (node->decl))
325 if (node->address_taken || !node->analyzed)
327 if (node->same_comdat_group)
329 struct cgraph_node *next;
331 /* If more than one function is in the same COMDAT group, it must
332 be shared even if just one function in the comdat group has
334 for (next = node->same_comdat_group;
336 next = next->same_comdat_group)
337 if (next->address_taken || !next->analyzed)
341 if (MAIN_NAME_P (DECL_NAME (node->decl)))
343 if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl)))
348 /* Mark visibility of all functions.
350 A local function is one whose calls can occur only in the current
351 compilation unit and all its calls are explicit, so we can change
352 its calling convention. We simply mark all static functions whose
353 address is not taken as local.
355 We also change the TREE_PUBLIC flag of all declarations that are public
356 in language point of view but we want to overwrite this default
357 via visibilities for the backend point of view. */
360 function_and_variable_visibility (bool whole_program)
362 struct cgraph_node *node;
363 struct varpool_node *vnode;
365 for (node = cgraph_nodes; node; node = node->next)
367 /* C++ FE on lack of COMDAT support create local COMDAT functions
368 (that ought to be shared but can not due to object format
369 limitations). It is neccesary to keep the flag to make rest of C++ FE
370 happy. Clear the flag here to avoid confusion in middle-end. */
371 if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
372 DECL_COMDAT (node->decl) = 0;
373 gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl))
374 || TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));
375 if (cgraph_externally_visible_p (node, whole_program))
377 gcc_assert (!node->global.inlined_to);
378 node->local.externally_visible = true;
381 node->local.externally_visible = false;
382 if (!node->local.externally_visible && node->analyzed
383 && !DECL_EXTERNAL (node->decl))
385 gcc_assert (whole_program || !TREE_PUBLIC (node->decl));
386 TREE_PUBLIC (node->decl) = 0;
387 DECL_COMDAT (node->decl) = 0;
388 DECL_WEAK (node->decl) = 0;
390 node->local.local = (cgraph_only_called_directly_p (node)
392 && !DECL_EXTERNAL (node->decl)
393 && !node->local.externally_visible);
395 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
397 if (!vnode->finalized)
399 gcc_assert ((!DECL_WEAK (vnode->decl) && !DECL_COMMON (vnode->decl))
400 || TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl));
402 && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl))
404 /* We can privatize comdat readonly variables whose address is not taken,
405 but doing so is not going to bring us optimization oppurtunities until
406 we start reordering datastructures. */
407 || DECL_COMDAT (vnode->decl)
408 || DECL_WEAK (vnode->decl)
409 || lookup_attribute ("externally_visible",
410 DECL_ATTRIBUTES (vnode->decl))))
411 vnode->externally_visible = true;
413 vnode->externally_visible = false;
414 if (!vnode->externally_visible)
416 gcc_assert (whole_program || !TREE_PUBLIC (vnode->decl));
417 TREE_PUBLIC (vnode->decl) = 0;
418 DECL_COMMON (vnode->decl) = 0;
420 gcc_assert (TREE_STATIC (vnode->decl));
425 fprintf (dump_file, "\nMarking local functions:");
426 for (node = cgraph_nodes; node; node = node->next)
427 if (node->local.local)
428 fprintf (dump_file, " %s", cgraph_node_name (node));
429 fprintf (dump_file, "\n\n");
430 fprintf (dump_file, "\nMarking externally visible functions:");
431 for (node = cgraph_nodes; node; node = node->next)
432 if (node->local.externally_visible)
433 fprintf (dump_file, " %s", cgraph_node_name (node));
434 fprintf (dump_file, "\n\n");
435 fprintf (dump_file, "\nMarking externally visible variables:");
436 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
437 if (vnode->externally_visible)
438 fprintf (dump_file, " %s", varpool_node_name (vnode));
439 fprintf (dump_file, "\n\n");
441 cgraph_function_flags_ready = true;
445 /* Local function pass handling visibilities. This happens before LTO streaming
446 so in particular -fwhole-program should be ignored at this level. */
449 local_function_and_variable_visibility (void)
451 return function_and_variable_visibility (flag_whole_program && !flag_lto && !flag_whopr);
454 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
458 "visibility", /* name */
460 local_function_and_variable_visibility,/* execute */
463 0, /* static_pass_number */
464 TV_CGRAPHOPT, /* tv_id */
465 0, /* properties_required */
466 0, /* properties_provided */
467 0, /* properties_destroyed */
468 0, /* todo_flags_start */
469 TODO_remove_functions | TODO_dump_cgraph/* todo_flags_finish */
473 /* Do not re-run on ltrans stage. */
476 gate_whole_program_function_and_variable_visibility (void)
481 /* Bring functionss local at LTO time whith -fwhole-program. */
484 whole_program_function_and_variable_visibility (void)
486 struct cgraph_node *node;
487 struct varpool_node *vnode;
489 function_and_variable_visibility (flag_whole_program);
491 for (node = cgraph_nodes; node; node = node->next)
492 if ((node->local.externally_visible && !DECL_COMDAT (node->decl))
493 && node->local.finalized)
494 cgraph_mark_needed_node (node);
495 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
496 if (vnode->externally_visible && !DECL_COMDAT (vnode->decl))
497 varpool_mark_needed_node (vnode);
500 fprintf (dump_file, "\nNeeded variables:");
501 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
503 fprintf (dump_file, " %s", varpool_node_name (vnode));
504 fprintf (dump_file, "\n\n");
509 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
513 "whole-program", /* name */
514 gate_whole_program_function_and_variable_visibility,/* gate */
515 whole_program_function_and_variable_visibility,/* execute */
518 0, /* static_pass_number */
519 TV_CGRAPHOPT, /* tv_id */
520 0, /* properties_required */
521 0, /* properties_provided */
522 0, /* properties_destroyed */
523 0, /* todo_flags_start */
524 TODO_dump_cgraph | TODO_remove_functions/* todo_flags_finish */
526 NULL, /* generate_summary */
527 NULL, /* write_summary */
528 NULL, /* read_summary */
529 NULL, /* function_read_summary */
530 NULL, /* stmt_fixup */
532 NULL, /* function_transform */
533 NULL, /* variable_transform */
536 /* Hash a cgraph node set element. */
539 hash_cgraph_node_set_element (const void *p)
541 const_cgraph_node_set_element element = (const_cgraph_node_set_element) p;
542 return htab_hash_pointer (element->node);
545 /* Compare two cgraph node set elements. */
548 eq_cgraph_node_set_element (const void *p1, const void *p2)
550 const_cgraph_node_set_element e1 = (const_cgraph_node_set_element) p1;
551 const_cgraph_node_set_element e2 = (const_cgraph_node_set_element) p2;
553 return e1->node == e2->node;
556 /* Create a new cgraph node set. */
559 cgraph_node_set_new (void)
561 cgraph_node_set new_node_set;
563 new_node_set = GGC_NEW (struct cgraph_node_set_def);
564 new_node_set->hashtab = htab_create_ggc (10,
565 hash_cgraph_node_set_element,
566 eq_cgraph_node_set_element,
568 new_node_set->nodes = NULL;
572 /* Add cgraph_node NODE to cgraph_node_set SET. */
575 cgraph_node_set_add (cgraph_node_set set, struct cgraph_node *node)
578 cgraph_node_set_element element;
579 struct cgraph_node_set_element_def dummy;
582 slot = htab_find_slot (set->hashtab, &dummy, INSERT);
584 if (*slot != HTAB_EMPTY_ENTRY)
586 element = (cgraph_node_set_element) *slot;
587 gcc_assert (node == element->node
588 && (VEC_index (cgraph_node_ptr, set->nodes, element->index)
593 /* Insert node into hash table. */
595 (cgraph_node_set_element) GGC_NEW (struct cgraph_node_set_element_def);
596 element->node = node;
597 element->index = VEC_length (cgraph_node_ptr, set->nodes);
600 /* Insert into node vector. */
601 VEC_safe_push (cgraph_node_ptr, gc, set->nodes, node);
604 /* Remove cgraph_node NODE from cgraph_node_set SET. */
607 cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node)
609 void **slot, **last_slot;
610 cgraph_node_set_element element, last_element;
611 struct cgraph_node *last_node;
612 struct cgraph_node_set_element_def dummy;
615 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
619 element = (cgraph_node_set_element) *slot;
620 gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
623 /* Remove from vector. We do this by swapping node with the last element
625 last_node = VEC_pop (cgraph_node_ptr, set->nodes);
626 if (last_node != node)
628 dummy.node = last_node;
629 last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
630 last_element = (cgraph_node_set_element) *last_slot;
631 gcc_assert (last_element);
633 /* Move the last element to the original spot of NODE. */
634 last_element->index = element->index;
635 VEC_replace (cgraph_node_ptr, set->nodes, last_element->index,
639 /* Remove element from hash table. */
640 htab_clear_slot (set->hashtab, slot);
644 /* Find NODE in SET and return an iterator to it if found. A null iterator
645 is returned if NODE is not in SET. */
647 cgraph_node_set_iterator
648 cgraph_node_set_find (cgraph_node_set set, struct cgraph_node *node)
651 struct cgraph_node_set_element_def dummy;
652 cgraph_node_set_element element;
653 cgraph_node_set_iterator csi;
656 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
658 csi.index = (unsigned) ~0;
661 element = (cgraph_node_set_element) *slot;
662 gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
664 csi.index = element->index;
671 /* Dump content of SET to file F. */
674 dump_cgraph_node_set (FILE *f, cgraph_node_set set)
676 cgraph_node_set_iterator iter;
678 for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter))
680 struct cgraph_node *node = csi_node (iter);
681 dump_cgraph_node (f, node);
685 /* Dump content of SET to stderr. */
688 debug_cgraph_node_set (cgraph_node_set set)
690 dump_cgraph_node_set (stderr, set);