In libobjc/: 2010-12-19 Nicola Pero <nicola.pero@meta-innovation.com>
[official-gcc.git] / gcc / ipa.c
blobbc73afa6cd459bffb178c018f91c08860aff720c
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"
30 #include "flags.h"
31 #include "pointer-set.h"
32 #include "target.h"
33 #include "tree-iterator.h"
35 /* Fill array order with all nodes with output flag set in the reverse
36 topological order. */
38 int
39 cgraph_postorder (struct cgraph_node **order)
41 struct cgraph_node *node, *node2;
42 int stack_size = 0;
43 int order_pos = 0;
44 struct cgraph_edge *edge, last;
45 int pass;
47 struct cgraph_node **stack =
48 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
50 /* We have to deal with cycles nicely, so use a depth first traversal
51 output algorithm. Ignore the fact that some functions won't need
52 to be output and put them into order as well, so we get dependencies
53 right through inline functions. */
54 for (node = cgraph_nodes; node; node = node->next)
55 node->aux = NULL;
56 for (pass = 0; pass < 2; pass++)
57 for (node = cgraph_nodes; node; node = node->next)
58 if (!node->aux
59 && (pass
60 || (!node->address_taken
61 && !node->global.inlined_to
62 && !cgraph_only_called_directly_p (node))))
64 node2 = node;
65 if (!node->callers)
66 node->aux = &last;
67 else
68 node->aux = node->callers;
69 while (node2)
71 while (node2->aux != &last)
73 edge = (struct cgraph_edge *) node2->aux;
74 if (edge->next_caller)
75 node2->aux = edge->next_caller;
76 else
77 node2->aux = &last;
78 /* Break possible cycles involving always-inline
79 functions by ignoring edges from always-inline
80 functions to non-always-inline functions. */
81 if (edge->caller->local.disregard_inline_limits
82 && !edge->callee->local.disregard_inline_limits)
83 continue;
84 if (!edge->caller->aux)
86 if (!edge->caller->callers)
87 edge->caller->aux = &last;
88 else
89 edge->caller->aux = edge->caller->callers;
90 stack[stack_size++] = node2;
91 node2 = edge->caller;
92 break;
95 if (node2->aux == &last)
97 order[order_pos++] = node2;
98 if (stack_size)
99 node2 = stack[--stack_size];
100 else
101 node2 = NULL;
105 free (stack);
106 for (node = cgraph_nodes; node; node = node->next)
107 node->aux = NULL;
108 return order_pos;
111 /* Look for all functions inlined to NODE and update their inlined_to pointers
112 to INLINED_TO. */
114 static void
115 update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
117 struct cgraph_edge *e;
118 for (e = node->callees; e; e = e->next_callee)
119 if (e->callee->global.inlined_to)
121 e->callee->global.inlined_to = inlined_to;
122 update_inlined_to_pointer (e->callee, inlined_to);
126 /* Add cgraph NODE to queue starting at FIRST.
128 The queue is linked via AUX pointers and terminated by pointer to 1.
129 We enqueue nodes at two occasions: when we find them reachable or when we find
130 their bodies needed for further clonning. In the second case we mark them
131 by pointer to 2 after processing so they are re-queue when they become
132 reachable. */
134 static void
135 enqueue_cgraph_node (struct cgraph_node *node, struct cgraph_node **first)
137 /* Node is still in queue; do nothing. */
138 if (node->aux && node->aux != (void *) 2)
139 return;
140 /* Node was already processed as unreachable, re-enqueue
141 only if it became reachable now. */
142 if (node->aux == (void *)2 && !node->reachable)
143 return;
144 node->aux = *first;
145 *first = node;
148 /* Add varpool NODE to queue starting at FIRST. */
150 static void
151 enqueue_varpool_node (struct varpool_node *node, struct varpool_node **first)
153 node->aux = *first;
154 *first = node;
157 /* Process references. */
159 static void
160 process_references (struct ipa_ref_list *list,
161 struct cgraph_node **first,
162 struct varpool_node **first_varpool,
163 bool before_inlining_p)
165 int i;
166 struct ipa_ref *ref;
167 for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
169 if (ref->refered_type == IPA_REF_CGRAPH)
171 struct cgraph_node *node = ipa_ref_node (ref);
172 if (!node->reachable
173 && node->analyzed
174 && (!DECL_EXTERNAL (node->decl)
175 || before_inlining_p))
176 node->reachable = true;
177 enqueue_cgraph_node (node, first);
179 else
181 struct varpool_node *node = ipa_ref_varpool_node (ref);
182 if (!node->needed)
184 varpool_mark_needed_node (node);
185 enqueue_varpool_node (node, first_varpool);
191 /* Return true when function can be marked local. */
193 static bool
194 cgraph_local_node_p (struct cgraph_node *node)
196 return (cgraph_only_called_directly_p (node)
197 && node->analyzed
198 && !DECL_EXTERNAL (node->decl)
199 && !node->local.externally_visible
200 && !node->reachable_from_other_partition
201 && !node->in_other_partition);
204 /* Perform reachability analysis and reclaim all unreachable nodes.
205 If BEFORE_INLINING_P is true this function is called before inlining
206 decisions has been made. If BEFORE_INLINING_P is false this function also
207 removes unneeded bodies of extern inline functions. */
209 bool
210 cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
212 struct cgraph_node *first = (struct cgraph_node *) (void *) 1;
213 struct varpool_node *first_varpool = (struct varpool_node *) (void *) 1;
214 struct cgraph_node *node, *next;
215 struct varpool_node *vnode, *vnext;
216 bool changed = false;
218 #ifdef ENABLE_CHECKING
219 verify_cgraph ();
220 #endif
221 if (file)
222 fprintf (file, "\nReclaiming functions:");
223 #ifdef ENABLE_CHECKING
224 for (node = cgraph_nodes; node; node = node->next)
225 gcc_assert (!node->aux);
226 for (vnode = varpool_nodes; vnode; vnode = vnode->next)
227 gcc_assert (!vnode->aux);
228 #endif
229 varpool_reset_queue ();
230 /* Mark functions whose bodies are obviously needed.
231 This is mostly when they can be referenced externally. Inline clones
232 are special since their declarations are shared with master clone and thus
233 cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them. */
234 for (node = cgraph_nodes; node; node = node->next)
235 if (node->analyzed && !node->global.inlined_to
236 && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
237 /* Keep around virtual functions for possible devirtualization. */
238 || (before_inlining_p
239 && DECL_VIRTUAL_P (node->decl)
240 && (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl)))
241 /* Also external functions with address taken are better to stay
242 for indirect inlining. */
243 || (before_inlining_p
244 && DECL_EXTERNAL (node->decl)
245 && node->address_taken)))
247 gcc_assert (!node->global.inlined_to);
248 enqueue_cgraph_node (node, &first);
249 node->reachable = true;
251 else
253 gcc_assert (!node->aux);
254 node->reachable = false;
257 /* Mark variables that are obviously needed. */
258 for (vnode = varpool_nodes; vnode; vnode = vnode->next)
260 vnode->next_needed = NULL;
261 vnode->prev_needed = NULL;
262 if (vnode->analyzed
263 && !varpool_can_remove_if_no_refs (vnode))
265 vnode->needed = false;
266 varpool_mark_needed_node (vnode);
267 enqueue_varpool_node (vnode, &first_varpool);
269 else
270 vnode->needed = false;
273 /* Perform reachability analysis. As a special case do not consider
274 extern inline functions not inlined as live because we won't output
275 them at all.
277 We maintain two worklist, one for cgraph nodes other for varpools and
278 are finished once both are empty. */
280 while (first != (struct cgraph_node *) (void *) 1
281 || first_varpool != (struct varpool_node *) (void *) 1)
283 if (first != (struct cgraph_node *) (void *) 1)
285 struct cgraph_edge *e;
286 node = first;
287 first = (struct cgraph_node *) first->aux;
288 if (!node->reachable)
289 node->aux = (void *)2;
291 /* If we found this node reachable, first mark on the callees
292 reachable too, unless they are direct calls to extern inline functions
293 we decided to not inline. */
294 if (node->reachable)
296 for (e = node->callees; e; e = e->next_callee)
298 if (!e->callee->reachable
299 && node->analyzed
300 && (!e->inline_failed
301 || !DECL_EXTERNAL (e->callee->decl)
302 || before_inlining_p))
303 e->callee->reachable = true;
304 enqueue_cgraph_node (e->callee, &first);
306 process_references (&node->ref_list, &first, &first_varpool, before_inlining_p);
309 /* If any function in a comdat group is reachable, force
310 all other functions in the same comdat group to be
311 also reachable. */
312 if (node->same_comdat_group
313 && node->reachable
314 && !node->global.inlined_to)
316 for (next = node->same_comdat_group;
317 next != node;
318 next = next->same_comdat_group)
319 if (!next->reachable)
321 next->reachable = true;
322 enqueue_cgraph_node (next, &first);
326 /* We can freely remove inline clones even if they are cloned, however if
327 function is clone of real clone, we must keep it around in order to
328 make materialize_clones produce function body with the changes
329 applied. */
330 while (node->clone_of && !node->clone_of->aux
331 && !gimple_has_body_p (node->decl))
333 bool noninline = node->clone_of->decl != node->decl;
334 node = node->clone_of;
335 if (noninline && !node->reachable && !node->aux)
337 enqueue_cgraph_node (node, &first);
338 break;
342 if (first_varpool != (struct varpool_node *) (void *) 1)
344 vnode = first_varpool;
345 first_varpool = (struct varpool_node *)first_varpool->aux;
346 vnode->aux = NULL;
347 process_references (&vnode->ref_list, &first, &first_varpool, before_inlining_p);
348 /* If any function in a comdat group is reachable, force
349 all other functions in the same comdat group to be
350 also reachable. */
351 if (vnode->same_comdat_group)
353 struct varpool_node *next;
354 for (next = vnode->same_comdat_group;
355 next != vnode;
356 next = next->same_comdat_group)
357 if (!next->needed)
359 varpool_mark_needed_node (next);
360 enqueue_varpool_node (next, &first_varpool);
366 /* Remove unreachable nodes.
368 Completely unreachable functions can be fully removed from the callgraph.
369 Extern inline functions that we decided to not inline need to become unanalyzed nodes of
370 callgraph (so we still have edges to them). We remove function body then.
372 Also we need to care functions that are unreachable but we need to keep them around
373 for later clonning. In this case we also turn them to unanalyzed nodes, but
374 keep the body around. */
375 for (node = cgraph_nodes; node; node = next)
377 next = node->next;
378 if (node->aux && !node->reachable)
380 cgraph_node_remove_callees (node);
381 ipa_remove_all_references (&node->ref_list);
382 node->analyzed = false;
383 node->local.inlinable = false;
385 if (!node->aux)
387 struct cgraph_edge *e;
388 bool found = false;
389 int i;
390 struct ipa_ref *ref;
392 node->global.inlined_to = NULL;
393 if (file)
394 fprintf (file, " %s", cgraph_node_name (node));
395 /* See if there is reachable caller. */
396 for (e = node->callers; e && !found; e = e->next_caller)
397 if (e->caller->reachable)
398 found = true;
399 for (i = 0; (ipa_ref_list_refering_iterate (&node->ref_list, i, ref)
400 && !found); i++)
401 if (ref->refering_type == IPA_REF_CGRAPH
402 && ipa_ref_refering_node (ref)->reachable)
403 found = true;
404 else if (ref->refering_type == IPA_REF_VARPOOL
405 && ipa_ref_refering_varpool_node (ref)->needed)
406 found = true;
408 /* If so, we need to keep node in the callgraph. */
409 if (found)
411 if (node->analyzed)
413 struct cgraph_node *clone;
415 /* If there are still clones, we must keep body around.
416 Otherwise we can just remove the body but keep the clone. */
417 for (clone = node->clones; clone;
418 clone = clone->next_sibling_clone)
419 if (clone->aux)
420 break;
421 if (!clone)
423 cgraph_release_function_body (node);
424 node->local.inlinable = false;
425 if (node->prev_sibling_clone)
426 node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
427 else if (node->clone_of)
428 node->clone_of->clones = node->next_sibling_clone;
429 if (node->next_sibling_clone)
430 node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
431 #ifdef ENABLE_CHECKING
432 if (node->clone_of)
433 node->former_clone_of = node->clone_of->decl;
434 #endif
435 node->clone_of = NULL;
436 node->next_sibling_clone = NULL;
437 node->prev_sibling_clone = NULL;
439 else
440 gcc_assert (!clone->in_other_partition);
441 node->analyzed = false;
442 changed = true;
443 cgraph_node_remove_callees (node);
444 ipa_remove_all_references (&node->ref_list);
447 else
449 cgraph_remove_node (node);
450 changed = true;
454 for (node = cgraph_nodes; node; node = node->next)
456 /* Inline clones might be kept around so their materializing allows further
457 cloning. If the function the clone is inlined into is removed, we need
458 to turn it into normal cone. */
459 if (node->global.inlined_to
460 && !node->callers)
462 gcc_assert (node->clones);
463 node->global.inlined_to = NULL;
464 update_inlined_to_pointer (node, node);
466 node->aux = NULL;
469 if (file)
470 fprintf (file, "\n");
472 /* We must release unused extern inlines or sanity checking will fail. Rest of transformations
473 are undesirable at -O0 since we do not want to remove anything. */
474 if (!optimize)
475 return changed;
477 if (file)
478 fprintf (file, "Reclaiming variables:");
479 for (vnode = varpool_nodes; vnode; vnode = vnext)
481 vnext = vnode->next;
482 if (!vnode->needed)
484 if (file)
485 fprintf (file, " %s", varpool_node_name (vnode));
486 varpool_remove_node (vnode);
487 changed = true;
491 /* Now update address_taken flags and try to promote functions to be local. */
493 if (file)
494 fprintf (file, "\nClearing address taken flags:");
495 for (node = cgraph_nodes; node; node = node->next)
496 if (node->address_taken
497 && !node->reachable_from_other_partition)
499 int i;
500 struct ipa_ref *ref;
501 bool found = false;
502 for (i = 0; ipa_ref_list_refering_iterate (&node->ref_list, i, ref)
503 && !found; i++)
505 gcc_assert (ref->use == IPA_REF_ADDR);
506 found = true;
508 if (!found)
510 if (file)
511 fprintf (file, " %s", cgraph_node_name (node));
512 node->address_taken = false;
513 changed = true;
514 if (cgraph_local_node_p (node))
516 node->local.local = true;
517 if (file)
518 fprintf (file, " (local)");
523 #ifdef ENABLE_CHECKING
524 verify_cgraph ();
525 #endif
527 /* Reclaim alias pairs for functions that have disappeared from the
528 call graph. */
529 remove_unreachable_alias_pairs ();
531 return changed;
534 /* Discover variables that have no longer address taken or that are read only
535 and update their flags.
537 FIXME: This can not be done in between gimplify and omp_expand since
538 readonly flag plays role on what is shared and what is not. Currently we do
539 this transformation as part of whole program visibility and re-do at
540 ipa-reference pass (to take into account clonning), but it would
541 make sense to do it before early optimizations. */
543 void
544 ipa_discover_readonly_nonaddressable_vars (void)
546 struct varpool_node *vnode;
547 if (dump_file)
548 fprintf (dump_file, "Clearing variable flags:");
549 for (vnode = varpool_nodes; vnode; vnode = vnode->next)
550 if (vnode->finalized && varpool_all_refs_explicit_p (vnode)
551 && (TREE_ADDRESSABLE (vnode->decl) || !TREE_READONLY (vnode->decl)))
553 bool written = false;
554 bool address_taken = false;
555 int i;
556 struct ipa_ref *ref;
557 for (i = 0; ipa_ref_list_refering_iterate (&vnode->ref_list, i, ref)
558 && (!written || !address_taken); i++)
559 switch (ref->use)
561 case IPA_REF_ADDR:
562 address_taken = true;
563 break;
564 case IPA_REF_LOAD:
565 break;
566 case IPA_REF_STORE:
567 written = true;
568 break;
570 if (TREE_ADDRESSABLE (vnode->decl) && !address_taken)
572 if (dump_file)
573 fprintf (dump_file, " %s (addressable)", varpool_node_name (vnode));
574 TREE_ADDRESSABLE (vnode->decl) = 0;
576 if (!TREE_READONLY (vnode->decl) && !address_taken && !written
577 /* Making variable in explicit section readonly can cause section
578 type conflict.
579 See e.g. gcc.c-torture/compile/pr23237.c */
580 && DECL_SECTION_NAME (vnode->decl) == NULL)
582 if (dump_file)
583 fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
584 TREE_READONLY (vnode->decl) = 1;
587 if (dump_file)
588 fprintf (dump_file, "\n");
591 /* Return true when there is a reference to node and it is not vtable. */
592 static bool
593 cgraph_address_taken_from_non_vtable_p (struct cgraph_node *node)
595 int i;
596 struct ipa_ref *ref;
597 for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++)
599 struct varpool_node *node;
600 if (ref->refered_type == IPA_REF_CGRAPH)
601 return true;
602 node = ipa_ref_varpool_node (ref);
603 if (!DECL_VIRTUAL_P (node->decl))
604 return true;
606 return false;
609 /* COMDAT functions must be shared only if they have address taken,
610 otherwise we can produce our own private implementation with
611 -fwhole-program.
612 Return true when turning COMDAT functoin static can not lead to wrong
613 code when the resulting object links with a library defining same COMDAT.
615 Virtual functions do have their addresses taken from the vtables,
616 but in C++ there is no way to compare their addresses for equality. */
618 bool
619 cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
621 if ((cgraph_address_taken_from_non_vtable_p (node)
622 && !DECL_VIRTUAL_P (node->decl))
623 || !node->analyzed)
624 return false;
625 if (node->same_comdat_group)
627 struct cgraph_node *next;
629 /* If more than one function is in the same COMDAT group, it must
630 be shared even if just one function in the comdat group has
631 address taken. */
632 for (next = node->same_comdat_group;
633 next != node; next = next->same_comdat_group)
634 if (cgraph_address_taken_from_non_vtable_p (node)
635 && !DECL_VIRTUAL_P (next->decl))
636 return false;
638 return true;
641 /* Return true when function NODE should be considered externally visible. */
643 static bool
644 cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program, bool aliased)
646 struct cgraph_node *alias;
647 if (!node->local.finalized)
648 return false;
649 if (!DECL_COMDAT (node->decl)
650 && (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)))
651 return false;
653 /* Do not even try to be smart about aliased nodes. Until we properly
654 represent everything by same body alias, these are just evil. */
655 if (aliased)
656 return true;
658 /* Do not try to localize built-in functions yet. One of problems is that we
659 end up mangling their asm for WHOPR that makes it impossible to call them
660 using the implicit built-in declarations anymore. Similarly this enables
661 us to remove them as unreachable before actual calls may appear during
662 expansion or folding. */
663 if (DECL_BUILT_IN (node->decl))
664 return true;
666 /* FIXME: We get wrong symbols with asm aliases in callgraph and LTO.
667 This is because very little of code knows that assembler name needs to
668 mangled. Avoid touching declarations with user asm name set to mask
669 some of the problems. */
670 if (DECL_ASSEMBLER_NAME_SET_P (node->decl)
671 && IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl))[0]=='*')
672 return true;
674 /* If linker counts on us, we must preserve the function. */
675 if (cgraph_used_from_object_file_p (node))
676 return true;
677 if (DECL_PRESERVE_P (node->decl))
678 return true;
679 if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (node->decl)))
680 return true;
681 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
682 && lookup_attribute ("dllexport", DECL_ATTRIBUTES (node->decl)))
683 return true;
684 /* When doing LTO or whole program, we can bring COMDAT functoins static.
685 This improves code quality and we know we will duplicate them at most twice
686 (in the case that we are not using plugin and link with object file
687 implementing same COMDAT) */
688 if ((in_lto_p || whole_program)
689 && DECL_COMDAT (node->decl)
690 && cgraph_comdat_can_be_unshared_p (node))
691 return false;
693 /* See if we have linker information about symbol not being used or
694 if we need to make guess based on the declaration.
696 Even if the linker clams the symbol is unused, never bring internal
697 symbols that are declared by user as used or externally visible.
698 This is needed for i.e. references from asm statements. */
699 for (alias = node->same_body; alias; alias = alias->next)
700 if (alias->resolution != LDPR_PREVAILING_DEF_IRONLY)
701 break;
702 if (!alias && node->resolution == LDPR_PREVAILING_DEF_IRONLY)
703 return false;
705 /* When doing link time optimizations, hidden symbols become local. */
706 if (in_lto_p
707 && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
708 || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL)
709 /* Be sure that node is defined in IR file, not in other object
710 file. In that case we don't set used_from_other_object_file. */
711 && node->analyzed)
713 else if (!whole_program)
714 return true;
716 if (MAIN_NAME_P (DECL_NAME (node->decl)))
717 return true;
719 return false;
722 /* Return true when variable VNODE should be considered externally visible. */
724 static bool
725 varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
727 struct varpool_node *alias;
728 if (!DECL_COMDAT (vnode->decl) && !TREE_PUBLIC (vnode->decl))
729 return false;
731 /* Do not even try to be smart about aliased nodes. Until we properly
732 represent everything by same body alias, these are just evil. */
733 if (aliased)
734 return true;
736 /* If linker counts on us, we must preserve the function. */
737 if (varpool_used_from_object_file_p (vnode))
738 return true;
740 /* FIXME: We get wrong symbols with asm aliases in callgraph and LTO.
741 This is because very little of code knows that assembler name needs to
742 mangled. Avoid touching declarations with user asm name set to mask
743 some of the problems. */
744 if (DECL_ASSEMBLER_NAME_SET_P (vnode->decl)
745 && IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (vnode->decl))[0]=='*')
746 return true;
748 if (DECL_PRESERVE_P (vnode->decl))
749 return true;
750 if (lookup_attribute ("externally_visible",
751 DECL_ATTRIBUTES (vnode->decl)))
752 return true;
753 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
754 && lookup_attribute ("dllexport",
755 DECL_ATTRIBUTES (vnode->decl)))
756 return true;
758 /* See if we have linker information about symbol not being used or
759 if we need to make guess based on the declaration.
761 Even if the linker clams the symbol is unused, never bring internal
762 symbols that are declared by user as used or externally visible.
763 This is needed for i.e. references from asm statements. */
764 if (varpool_used_from_object_file_p (vnode))
765 return true;
766 for (alias = vnode->extra_name; alias; alias = alias->next)
767 if (alias->resolution != LDPR_PREVAILING_DEF_IRONLY)
768 break;
769 if (!alias && vnode->resolution == LDPR_PREVAILING_DEF_IRONLY)
770 return false;
772 /* As a special case, the COMDAT virutal tables can be unshared.
773 In LTO mode turn vtables into static variables. The variable is readonly,
774 so this does not enable more optimization, but referring static var
775 is faster for dynamic linking. Also this match logic hidding vtables
776 from LTO symbol tables. */
777 if ((in_lto_p || flag_whole_program)
778 && !vnode->force_output
779 && DECL_COMDAT (vnode->decl) && DECL_VIRTUAL_P (vnode->decl))
780 return false;
782 /* When doing link time optimizations, hidden symbols become local. */
783 if (in_lto_p
784 && (DECL_VISIBILITY (vnode->decl) == VISIBILITY_HIDDEN
785 || DECL_VISIBILITY (vnode->decl) == VISIBILITY_INTERNAL)
786 /* Be sure that node is defined in IR file, not in other object
787 file. In that case we don't set used_from_other_object_file. */
788 && vnode->finalized)
790 else if (!flag_whole_program)
791 return true;
793 /* Do not attempt to privatize COMDATS by default.
794 This would break linking with C++ libraries sharing
795 inline definitions.
797 FIXME: We can do so for readonly vars with no address taken and
798 possibly also for vtables since no direct pointer comparsion is done.
799 It might be interesting to do so to reduce linking overhead. */
800 if (DECL_COMDAT (vnode->decl) || DECL_WEAK (vnode->decl))
801 return true;
802 return false;
805 /* Dissolve the same_comdat_group list in which NODE resides. */
807 static void
808 dissolve_same_comdat_group_list (struct cgraph_node *node)
810 struct cgraph_node *n = node, *next;
813 next = n->same_comdat_group;
814 n->same_comdat_group = NULL;
815 n = next;
817 while (n != node);
820 /* Mark visibility of all functions.
822 A local function is one whose calls can occur only in the current
823 compilation unit and all its calls are explicit, so we can change
824 its calling convention. We simply mark all static functions whose
825 address is not taken as local.
827 We also change the TREE_PUBLIC flag of all declarations that are public
828 in language point of view but we want to overwrite this default
829 via visibilities for the backend point of view. */
831 static unsigned int
832 function_and_variable_visibility (bool whole_program)
834 struct cgraph_node *node;
835 struct varpool_node *vnode;
836 struct pointer_set_t *aliased_nodes = pointer_set_create ();
837 struct pointer_set_t *aliased_vnodes = pointer_set_create ();
838 unsigned i;
839 alias_pair *p;
841 /* Discover aliased nodes. */
842 FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
844 if (dump_file)
845 fprintf (dump_file, "Alias %s->%s",
846 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
847 IDENTIFIER_POINTER (p->target));
849 if ((node = cgraph_node_for_asm (p->target)) != NULL)
851 gcc_assert (node->needed);
852 pointer_set_insert (aliased_nodes, node);
853 if (dump_file)
854 fprintf (dump_file, " node %s/%i",
855 cgraph_node_name (node), node->uid);
857 else if ((vnode = varpool_node_for_asm (p->target)) != NULL)
859 gcc_assert (vnode->needed);
860 pointer_set_insert (aliased_vnodes, vnode);
861 if (dump_file)
862 fprintf (dump_file, " varpool node %s",
863 varpool_node_name (vnode));
865 if (dump_file)
866 fprintf (dump_file, "\n");
869 for (node = cgraph_nodes; node; node = node->next)
871 int flags = flags_from_decl_or_type (node->decl);
872 if (optimize
873 && (flags & (ECF_CONST | ECF_PURE))
874 && !(flags & ECF_LOOPING_CONST_OR_PURE))
876 DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
877 DECL_STATIC_DESTRUCTOR (node->decl) = 0;
880 /* C++ FE on lack of COMDAT support create local COMDAT functions
881 (that ought to be shared but can not due to object format
882 limitations). It is neccesary to keep the flag to make rest of C++ FE
883 happy. Clear the flag here to avoid confusion in middle-end. */
884 if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
885 DECL_COMDAT (node->decl) = 0;
886 /* For external decls stop tracking same_comdat_group, it doesn't matter
887 what comdat group they are in when they won't be emitted in this TU,
888 and simplifies later passes. */
889 if (node->same_comdat_group && DECL_EXTERNAL (node->decl))
891 #ifdef ENABLE_CHECKING
892 struct cgraph_node *n;
894 for (n = node->same_comdat_group;
895 n != node;
896 n = n->same_comdat_group)
897 /* If at least one of same comdat group functions is external,
898 all of them have to be, otherwise it is a front-end bug. */
899 gcc_assert (DECL_EXTERNAL (n->decl));
900 #endif
901 dissolve_same_comdat_group_list (node);
903 gcc_assert ((!DECL_WEAK (node->decl) && !DECL_COMDAT (node->decl))
904 || TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl));
905 if (cgraph_externally_visible_p (node, whole_program,
906 pointer_set_contains (aliased_nodes,
907 node)))
909 gcc_assert (!node->global.inlined_to);
910 node->local.externally_visible = true;
912 else
913 node->local.externally_visible = false;
914 if (!node->local.externally_visible && node->analyzed
915 && !DECL_EXTERNAL (node->decl))
917 struct cgraph_node *alias;
918 gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl));
919 cgraph_make_decl_local (node->decl);
920 node->resolution = LDPR_PREVAILING_DEF_IRONLY;
921 for (alias = node->same_body; alias; alias = alias->next)
922 cgraph_make_decl_local (alias->decl);
923 if (node->same_comdat_group)
924 /* cgraph_externally_visible_p has already checked all other nodes
925 in the group and they will all be made local. We need to
926 dissolve the group at once so that the predicate does not
927 segfault though. */
928 dissolve_same_comdat_group_list (node);
930 node->local.local = cgraph_local_node_p (node);
932 for (vnode = varpool_nodes; vnode; vnode = vnode->next)
934 /* weak flag makes no sense on local variables. */
935 gcc_assert (!DECL_WEAK (vnode->decl)
936 || TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl));
937 /* In several cases declarations can not be common:
939 - when declaration has initializer
940 - when it is in weak
941 - when it has specific section
942 - when it resides in non-generic address space.
943 - if declaration is local, it will get into .local common section
944 so common flag is not needed. Frontends still produce these in
945 certain cases, such as for:
947 static int a __attribute__ ((common))
949 Canonicalize things here and clear the redundant flag. */
950 if (DECL_COMMON (vnode->decl)
951 && (!(TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl))
952 || (DECL_INITIAL (vnode->decl)
953 && DECL_INITIAL (vnode->decl) != error_mark_node)
954 || DECL_WEAK (vnode->decl)
955 || DECL_SECTION_NAME (vnode->decl) != NULL
956 || ! (ADDR_SPACE_GENERIC_P
957 (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
958 DECL_COMMON (vnode->decl) = 0;
960 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
962 if (!vnode->finalized)
963 continue;
964 if (vnode->needed
965 && varpool_externally_visible_p
966 (vnode,
967 pointer_set_contains (aliased_vnodes, vnode)))
968 vnode->externally_visible = true;
969 else
970 vnode->externally_visible = false;
971 if (!vnode->externally_visible)
973 gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
974 cgraph_make_decl_local (vnode->decl);
975 vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
977 gcc_assert (TREE_STATIC (vnode->decl));
979 pointer_set_destroy (aliased_nodes);
980 pointer_set_destroy (aliased_vnodes);
982 if (dump_file)
984 fprintf (dump_file, "\nMarking local functions:");
985 for (node = cgraph_nodes; node; node = node->next)
986 if (node->local.local)
987 fprintf (dump_file, " %s", cgraph_node_name (node));
988 fprintf (dump_file, "\n\n");
989 fprintf (dump_file, "\nMarking externally visible functions:");
990 for (node = cgraph_nodes; node; node = node->next)
991 if (node->local.externally_visible)
992 fprintf (dump_file, " %s", cgraph_node_name (node));
993 fprintf (dump_file, "\n\n");
994 fprintf (dump_file, "\nMarking externally visible variables:");
995 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
996 if (vnode->externally_visible)
997 fprintf (dump_file, " %s", varpool_node_name (vnode));
998 fprintf (dump_file, "\n\n");
1000 cgraph_function_flags_ready = true;
1001 return 0;
1004 /* Local function pass handling visibilities. This happens before LTO streaming
1005 so in particular -fwhole-program should be ignored at this level. */
1007 static unsigned int
1008 local_function_and_variable_visibility (void)
1010 return function_and_variable_visibility (flag_whole_program && !flag_lto);
1013 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
1016 SIMPLE_IPA_PASS,
1017 "visibility", /* name */
1018 NULL, /* gate */
1019 local_function_and_variable_visibility,/* execute */
1020 NULL, /* sub */
1021 NULL, /* next */
1022 0, /* static_pass_number */
1023 TV_CGRAPHOPT, /* tv_id */
1024 0, /* properties_required */
1025 0, /* properties_provided */
1026 0, /* properties_destroyed */
1027 0, /* todo_flags_start */
1028 TODO_remove_functions | TODO_dump_cgraph
1029 | TODO_ggc_collect /* todo_flags_finish */
1033 /* Do not re-run on ltrans stage. */
1035 static bool
1036 gate_whole_program_function_and_variable_visibility (void)
1038 return !flag_ltrans;
1041 /* Bring functionss local at LTO time whith -fwhole-program. */
1043 static unsigned int
1044 whole_program_function_and_variable_visibility (void)
1046 struct cgraph_node *node;
1047 struct varpool_node *vnode;
1049 function_and_variable_visibility (flag_whole_program);
1051 for (node = cgraph_nodes; node; node = node->next)
1052 if ((node->local.externally_visible && !DECL_COMDAT (node->decl))
1053 && node->local.finalized)
1054 cgraph_mark_needed_node (node);
1055 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
1056 if (vnode->externally_visible && !DECL_COMDAT (vnode->decl))
1057 varpool_mark_needed_node (vnode);
1058 if (dump_file)
1060 fprintf (dump_file, "\nNeeded variables:");
1061 for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
1062 if (vnode->needed)
1063 fprintf (dump_file, " %s", varpool_node_name (vnode));
1064 fprintf (dump_file, "\n\n");
1066 if (optimize)
1067 ipa_discover_readonly_nonaddressable_vars ();
1068 return 0;
1071 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
1074 IPA_PASS,
1075 "whole-program", /* name */
1076 gate_whole_program_function_and_variable_visibility,/* gate */
1077 whole_program_function_and_variable_visibility,/* execute */
1078 NULL, /* sub */
1079 NULL, /* next */
1080 0, /* static_pass_number */
1081 TV_CGRAPHOPT, /* tv_id */
1082 0, /* properties_required */
1083 0, /* properties_provided */
1084 0, /* properties_destroyed */
1085 0, /* todo_flags_start */
1086 TODO_remove_functions | TODO_dump_cgraph
1087 | TODO_ggc_collect /* todo_flags_finish */
1089 NULL, /* generate_summary */
1090 NULL, /* write_summary */
1091 NULL, /* read_summary */
1092 NULL, /* write_optimization_summary */
1093 NULL, /* read_optimization_summary */
1094 NULL, /* stmt_fixup */
1095 0, /* TODOs */
1096 NULL, /* function_transform */
1097 NULL, /* variable_transform */
1100 /* Hash a cgraph node set element. */
1102 static hashval_t
1103 hash_cgraph_node_set_element (const void *p)
1105 const_cgraph_node_set_element element = (const_cgraph_node_set_element) p;
1106 return htab_hash_pointer (element->node);
1109 /* Compare two cgraph node set elements. */
1111 static int
1112 eq_cgraph_node_set_element (const void *p1, const void *p2)
1114 const_cgraph_node_set_element e1 = (const_cgraph_node_set_element) p1;
1115 const_cgraph_node_set_element e2 = (const_cgraph_node_set_element) p2;
1117 return e1->node == e2->node;
1120 /* Create a new cgraph node set. */
1122 cgraph_node_set
1123 cgraph_node_set_new (void)
1125 cgraph_node_set new_node_set;
1127 new_node_set = ggc_alloc_cgraph_node_set_def ();
1128 new_node_set->hashtab = htab_create_ggc (10,
1129 hash_cgraph_node_set_element,
1130 eq_cgraph_node_set_element,
1131 NULL);
1132 new_node_set->nodes = NULL;
1133 return new_node_set;
1136 /* Add cgraph_node NODE to cgraph_node_set SET. */
1138 void
1139 cgraph_node_set_add (cgraph_node_set set, struct cgraph_node *node)
1141 void **slot;
1142 cgraph_node_set_element element;
1143 struct cgraph_node_set_element_def dummy;
1145 dummy.node = node;
1146 slot = htab_find_slot (set->hashtab, &dummy, INSERT);
1148 if (*slot != HTAB_EMPTY_ENTRY)
1150 element = (cgraph_node_set_element) *slot;
1151 gcc_assert (node == element->node
1152 && (VEC_index (cgraph_node_ptr, set->nodes, element->index)
1153 == node));
1154 return;
1157 /* Insert node into hash table. */
1158 element = ggc_alloc_cgraph_node_set_element_def ();
1159 element->node = node;
1160 element->index = VEC_length (cgraph_node_ptr, set->nodes);
1161 *slot = element;
1163 /* Insert into node vector. */
1164 VEC_safe_push (cgraph_node_ptr, gc, set->nodes, node);
1167 /* Remove cgraph_node NODE from cgraph_node_set SET. */
1169 void
1170 cgraph_node_set_remove (cgraph_node_set set, struct cgraph_node *node)
1172 void **slot, **last_slot;
1173 cgraph_node_set_element element, last_element;
1174 struct cgraph_node *last_node;
1175 struct cgraph_node_set_element_def dummy;
1177 dummy.node = node;
1178 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1179 if (slot == NULL)
1180 return;
1182 element = (cgraph_node_set_element) *slot;
1183 gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
1184 == node);
1186 /* Remove from vector. We do this by swapping node with the last element
1187 of the vector. */
1188 last_node = VEC_pop (cgraph_node_ptr, set->nodes);
1189 if (last_node != node)
1191 dummy.node = last_node;
1192 last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1193 last_element = (cgraph_node_set_element) *last_slot;
1194 gcc_assert (last_element);
1196 /* Move the last element to the original spot of NODE. */
1197 last_element->index = element->index;
1198 VEC_replace (cgraph_node_ptr, set->nodes, last_element->index,
1199 last_node);
1202 /* Remove element from hash table. */
1203 htab_clear_slot (set->hashtab, slot);
1204 ggc_free (element);
1207 /* Find NODE in SET and return an iterator to it if found. A null iterator
1208 is returned if NODE is not in SET. */
1210 cgraph_node_set_iterator
1211 cgraph_node_set_find (cgraph_node_set set, struct cgraph_node *node)
1213 void **slot;
1214 struct cgraph_node_set_element_def dummy;
1215 cgraph_node_set_element element;
1216 cgraph_node_set_iterator csi;
1218 dummy.node = node;
1219 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1220 if (slot == NULL)
1221 csi.index = (unsigned) ~0;
1222 else
1224 element = (cgraph_node_set_element) *slot;
1225 gcc_assert (VEC_index (cgraph_node_ptr, set->nodes, element->index)
1226 == node);
1227 csi.index = element->index;
1229 csi.set = set;
1231 return csi;
1234 /* Dump content of SET to file F. */
1236 void
1237 dump_cgraph_node_set (FILE *f, cgraph_node_set set)
1239 cgraph_node_set_iterator iter;
1241 for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter))
1243 struct cgraph_node *node = csi_node (iter);
1244 fprintf (f, " %s/%i", cgraph_node_name (node), node->uid);
1246 fprintf (f, "\n");
1249 /* Dump content of SET to stderr. */
1251 DEBUG_FUNCTION void
1252 debug_cgraph_node_set (cgraph_node_set set)
1254 dump_cgraph_node_set (stderr, set);
1257 /* Hash a varpool node set element. */
1259 static hashval_t
1260 hash_varpool_node_set_element (const void *p)
1262 const_varpool_node_set_element element = (const_varpool_node_set_element) p;
1263 return htab_hash_pointer (element->node);
1266 /* Compare two varpool node set elements. */
1268 static int
1269 eq_varpool_node_set_element (const void *p1, const void *p2)
1271 const_varpool_node_set_element e1 = (const_varpool_node_set_element) p1;
1272 const_varpool_node_set_element e2 = (const_varpool_node_set_element) p2;
1274 return e1->node == e2->node;
1277 /* Create a new varpool node set. */
1279 varpool_node_set
1280 varpool_node_set_new (void)
1282 varpool_node_set new_node_set;
1284 new_node_set = ggc_alloc_varpool_node_set_def ();
1285 new_node_set->hashtab = htab_create_ggc (10,
1286 hash_varpool_node_set_element,
1287 eq_varpool_node_set_element,
1288 NULL);
1289 new_node_set->nodes = NULL;
1290 return new_node_set;
1293 /* Add varpool_node NODE to varpool_node_set SET. */
1295 void
1296 varpool_node_set_add (varpool_node_set set, struct varpool_node *node)
1298 void **slot;
1299 varpool_node_set_element element;
1300 struct varpool_node_set_element_def dummy;
1302 dummy.node = node;
1303 slot = htab_find_slot (set->hashtab, &dummy, INSERT);
1305 if (*slot != HTAB_EMPTY_ENTRY)
1307 element = (varpool_node_set_element) *slot;
1308 gcc_assert (node == element->node
1309 && (VEC_index (varpool_node_ptr, set->nodes, element->index)
1310 == node));
1311 return;
1314 /* Insert node into hash table. */
1315 element = ggc_alloc_varpool_node_set_element_def ();
1316 element->node = node;
1317 element->index = VEC_length (varpool_node_ptr, set->nodes);
1318 *slot = element;
1320 /* Insert into node vector. */
1321 VEC_safe_push (varpool_node_ptr, gc, set->nodes, node);
1324 /* Remove varpool_node NODE from varpool_node_set SET. */
1326 void
1327 varpool_node_set_remove (varpool_node_set set, struct varpool_node *node)
1329 void **slot, **last_slot;
1330 varpool_node_set_element element, last_element;
1331 struct varpool_node *last_node;
1332 struct varpool_node_set_element_def dummy;
1334 dummy.node = node;
1335 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1336 if (slot == NULL)
1337 return;
1339 element = (varpool_node_set_element) *slot;
1340 gcc_assert (VEC_index (varpool_node_ptr, set->nodes, element->index)
1341 == node);
1343 /* Remove from vector. We do this by swapping node with the last element
1344 of the vector. */
1345 last_node = VEC_pop (varpool_node_ptr, set->nodes);
1346 if (last_node != node)
1348 dummy.node = last_node;
1349 last_slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1350 last_element = (varpool_node_set_element) *last_slot;
1351 gcc_assert (last_element);
1353 /* Move the last element to the original spot of NODE. */
1354 last_element->index = element->index;
1355 VEC_replace (varpool_node_ptr, set->nodes, last_element->index,
1356 last_node);
1359 /* Remove element from hash table. */
1360 htab_clear_slot (set->hashtab, slot);
1361 ggc_free (element);
1364 /* Find NODE in SET and return an iterator to it if found. A null iterator
1365 is returned if NODE is not in SET. */
1367 varpool_node_set_iterator
1368 varpool_node_set_find (varpool_node_set set, struct varpool_node *node)
1370 void **slot;
1371 struct varpool_node_set_element_def dummy;
1372 varpool_node_set_element element;
1373 varpool_node_set_iterator vsi;
1375 dummy.node = node;
1376 slot = htab_find_slot (set->hashtab, &dummy, NO_INSERT);
1377 if (slot == NULL)
1378 vsi.index = (unsigned) ~0;
1379 else
1381 element = (varpool_node_set_element) *slot;
1382 gcc_assert (VEC_index (varpool_node_ptr, set->nodes, element->index)
1383 == node);
1384 vsi.index = element->index;
1386 vsi.set = set;
1388 return vsi;
1391 /* Dump content of SET to file F. */
1393 void
1394 dump_varpool_node_set (FILE *f, varpool_node_set set)
1396 varpool_node_set_iterator iter;
1398 for (iter = vsi_start (set); !vsi_end_p (iter); vsi_next (&iter))
1400 struct varpool_node *node = vsi_node (iter);
1401 fprintf (f, " %s", varpool_node_name (node));
1403 fprintf (f, "\n");
1406 /* Dump content of SET to stderr. */
1408 DEBUG_FUNCTION void
1409 debug_varpool_node_set (varpool_node_set set)
1411 dump_varpool_node_set (stderr, set);
1415 /* Simple ipa profile pass propagating frequencies across the callgraph. */
1417 static unsigned int
1418 ipa_profile (void)
1420 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1421 struct cgraph_edge *e;
1422 int order_pos;
1423 bool something_changed = false;
1424 int i;
1426 order_pos = cgraph_postorder (order);
1427 for (i = order_pos - 1; i >= 0; i--)
1429 if (order[i]->local.local && cgraph_propagate_frequency (order[i]))
1431 for (e = order[i]->callees; e; e = e->next_callee)
1432 if (e->callee->local.local && !e->callee->aux)
1434 something_changed = true;
1435 e->callee->aux = (void *)1;
1438 order[i]->aux = NULL;
1441 while (something_changed)
1443 something_changed = false;
1444 for (i = order_pos - 1; i >= 0; i--)
1446 if (order[i]->aux && cgraph_propagate_frequency (order[i]))
1448 for (e = order[i]->callees; e; e = e->next_callee)
1449 if (e->callee->local.local && !e->callee->aux)
1451 something_changed = true;
1452 e->callee->aux = (void *)1;
1455 order[i]->aux = NULL;
1458 free (order);
1459 return 0;
1462 static bool
1463 gate_ipa_profile (void)
1465 return flag_ipa_profile;
1468 struct ipa_opt_pass_d pass_ipa_profile =
1471 IPA_PASS,
1472 "ipa-profile", /* name */
1473 gate_ipa_profile, /* gate */
1474 ipa_profile, /* execute */
1475 NULL, /* sub */
1476 NULL, /* next */
1477 0, /* static_pass_number */
1478 TV_IPA_PROFILE, /* tv_id */
1479 0, /* properties_required */
1480 0, /* properties_provided */
1481 0, /* properties_destroyed */
1482 0, /* todo_flags_start */
1483 0 /* todo_flags_finish */
1485 NULL, /* generate_summary */
1486 NULL, /* write_summary */
1487 NULL, /* read_summary */
1488 NULL, /* write_optimization_summary */
1489 NULL, /* read_optimization_summary */
1490 NULL, /* stmt_fixup */
1491 0, /* TODOs */
1492 NULL, /* function_transform */
1493 NULL /* variable_transform */
1496 /* Generate and emit a static constructor or destructor. WHICH must
1497 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1498 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1499 initialization priority for this constructor or destructor.
1501 FINAL specify whether the externally visible name for collect2 should
1502 be produced. */
1504 static void
1505 cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
1507 static int counter = 0;
1508 char which_buf[16];
1509 tree decl, name, resdecl;
1511 /* The priority is encoded in the constructor or destructor name.
1512 collect2 will sort the names and arrange that they are called at
1513 program startup. */
1514 if (final)
1515 sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
1516 else
1517 /* Proudce sane name but one not recognizable by collect2, just for the
1518 case we fail to inline the function. */
1519 sprintf (which_buf, "sub_%c_%.5d_%d", which, priority, counter++);
1520 name = get_file_function_name (which_buf);
1522 decl = build_decl (input_location, FUNCTION_DECL, name,
1523 build_function_type_list (void_type_node, NULL_TREE));
1524 current_function_decl = decl;
1526 resdecl = build_decl (input_location,
1527 RESULT_DECL, NULL_TREE, void_type_node);
1528 DECL_ARTIFICIAL (resdecl) = 1;
1529 DECL_RESULT (decl) = resdecl;
1530 DECL_CONTEXT (resdecl) = decl;
1532 allocate_struct_function (decl, false);
1534 TREE_STATIC (decl) = 1;
1535 TREE_USED (decl) = 1;
1536 DECL_ARTIFICIAL (decl) = 1;
1537 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1538 DECL_SAVED_TREE (decl) = body;
1539 if (!targetm.have_ctors_dtors && final)
1541 TREE_PUBLIC (decl) = 1;
1542 DECL_PRESERVE_P (decl) = 1;
1544 DECL_UNINLINABLE (decl) = 1;
1546 DECL_INITIAL (decl) = make_node (BLOCK);
1547 TREE_USED (DECL_INITIAL (decl)) = 1;
1549 DECL_SOURCE_LOCATION (decl) = input_location;
1550 cfun->function_end_locus = input_location;
1552 switch (which)
1554 case 'I':
1555 DECL_STATIC_CONSTRUCTOR (decl) = 1;
1556 decl_init_priority_insert (decl, priority);
1557 break;
1558 case 'D':
1559 DECL_STATIC_DESTRUCTOR (decl) = 1;
1560 decl_fini_priority_insert (decl, priority);
1561 break;
1562 default:
1563 gcc_unreachable ();
1566 gimplify_function_tree (decl);
1568 cgraph_add_new_function (decl, false);
1570 set_cfun (NULL);
1571 current_function_decl = NULL;
1574 /* Generate and emit a static constructor or destructor. WHICH must
1575 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1576 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1577 initialization priority for this constructor or destructor. */
1579 void
1580 cgraph_build_static_cdtor (char which, tree body, int priority)
1582 cgraph_build_static_cdtor_1 (which, body, priority, false);
1585 /* A vector of FUNCTION_DECLs declared as static constructors. */
1586 static VEC(tree, heap) *static_ctors;
1587 /* A vector of FUNCTION_DECLs declared as static destructors. */
1588 static VEC(tree, heap) *static_dtors;
1590 /* When target does not have ctors and dtors, we call all constructor
1591 and destructor by special initialization/destruction function
1592 recognized by collect2.
1594 When we are going to build this function, collect all constructors and
1595 destructors and turn them into normal functions. */
1597 static void
1598 record_cdtor_fn (struct cgraph_node *node)
1600 if (DECL_STATIC_CONSTRUCTOR (node->decl))
1601 VEC_safe_push (tree, heap, static_ctors, node->decl);
1602 if (DECL_STATIC_DESTRUCTOR (node->decl))
1603 VEC_safe_push (tree, heap, static_dtors, node->decl);
1604 node = cgraph_node (node->decl);
1605 node->local.disregard_inline_limits = 1;
1608 /* Define global constructors/destructor functions for the CDTORS, of
1609 which they are LEN. The CDTORS are sorted by initialization
1610 priority. If CTOR_P is true, these are constructors; otherwise,
1611 they are destructors. */
1613 static void
1614 build_cdtor (bool ctor_p, VEC (tree, heap) *cdtors)
1616 size_t i,j;
1617 size_t len = VEC_length (tree, cdtors);
1619 i = 0;
1620 while (i < len)
1622 tree body;
1623 tree fn;
1624 priority_type priority;
1626 priority = 0;
1627 body = NULL_TREE;
1628 j = i;
1631 priority_type p;
1632 fn = VEC_index (tree, cdtors, j);
1633 p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
1634 if (j == i)
1635 priority = p;
1636 else if (p != priority)
1637 break;
1638 j++;
1640 while (j < len);
1642 /* When there is only one cdtor and target supports them, do nothing. */
1643 if (j == i + 1
1644 && targetm.have_ctors_dtors)
1646 i++;
1647 continue;
1649 /* Find the next batch of constructors/destructors with the same
1650 initialization priority. */
1651 for (;i < j; i++)
1653 tree call;
1654 fn = VEC_index (tree, cdtors, i);
1655 call = build_call_expr (fn, 0);
1656 if (ctor_p)
1657 DECL_STATIC_CONSTRUCTOR (fn) = 0;
1658 else
1659 DECL_STATIC_DESTRUCTOR (fn) = 0;
1660 /* We do not want to optimize away pure/const calls here.
1661 When optimizing, these should be already removed, when not
1662 optimizing, we want user to be able to breakpoint in them. */
1663 TREE_SIDE_EFFECTS (call) = 1;
1664 append_to_statement_list (call, &body);
1666 gcc_assert (body != NULL_TREE);
1667 /* Generate a function to call all the function of like
1668 priority. */
1669 cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true);
1673 /* Comparison function for qsort. P1 and P2 are actually of type
1674 "tree *" and point to static constructors. DECL_INIT_PRIORITY is
1675 used to determine the sort order. */
1677 static int
1678 compare_ctor (const void *p1, const void *p2)
1680 tree f1;
1681 tree f2;
1682 int priority1;
1683 int priority2;
1685 f1 = *(const tree *)p1;
1686 f2 = *(const tree *)p2;
1687 priority1 = DECL_INIT_PRIORITY (f1);
1688 priority2 = DECL_INIT_PRIORITY (f2);
1690 if (priority1 < priority2)
1691 return -1;
1692 else if (priority1 > priority2)
1693 return 1;
1694 else
1695 /* Ensure a stable sort. Constructors are executed in backwarding
1696 order to make LTO initialize braries first. */
1697 return DECL_UID (f2) - DECL_UID (f1);
1700 /* Comparison function for qsort. P1 and P2 are actually of type
1701 "tree *" and point to static destructors. DECL_FINI_PRIORITY is
1702 used to determine the sort order. */
1704 static int
1705 compare_dtor (const void *p1, const void *p2)
1707 tree f1;
1708 tree f2;
1709 int priority1;
1710 int priority2;
1712 f1 = *(const tree *)p1;
1713 f2 = *(const tree *)p2;
1714 priority1 = DECL_FINI_PRIORITY (f1);
1715 priority2 = DECL_FINI_PRIORITY (f2);
1717 if (priority1 < priority2)
1718 return -1;
1719 else if (priority1 > priority2)
1720 return 1;
1721 else
1722 /* Ensure a stable sort. */
1723 return DECL_UID (f1) - DECL_UID (f2);
1726 /* Generate functions to call static constructors and destructors
1727 for targets that do not support .ctors/.dtors sections. These
1728 functions have magic names which are detected by collect2. */
1730 static void
1731 build_cdtor_fns (void)
1733 if (!VEC_empty (tree, static_ctors))
1735 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1736 VEC_qsort (tree, static_ctors, compare_ctor);
1737 build_cdtor (/*ctor_p=*/true, static_ctors);
1740 if (!VEC_empty (tree, static_dtors))
1742 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1743 VEC_qsort (tree, static_dtors, compare_dtor);
1744 build_cdtor (/*ctor_p=*/false, static_dtors);
1748 /* Look for constructors and destructors and produce function calling them.
1749 This is needed for targets not supporting ctors or dtors, but we perform the
1750 transformation also at linktime to merge possibly numberous
1751 constructors/destructors into single function to improve code locality and
1752 reduce size. */
1754 static unsigned int
1755 ipa_cdtor_merge (void)
1757 struct cgraph_node *node;
1758 for (node = cgraph_nodes; node; node = node->next)
1759 if (node->analyzed
1760 && (DECL_STATIC_CONSTRUCTOR (node->decl)
1761 || DECL_STATIC_DESTRUCTOR (node->decl)))
1762 record_cdtor_fn (node);
1763 build_cdtor_fns ();
1764 VEC_free (tree, heap, static_ctors);
1765 VEC_free (tree, heap, static_dtors);
1766 return 0;
1769 /* Perform the pass when we have no ctors/dtors support
1770 or at LTO time to merge multiple constructors into single
1771 function. */
1773 static bool
1774 gate_ipa_cdtor_merge (void)
1776 return !targetm.have_ctors_dtors || (optimize && in_lto_p);
1779 struct ipa_opt_pass_d pass_ipa_cdtor_merge =
1782 IPA_PASS,
1783 "cdtor", /* name */
1784 gate_ipa_cdtor_merge, /* gate */
1785 ipa_cdtor_merge, /* execute */
1786 NULL, /* sub */
1787 NULL, /* next */
1788 0, /* static_pass_number */
1789 TV_CGRAPHOPT, /* tv_id */
1790 0, /* properties_required */
1791 0, /* properties_provided */
1792 0, /* properties_destroyed */
1793 0, /* todo_flags_start */
1794 0 /* todo_flags_finish */
1796 NULL, /* generate_summary */
1797 NULL, /* write_summary */
1798 NULL, /* read_summary */
1799 NULL, /* write_optimization_summary */
1800 NULL, /* read_optimization_summary */
1801 NULL, /* stmt_fixup */
1802 0, /* TODOs */
1803 NULL, /* function_transform */
1804 NULL /* variable_transform */