Merged r158704 through r158906 into branch.
[official-gcc.git] / gcc / ipa.c
blob36fe714abb3c0358eafc90c079ec093950971a21
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
10 version.
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
15 for more details.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "cgraph.h"
26 #include "tree-pass.h"
27 #include "timevar.h"
28 #include "gimple.h"
29 #include "ggc.h"
31 /* Fill array order with all nodes with output flag set in the reverse
32 topological order. */
34 int
35 cgraph_postorder (struct cgraph_node **order)
37 struct cgraph_node *node, *node2;
38 int stack_size = 0;
39 int order_pos = 0;
40 struct cgraph_edge *edge, last;
41 int pass;
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)
51 node->aux = NULL;
52 for (pass = 0; pass < 2; pass++)
53 for (node = cgraph_nodes; node; node = node->next)
54 if (!node->aux
55 && (pass
56 || (!cgraph_only_called_directly_p (node)
57 && !node->address_taken)))
59 node2 = node;
60 if (!node->callers)
61 node->aux = &last;
62 else
63 node->aux = node->callers;
64 while (node2)
66 while (node2->aux != &last)
68 edge = (struct cgraph_edge *) node2->aux;
69 if (edge->next_caller)
70 node2->aux = edge->next_caller;
71 else
72 node2->aux = &last;
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)
78 continue;
79 if (!edge->caller->aux)
81 if (!edge->caller->callers)
82 edge->caller->aux = &last;
83 else
84 edge->caller->aux = edge->caller->callers;
85 stack[stack_size++] = node2;
86 node2 = edge->caller;
87 break;
90 if (node2->aux == &last)
92 order[order_pos++] = node2;
93 if (stack_size)
94 node2 = stack[--stack_size];
95 else
96 node2 = NULL;
100 free (stack);
101 for (node = cgraph_nodes; node; node = node->next)
102 node->aux = NULL;
103 return order_pos;
106 /* Look for all functions inlined to NODE and update their inlined_to pointers
107 to INLINED_TO. */
109 static void
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. */
126 bool
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
135 verify_cgraph ();
136 #endif
137 if (file)
138 fprintf (file, "\nReclaiming functions:");
139 #ifdef ENABLE_CHECKING
140 for (node = cgraph_nodes; node; node = node->next)
141 gcc_assert (!node->aux);
142 #endif
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))
146 || !node->analyzed
147 || before_inlining_p))
149 gcc_assert (!node->global.inlined_to);
150 node->aux = first;
151 first = node;
152 node->reachable = true;
154 else
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
162 them at all. */
163 while (first != (void *) 1)
165 struct cgraph_edge *e;
166 node = first;
167 first = (struct cgraph_node *) first->aux;
168 node->aux = processed;
170 if (node->reachable)
171 for (e = node->callees; e; e = e->next_callee)
172 if (!e->callee->reachable
173 && node->analyzed
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;
180 if (!e->callee->aux
181 || (e->callee->aux == processed
182 && prev_reachable != e->callee->reachable))
184 e->callee->aux = first;
185 first = e->callee;
189 /* If any function in a comdat group is reachable, force
190 all other functions in the same comdat group to be
191 also reachable. */
192 if (node->same_comdat_group
193 && node->reachable
194 && !node->global.inlined_to)
196 for (next = node->same_comdat_group;
197 next != node;
198 next = next->same_comdat_group)
199 if (!next->reachable)
201 next->aux = first;
202 first = next;
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
210 applied. */
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;
215 if (noninline)
217 node->aux = first;
218 first = node;
219 break;
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
227 eliminated.
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)
234 next = node->next;
235 if (node->aux && !node->reachable)
237 cgraph_node_remove_callees (node);
238 node->analyzed = false;
239 node->local.inlinable = false;
241 if (!node->aux)
243 node->global.inlined_to = NULL;
244 if (file)
245 fprintf (file, " %s", cgraph_node_name (node));
246 if (!node->analyzed || !DECL_EXTERNAL (node->decl) || before_inlining_p)
247 cgraph_remove_node (node);
248 else
250 struct cgraph_edge *e;
252 /* See if there is reachable caller. */
253 for (e = node->callers; e; e = e->next_caller)
254 if (e->caller->aux)
255 break;
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)
266 if (clone->aux)
267 break;
268 if (!clone)
270 cgraph_release_function_body (node);
271 node->analyzed = false;
272 node->local.inlinable = false;
274 else
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;
287 else
288 cgraph_remove_node (node);
290 changed = true;
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
299 && !node->callers)
301 gcc_assert (node->clones);
302 node->global.inlined_to = NULL;
303 update_inlined_to_pointer (node, node);
305 node->aux = NULL;
307 #ifdef ENABLE_CHECKING
308 verify_cgraph ();
309 #endif
311 /* Reclaim alias pairs for functions that have disappeared from the
312 call graph. */
313 remove_unreachable_alias_pairs ();
315 return changed;
318 static bool
319 cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program)
321 if (!node->local.finalized)
322 return false;
323 if (!DECL_COMDAT (node->decl)
324 && (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)))
325 return false;
326 if (!whole_program)
327 return true;
328 if (DECL_PRESERVE_P (node->decl))
329 return true;
330 /* COMDAT functions must be shared only if they have address taken,
331 otherwise we can produce our own private implementation with
332 -fwhole-program. */
333 if (DECL_COMDAT (node->decl))
335 if (node->address_taken || !node->analyzed)
336 return true;
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
343 address taken. */
344 for (next = node->same_comdat_group;
345 next != node;
346 next = next->same_comdat_group)
347 if (next->address_taken || !next->analyzed)
348 return true;
351 if (MAIN_NAME_P (DECL_NAME (node->decl)))
352 return true;
353 if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl)))
354 return true;
355 return false;
358 /* Dissolve the same_comdat_group list in which NODE resides. */
360 static void
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;
368 n = next;
370 while (n != node);
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. */
384 static unsigned int
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;
407 n != node;
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));
412 #endif
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;
422 else
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
433 segfault though. */
434 dissolve_same_comdat_group_list (node);
436 node->local.local = (cgraph_only_called_directly_p (node)
437 && node->analyzed
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
449 - when it is in weak
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)
472 continue;
473 if (vnode->needed
474 && (DECL_COMDAT (vnode->decl) || TREE_PUBLIC (vnode->decl))
475 && (!whole_program
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;
484 else
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));
494 if (dump_file)
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;
513 return 0;
516 /* Local function pass handling visibilities. This happens before LTO streaming
517 so in particular -fwhole-program should be ignored at this level. */
519 static unsigned int
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 =
528 SIMPLE_IPA_PASS,
529 "visibility", /* name */
530 NULL, /* gate */
531 local_function_and_variable_visibility,/* execute */
532 NULL, /* sub */
533 NULL, /* next */
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/* todo_flags_finish */
544 /* Do not re-run on ltrans stage. */
546 static bool
547 gate_whole_program_function_and_variable_visibility (void)
549 return !flag_ltrans;
552 /* Bring functionss local at LTO time whith -fwhole-program. */
554 static unsigned int
555 whole_program_function_and_variable_visibility (void)
557 struct cgraph_node *node;
558 struct varpool_node *vnode;
560 function_and_variable_visibility (flag_whole_program);
562 for (node = cgraph_nodes; node; node = node->next)
563 if ((node->local.externally_visible && !DECL_COMDAT (node->decl))
564 && node->local.finalized)
565 cgraph_mark_needed_node (node);
566 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
567 if (vnode->externally_visible && !DECL_COMDAT (vnode->decl))
568 varpool_mark_needed_node (vnode);
569 if (dump_file)
571 fprintf (dump_file, "\nNeeded variables:");
572 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
573 if (vnode->needed)
574 fprintf (dump_file, " %s", varpool_node_name (vnode));
575 fprintf (dump_file, "\n\n");
577 return 0;
580 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
583 IPA_PASS,
584 "whole-program", /* name */
585 gate_whole_program_function_and_variable_visibility,/* gate */
586 whole_program_function_and_variable_visibility,/* execute */
587 NULL, /* sub */
588 NULL, /* next */
589 0, /* static_pass_number */
590 TV_CGRAPHOPT, /* tv_id */
591 0, /* properties_required */
592 0, /* properties_provided */
593 0, /* properties_destroyed */
594 0, /* todo_flags_start */
595 TODO_dump_cgraph | TODO_remove_functions/* todo_flags_finish */
597 NULL, /* generate_summary */
598 NULL, /* write_summary */
599 NULL, /* read_summary */
600 NULL, /* write_optimization_summary */
601 NULL, /* read_optimization_summary */
602 NULL, /* stmt_fixup */
603 0, /* TODOs */
604 NULL, /* function_transform */
605 NULL, /* variable_transform */
608 /* Hash a cgraph node set element. */
610 static hashval_t
611 hash_cgraph_node_set_element (const void *p)
613 const_cgraph_node_set_element element = (const_cgraph_node_set_element) p;
614 return htab_hash_pointer (element->node);
617 /* Compare two cgraph node set elements. */
619 static int
620 eq_cgraph_node_set_element (const void *p1, const void *p2)
622 const_cgraph_node_set_element e1 = (const_cgraph_node_set_element) p1;
623 const_cgraph_node_set_element e2 = (const_cgraph_node_set_element) p2;
625 return e1->node == e2->node;
628 /* Create a new cgraph node set. */
630 cgraph_node_set
631 cgraph_node_set_new (void)
633 cgraph_node_set new_node_set;
635 new_node_set = GGC_NEW (struct cgraph_node_set_def);
636 new_node_set->hashtab = htab_create_ggc (10,
637 hash_cgraph_node_set_element,
638 eq_cgraph_node_set_element,
639 NULL);
640 new_node_set->nodes = NULL;
641 return new_node_set;
644 /* Add cgraph_node NODE to cgraph_node_set SET. */
646 void
647 cgraph_node_set_add (cgraph_node_set set, struct cgraph_node *node)
649 void **slot;
650 cgraph_node_set_element element;
651 struct cgraph_node_set_element_def dummy;
653 dummy.node = node;
654 slot = htab_find_slot (set->hashtab, &dummy, INSERT);
656 if (*slot != HTAB_EMPTY_ENTRY)
658 element = (cgraph_node_set_element) *slot;
659 gcc_assert (node == element->node
660 && (VEC_index (cgraph_node_ptr, set->nodes, element->index)
661 == node));
662 return;
665 /* Insert node into hash table. */
666 element =
667 (cgraph_node_set_element) GGC_NEW (struct cgraph_node_set_element_def);
668 element->node = node;
669 element->index = VEC_length (cgraph_node_ptr, set->nodes);
670 *slot = element;
672 /* Insert into node vector. */
673 VEC_safe_push (cgraph_node_ptr, gc, set->nodes, node);
676 /* Remove cgraph_node NODE from cgraph_node_set SET. */
678 void
679 cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node)
681 void **slot, **last_slot;
682 cgraph_node_set_element element, last_element;
683 struct cgraph_node *last_node;
684 struct cgraph_node_set_element_def dummy;
686 dummy.node = node;
687 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
688 if (slot == NULL)
689 return;
691 element = (cgraph_node_set_element) *slot;
692 gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
693 == node);
695 /* Remove from vector. We do this by swapping node with the last element
696 of the vector. */
697 last_node = VEC_pop (cgraph_node_ptr, set->nodes);
698 if (last_node != node)
700 dummy.node = last_node;
701 last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
702 last_element = (cgraph_node_set_element) *last_slot;
703 gcc_assert (last_element);
705 /* Move the last element to the original spot of NODE. */
706 last_element->index = element->index;
707 VEC_replace (cgraph_node_ptr, set->nodes, last_element->index,
708 last_node);
711 /* Remove element from hash table. */
712 htab_clear_slot (set->hashtab, slot);
713 ggc_free (element);
716 /* Find NODE in SET and return an iterator to it if found. A null iterator
717 is returned if NODE is not in SET. */
719 cgraph_node_set_iterator
720 cgraph_node_set_find (cgraph_node_set set, struct cgraph_node *node)
722 void **slot;
723 struct cgraph_node_set_element_def dummy;
724 cgraph_node_set_element element;
725 cgraph_node_set_iterator csi;
727 dummy.node = node;
728 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
729 if (slot == NULL)
730 csi.index = (unsigned) ~0;
731 else
733 element = (cgraph_node_set_element) *slot;
734 gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
735 == node);
736 csi.index = element->index;
738 csi.set = set;
740 return csi;
743 /* Dump content of SET to file F. */
745 void
746 dump_cgraph_node_set (FILE *f, cgraph_node_set set)
748 cgraph_node_set_iterator iter;
750 for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter))
752 struct cgraph_node *node = csi_node (iter);
753 dump_cgraph_node (f, node);
757 /* Dump content of SET to stderr. */
759 void
760 debug_cgraph_node_set (cgraph_node_set set)
762 dump_cgraph_node_set (stderr, set);
765 /* Hash a varpool node set element. */
767 static hashval_t
768 hash_varpool_node_set_element (const void *p)
770 const_varpool_node_set_element element = (const_varpool_node_set_element) p;
771 return htab_hash_pointer (element->node);
774 /* Compare two varpool node set elements. */
776 static int
777 eq_varpool_node_set_element (const void *p1, const void *p2)
779 const_varpool_node_set_element e1 = (const_varpool_node_set_element) p1;
780 const_varpool_node_set_element e2 = (const_varpool_node_set_element) p2;
782 return e1->node == e2->node;
785 /* Create a new varpool node set. */
787 varpool_node_set
788 varpool_node_set_new (void)
790 varpool_node_set new_node_set;
792 new_node_set = GGC_NEW (struct varpool_node_set_def);
793 new_node_set->hashtab = htab_create_ggc (10,
794 hash_varpool_node_set_element,
795 eq_varpool_node_set_element,
796 NULL);
797 new_node_set->nodes = NULL;
798 return new_node_set;
801 /* Add varpool_node NODE to varpool_node_set SET. */
803 void
804 varpool_node_set_add (varpool_node_set set, struct varpool_node *node)
806 void **slot;
807 varpool_node_set_element element;
808 struct varpool_node_set_element_def dummy;
810 dummy.node = node;
811 slot = htab_find_slot (set->hashtab, &dummy, INSERT);
813 if (*slot != HTAB_EMPTY_ENTRY)
815 element = (varpool_node_set_element) *slot;
816 gcc_assert (node == element->node
817 && (VEC_index (varpool_node_ptr, set->nodes, element->index)
818 == node));
819 return;
822 /* Insert node into hash table. */
823 element =
824 (varpool_node_set_element) GGC_NEW (struct varpool_node_set_element_def);
825 element->node = node;
826 element->index = VEC_length (varpool_node_ptr, set->nodes);
827 *slot = element;
829 /* Insert into node vector. */
830 VEC_safe_push (varpool_node_ptr, gc, set->nodes, node);
833 /* Remove varpool_node NODE from varpool_node_set SET. */
835 void
836 varpool_node_set_remove (varpool_node_set set, struct varpool_node *node)
838 void **slot, **last_slot;
839 varpool_node_set_element element, last_element;
840 struct varpool_node *last_node;
841 struct varpool_node_set_element_def dummy;
843 dummy.node = node;
844 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
845 if (slot == NULL)
846 return;
848 element = (varpool_node_set_element) *slot;
849 gcc_assert (VEC_index (varpool_node_ptr, set->nodes, element->index)
850 == node);
852 /* Remove from vector. We do this by swapping node with the last element
853 of the vector. */
854 last_node = VEC_pop (varpool_node_ptr, set->nodes);
855 if (last_node != node)
857 dummy.node = last_node;
858 last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
859 last_element = (varpool_node_set_element) *last_slot;
860 gcc_assert (last_element);
862 /* Move the last element to the original spot of NODE. */
863 last_element->index = element->index;
864 VEC_replace (varpool_node_ptr, set->nodes, last_element->index,
865 last_node);
868 /* Remove element from hash table. */
869 htab_clear_slot (set->hashtab, slot);
870 ggc_free (element);
873 /* Find NODE in SET and return an iterator to it if found. A null iterator
874 is returned if NODE is not in SET. */
876 varpool_node_set_iterator
877 varpool_node_set_find (varpool_node_set set, struct varpool_node *node)
879 void **slot;
880 struct varpool_node_set_element_def dummy;
881 varpool_node_set_element element;
882 varpool_node_set_iterator vsi;
884 dummy.node = node;
885 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
886 if (slot == NULL)
887 vsi.index = (unsigned) ~0;
888 else
890 element = (varpool_node_set_element) *slot;
891 gcc_assert (VEC_index (varpool_node_ptr, set->nodes, element->index)
892 == node);
893 vsi.index = element->index;
895 vsi.set = set;
897 return vsi;
900 /* Dump content of SET to file F. */
902 void
903 dump_varpool_node_set (FILE *f, varpool_node_set set)
905 varpool_node_set_iterator iter;
907 for (iter = vsi_start (set); !vsi_end_p (iter); vsi_next (&iter))
909 struct varpool_node *node = vsi_node (iter);
910 dump_varpool_node (f, node);
914 /* Dump content of SET to stderr. */
916 void
917 debug_varpool_node_set (varpool_node_set set)
919 dump_varpool_node_set (stderr, set);
923 /* Simple ipa profile pass propagating frequencies across the callgraph. */
925 static unsigned int
926 ipa_profile (void)
928 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
929 struct cgraph_edge *e;
930 int order_pos;
931 bool something_changed = false;
932 int i;
934 order_pos = cgraph_postorder (order);
935 for (i = order_pos - 1; i >= 0; i--)
937 if (order[i]->local.local && cgraph_propagate_frequency (order[i]))
939 for (e = order[i]->callees; e; e = e->next_callee)
940 if (e->callee->local.local && !e->callee->aux)
942 something_changed = true;
943 e->callee->aux = (void *)1;
946 order[i]->aux = NULL;
949 while (something_changed)
951 something_changed = false;
952 for (i = order_pos - 1; i >= 0; i--)
954 if (order[i]->aux && cgraph_propagate_frequency (order[i]))
956 for (e = order[i]->callees; e; e = e->next_callee)
957 if (e->callee->local.local && !e->callee->aux)
959 something_changed = true;
960 e->callee->aux = (void *)1;
963 order[i]->aux = NULL;
966 free (order);
967 return 0;
970 static bool
971 gate_ipa_profile (void)
973 return flag_ipa_profile;
976 struct ipa_opt_pass_d pass_ipa_profile =
979 IPA_PASS,
980 "ipa-profile", /* name */
981 gate_ipa_profile, /* gate */
982 ipa_profile, /* execute */
983 NULL, /* sub */
984 NULL, /* next */
985 0, /* static_pass_number */
986 TV_IPA_PROFILE, /* tv_id */
987 0, /* properties_required */
988 0, /* properties_provided */
989 0, /* properties_destroyed */
990 0, /* todo_flags_start */
991 0 /* todo_flags_finish */
993 NULL, /* generate_summary */
994 NULL, /* write_summary */
995 NULL, /* read_summary */
996 NULL, /* write_optimization_summary */
997 NULL, /* read_optimization_summary */
998 NULL, /* stmt_fixup */
999 0, /* TODOs */
1000 NULL, /* function_transform */
1001 NULL /* variable_transform */