Merged revisions 195901,195904,196012 via svnmerge from
[official-gcc.git] / main / gcc / ipa.c
blob73fb7904ddcbd02d054ff57b68bd205ac4a28d6a
1 /* Basic IPA optimizations and utilities.
2 Copyright (C) 2003-2013 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "cgraph.h"
25 #include "toplev.h"
26 #include "tree-pass.h"
27 #include "gimple.h"
28 #include "ggc.h"
29 #include "flags.h"
30 #include "pointer-set.h"
31 #include "target.h"
32 #include "tree-iterator.h"
33 #include "l-ipo.h"
34 #include "ipa-utils.h"
35 #include "pointer-set.h"
36 #include "ipa-inline.h"
38 /* Look for all functions inlined to NODE and update their inlined_to pointers
39 to INLINED_TO. */
41 static void
42 update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
44 struct cgraph_edge *e;
45 for (e = node->callees; e; e = e->next_callee)
46 if (e->callee->global.inlined_to)
48 e->callee->global.inlined_to = inlined_to;
49 update_inlined_to_pointer (e->callee, inlined_to);
53 /* Add symtab NODE to queue starting at FIRST.
55 The queue is linked via AUX pointers and terminated by pointer to 1.
56 We enqueue nodes at two occasions: when we find them reachable or when we find
57 their bodies needed for further clonning. In the second case we mark them
58 by pointer to 2 after processing so they are re-queue when they become
59 reachable. */
61 static void
62 enqueue_node (symtab_node node, symtab_node *first,
63 struct pointer_set_t *reachable)
65 /* Node is still in queue; do nothing. */
66 if (node->symbol.aux && node->symbol.aux != (void *) 2)
67 return;
68 /* Node was already processed as unreachable, re-enqueue
69 only if it became reachable now. */
70 if (node->symbol.aux == (void *)2 && !pointer_set_contains (reachable, node))
71 return;
72 node->symbol.aux = *first;
73 *first = node;
76 /* Process references. */
78 static void
79 process_references (struct ipa_ref_list *list,
80 symtab_node *first,
81 bool before_inlining_p,
82 struct pointer_set_t *reachable)
84 int i;
85 struct ipa_ref *ref;
86 for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
88 if (is_a <cgraph_node> (ref->referred))
90 struct cgraph_node *node = ipa_ref_node (ref);
92 if (node->analyzed
93 && (!(DECL_EXTERNAL (node->symbol.decl)
94 || cgraph_is_aux_decl_external (node))
95 || node->alias
96 || before_inlining_p))
97 pointer_set_insert (reachable, node);
98 enqueue_node ((symtab_node) node, first, reachable);
100 else
102 struct varpool_node *node = ipa_ref_varpool_node (ref);
104 if (node->analyzed
105 && (!DECL_EXTERNAL (node->symbol.decl)
106 || node->alias
107 || before_inlining_p))
108 pointer_set_insert (reachable, node);
109 enqueue_node ((symtab_node) node, first, reachable);
115 /* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
117 static bool
118 cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
120 /* FIXME: Aliases can be local, but i386 gets thunks wrong then. */
121 return !(cgraph_only_called_directly_or_aliased_p (node)
122 && !ipa_ref_has_aliases_p (&node->symbol.ref_list)
123 && node->analyzed
124 && !DECL_EXTERNAL (node->symbol.decl)
125 && !node->symbol.externally_visible
126 && !node->symbol.used_from_other_partition
127 && !node->symbol.in_other_partition);
130 /* Return true when function can be marked local. */
132 static bool
133 cgraph_local_node_p (struct cgraph_node *node)
135 struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);
137 /* FIXME: thunks can be considered local, but we need prevent i386
138 from attempting to change calling convention of them. */
139 if (n->thunk.thunk_p)
140 return false;
141 return !cgraph_for_node_and_aliases (n,
142 cgraph_non_local_node_p_1, NULL, true);
146 /* Return true when NODE has ADDR reference. */
148 static bool
149 has_addr_references_p (struct cgraph_node *node,
150 void *data ATTRIBUTE_UNUSED)
152 int i;
153 struct ipa_ref *ref;
155 for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
156 i, ref); i++)
157 if (ref->use == IPA_REF_ADDR)
158 return true;
159 return false;
162 /* Perform reachability analysis and reclaim all unreachable nodes.
164 The algorithm is basically mark&sweep but with some extra refinements:
166 - reachable extern inline functions needs special handling; the bodies needs
167 to stay in memory until inlining in hope that they will be inlined.
168 After inlining we release their bodies and turn them into unanalyzed
169 nodes even when they are reachable.
171 BEFORE_INLINING_P specify whether we are before or after inlining.
173 - virtual functions are kept in callgraph even if they seem unreachable in
174 hope calls to them will be devirtualized.
176 Again we remove them after inlining. In late optimization some
177 devirtualization may happen, but it is not importnat since we won't inline
178 the call. In theory early opts and IPA should work out all important cases.
180 - virtual clones needs bodies of their origins for later materialization;
181 this means that we want to keep the body even if the origin is unreachable
182 otherwise. To avoid origin from sitting in the callgraph and being
183 walked by IPA passes, we turn them into unanalyzed nodes with body
184 defined.
186 We maintain set of function declaration where body needs to stay in
187 body_needed_for_clonning
189 Inline clones represent special case: their declaration match the
190 declaration of origin and cgraph_remove_node already knows how to
191 reshape callgraph and preserve body when offline copy of function or
192 inline clone is being removed.
194 - C++ virtual tables keyed to other unit are represented as DECL_EXTERNAL
195 variables with DECL_INITIAL set. We finalize these and keep reachable
196 ones around for constant folding purposes. After inlining we however
197 stop walking their references to let everything static referneced by them
198 to be removed when it is otherwise unreachable.
200 We maintain queue of both reachable symbols (i.e. defined symbols that needs
201 to stay) and symbols that are in boundary (i.e. external symbols referenced
202 by reachable symbols or origins of clones). The queue is represented
203 as linked list by AUX pointer terminated by 1.
205 A the end we keep all reachable symbols. For symbols in boundary we always
206 turn definition into a declaration, but we may keep function body around
207 based on body_needed_for_clonning
209 All symbols that enter the queue have AUX pointer non-zero and are in the
210 boundary. Pointer set REACHABLE is used to track reachable symbols.
212 Every symbol can be visited twice - once as part of boundary and once
213 as real reachable symbol. enqueue_node needs to decide whether the
214 node needs to be re-queued for second processing. For this purpose
215 we set AUX pointer of processed symbols in the boundary to constant 2. */
217 bool
218 symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
220 symtab_node first = (symtab_node) (void *) 1;
221 struct cgraph_node *node, *next;
222 struct varpool_node *vnode, *vnext;
223 bool changed = false;
224 struct pointer_set_t *reachable = pointer_set_create ();
225 struct pointer_set_t *body_needed_for_clonning = pointer_set_create ();
227 /* In LIPO mode, do not remove functions until after global linking
228 is performed. Otherwise functions needed for cross module inlining
229 may get eliminated. Global linking will be done just before tree
230 profiling. */
231 if (L_IPO_COMP_MODE
232 && !cgraph_pre_profiling_inlining_done)
233 return false;
235 #ifdef ENABLE_CHECKING
236 verify_symtab ();
237 #endif
238 if (file)
239 fprintf (file, "\nReclaiming functions:");
240 #ifdef ENABLE_CHECKING
241 FOR_EACH_FUNCTION (node)
242 gcc_assert (!node->symbol.aux);
243 FOR_EACH_VARIABLE (vnode)
244 gcc_assert (!vnode->symbol.aux);
245 #endif
246 /* Mark functions whose bodies are obviously needed.
247 This is mostly when they can be referenced externally. Inline clones
248 are special since their declarations are shared with master clone and thus
249 cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them. */
250 FOR_EACH_DEFINED_FUNCTION (node)
251 if (!node->global.inlined_to
252 && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
253 /* Keep around virtual functions for possible devirtualization. */
254 || (before_inlining_p
255 && DECL_VIRTUAL_P (node->symbol.decl)
256 && cgraph_is_aux_decl_external (node))))
258 gcc_assert (!node->global.inlined_to);
259 pointer_set_insert (reachable, node);
260 enqueue_node ((symtab_node)node, &first, reachable);
262 else
263 gcc_assert (!node->symbol.aux);
265 /* Mark variables that are obviously needed. */
266 FOR_EACH_DEFINED_VARIABLE (vnode)
267 if (!varpool_can_remove_if_no_refs (vnode))
269 pointer_set_insert (reachable, vnode);
270 enqueue_node ((symtab_node)vnode, &first, reachable);
273 /* Perform reachability analysis. */
274 while (first != (symtab_node) (void *) 1)
276 bool in_boundary_p = !pointer_set_contains (reachable, first);
277 symtab_node node = first;
279 first = (symtab_node)first->symbol.aux;
281 /* If we are processing symbol in boundary, mark its AUX pointer for
282 possible later re-processing in enqueue_node. */
283 if (in_boundary_p)
284 node->symbol.aux = (void *)2;
285 else
287 /* If any symbol in a comdat group is reachable, force
288 all other in the same comdat group to be also reachable. */
289 if (node->symbol.same_comdat_group)
291 symtab_node next;
292 for (next = node->symbol.same_comdat_group;
293 next != node;
294 next = next->symbol.same_comdat_group)
295 if (!pointer_set_insert (reachable, next))
296 enqueue_node ((symtab_node) next, &first, reachable);
298 /* Mark references as reachable. */
299 process_references (&node->symbol.ref_list, &first,
300 before_inlining_p, reachable);
303 if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
305 /* Mark the callees reachable unless they are direct calls to extern
306 inline functions we decided to not inline. */
307 if (!in_boundary_p)
309 struct cgraph_edge *e;
310 for (e = cnode->callees; e; e = e->next_callee)
312 if (e->callee->analyzed
313 && (!e->inline_failed
314 || !(DECL_EXTERNAL (e->callee->symbol.decl)
315 || cgraph_is_aux_decl_external (e->callee))
316 || cnode->alias
317 || before_inlining_p))
318 pointer_set_insert (reachable, e->callee);
319 enqueue_node ((symtab_node) e->callee, &first, reachable);
322 /* When inline clone exists, mark body to be preserved so when removing
323 offline copy of the function we don't kill it. */
324 if (!cnode->alias && cnode->global.inlined_to)
325 pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
328 /* For non-inline clones, force their origins to the boundary and ensure
329 that body is not removed. */
330 while (cnode->clone_of
331 && !gimple_has_body_p (cnode->symbol.decl))
333 bool noninline = cnode->clone_of->symbol.decl != cnode->symbol.decl;
334 cnode = cnode->clone_of;
335 if (noninline)
337 pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
338 enqueue_node ((symtab_node)cnode, &first, reachable);
339 break;
343 /* When we see constructor of external variable, keep referred nodes in the
344 boundary. This will also hold initializers of the external vars NODE
345 refers to. */
346 varpool_node *vnode = dyn_cast <varpool_node> (node);
347 if (vnode
348 && DECL_EXTERNAL (node->symbol.decl)
349 && !vnode->alias
350 && in_boundary_p)
352 struct ipa_ref *ref;
353 for (int i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
354 enqueue_node (ref->referred, &first, reachable);
358 /* Remove unreachable functions. */
359 for (node = cgraph_first_function (); node; node = next)
361 next = cgraph_next_function (node);
362 if (!node->symbol.aux)
364 if (file)
365 fprintf (file, " %s", cgraph_node_name (node));
366 cgraph_remove_node (node);
367 changed = true;
369 else if (!pointer_set_contains (reachable, node))
371 if (node->analyzed)
373 if (file)
374 fprintf (file, " %s", cgraph_node_name (node));
375 #ifdef FIXME_LIPO
376 error " Check the following code "
377 #endif
378 if (!cgraph_is_aux_decl_external (node))
380 cgraph_node_remove_callees (node);
381 ipa_remove_all_references (&node->symbol.ref_list);
383 changed = true;
385 if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl)
386 && (node->local.finalized || !DECL_ARTIFICIAL (node->symbol.decl)))
387 cgraph_release_function_body (node);
388 node->analyzed = false;
392 /* Inline clones might be kept around so their materializing allows further
393 cloning. If the function the clone is inlined into is removed, we need
394 to turn it into normal cone. */
395 FOR_EACH_FUNCTION (node)
397 if (node->global.inlined_to
398 && !node->callers)
400 /* Clean up dangling references from callees as well.
401 TODO -- should be done recursively. */
402 if (L_IPO_COMP_MODE)
404 struct cgraph_edge *e;
405 for (e = node->callees; e; e = e->next_callee)
407 struct cgraph_node *callee_node;
409 callee_node = e->callee;
410 if (callee_node->global.inlined_to)
411 callee_node->global.inlined_to = node;
414 gcc_assert (node->clones);
415 node->global.inlined_to = NULL;
416 update_inlined_to_pointer (node, node);
418 node->symbol.aux = NULL;
421 /* Remove unreachable variables. */
422 if (file)
423 fprintf (file, "\n");
425 if (file)
426 fprintf (file, "Reclaiming variables:");
427 for (vnode = varpool_first_variable (); vnode; vnode = vnext)
429 vnext = varpool_next_variable (vnode);
430 if (!vnode->symbol.aux)
432 if (file)
433 fprintf (file, " %s", varpool_node_name (vnode));
434 varpool_remove_node (vnode);
435 changed = true;
437 else if (!pointer_set_contains (reachable, vnode))
439 if (vnode->analyzed)
441 if (file)
442 fprintf (file, " %s", varpool_node_name (vnode));
443 changed = true;
445 vnode->analyzed = false;
446 vnode->symbol.aux = NULL;
448 else
449 vnode->symbol.aux = NULL;
452 pointer_set_destroy (reachable);
453 pointer_set_destroy (body_needed_for_clonning);
455 /* Now update address_taken flags and try to promote functions to be local. */
456 if (file)
457 fprintf (file, "\nClearing address taken flags:");
458 FOR_EACH_DEFINED_FUNCTION (node)
459 if (node->symbol.address_taken
460 && !node->symbol.used_from_other_partition)
462 if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true))
464 if (file)
465 fprintf (file, " %s", cgraph_node_name (node));
466 node->symbol.address_taken = false;
467 changed = true;
468 if (cgraph_local_node_p (node))
470 node->local.local = true;
471 if (file)
472 fprintf (file, " (local)");
476 if (file)
477 fprintf (file, "\n");
479 #ifdef ENABLE_CHECKING
480 verify_symtab ();
481 #endif
483 /* If we removed something, perhaps profile could be improved. */
484 if (changed && optimize && inline_edge_summary_vec.exists ())
485 FOR_EACH_DEFINED_FUNCTION (node)
486 cgraph_propagate_frequency (node);
488 return changed;
491 /* Discover variables that have no longer address taken or that are read only
492 and update their flags.
494 FIXME: This can not be done in between gimplify and omp_expand since
495 readonly flag plays role on what is shared and what is not. Currently we do
496 this transformation as part of whole program visibility and re-do at
497 ipa-reference pass (to take into account clonning), but it would
498 make sense to do it before early optimizations. */
500 void
501 ipa_discover_readonly_nonaddressable_vars (void)
503 struct varpool_node *vnode;
504 if (dump_file)
505 fprintf (dump_file, "Clearing variable flags:");
506 FOR_EACH_VARIABLE (vnode)
507 if (vnode->finalized && varpool_all_refs_explicit_p (vnode)
508 && (TREE_ADDRESSABLE (vnode->symbol.decl)
509 || !TREE_READONLY (vnode->symbol.decl)))
511 bool written = false;
512 bool address_taken = false;
513 int i;
514 struct ipa_ref *ref;
515 for (i = 0; ipa_ref_list_referring_iterate (&vnode->symbol.ref_list,
516 i, ref)
517 && (!written || !address_taken); i++)
518 switch (ref->use)
520 case IPA_REF_ADDR:
521 address_taken = true;
522 break;
523 case IPA_REF_LOAD:
524 break;
525 case IPA_REF_STORE:
526 written = true;
527 break;
529 if (TREE_ADDRESSABLE (vnode->symbol.decl) && !address_taken)
531 if (dump_file)
532 fprintf (dump_file, " %s (addressable)", varpool_node_name (vnode));
533 TREE_ADDRESSABLE (vnode->symbol.decl) = 0;
535 if (!TREE_READONLY (vnode->symbol.decl) && !address_taken && !written
536 /* Making variable in explicit section readonly can cause section
537 type conflict.
538 See e.g. gcc.c-torture/compile/pr23237.c */
539 && DECL_SECTION_NAME (vnode->symbol.decl) == NULL)
541 if (dump_file)
542 fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
543 TREE_READONLY (vnode->symbol.decl) = 1;
546 if (dump_file)
547 fprintf (dump_file, "\n");
550 /* Return true when there is a reference to node and it is not vtable. */
551 static bool
552 cgraph_address_taken_from_non_vtable_p (struct cgraph_node *node)
554 int i;
555 struct ipa_ref *ref;
556 for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
557 i, ref); i++)
558 if (ref->use == IPA_REF_ADDR)
560 struct varpool_node *node;
561 if (is_a <cgraph_node> (ref->referring))
562 return true;
563 node = ipa_ref_referring_varpool_node (ref);
564 if (!DECL_VIRTUAL_P (node->symbol.decl))
565 return true;
567 return false;
570 /* COMDAT functions must be shared only if they have address taken,
571 otherwise we can produce our own private implementation with
572 -fwhole-program.
573 Return true when turning COMDAT functoin static can not lead to wrong
574 code when the resulting object links with a library defining same COMDAT.
576 Virtual functions do have their addresses taken from the vtables,
577 but in C++ there is no way to compare their addresses for equality. */
579 bool
580 cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
582 if ((cgraph_address_taken_from_non_vtable_p (node)
583 && !DECL_VIRTUAL_P (node->symbol.decl))
584 || !node->analyzed)
585 return false;
586 if (node->symbol.same_comdat_group)
588 struct cgraph_node *next;
590 /* If more than one function is in the same COMDAT group, it must
591 be shared even if just one function in the comdat group has
592 address taken. */
593 for (next = cgraph (node->symbol.same_comdat_group);
594 next != node; next = cgraph (next->symbol.same_comdat_group))
595 if (cgraph_address_taken_from_non_vtable_p (next)
596 && !DECL_VIRTUAL_P (next->symbol.decl))
597 return false;
599 return true;
602 /* Return true when function NODE should be considered externally visible. */
604 static bool
605 cgraph_externally_visible_p (struct cgraph_node *node,
606 bool whole_program, bool aliased)
608 if (!node->local.finalized)
609 return false;
610 if (!DECL_COMDAT (node->symbol.decl)
611 && (!TREE_PUBLIC (node->symbol.decl)
612 || DECL_EXTERNAL (node->symbol.decl)))
613 return false;
615 /* Do not even try to be smart about aliased nodes. Until we properly
616 represent everything by same body alias, these are just evil. */
617 if (aliased)
618 return true;
620 /* Do not try to localize built-in functions yet. One of problems is that we
621 end up mangling their asm for WHOPR that makes it impossible to call them
622 using the implicit built-in declarations anymore. Similarly this enables
623 us to remove them as unreachable before actual calls may appear during
624 expansion or folding. */
625 if (DECL_BUILT_IN (node->symbol.decl))
626 return true;
628 /* If linker counts on us, we must preserve the function. */
629 if (symtab_used_from_object_file_p ((symtab_node) node))
630 return true;
631 if (DECL_PRESERVE_P (node->symbol.decl))
632 return true;
633 if (lookup_attribute ("externally_visible",
634 DECL_ATTRIBUTES (node->symbol.decl)))
635 return true;
636 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
637 && lookup_attribute ("dllexport",
638 DECL_ATTRIBUTES (node->symbol.decl)))
639 return true;
640 if (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
641 return false;
642 /* When doing LTO or whole program, we can bring COMDAT functoins static.
643 This improves code quality and we know we will duplicate them at most twice
644 (in the case that we are not using plugin and link with object file
645 implementing same COMDAT) */
646 if ((in_lto_p || whole_program)
647 && DECL_COMDAT (node->symbol.decl)
648 && cgraph_comdat_can_be_unshared_p (node))
649 return false;
651 /* When doing link time optimizations, hidden symbols become local. */
652 if (in_lto_p
653 && (DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_HIDDEN
654 || DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL)
655 /* Be sure that node is defined in IR file, not in other object
656 file. In that case we don't set used_from_other_object_file. */
657 && node->analyzed)
659 else if (!whole_program)
660 return true;
662 if (MAIN_NAME_P (DECL_NAME (node->symbol.decl)))
663 return true;
665 return false;
668 /* Return true when variable VNODE should be considered externally visible. */
670 bool
671 varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
673 /* Do not touch weakrefs; while they are not externally visible,
674 dropping their DECL_EXTERNAL flags confuse most
675 of code handling them. */
676 if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl))
677 return true;
679 if (DECL_EXTERNAL (vnode->symbol.decl))
680 return true;
682 if (!DECL_COMDAT (vnode->symbol.decl) && !TREE_PUBLIC (vnode->symbol.decl))
683 return false;
685 /* Do not even try to be smart about aliased nodes. Until we properly
686 represent everything by same body alias, these are just evil. */
687 if (aliased)
688 return true;
690 /* If linker counts on us, we must preserve the function. */
691 if (symtab_used_from_object_file_p ((symtab_node) vnode))
692 return true;
694 if (DECL_HARD_REGISTER (vnode->symbol.decl))
695 return true;
696 if (DECL_PRESERVE_P (vnode->symbol.decl))
697 return true;
698 if (lookup_attribute ("externally_visible",
699 DECL_ATTRIBUTES (vnode->symbol.decl)))
700 return true;
701 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
702 && lookup_attribute ("dllexport",
703 DECL_ATTRIBUTES (vnode->symbol.decl)))
704 return true;
706 /* See if we have linker information about symbol not being used or
707 if we need to make guess based on the declaration.
709 Even if the linker clams the symbol is unused, never bring internal
710 symbols that are declared by user as used or externally visible.
711 This is needed for i.e. references from asm statements. */
712 if (symtab_used_from_object_file_p ((symtab_node) vnode))
713 return true;
714 if (vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
715 return false;
717 /* As a special case, the COMDAT virtual tables can be unshared.
718 In LTO mode turn vtables into static variables. The variable is readonly,
719 so this does not enable more optimization, but referring static var
720 is faster for dynamic linking. Also this match logic hidding vtables
721 from LTO symbol tables. */
722 if ((in_lto_p || flag_whole_program)
723 && !vnode->symbol.force_output
724 && DECL_COMDAT (vnode->symbol.decl) && DECL_VIRTUAL_P (vnode->symbol.decl))
725 return false;
727 /* When doing link time optimizations, hidden symbols become local. */
728 if (in_lto_p
729 && (DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_HIDDEN
730 || DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL)
731 /* Be sure that node is defined in IR file, not in other object
732 file. In that case we don't set used_from_other_object_file. */
733 && vnode->finalized)
735 else if (!flag_whole_program)
736 return true;
738 /* Do not attempt to privatize COMDATS by default.
739 This would break linking with C++ libraries sharing
740 inline definitions.
742 FIXME: We can do so for readonly vars with no address taken and
743 possibly also for vtables since no direct pointer comparsion is done.
744 It might be interesting to do so to reduce linking overhead. */
745 if (DECL_COMDAT (vnode->symbol.decl) || DECL_WEAK (vnode->symbol.decl))
746 return true;
747 return false;
750 /* Mark visibility of all functions.
752 A local function is one whose calls can occur only in the current
753 compilation unit and all its calls are explicit, so we can change
754 its calling convention. We simply mark all static functions whose
755 address is not taken as local.
757 We also change the TREE_PUBLIC flag of all declarations that are public
758 in language point of view but we want to overwrite this default
759 via visibilities for the backend point of view. */
761 static unsigned int
762 function_and_variable_visibility (bool whole_program)
764 struct cgraph_node *node;
765 struct varpool_node *vnode;
766 struct pointer_set_t *aliased_nodes = pointer_set_create ();
767 struct pointer_set_t *aliased_vnodes = pointer_set_create ();
768 unsigned i;
769 alias_pair *p;
771 /* Discover aliased nodes. */
772 FOR_EACH_VEC_SAFE_ELT (alias_pairs, i, p)
774 if (dump_file)
775 fprintf (dump_file, "Alias %s->%s",
776 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
777 IDENTIFIER_POINTER (p->target));
779 if ((node = cgraph_node_for_asm (p->target)) != NULL
780 && !DECL_EXTERNAL (node->symbol.decl))
782 if (!node->analyzed)
783 continue;
784 cgraph_mark_force_output_node (node);
785 pointer_set_insert (aliased_nodes, node);
786 if (dump_file)
787 fprintf (dump_file, " node %s/%i",
788 cgraph_node_name (node), node->uid);
790 else if ((vnode = varpool_node_for_asm (p->target)) != NULL
791 && !DECL_EXTERNAL (vnode->symbol.decl))
793 vnode->symbol.force_output = 1;
794 pointer_set_insert (aliased_vnodes, vnode);
795 if (dump_file)
796 fprintf (dump_file, " varpool node %s",
797 varpool_node_name (vnode));
799 if (dump_file)
800 fprintf (dump_file, "\n");
803 FOR_EACH_FUNCTION (node)
805 int flags = flags_from_decl_or_type (node->symbol.decl);
807 /* Optimize away PURE and CONST constructors and destructors. */
808 if (optimize
809 && (flags & (ECF_CONST | ECF_PURE))
810 && !(flags & ECF_LOOPING_CONST_OR_PURE))
812 DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0;
813 DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0;
816 /* Frontends and alias code marks nodes as needed before parsing is finished.
817 We may end up marking as node external nodes where this flag is meaningless
818 strip it. */
819 if (node->symbol.force_output
820 && (DECL_EXTERNAL (node->symbol.decl) || !node->analyzed))
821 node->symbol.force_output = 0;
823 /* C++ FE on lack of COMDAT support create local COMDAT functions
824 (that ought to be shared but can not due to object format
825 limitations). It is necessary to keep the flag to make rest of C++ FE
826 happy. Clear the flag here to avoid confusion in middle-end. */
827 if (DECL_COMDAT (node->symbol.decl) && !TREE_PUBLIC (node->symbol.decl))
828 DECL_COMDAT (node->symbol.decl) = 0;
829 /* For external decls stop tracking same_comdat_group, it doesn't matter
830 what comdat group they are in when they won't be emitted in this TU,
831 and simplifies later passes. */
832 if (node->symbol.same_comdat_group && DECL_EXTERNAL (node->symbol.decl))
834 #ifdef ENABLE_CHECKING
835 symtab_node n;
837 for (n = node->symbol.same_comdat_group;
838 n != (symtab_node)node;
839 n = n->symbol.same_comdat_group)
840 /* If at least one of same comdat group functions is external,
841 all of them have to be, otherwise it is a front-end bug. */
842 gcc_assert (DECL_EXTERNAL (n->symbol.decl));
843 #endif
844 symtab_dissolve_same_comdat_group_list ((symtab_node) node);
846 gcc_assert ((!DECL_WEAK (node->symbol.decl)
847 && !DECL_COMDAT (node->symbol.decl))
848 || TREE_PUBLIC (node->symbol.decl)
849 || DECL_EXTERNAL (node->symbol.decl));
850 if (cgraph_externally_visible_p (node, whole_program,
851 pointer_set_contains (aliased_nodes,
852 node)))
854 gcc_assert (!node->global.inlined_to);
855 node->symbol.externally_visible = true;
857 else
858 node->symbol.externally_visible = false;
859 if (!node->symbol.externally_visible && node->analyzed
860 && !DECL_EXTERNAL (node->symbol.decl))
862 gcc_assert (whole_program || in_lto_p
863 || !TREE_PUBLIC (node->symbol.decl));
864 symtab_make_decl_local (node->symbol.decl);
865 node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
866 if (node->symbol.same_comdat_group)
867 /* cgraph_externally_visible_p has already checked all other nodes
868 in the group and they will all be made local. We need to
869 dissolve the group at once so that the predicate does not
870 segfault though. */
871 symtab_dissolve_same_comdat_group_list ((symtab_node) node);
874 if (node->thunk.thunk_p
875 && TREE_PUBLIC (node->symbol.decl))
877 struct cgraph_node *decl_node = node;
879 decl_node = cgraph_function_node (decl_node->callees->callee, NULL);
881 /* Thunks have the same visibility as function they are attached to.
882 Make sure the C++ front end set this up properly. */
883 if (DECL_ONE_ONLY (decl_node->symbol.decl))
885 gcc_checking_assert (DECL_COMDAT (node->symbol.decl)
886 == DECL_COMDAT (decl_node->symbol.decl));
887 gcc_checking_assert (DECL_COMDAT_GROUP (node->symbol.decl)
888 == DECL_COMDAT_GROUP (decl_node->symbol.decl));
889 gcc_checking_assert (node->symbol.same_comdat_group);
891 if (DECL_EXTERNAL (decl_node->symbol.decl))
892 DECL_EXTERNAL (node->symbol.decl) = 1;
895 FOR_EACH_DEFINED_FUNCTION (node)
896 node->local.local = cgraph_local_node_p (node);
897 FOR_EACH_VARIABLE (vnode)
899 /* weak flag makes no sense on local variables. */
900 gcc_assert (!DECL_WEAK (vnode->symbol.decl)
901 || TREE_PUBLIC (vnode->symbol.decl)
902 || DECL_EXTERNAL (vnode->symbol.decl));
903 /* In several cases declarations can not be common:
905 - when declaration has initializer
906 - when it is in weak
907 - when it has specific section
908 - when it resides in non-generic address space.
909 - if declaration is local, it will get into .local common section
910 so common flag is not needed. Frontends still produce these in
911 certain cases, such as for:
913 static int a __attribute__ ((common))
915 Canonicalize things here and clear the redundant flag. */
916 if (DECL_COMMON (vnode->symbol.decl)
917 && (!(TREE_PUBLIC (vnode->symbol.decl)
918 || DECL_EXTERNAL (vnode->symbol.decl))
919 || (DECL_INITIAL (vnode->symbol.decl)
920 && DECL_INITIAL (vnode->symbol.decl) != error_mark_node)
921 || DECL_WEAK (vnode->symbol.decl)
922 || DECL_SECTION_NAME (vnode->symbol.decl) != NULL
923 || ! (ADDR_SPACE_GENERIC_P
924 (TYPE_ADDR_SPACE (TREE_TYPE (vnode->symbol.decl))))))
925 DECL_COMMON (vnode->symbol.decl) = 0;
927 FOR_EACH_DEFINED_VARIABLE (vnode)
929 if (!vnode->finalized)
930 continue;
932 if (varpool_externally_visible_p
933 (vnode,
934 pointer_set_contains (aliased_vnodes, vnode)))
935 vnode->symbol.externally_visible = true;
936 else
937 vnode->symbol.externally_visible = false;
938 if (!vnode->symbol.externally_visible)
940 gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl));
941 symtab_make_decl_local (vnode->symbol.decl);
942 if (vnode->symbol.same_comdat_group)
943 symtab_dissolve_same_comdat_group_list ((symtab_node) vnode);
944 vnode->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
946 /* Static variables defined in auxiliary modules are externalized to
947 allow cross module inlining. */
948 gcc_assert (TREE_STATIC (vnode->symbol.decl)
949 || varpool_is_auxiliary (vnode));
951 pointer_set_destroy (aliased_nodes);
952 pointer_set_destroy (aliased_vnodes);
954 if (dump_file)
956 fprintf (dump_file, "\nMarking local functions:");
957 FOR_EACH_DEFINED_FUNCTION (node)
958 if (node->local.local)
959 fprintf (dump_file, " %s", cgraph_node_name (node));
960 fprintf (dump_file, "\n\n");
961 fprintf (dump_file, "\nMarking externally visible functions:");
962 FOR_EACH_DEFINED_FUNCTION (node)
963 if (node->symbol.externally_visible)
964 fprintf (dump_file, " %s", cgraph_node_name (node));
965 fprintf (dump_file, "\n\n");
966 fprintf (dump_file, "\nMarking externally visible variables:");
967 FOR_EACH_DEFINED_VARIABLE (vnode)
968 if (vnode->symbol.externally_visible)
969 fprintf (dump_file, " %s", varpool_node_name (vnode));
970 fprintf (dump_file, "\n\n");
972 cgraph_function_flags_ready = true;
973 return 0;
976 /* Local function pass handling visibilities. This happens before LTO streaming
977 so in particular -fwhole-program should be ignored at this level. */
979 static unsigned int
980 local_function_and_variable_visibility (void)
982 return function_and_variable_visibility (flag_whole_program && !flag_lto);
985 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
988 SIMPLE_IPA_PASS,
989 "visibility", /* name */
990 OPTGROUP_NONE, /* optinfo_flags */
991 NULL, /* gate */
992 local_function_and_variable_visibility,/* execute */
993 NULL, /* sub */
994 NULL, /* next */
995 0, /* static_pass_number */
996 TV_CGRAPHOPT, /* tv_id */
997 0, /* properties_required */
998 0, /* properties_provided */
999 0, /* properties_destroyed */
1000 0, /* todo_flags_start */
1001 TODO_remove_functions | TODO_dump_symtab
1002 | TODO_ggc_collect /* todo_flags_finish */
1006 /* Free inline summary. */
1008 static unsigned
1009 free_inline_summary (void)
1011 inline_free_summary ();
1012 return 0;
1015 struct simple_ipa_opt_pass pass_ipa_free_inline_summary =
1018 SIMPLE_IPA_PASS,
1019 "*free_inline_summary", /* name */
1020 OPTGROUP_NONE, /* optinfo_flags */
1021 NULL, /* gate */
1022 free_inline_summary, /* execute */
1023 NULL, /* sub */
1024 NULL, /* next */
1025 0, /* static_pass_number */
1026 TV_IPA_FREE_INLINE_SUMMARY, /* tv_id */
1027 0, /* properties_required */
1028 0, /* properties_provided */
1029 0, /* properties_destroyed */
1030 0, /* todo_flags_start */
1031 TODO_ggc_collect /* todo_flags_finish */
1035 /* Do not re-run on ltrans stage. */
1037 static bool
1038 gate_whole_program_function_and_variable_visibility (void)
1040 return !flag_ltrans;
1043 /* Bring functionss local at LTO time with -fwhole-program. */
1045 static unsigned int
1046 whole_program_function_and_variable_visibility (void)
1048 function_and_variable_visibility (flag_whole_program);
1049 if (optimize)
1050 ipa_discover_readonly_nonaddressable_vars ();
1051 return 0;
1054 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
1057 IPA_PASS,
1058 "whole-program", /* name */
1059 OPTGROUP_NONE, /* optinfo_flags */
1060 gate_whole_program_function_and_variable_visibility,/* gate */
1061 whole_program_function_and_variable_visibility,/* execute */
1062 NULL, /* sub */
1063 NULL, /* next */
1064 0, /* static_pass_number */
1065 TV_CGRAPHOPT, /* tv_id */
1066 0, /* properties_required */
1067 0, /* properties_provided */
1068 0, /* properties_destroyed */
1069 0, /* todo_flags_start */
1070 TODO_remove_functions | TODO_dump_symtab
1071 | TODO_ggc_collect /* todo_flags_finish */
1073 NULL, /* generate_summary */
1074 NULL, /* write_summary */
1075 NULL, /* read_summary */
1076 NULL, /* write_optimization_summary */
1077 NULL, /* read_optimization_summary */
1078 NULL, /* stmt_fixup */
1079 0, /* TODOs */
1080 NULL, /* function_transform */
1081 NULL, /* variable_transform */
1085 /* Simple ipa profile pass propagating frequencies across the callgraph. */
1087 static unsigned int
1088 ipa_profile (void)
1090 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1091 struct cgraph_edge *e;
1092 int order_pos;
1093 bool something_changed = false;
1094 int i;
1096 order_pos = ipa_reverse_postorder (order);
1097 for (i = order_pos - 1; i >= 0; i--)
1099 if (order[i]->local.local && cgraph_propagate_frequency (order[i]))
1101 for (e = order[i]->callees; e; e = e->next_callee)
1102 if (e->callee->local.local && !e->callee->symbol.aux)
1104 something_changed = true;
1105 e->callee->symbol.aux = (void *)1;
1108 order[i]->symbol.aux = NULL;
1111 while (something_changed)
1113 something_changed = false;
1114 for (i = order_pos - 1; i >= 0; i--)
1116 if (order[i]->symbol.aux && cgraph_propagate_frequency (order[i]))
1118 for (e = order[i]->callees; e; e = e->next_callee)
1119 if (e->callee->local.local && !e->callee->symbol.aux)
1121 something_changed = true;
1122 e->callee->symbol.aux = (void *)1;
1125 order[i]->symbol.aux = NULL;
1128 free (order);
1129 return 0;
1132 static bool
1133 gate_ipa_profile (void)
1135 return flag_ipa_profile;
1138 struct ipa_opt_pass_d pass_ipa_profile =
1141 IPA_PASS,
1142 "profile_estimate", /* name */
1143 OPTGROUP_NONE, /* optinfo_flags */
1144 gate_ipa_profile, /* gate */
1145 ipa_profile, /* execute */
1146 NULL, /* sub */
1147 NULL, /* next */
1148 0, /* static_pass_number */
1149 TV_IPA_PROFILE, /* tv_id */
1150 0, /* properties_required */
1151 0, /* properties_provided */
1152 0, /* properties_destroyed */
1153 0, /* todo_flags_start */
1154 0 /* todo_flags_finish */
1156 NULL, /* generate_summary */
1157 NULL, /* write_summary */
1158 NULL, /* read_summary */
1159 NULL, /* write_optimization_summary */
1160 NULL, /* read_optimization_summary */
1161 NULL, /* stmt_fixup */
1162 0, /* TODOs */
1163 NULL, /* function_transform */
1164 NULL /* variable_transform */
1167 /* Generate and emit a static constructor or destructor. WHICH must
1168 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1169 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1170 initialization priority for this constructor or destructor.
1172 FINAL specify whether the externally visible name for collect2 should
1173 be produced. */
1175 static void
1176 cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
1178 static int counter = 0;
1179 char which_buf[16];
1180 tree decl, name, resdecl;
1182 /* The priority is encoded in the constructor or destructor name.
1183 collect2 will sort the names and arrange that they are called at
1184 program startup. */
1185 if (final)
1186 sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
1187 else
1188 /* Proudce sane name but one not recognizable by collect2, just for the
1189 case we fail to inline the function. */
1190 sprintf (which_buf, "sub_%c_%.5d_%d", which, priority, counter++);
1191 name = get_file_function_name (which_buf);
1193 decl = build_decl (input_location, FUNCTION_DECL, name,
1194 build_function_type_list (void_type_node, NULL_TREE));
1195 current_function_decl = decl;
1197 resdecl = build_decl (input_location,
1198 RESULT_DECL, NULL_TREE, void_type_node);
1199 DECL_ARTIFICIAL (resdecl) = 1;
1200 DECL_RESULT (decl) = resdecl;
1201 DECL_CONTEXT (resdecl) = decl;
1203 allocate_struct_function (decl, false);
1205 TREE_STATIC (decl) = 1;
1206 TREE_USED (decl) = 1;
1207 DECL_ARTIFICIAL (decl) = 1;
1208 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1209 DECL_SAVED_TREE (decl) = body;
1210 if (!targetm.have_ctors_dtors && final)
1212 TREE_PUBLIC (decl) = 1;
1213 DECL_PRESERVE_P (decl) = 1;
1215 DECL_UNINLINABLE (decl) = 1;
1217 DECL_INITIAL (decl) = make_node (BLOCK);
1218 TREE_USED (DECL_INITIAL (decl)) = 1;
1220 DECL_SOURCE_LOCATION (decl) = input_location;
1221 cfun->function_end_locus = input_location;
1223 switch (which)
1225 case 'I':
1226 DECL_STATIC_CONSTRUCTOR (decl) = 1;
1227 decl_init_priority_insert (decl, priority);
1228 break;
1229 case 'D':
1230 DECL_STATIC_DESTRUCTOR (decl) = 1;
1231 decl_fini_priority_insert (decl, priority);
1232 break;
1233 default:
1234 gcc_unreachable ();
1237 gimplify_function_tree (decl);
1239 cgraph_add_new_function (decl, false);
1241 set_cfun (NULL);
1242 current_function_decl = NULL;
1245 /* Generate and emit a static constructor or destructor. WHICH must
1246 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1247 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1248 initialization priority for this constructor or destructor. */
1250 void
1251 cgraph_build_static_cdtor (char which, tree body, int priority)
1253 cgraph_build_static_cdtor_1 (which, body, priority, false);
1256 /* A vector of FUNCTION_DECLs declared as static constructors. */
1257 static vec<tree> static_ctors;
1258 /* A vector of FUNCTION_DECLs declared as static destructors. */
1259 static vec<tree> static_dtors;
1261 /* When target does not have ctors and dtors, we call all constructor
1262 and destructor by special initialization/destruction function
1263 recognized by collect2.
1265 When we are going to build this function, collect all constructors and
1266 destructors and turn them into normal functions. */
1268 static void
1269 record_cdtor_fn (struct cgraph_node *node)
1271 if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
1272 static_ctors.safe_push (node->symbol.decl);
1273 if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
1274 static_dtors.safe_push (node->symbol.decl);
1275 node = cgraph_get_node (node->symbol.decl);
1276 DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl) = 1;
1279 /* Define global constructors/destructor functions for the CDTORS, of
1280 which they are LEN. The CDTORS are sorted by initialization
1281 priority. If CTOR_P is true, these are constructors; otherwise,
1282 they are destructors. */
1284 static void
1285 build_cdtor (bool ctor_p, vec<tree> cdtors)
1287 size_t i,j;
1288 size_t len = cdtors.length ();
1290 i = 0;
1291 while (i < len)
1293 tree body;
1294 tree fn;
1295 priority_type priority;
1297 priority = 0;
1298 body = NULL_TREE;
1299 j = i;
1302 priority_type p;
1303 fn = cdtors[j];
1304 p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
1305 if (j == i)
1306 priority = p;
1307 else if (p != priority)
1308 break;
1309 j++;
1311 while (j < len);
1313 /* When there is only one cdtor and target supports them, do nothing. */
1314 if (j == i + 1
1315 && targetm.have_ctors_dtors)
1317 i++;
1318 continue;
1320 /* Find the next batch of constructors/destructors with the same
1321 initialization priority. */
1322 for (;i < j; i++)
1324 tree call;
1325 fn = cdtors[i];
1326 call = build_call_expr (fn, 0);
1327 if (ctor_p)
1328 DECL_STATIC_CONSTRUCTOR (fn) = 0;
1329 else
1330 DECL_STATIC_DESTRUCTOR (fn) = 0;
1331 /* We do not want to optimize away pure/const calls here.
1332 When optimizing, these should be already removed, when not
1333 optimizing, we want user to be able to breakpoint in them. */
1334 TREE_SIDE_EFFECTS (call) = 1;
1335 append_to_statement_list (call, &body);
1337 gcc_assert (body != NULL_TREE);
1338 /* Generate a function to call all the function of like
1339 priority. */
1340 cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true);
1344 /* Comparison function for qsort. P1 and P2 are actually of type
1345 "tree *" and point to static constructors. DECL_INIT_PRIORITY is
1346 used to determine the sort order. */
1348 static int
1349 compare_ctor (const void *p1, const void *p2)
1351 tree f1;
1352 tree f2;
1353 int priority1;
1354 int priority2;
1356 f1 = *(const tree *)p1;
1357 f2 = *(const tree *)p2;
1358 priority1 = DECL_INIT_PRIORITY (f1);
1359 priority2 = DECL_INIT_PRIORITY (f2);
1361 if (priority1 < priority2)
1362 return -1;
1363 else if (priority1 > priority2)
1364 return 1;
1365 else
1366 /* Ensure a stable sort. Constructors are executed in backwarding
1367 order to make LTO initialize braries first. */
1368 return DECL_UID (f2) - DECL_UID (f1);
1371 /* Comparison function for qsort. P1 and P2 are actually of type
1372 "tree *" and point to static destructors. DECL_FINI_PRIORITY is
1373 used to determine the sort order. */
1375 static int
1376 compare_dtor (const void *p1, const void *p2)
1378 tree f1;
1379 tree f2;
1380 int priority1;
1381 int priority2;
1383 f1 = *(const tree *)p1;
1384 f2 = *(const tree *)p2;
1385 priority1 = DECL_FINI_PRIORITY (f1);
1386 priority2 = DECL_FINI_PRIORITY (f2);
1388 if (priority1 < priority2)
1389 return -1;
1390 else if (priority1 > priority2)
1391 return 1;
1392 else
1393 /* Ensure a stable sort. */
1394 return DECL_UID (f1) - DECL_UID (f2);
1397 /* Generate functions to call static constructors and destructors
1398 for targets that do not support .ctors/.dtors sections. These
1399 functions have magic names which are detected by collect2. */
1401 static void
1402 build_cdtor_fns (void)
1404 if (!static_ctors.is_empty ())
1406 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1407 static_ctors.qsort (compare_ctor);
1408 build_cdtor (/*ctor_p=*/true, static_ctors);
1411 if (!static_dtors.is_empty ())
1413 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1414 static_dtors.qsort (compare_dtor);
1415 build_cdtor (/*ctor_p=*/false, static_dtors);
1419 /* Look for constructors and destructors and produce function calling them.
1420 This is needed for targets not supporting ctors or dtors, but we perform the
1421 transformation also at linktime to merge possibly numerous
1422 constructors/destructors into single function to improve code locality and
1423 reduce size. */
1425 static unsigned int
1426 ipa_cdtor_merge (void)
1428 struct cgraph_node *node;
1429 FOR_EACH_DEFINED_FUNCTION (node)
1430 if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
1431 || DECL_STATIC_DESTRUCTOR (node->symbol.decl))
1432 record_cdtor_fn (node);
1433 build_cdtor_fns ();
1434 static_ctors.release ();
1435 static_dtors.release ();
1436 return 0;
1439 /* Perform the pass when we have no ctors/dtors support
1440 or at LTO time to merge multiple constructors into single
1441 function. */
1443 static bool
1444 gate_ipa_cdtor_merge (void)
1446 return !targetm.have_ctors_dtors || (optimize && in_lto_p);
1449 struct ipa_opt_pass_d pass_ipa_cdtor_merge =
1452 IPA_PASS,
1453 "cdtor", /* name */
1454 OPTGROUP_NONE, /* optinfo_flags */
1455 gate_ipa_cdtor_merge, /* gate */
1456 ipa_cdtor_merge, /* execute */
1457 NULL, /* sub */
1458 NULL, /* next */
1459 0, /* static_pass_number */
1460 TV_CGRAPHOPT, /* tv_id */
1461 0, /* properties_required */
1462 0, /* properties_provided */
1463 0, /* properties_destroyed */
1464 0, /* todo_flags_start */
1465 0 /* todo_flags_finish */
1467 NULL, /* generate_summary */
1468 NULL, /* write_summary */
1469 NULL, /* read_summary */
1470 NULL, /* write_optimization_summary */
1471 NULL, /* read_optimization_summary */
1472 NULL, /* stmt_fixup */
1473 0, /* TODOs */
1474 NULL, /* function_transform */
1475 NULL /* variable_transform */