1 /* Basic IPA optimizations and utilities.
2 Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
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 /* Break possible cycles involving always-inline
74 functions by ignoring edges from always-inline
75 functions to non-always-inline functions. */
76 if (edge->caller->local.disregard_inline_limits
77 && !edge->callee->local.disregard_inline_limits)
79 if (!edge->caller->aux)
81 if (!edge->caller->callers)
82 edge->caller->aux = &last;
84 edge->caller->aux = edge->caller->callers;
85 stack[stack_size++] = node2;
90 if (node2->aux == &last)
92 order[order_pos++] = node2;
94 node2 = stack[--stack_size];
101 for (node = cgraph_nodes; node; node = node->next)
106 /* Look for all functions inlined to NODE and update their inlined_to pointers
110 update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
112 struct cgraph_edge *e;
113 for (e = node->callees; e; e = e->next_callee)
114 if (e->callee->global.inlined_to)
116 e->callee->global.inlined_to = inlined_to;
117 update_inlined_to_pointer (e->callee, inlined_to);
121 /* Perform reachability analysis and reclaim all unreachable nodes.
122 If BEFORE_INLINING_P is true this function is called before inlining
123 decisions has been made. If BEFORE_INLINING_P is false this function also
124 removes unneeded bodies of extern inline functions. */
127 cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
129 struct cgraph_node *first = (struct cgraph_node *) (void *) 1;
130 struct cgraph_node *processed = (struct cgraph_node *) (void *) 2;
131 struct cgraph_node *node, *next;
132 bool changed = false;
134 #ifdef ENABLE_CHECKING
138 fprintf (file, "\nReclaiming functions:");
139 #ifdef ENABLE_CHECKING
140 for (node = cgraph_nodes; node; node = node->next)
141 gcc_assert (!node->aux);
143 for (node = cgraph_nodes; node; node = node->next)
144 if (!cgraph_can_remove_if_no_direct_calls_p (node)
145 && ((!DECL_EXTERNAL (node->decl))
147 || before_inlining_p))
149 gcc_assert (!node->global.inlined_to);
152 node->reachable = true;
156 gcc_assert (!node->aux);
157 node->reachable = false;
160 /* Perform reachability analysis. As a special case do not consider
161 extern inline functions not inlined as live because we won't output
163 while (first != (void *) 1)
165 struct cgraph_edge *e;
167 first = (struct cgraph_node *) first->aux;
168 node->aux = processed;
171 for (e = node->callees; e; e = e->next_callee)
172 if (!e->callee->reachable
174 && (!e->inline_failed || !e->callee->analyzed
175 || (!DECL_EXTERNAL (e->callee->decl))
176 || before_inlining_p))
178 bool prev_reachable = e->callee->reachable;
179 e->callee->reachable |= node->reachable;
181 || (e->callee->aux == processed
182 && prev_reachable != e->callee->reachable))
184 e->callee->aux = first;
189 /* If any function in a comdat group is reachable, force
190 all other functions in the same comdat group to be
192 if (node->same_comdat_group
194 && !node->global.inlined_to)
196 for (next = node->same_comdat_group;
198 next = next->same_comdat_group)
199 if (!next->reachable)
203 next->reachable = true;
207 /* We can freely remove inline clones even if they are cloned, however if
208 function is clone of real clone, we must keep it around in order to
209 make materialize_clones produce function body with the changes
211 while (node->clone_of && !node->clone_of->aux && !gimple_has_body_p (node->decl))
213 bool noninline = node->clone_of->decl != node->decl;
214 node = node->clone_of;
224 /* Remove unreachable nodes. Extern inline functions need special care;
225 Unreachable extern inline functions shall be removed.
226 Reachable extern inline functions we never inlined shall get their bodies
228 Reachable extern inline functions we sometimes inlined will be turned into
229 unanalyzed nodes so they look like for true extern functions to the rest
230 of code. Body of such functions is released via remove_node once the
231 inline clones are eliminated. */
232 for (node = cgraph_nodes; node; node = next)
235 if (node->aux && !node->reachable)
237 cgraph_node_remove_callees (node);
238 node->analyzed = false;
239 node->local.inlinable = false;
243 node->global.inlined_to = NULL;
245 fprintf (file, " %s", cgraph_node_name (node));
246 if (!node->analyzed || !DECL_EXTERNAL (node->decl) || before_inlining_p)
247 cgraph_remove_node (node);
250 struct cgraph_edge *e;
252 /* See if there is reachable caller. */
253 for (e = node->callers; e; e = e->next_caller)
257 /* If so, we need to keep node in the callgraph. */
258 if (e || node->needed)
260 struct cgraph_node *clone;
262 /* If there are still clones, we must keep body around.
263 Otherwise we can just remove the body but keep the clone. */
264 for (clone = node->clones; clone;
265 clone = clone->next_sibling_clone)
270 cgraph_release_function_body (node);
271 node->analyzed = false;
272 node->local.inlinable = false;
275 gcc_assert (!clone->in_other_partition);
276 cgraph_node_remove_callees (node);
277 if (node->prev_sibling_clone)
278 node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
279 else if (node->clone_of)
280 node->clone_of->clones = node->next_sibling_clone;
281 if (node->next_sibling_clone)
282 node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
283 node->clone_of = NULL;
284 node->next_sibling_clone = NULL;
285 node->prev_sibling_clone = NULL;
288 cgraph_remove_node (node);
293 for (node = cgraph_nodes; node; node = node->next)
295 /* Inline clones might be kept around so their materializing allows further
296 cloning. If the function the clone is inlined into is removed, we need
297 to turn it into normal cone. */
298 if (node->global.inlined_to
301 gcc_assert (node->clones);
302 node->global.inlined_to = NULL;
303 update_inlined_to_pointer (node, node);
307 #ifdef ENABLE_CHECKING
311 /* Reclaim alias pairs for functions that have disappeared from the
313 remove_unreachable_alias_pairs ();
319 cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program)
321 if (!node->local.finalized)
323 if (!DECL_COMDAT (node->decl)
324 && (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)))
328 if (DECL_PRESERVE_P (node->decl))
330 /* COMDAT functions must be shared only if they have address taken,
331 otherwise we can produce our own private implementation with
333 if (DECL_COMDAT (node->decl))
335 if (node->address_taken || !node->analyzed)
337 if (node->same_comdat_group)
339 struct cgraph_node *next;
341 /* If more than one function is in the same COMDAT group, it must
342 be shared even if just one function in the comdat group has
344 for (next = node->same_comdat_group;
346 next = next->same_comdat_group)
347 if (next->address_taken || !next->analyzed)
351 if (MAIN_NAME_P (DECL_NAME (node->decl)))
353 if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl)))
358 /* Dissolve the same_comdat_group list in which NODE resides. */
361 dissolve_same_comdat_group_list (struct cgraph_node *node)
363 struct cgraph_node *n = node, *next;
366 next = n->same_comdat_group;
367 n->same_comdat_group = NULL;
373 /* Mark visibility of all functions.
375 A local function is one whose calls can occur only in the current
376 compilation unit and all its calls are explicit, so we can change
377 its calling convention. We simply mark all static functions whose
378 address is not taken as local.
380 We also change the TREE_PUBLIC flag of all declarations that are public
381 in language point of view but we want to overwrite this default
382 via visibilities for the backend point of view. */
385 function_and_variable_visibility (bool whole_program)
387 struct cgraph_node *node;
388 struct varpool_node *vnode;
390 for (node = cgraph_nodes; node; node = node->next)
392 /* C++ FE on lack of COMDAT support create local COMDAT functions
393 (that ought to be shared but can not due to object format
394 limitations). It is neccesary to keep the flag to make rest of C++ FE
395 happy. Clear the flag here to avoid confusion in middle-end. */
396 if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
397 DECL_COMDAT (node->decl) = 0;
398 /* For external decls stop tracking same_comdat_group, it doesn't matter
399 what comdat group they are in when they won't be emitted in this TU,
400 and simplifies later passes. */
401 if (node->same_comdat_group && DECL_EXTERNAL (node->decl))
403 #ifdef ENABLE_CHECKING
404 struct cgraph_node *n;
406 for (n = node->same_comdat_group;
408 n = n->same_comdat_group)
409 /* If at least one of same comdat group functions is external,
410 all of them have to be, otherwise it is a front-end bug. */
411 gcc_assert (DECL_EXTERNAL (n->decl));
413 dissolve_same_comdat_group_list (node);
415 gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl))
416 || TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));
417 if (cgraph_externally_visible_p (node, whole_program))
419 gcc_assert (!node->global.inlined_to);
420 node->local.externally_visible = true;
423 node->local.externally_visible = false;
424 if (!node->local.externally_visible && node->analyzed
425 && !DECL_EXTERNAL (node->decl))
427 gcc_assert (whole_program || !TREE_PUBLIC (node->decl));
428 cgraph_make_decl_local (node->decl);
429 if (node->same_comdat_group)
430 /* cgraph_externally_visible_p has already checked all other nodes
431 in the group and they will all be made local. We need to
432 dissolve the group at once so that the predicate does not
434 dissolve_same_comdat_group_list (node);
436 node->local.local = (cgraph_only_called_directly_p (node)
438 && !DECL_EXTERNAL (node->decl)
439 && !node->local.externally_visible);
441 for (vnode = varpool_nodes; vnode; vnode = vnode->next)
443 /* weak flag makes no sense on local variables. */
444 gcc_assert (!DECL_WEAK (vnode->decl)
445 || TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl));
446 /* In several cases declarations can not be common:
448 - when declaration has initializer
450 - when it has specific section
451 - when it resides in non-generic address space.
452 - if declaration is local, it will get into .local common section
453 so common flag is not needed. Frontends still produce these in
454 certain cases, such as for:
456 static int a __attribute__ ((common))
458 Canonicalize things here and clear the redundant flag. */
459 if (DECL_COMMON (vnode->decl)
460 && (!(TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl))
461 || (DECL_INITIAL (vnode->decl)
462 && DECL_INITIAL (vnode->decl) != error_mark_node)
463 || DECL_WEAK (vnode->decl)
464 || DECL_SECTION_NAME (vnode->decl) != NULL
465 || ! (ADDR_SPACE_GENERIC_P
466 (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
467 DECL_COMMON (vnode->decl) = 0;
469 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
471 if (!vnode->finalized)
474 && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl))
476 /* We can privatize comdat readonly variables whose address is not taken,
477 but doing so is not going to bring us optimization oppurtunities until
478 we start reordering datastructures. */
479 || DECL_COMDAT (vnode->decl)
480 || DECL_WEAK (vnode->decl)
481 || lookup_attribute ("externally_visible",
482 DECL_ATTRIBUTES (vnode->decl))))
483 vnode->externally_visible = true;
485 vnode->externally_visible = false;
486 if (!vnode->externally_visible)
488 gcc_assert (whole_program || !TREE_PUBLIC (vnode->decl));
489 cgraph_make_decl_local (vnode->decl);
491 gcc_assert (TREE_STATIC (vnode->decl));
496 fprintf (dump_file, "\nMarking local functions:");
497 for (node = cgraph_nodes; node; node = node->next)
498 if (node->local.local)
499 fprintf (dump_file, " %s", cgraph_node_name (node));
500 fprintf (dump_file, "\n\n");
501 fprintf (dump_file, "\nMarking externally visible functions:");
502 for (node = cgraph_nodes; node; node = node->next)
503 if (node->local.externally_visible)
504 fprintf (dump_file, " %s", cgraph_node_name (node));
505 fprintf (dump_file, "\n\n");
506 fprintf (dump_file, "\nMarking externally visible variables:");
507 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
508 if (vnode->externally_visible)
509 fprintf (dump_file, " %s", varpool_node_name (vnode));
510 fprintf (dump_file, "\n\n");
512 cgraph_function_flags_ready = true;
516 /* Local function pass handling visibilities. This happens before LTO streaming
517 so in particular -fwhole-program should be ignored at this level. */
520 local_function_and_variable_visibility (void)
522 return function_and_variable_visibility (flag_whole_program && !flag_lto && !flag_whopr);
525 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
529 "visibility", /* name */
531 local_function_and_variable_visibility,/* execute */
534 0, /* static_pass_number */
535 TV_CGRAPHOPT, /* tv_id */
536 0, /* properties_required */
537 0, /* properties_provided */
538 0, /* properties_destroyed */
539 0, /* todo_flags_start */
540 TODO_remove_functions | TODO_dump_cgraph
541 | TODO_ggc_collect /* todo_flags_finish */
545 /* Do not re-run on ltrans stage. */
548 gate_whole_program_function_and_variable_visibility (void)
553 /* Bring functionss local at LTO time whith -fwhole-program. */
556 whole_program_function_and_variable_visibility (void)
558 struct cgraph_node *node;
559 struct varpool_node *vnode;
561 function_and_variable_visibility (flag_whole_program);
563 for (node = cgraph_nodes; node; node = node->next)
564 if ((node->local.externally_visible && !DECL_COMDAT (node->decl))
565 && node->local.finalized)
566 cgraph_mark_needed_node (node);
567 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
568 if (vnode->externally_visible && !DECL_COMDAT (vnode->decl))
569 varpool_mark_needed_node (vnode);
572 fprintf (dump_file, "\nNeeded variables:");
573 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
575 fprintf (dump_file, " %s", varpool_node_name (vnode));
576 fprintf (dump_file, "\n\n");
581 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
585 "whole-program", /* name */
586 gate_whole_program_function_and_variable_visibility,/* gate */
587 whole_program_function_and_variable_visibility,/* execute */
590 0, /* static_pass_number */
591 TV_CGRAPHOPT, /* tv_id */
592 0, /* properties_required */
593 0, /* properties_provided */
594 0, /* properties_destroyed */
595 0, /* todo_flags_start */
596 TODO_remove_functions | TODO_dump_cgraph
597 | TODO_ggc_collect /* todo_flags_finish */
599 NULL, /* generate_summary */
600 NULL, /* write_summary */
601 NULL, /* read_summary */
602 NULL, /* write_optimization_summary */
603 NULL, /* read_optimization_summary */
604 NULL, /* stmt_fixup */
606 NULL, /* function_transform */
607 NULL, /* variable_transform */
610 /* Hash a cgraph node set element. */
613 hash_cgraph_node_set_element (const void *p)
615 const_cgraph_node_set_element element = (const_cgraph_node_set_element) p;
616 return htab_hash_pointer (element->node);
619 /* Compare two cgraph node set elements. */
622 eq_cgraph_node_set_element (const void *p1, const void *p2)
624 const_cgraph_node_set_element e1 = (const_cgraph_node_set_element) p1;
625 const_cgraph_node_set_element e2 = (const_cgraph_node_set_element) p2;
627 return e1->node == e2->node;
630 /* Create a new cgraph node set. */
633 cgraph_node_set_new (void)
635 cgraph_node_set new_node_set;
637 new_node_set = GGC_NEW (struct cgraph_node_set_def);
638 new_node_set->hashtab = htab_create_ggc (10,
639 hash_cgraph_node_set_element,
640 eq_cgraph_node_set_element,
642 new_node_set->nodes = NULL;
646 /* Add cgraph_node NODE to cgraph_node_set SET. */
649 cgraph_node_set_add (cgraph_node_set set, struct cgraph_node *node)
652 cgraph_node_set_element element;
653 struct cgraph_node_set_element_def dummy;
656 slot = htab_find_slot (set->hashtab, &dummy, INSERT);
658 if (*slot != HTAB_EMPTY_ENTRY)
660 element = (cgraph_node_set_element) *slot;
661 gcc_assert (node == element->node
662 && (VEC_index (cgraph_node_ptr, set->nodes, element->index)
667 /* Insert node into hash table. */
669 (cgraph_node_set_element) GGC_NEW (struct cgraph_node_set_element_def);
670 element->node = node;
671 element->index = VEC_length (cgraph_node_ptr, set->nodes);
674 /* Insert into node vector. */
675 VEC_safe_push (cgraph_node_ptr, gc, set->nodes, node);
678 /* Remove cgraph_node NODE from cgraph_node_set SET. */
681 cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node)
683 void **slot, **last_slot;
684 cgraph_node_set_element element, last_element;
685 struct cgraph_node *last_node;
686 struct cgraph_node_set_element_def dummy;
689 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
693 element = (cgraph_node_set_element) *slot;
694 gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
697 /* Remove from vector. We do this by swapping node with the last element
699 last_node = VEC_pop (cgraph_node_ptr, set->nodes);
700 if (last_node != node)
702 dummy.node = last_node;
703 last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
704 last_element = (cgraph_node_set_element) *last_slot;
705 gcc_assert (last_element);
707 /* Move the last element to the original spot of NODE. */
708 last_element->index = element->index;
709 VEC_replace (cgraph_node_ptr, set->nodes, last_element->index,
713 /* Remove element from hash table. */
714 htab_clear_slot (set->hashtab, slot);
718 /* Find NODE in SET and return an iterator to it if found. A null iterator
719 is returned if NODE is not in SET. */
721 cgraph_node_set_iterator
722 cgraph_node_set_find (cgraph_node_set set, struct cgraph_node *node)
725 struct cgraph_node_set_element_def dummy;
726 cgraph_node_set_element element;
727 cgraph_node_set_iterator csi;
730 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
732 csi.index = (unsigned) ~0;
735 element = (cgraph_node_set_element) *slot;
736 gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
738 csi.index = element->index;
745 /* Dump content of SET to file F. */
748 dump_cgraph_node_set (FILE *f, cgraph_node_set set)
750 cgraph_node_set_iterator iter;
752 for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter))
754 struct cgraph_node *node = csi_node (iter);
755 dump_cgraph_node (f, node);
759 /* Dump content of SET to stderr. */
762 debug_cgraph_node_set (cgraph_node_set set)
764 dump_cgraph_node_set (stderr, set);
767 /* Hash a varpool node set element. */
770 hash_varpool_node_set_element (const void *p)
772 const_varpool_node_set_element element = (const_varpool_node_set_element) p;
773 return htab_hash_pointer (element->node);
776 /* Compare two varpool node set elements. */
779 eq_varpool_node_set_element (const void *p1, const void *p2)
781 const_varpool_node_set_element e1 = (const_varpool_node_set_element) p1;
782 const_varpool_node_set_element e2 = (const_varpool_node_set_element) p2;
784 return e1->node == e2->node;
787 /* Create a new varpool node set. */
790 varpool_node_set_new (void)
792 varpool_node_set new_node_set;
794 new_node_set = GGC_NEW (struct varpool_node_set_def);
795 new_node_set->hashtab = htab_create_ggc (10,
796 hash_varpool_node_set_element,
797 eq_varpool_node_set_element,
799 new_node_set->nodes = NULL;
803 /* Add varpool_node NODE to varpool_node_set SET. */
806 varpool_node_set_add (varpool_node_set set, struct varpool_node *node)
809 varpool_node_set_element element;
810 struct varpool_node_set_element_def dummy;
813 slot = htab_find_slot (set->hashtab, &dummy, INSERT);
815 if (*slot != HTAB_EMPTY_ENTRY)
817 element = (varpool_node_set_element) *slot;
818 gcc_assert (node == element->node
819 && (VEC_index (varpool_node_ptr, set->nodes, element->index)
824 /* Insert node into hash table. */
826 (varpool_node_set_element) GGC_NEW (struct varpool_node_set_element_def);
827 element->node = node;
828 element->index = VEC_length (varpool_node_ptr, set->nodes);
831 /* Insert into node vector. */
832 VEC_safe_push (varpool_node_ptr, gc, set->nodes, node);
835 /* Remove varpool_node NODE from varpool_node_set SET. */
838 varpool_node_set_remove (varpool_node_set set, struct varpool_node *node)
840 void **slot, **last_slot;
841 varpool_node_set_element element, last_element;
842 struct varpool_node *last_node;
843 struct varpool_node_set_element_def dummy;
846 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
850 element = (varpool_node_set_element) *slot;
851 gcc_assert (VEC_index (varpool_node_ptr, set->nodes, element->index)
854 /* Remove from vector. We do this by swapping node with the last element
856 last_node = VEC_pop (varpool_node_ptr, set->nodes);
857 if (last_node != node)
859 dummy.node = last_node;
860 last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
861 last_element = (varpool_node_set_element) *last_slot;
862 gcc_assert (last_element);
864 /* Move the last element to the original spot of NODE. */
865 last_element->index = element->index;
866 VEC_replace (varpool_node_ptr, set->nodes, last_element->index,
870 /* Remove element from hash table. */
871 htab_clear_slot (set->hashtab, slot);
875 /* Find NODE in SET and return an iterator to it if found. A null iterator
876 is returned if NODE is not in SET. */
878 varpool_node_set_iterator
879 varpool_node_set_find (varpool_node_set set, struct varpool_node *node)
882 struct varpool_node_set_element_def dummy;
883 varpool_node_set_element element;
884 varpool_node_set_iterator vsi;
887 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
889 vsi.index = (unsigned) ~0;
892 element = (varpool_node_set_element) *slot;
893 gcc_assert (VEC_index (varpool_node_ptr, set->nodes, element->index)
895 vsi.index = element->index;
902 /* Dump content of SET to file F. */
905 dump_varpool_node_set (FILE *f, varpool_node_set set)
907 varpool_node_set_iterator iter;
909 for (iter = vsi_start (set); !vsi_end_p (iter); vsi_next (&iter))
911 struct varpool_node *node = vsi_node (iter);
912 dump_varpool_node (f, node);
916 /* Dump content of SET to stderr. */
919 debug_varpool_node_set (varpool_node_set set)
921 dump_varpool_node_set (stderr, set);
925 /* Simple ipa profile pass propagating frequencies across the callgraph. */
930 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
931 struct cgraph_edge *e;
933 bool something_changed = false;
936 order_pos = cgraph_postorder (order);
937 for (i = order_pos - 1; i >= 0; i--)
939 if (order[i]->local.local && cgraph_propagate_frequency (order[i]))
941 for (e = order[i]->callees; e; e = e->next_callee)
942 if (e->callee->local.local && !e->callee->aux)
944 something_changed = true;
945 e->callee->aux = (void *)1;
948 order[i]->aux = NULL;
951 while (something_changed)
953 something_changed = false;
954 for (i = order_pos - 1; i >= 0; i--)
956 if (order[i]->aux && cgraph_propagate_frequency (order[i]))
958 for (e = order[i]->callees; e; e = e->next_callee)
959 if (e->callee->local.local && !e->callee->aux)
961 something_changed = true;
962 e->callee->aux = (void *)1;
965 order[i]->aux = NULL;
973 gate_ipa_profile (void)
975 return flag_ipa_profile;
978 struct ipa_opt_pass_d pass_ipa_profile =
982 "ipa-profile", /* name */
983 gate_ipa_profile, /* gate */
984 ipa_profile, /* execute */
987 0, /* static_pass_number */
988 TV_IPA_PROFILE, /* tv_id */
989 0, /* properties_required */
990 0, /* properties_provided */
991 0, /* properties_destroyed */
992 0, /* todo_flags_start */
993 0 /* todo_flags_finish */
995 NULL, /* generate_summary */
996 NULL, /* write_summary */
997 NULL, /* read_summary */
998 NULL, /* write_optimization_summary */
999 NULL, /* read_optimization_summary */
1000 NULL, /* stmt_fixup */
1002 NULL, /* function_transform */
1003 NULL /* variable_transform */