Update count_scale for AutoFDO to prevent over-scale.
[official-gcc.git] / gcc-4_8 / gcc / ipa.c
blob3885e663b3e83f1be65b83a718b62be06b88508c
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))))
257 gcc_assert (!node->global.inlined_to);
258 pointer_set_insert (reachable, node);
259 enqueue_node ((symtab_node)node, &first, reachable);
261 else
262 gcc_assert (!node->symbol.aux);
264 /* Mark variables that are obviously needed. */
265 FOR_EACH_DEFINED_VARIABLE (vnode)
266 if (!varpool_can_remove_if_no_refs (vnode))
268 pointer_set_insert (reachable, vnode);
269 enqueue_node ((symtab_node)vnode, &first, reachable);
272 /* Perform reachability analysis. */
273 while (first != (symtab_node) (void *) 1)
275 bool in_boundary_p = !pointer_set_contains (reachable, first);
276 symtab_node node = first;
278 first = (symtab_node)first->symbol.aux;
280 /* If we are processing symbol in boundary, mark its AUX pointer for
281 possible later re-processing in enqueue_node. */
282 if (in_boundary_p)
283 node->symbol.aux = (void *)2;
284 else
286 /* If any symbol in a comdat group is reachable, force
287 all other in the same comdat group to be also reachable. */
288 if (node->symbol.same_comdat_group)
290 symtab_node next;
291 for (next = node->symbol.same_comdat_group;
292 next != node;
293 next = next->symbol.same_comdat_group)
294 if (!pointer_set_insert (reachable, next))
295 enqueue_node ((symtab_node) next, &first, reachable);
297 /* Mark references as reachable. */
298 process_references (&node->symbol.ref_list, &first,
299 before_inlining_p, reachable);
302 if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
304 /* Mark the callees reachable unless they are direct calls to extern
305 inline functions we decided to not inline. */
306 if (!in_boundary_p)
308 struct cgraph_edge *e;
309 for (e = cnode->callees; e; e = e->next_callee)
311 if (e->callee->analyzed
312 && (!e->inline_failed
313 || !(DECL_EXTERNAL (e->callee->symbol.decl)
314 || cgraph_is_aux_decl_external (e->callee))
315 || cnode->alias
316 || before_inlining_p))
317 pointer_set_insert (reachable, e->callee);
318 enqueue_node ((symtab_node) e->callee, &first, reachable);
321 /* When inline clone exists, mark body to be preserved so when removing
322 offline copy of the function we don't kill it. */
323 if (!cnode->alias && cnode->global.inlined_to)
324 pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
327 /* For non-inline clones, force their origins to the boundary and ensure
328 that body is not removed. */
329 while (cnode->clone_of
330 && !gimple_has_body_p (cnode->symbol.decl))
332 bool noninline = cnode->clone_of->symbol.decl != cnode->symbol.decl;
333 cnode = cnode->clone_of;
334 if (noninline)
336 pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
337 enqueue_node ((symtab_node)cnode, &first, reachable);
338 break;
342 /* When we see constructor of external variable, keep referred nodes in the
343 boundary. This will also hold initializers of the external vars NODE
344 refers to. */
345 varpool_node *vnode = dyn_cast <varpool_node> (node);
346 if (vnode
347 && DECL_EXTERNAL (node->symbol.decl)
348 && !vnode->alias
349 && in_boundary_p)
351 struct ipa_ref *ref;
352 for (int i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
353 enqueue_node (ref->referred, &first, reachable);
357 /* Remove unreachable functions. */
358 for (node = cgraph_first_function (); node; node = next)
360 next = cgraph_next_function (node);
361 if (!node->symbol.aux)
363 if (file)
364 fprintf (file, " %s", cgraph_node_name (node));
365 cgraph_remove_node (node);
366 changed = true;
368 else if (!pointer_set_contains (reachable, node))
370 if (node->analyzed)
372 if (file)
373 fprintf (file, " %s", cgraph_node_name (node));
374 #ifdef FIXME_LIPO
375 error " Check the following code "
376 #endif
377 if (!cgraph_is_aux_decl_external (node))
379 cgraph_node_remove_callees (node);
380 ipa_remove_all_references (&node->symbol.ref_list);
382 changed = true;
384 if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl)
385 && (node->local.finalized || !DECL_ARTIFICIAL (node->symbol.decl)))
386 cgraph_release_function_body (node);
387 node->analyzed = false;
391 /* Inline clones might be kept around so their materializing allows further
392 cloning. If the function the clone is inlined into is removed, we need
393 to turn it into normal cone. */
394 FOR_EACH_FUNCTION (node)
396 if (node->global.inlined_to
397 && !node->callers)
399 /* Clean up dangling references from callees as well.
400 TODO -- should be done recursively. */
401 if (L_IPO_COMP_MODE)
403 struct cgraph_edge *e;
404 for (e = node->callees; e; e = e->next_callee)
406 struct cgraph_node *callee_node;
408 callee_node = e->callee;
409 if (callee_node->global.inlined_to)
410 callee_node->global.inlined_to = node;
413 gcc_assert (node->clones);
414 node->global.inlined_to = NULL;
415 update_inlined_to_pointer (node, node);
417 node->symbol.aux = NULL;
420 /* Remove unreachable variables. */
421 if (file)
422 fprintf (file, "\n");
424 if (file)
425 fprintf (file, "Reclaiming variables:");
426 for (vnode = varpool_first_variable (); vnode; vnode = vnext)
428 vnext = varpool_next_variable (vnode);
429 if (!vnode->symbol.aux)
431 if (file)
432 fprintf (file, " %s", varpool_node_name (vnode));
433 varpool_remove_node (vnode);
434 changed = true;
436 else if (!pointer_set_contains (reachable, vnode))
438 if (vnode->analyzed)
440 if (file)
441 fprintf (file, " %s", varpool_node_name (vnode));
442 changed = true;
444 vnode->analyzed = false;
445 vnode->symbol.aux = NULL;
447 else
448 vnode->symbol.aux = NULL;
451 pointer_set_destroy (reachable);
452 pointer_set_destroy (body_needed_for_clonning);
454 /* Now update address_taken flags and try to promote functions to be local. */
455 if (file)
456 fprintf (file, "\nClearing address taken flags:");
457 FOR_EACH_DEFINED_FUNCTION (node)
458 if (node->symbol.address_taken
459 && !node->symbol.used_from_other_partition)
461 if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true))
463 if (file)
464 fprintf (file, " %s", cgraph_node_name (node));
465 node->symbol.address_taken = false;
466 changed = true;
467 if (cgraph_local_node_p (node))
469 node->local.local = true;
470 if (file)
471 fprintf (file, " (local)");
475 if (file)
476 fprintf (file, "\n");
478 #ifdef ENABLE_CHECKING
479 verify_symtab ();
480 #endif
482 /* If we removed something, perhaps profile could be improved. */
483 if (changed && optimize && inline_edge_summary_vec.exists ())
484 FOR_EACH_DEFINED_FUNCTION (node)
485 cgraph_propagate_frequency (node);
487 return changed;
490 /* Discover variables that have no longer address taken or that are read only
491 and update their flags.
493 FIXME: This can not be done in between gimplify and omp_expand since
494 readonly flag plays role on what is shared and what is not. Currently we do
495 this transformation as part of whole program visibility and re-do at
496 ipa-reference pass (to take into account clonning), but it would
497 make sense to do it before early optimizations. */
499 void
500 ipa_discover_readonly_nonaddressable_vars (void)
502 struct varpool_node *vnode;
503 if (dump_file)
504 fprintf (dump_file, "Clearing variable flags:");
505 FOR_EACH_VARIABLE (vnode)
506 if (vnode->finalized && varpool_all_refs_explicit_p (vnode)
507 && (TREE_ADDRESSABLE (vnode->symbol.decl)
508 || !TREE_READONLY (vnode->symbol.decl)))
510 bool written = false;
511 bool address_taken = false;
512 int i;
513 struct ipa_ref *ref;
514 for (i = 0; ipa_ref_list_referring_iterate (&vnode->symbol.ref_list,
515 i, ref)
516 && (!written || !address_taken); i++)
517 switch (ref->use)
519 case IPA_REF_ADDR:
520 address_taken = true;
521 break;
522 case IPA_REF_LOAD:
523 break;
524 case IPA_REF_STORE:
525 written = true;
526 break;
528 if (TREE_ADDRESSABLE (vnode->symbol.decl) && !address_taken)
530 if (dump_file)
531 fprintf (dump_file, " %s (addressable)", varpool_node_name (vnode));
532 TREE_ADDRESSABLE (vnode->symbol.decl) = 0;
534 if (!TREE_READONLY (vnode->symbol.decl) && !address_taken && !written
535 /* Making variable in explicit section readonly can cause section
536 type conflict.
537 See e.g. gcc.c-torture/compile/pr23237.c */
538 && DECL_SECTION_NAME (vnode->symbol.decl) == NULL)
540 if (dump_file)
541 fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
542 TREE_READONLY (vnode->symbol.decl) = 1;
545 if (dump_file)
546 fprintf (dump_file, "\n");
549 /* Return true when there is a reference to node and it is not vtable. */
550 static bool
551 cgraph_address_taken_from_non_vtable_p (struct cgraph_node *node)
553 int i;
554 struct ipa_ref *ref;
555 for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
556 i, ref); i++)
557 if (ref->use == IPA_REF_ADDR)
559 struct varpool_node *node;
560 if (is_a <cgraph_node> (ref->referring))
561 return true;
562 node = ipa_ref_referring_varpool_node (ref);
563 if (!DECL_VIRTUAL_P (node->symbol.decl))
564 return true;
566 return false;
569 /* COMDAT functions must be shared only if they have address taken,
570 otherwise we can produce our own private implementation with
571 -fwhole-program.
572 Return true when turning COMDAT functoin static can not lead to wrong
573 code when the resulting object links with a library defining same COMDAT.
575 Virtual functions do have their addresses taken from the vtables,
576 but in C++ there is no way to compare their addresses for equality. */
578 bool
579 cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
581 if ((cgraph_address_taken_from_non_vtable_p (node)
582 && !DECL_VIRTUAL_P (node->symbol.decl))
583 || !node->analyzed)
584 return false;
585 if (node->symbol.same_comdat_group)
587 struct cgraph_node *next;
589 /* If more than one function is in the same COMDAT group, it must
590 be shared even if just one function in the comdat group has
591 address taken. */
592 for (next = cgraph (node->symbol.same_comdat_group);
593 next != node; next = cgraph (next->symbol.same_comdat_group))
594 if (cgraph_address_taken_from_non_vtable_p (next)
595 && !DECL_VIRTUAL_P (next->symbol.decl))
596 return false;
598 return true;
601 /* Return true when function NODE should be considered externally visible. */
603 static bool
604 cgraph_externally_visible_p (struct cgraph_node *node,
605 bool whole_program, bool aliased)
607 if (!node->local.finalized)
608 return false;
609 if (!DECL_COMDAT (node->symbol.decl)
610 && (!TREE_PUBLIC (node->symbol.decl)
611 || DECL_EXTERNAL (node->symbol.decl)))
612 return false;
614 /* Do not even try to be smart about aliased nodes. Until we properly
615 represent everything by same body alias, these are just evil. */
616 if (aliased)
617 return true;
619 /* Do not try to localize built-in functions yet. One of problems is that we
620 end up mangling their asm for WHOPR that makes it impossible to call them
621 using the implicit built-in declarations anymore. Similarly this enables
622 us to remove them as unreachable before actual calls may appear during
623 expansion or folding. */
624 if (DECL_BUILT_IN (node->symbol.decl))
625 return true;
627 /* If linker counts on us, we must preserve the function. */
628 if (symtab_used_from_object_file_p ((symtab_node) node))
629 return true;
630 if (DECL_PRESERVE_P (node->symbol.decl))
631 return true;
632 if (lookup_attribute ("externally_visible",
633 DECL_ATTRIBUTES (node->symbol.decl)))
634 return true;
635 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
636 && lookup_attribute ("dllexport",
637 DECL_ATTRIBUTES (node->symbol.decl)))
638 return true;
639 if (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
640 return false;
641 /* When doing LTO or whole program, we can bring COMDAT functoins static.
642 This improves code quality and we know we will duplicate them at most twice
643 (in the case that we are not using plugin and link with object file
644 implementing same COMDAT) */
645 if ((in_lto_p || whole_program)
646 && DECL_COMDAT (node->symbol.decl)
647 && cgraph_comdat_can_be_unshared_p (node))
648 return false;
650 /* When doing link time optimizations, hidden symbols become local. */
651 if (in_lto_p
652 && (DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_HIDDEN
653 || DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL)
654 /* Be sure that node is defined in IR file, not in other object
655 file. In that case we don't set used_from_other_object_file. */
656 && node->analyzed)
658 else if (!whole_program)
659 return true;
661 if (MAIN_NAME_P (DECL_NAME (node->symbol.decl)))
662 return true;
664 return false;
667 /* Return true when variable VNODE should be considered externally visible. */
669 bool
670 varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
672 /* Do not touch weakrefs; while they are not externally visible,
673 dropping their DECL_EXTERNAL flags confuse most
674 of code handling them. */
675 if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl))
676 return true;
678 if (DECL_EXTERNAL (vnode->symbol.decl))
679 return true;
681 if (!DECL_COMDAT (vnode->symbol.decl) && !TREE_PUBLIC (vnode->symbol.decl))
682 return false;
684 /* Do not even try to be smart about aliased nodes. Until we properly
685 represent everything by same body alias, these are just evil. */
686 if (aliased)
687 return true;
689 /* If linker counts on us, we must preserve the function. */
690 if (symtab_used_from_object_file_p ((symtab_node) vnode))
691 return true;
693 if (DECL_HARD_REGISTER (vnode->symbol.decl))
694 return true;
695 if (DECL_PRESERVE_P (vnode->symbol.decl))
696 return true;
697 if (lookup_attribute ("externally_visible",
698 DECL_ATTRIBUTES (vnode->symbol.decl)))
699 return true;
700 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
701 && lookup_attribute ("dllexport",
702 DECL_ATTRIBUTES (vnode->symbol.decl)))
703 return true;
705 /* See if we have linker information about symbol not being used or
706 if we need to make guess based on the declaration.
708 Even if the linker clams the symbol is unused, never bring internal
709 symbols that are declared by user as used or externally visible.
710 This is needed for i.e. references from asm statements. */
711 if (symtab_used_from_object_file_p ((symtab_node) vnode))
712 return true;
713 if (vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
714 return false;
716 /* As a special case, the COMDAT virtual tables can be unshared.
717 In LTO mode turn vtables into static variables. The variable is readonly,
718 so this does not enable more optimization, but referring static var
719 is faster for dynamic linking. Also this match logic hidding vtables
720 from LTO symbol tables. */
721 if ((in_lto_p || flag_whole_program)
722 && !vnode->symbol.force_output
723 && DECL_COMDAT (vnode->symbol.decl) && DECL_VIRTUAL_P (vnode->symbol.decl))
724 return false;
726 /* When doing link time optimizations, hidden symbols become local. */
727 if (in_lto_p
728 && (DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_HIDDEN
729 || DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL)
730 /* Be sure that node is defined in IR file, not in other object
731 file. In that case we don't set used_from_other_object_file. */
732 && vnode->finalized)
734 else if (!flag_whole_program)
735 return true;
737 /* Do not attempt to privatize COMDATS by default.
738 This would break linking with C++ libraries sharing
739 inline definitions.
741 FIXME: We can do so for readonly vars with no address taken and
742 possibly also for vtables since no direct pointer comparsion is done.
743 It might be interesting to do so to reduce linking overhead. */
744 if (DECL_COMDAT (vnode->symbol.decl) || DECL_WEAK (vnode->symbol.decl))
745 return true;
746 return false;
749 /* Mark visibility of all functions.
751 A local function is one whose calls can occur only in the current
752 compilation unit and all its calls are explicit, so we can change
753 its calling convention. We simply mark all static functions whose
754 address is not taken as local.
756 We also change the TREE_PUBLIC flag of all declarations that are public
757 in language point of view but we want to overwrite this default
758 via visibilities for the backend point of view. */
760 static unsigned int
761 function_and_variable_visibility (bool whole_program)
763 struct cgraph_node *node;
764 struct varpool_node *vnode;
765 struct pointer_set_t *aliased_nodes = pointer_set_create ();
766 struct pointer_set_t *aliased_vnodes = pointer_set_create ();
767 unsigned i;
768 alias_pair *p;
770 /* Discover aliased nodes. */
771 FOR_EACH_VEC_SAFE_ELT (alias_pairs, i, p)
773 if (dump_file)
774 fprintf (dump_file, "Alias %s->%s",
775 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
776 IDENTIFIER_POINTER (p->target));
778 if ((node = cgraph_node_for_asm (p->target)) != NULL
779 && !DECL_EXTERNAL (node->symbol.decl))
781 if (!node->analyzed)
782 continue;
783 cgraph_mark_force_output_node (node);
784 pointer_set_insert (aliased_nodes, node);
785 if (dump_file)
786 fprintf (dump_file, " node %s/%i",
787 cgraph_node_name (node), node->uid);
789 else if ((vnode = varpool_node_for_asm (p->target)) != NULL
790 && !DECL_EXTERNAL (vnode->symbol.decl))
792 vnode->symbol.force_output = 1;
793 pointer_set_insert (aliased_vnodes, vnode);
794 if (dump_file)
795 fprintf (dump_file, " varpool node %s",
796 varpool_node_name (vnode));
798 if (dump_file)
799 fprintf (dump_file, "\n");
802 FOR_EACH_FUNCTION (node)
804 int flags = flags_from_decl_or_type (node->symbol.decl);
806 /* Optimize away PURE and CONST constructors and destructors. */
807 if (optimize
808 && (flags & (ECF_CONST | ECF_PURE))
809 && !(flags & ECF_LOOPING_CONST_OR_PURE))
811 DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0;
812 DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0;
815 /* Frontends and alias code marks nodes as needed before parsing is finished.
816 We may end up marking as node external nodes where this flag is meaningless
817 strip it. */
818 if (node->symbol.force_output
819 && (DECL_EXTERNAL (node->symbol.decl) || !node->analyzed))
820 node->symbol.force_output = 0;
822 /* C++ FE on lack of COMDAT support create local COMDAT functions
823 (that ought to be shared but can not due to object format
824 limitations). It is necessary to keep the flag to make rest of C++ FE
825 happy. Clear the flag here to avoid confusion in middle-end. */
826 if (DECL_COMDAT (node->symbol.decl) && !TREE_PUBLIC (node->symbol.decl))
827 DECL_COMDAT (node->symbol.decl) = 0;
828 /* For external decls stop tracking same_comdat_group, it doesn't matter
829 what comdat group they are in when they won't be emitted in this TU,
830 and simplifies later passes. */
831 if (node->symbol.same_comdat_group && DECL_EXTERNAL (node->symbol.decl))
833 #ifdef ENABLE_CHECKING
834 symtab_node n;
836 for (n = node->symbol.same_comdat_group;
837 n != (symtab_node)node;
838 n = n->symbol.same_comdat_group)
839 /* If at least one of same comdat group functions is external,
840 all of them have to be, otherwise it is a front-end bug. */
841 gcc_assert (DECL_EXTERNAL (n->symbol.decl));
842 #endif
843 symtab_dissolve_same_comdat_group_list ((symtab_node) node);
845 gcc_assert ((!DECL_WEAK (node->symbol.decl)
846 && !DECL_COMDAT (node->symbol.decl))
847 || TREE_PUBLIC (node->symbol.decl)
848 || DECL_EXTERNAL (node->symbol.decl));
849 if (cgraph_externally_visible_p (node, whole_program,
850 pointer_set_contains (aliased_nodes,
851 node)))
853 gcc_assert (!node->global.inlined_to);
854 node->symbol.externally_visible = true;
856 else
857 node->symbol.externally_visible = false;
858 if (!node->symbol.externally_visible && node->analyzed
859 && !DECL_EXTERNAL (node->symbol.decl))
861 gcc_assert (whole_program || in_lto_p
862 || !TREE_PUBLIC (node->symbol.decl));
863 symtab_make_decl_local (node->symbol.decl);
864 node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
865 if (node->symbol.same_comdat_group)
866 /* cgraph_externally_visible_p has already checked all other nodes
867 in the group and they will all be made local. We need to
868 dissolve the group at once so that the predicate does not
869 segfault though. */
870 symtab_dissolve_same_comdat_group_list ((symtab_node) node);
873 if (node->thunk.thunk_p
874 && TREE_PUBLIC (node->symbol.decl))
876 struct cgraph_node *decl_node = node;
878 decl_node = cgraph_function_node (decl_node->callees->callee, NULL);
880 /* Thunks have the same visibility as function they are attached to.
881 Make sure the C++ front end set this up properly. */
882 if (DECL_ONE_ONLY (decl_node->symbol.decl))
884 gcc_checking_assert (DECL_COMDAT (node->symbol.decl)
885 == DECL_COMDAT (decl_node->symbol.decl));
886 gcc_checking_assert (DECL_COMDAT_GROUP (node->symbol.decl)
887 == DECL_COMDAT_GROUP (decl_node->symbol.decl));
888 gcc_checking_assert (node->symbol.same_comdat_group);
890 if (DECL_EXTERNAL (decl_node->symbol.decl))
891 DECL_EXTERNAL (node->symbol.decl) = 1;
894 FOR_EACH_DEFINED_FUNCTION (node)
895 node->local.local = cgraph_local_node_p (node);
896 FOR_EACH_VARIABLE (vnode)
898 /* weak flag makes no sense on local variables. */
899 gcc_assert (!DECL_WEAK (vnode->symbol.decl)
900 || TREE_PUBLIC (vnode->symbol.decl)
901 || DECL_EXTERNAL (vnode->symbol.decl));
902 /* In several cases declarations can not be common:
904 - when declaration has initializer
905 - when it is in weak
906 - when it has specific section
907 - when it resides in non-generic address space.
908 - if declaration is local, it will get into .local common section
909 so common flag is not needed. Frontends still produce these in
910 certain cases, such as for:
912 static int a __attribute__ ((common))
914 Canonicalize things here and clear the redundant flag. */
915 if (DECL_COMMON (vnode->symbol.decl)
916 && (!(TREE_PUBLIC (vnode->symbol.decl)
917 || DECL_EXTERNAL (vnode->symbol.decl))
918 || (DECL_INITIAL (vnode->symbol.decl)
919 && DECL_INITIAL (vnode->symbol.decl) != error_mark_node)
920 || DECL_WEAK (vnode->symbol.decl)
921 || DECL_SECTION_NAME (vnode->symbol.decl) != NULL
922 || ! (ADDR_SPACE_GENERIC_P
923 (TYPE_ADDR_SPACE (TREE_TYPE (vnode->symbol.decl))))))
924 DECL_COMMON (vnode->symbol.decl) = 0;
926 FOR_EACH_DEFINED_VARIABLE (vnode)
928 if (!vnode->finalized)
929 continue;
931 if (varpool_externally_visible_p
932 (vnode,
933 pointer_set_contains (aliased_vnodes, vnode)))
934 vnode->symbol.externally_visible = true;
935 else
936 vnode->symbol.externally_visible = false;
937 if (!vnode->symbol.externally_visible)
939 gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl));
940 symtab_make_decl_local (vnode->symbol.decl);
941 if (vnode->symbol.same_comdat_group)
942 symtab_dissolve_same_comdat_group_list ((symtab_node) vnode);
943 vnode->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
945 /* Static variables defined in auxiliary modules are externalized to
946 allow cross module inlining. */
947 gcc_assert (TREE_STATIC (vnode->symbol.decl)
948 || varpool_is_auxiliary (vnode));
950 pointer_set_destroy (aliased_nodes);
951 pointer_set_destroy (aliased_vnodes);
953 if (dump_file)
955 fprintf (dump_file, "\nMarking local functions:");
956 FOR_EACH_DEFINED_FUNCTION (node)
957 if (node->local.local)
958 fprintf (dump_file, " %s", cgraph_node_name (node));
959 fprintf (dump_file, "\n\n");
960 fprintf (dump_file, "\nMarking externally visible functions:");
961 FOR_EACH_DEFINED_FUNCTION (node)
962 if (node->symbol.externally_visible)
963 fprintf (dump_file, " %s", cgraph_node_name (node));
964 fprintf (dump_file, "\n\n");
965 fprintf (dump_file, "\nMarking externally visible variables:");
966 FOR_EACH_DEFINED_VARIABLE (vnode)
967 if (vnode->symbol.externally_visible)
968 fprintf (dump_file, " %s", varpool_node_name (vnode));
969 fprintf (dump_file, "\n\n");
971 cgraph_function_flags_ready = true;
972 return 0;
975 /* Local function pass handling visibilities. This happens before LTO streaming
976 so in particular -fwhole-program should be ignored at this level. */
978 static unsigned int
979 local_function_and_variable_visibility (void)
981 return function_and_variable_visibility (flag_whole_program && !flag_lto);
984 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
987 SIMPLE_IPA_PASS,
988 "visibility", /* name */
989 OPTGROUP_NONE, /* optinfo_flags */
990 NULL, /* gate */
991 local_function_and_variable_visibility,/* execute */
992 NULL, /* sub */
993 NULL, /* next */
994 0, /* static_pass_number */
995 TV_CGRAPHOPT, /* tv_id */
996 0, /* properties_required */
997 0, /* properties_provided */
998 0, /* properties_destroyed */
999 0, /* todo_flags_start */
1000 TODO_remove_functions | TODO_dump_symtab
1001 | TODO_ggc_collect /* todo_flags_finish */
1005 /* Free inline summary. */
1007 static unsigned
1008 free_inline_summary (void)
1010 inline_free_summary ();
1011 return 0;
1014 struct simple_ipa_opt_pass pass_ipa_free_inline_summary =
1017 SIMPLE_IPA_PASS,
1018 "*free_inline_summary", /* name */
1019 OPTGROUP_NONE, /* optinfo_flags */
1020 NULL, /* gate */
1021 free_inline_summary, /* execute */
1022 NULL, /* sub */
1023 NULL, /* next */
1024 0, /* static_pass_number */
1025 TV_IPA_FREE_INLINE_SUMMARY, /* tv_id */
1026 0, /* properties_required */
1027 0, /* properties_provided */
1028 0, /* properties_destroyed */
1029 0, /* todo_flags_start */
1030 TODO_ggc_collect /* todo_flags_finish */
1034 /* Do not re-run on ltrans stage. */
1036 static bool
1037 gate_whole_program_function_and_variable_visibility (void)
1039 return !flag_ltrans;
1042 /* Bring functionss local at LTO time with -fwhole-program. */
1044 static unsigned int
1045 whole_program_function_and_variable_visibility (void)
1047 function_and_variable_visibility (flag_whole_program);
1048 if (optimize)
1049 ipa_discover_readonly_nonaddressable_vars ();
1050 return 0;
1053 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
1056 IPA_PASS,
1057 "whole-program", /* name */
1058 OPTGROUP_NONE, /* optinfo_flags */
1059 gate_whole_program_function_and_variable_visibility,/* gate */
1060 whole_program_function_and_variable_visibility,/* execute */
1061 NULL, /* sub */
1062 NULL, /* next */
1063 0, /* static_pass_number */
1064 TV_CGRAPHOPT, /* tv_id */
1065 0, /* properties_required */
1066 0, /* properties_provided */
1067 0, /* properties_destroyed */
1068 0, /* todo_flags_start */
1069 TODO_remove_functions | TODO_dump_symtab
1070 | TODO_ggc_collect /* todo_flags_finish */
1072 NULL, /* generate_summary */
1073 NULL, /* write_summary */
1074 NULL, /* read_summary */
1075 NULL, /* write_optimization_summary */
1076 NULL, /* read_optimization_summary */
1077 NULL, /* stmt_fixup */
1078 0, /* TODOs */
1079 NULL, /* function_transform */
1080 NULL, /* variable_transform */
1084 /* Simple ipa profile pass propagating frequencies across the callgraph. */
1086 static unsigned int
1087 ipa_profile (void)
1089 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1090 struct cgraph_edge *e;
1091 int order_pos;
1092 bool something_changed = false;
1093 int i;
1095 order_pos = ipa_reverse_postorder (order);
1096 for (i = order_pos - 1; i >= 0; i--)
1098 if (order[i]->local.local && cgraph_propagate_frequency (order[i]))
1100 for (e = order[i]->callees; e; e = e->next_callee)
1101 if (e->callee->local.local && !e->callee->symbol.aux)
1103 something_changed = true;
1104 e->callee->symbol.aux = (void *)1;
1107 order[i]->symbol.aux = NULL;
1110 while (something_changed)
1112 something_changed = false;
1113 for (i = order_pos - 1; i >= 0; i--)
1115 if (order[i]->symbol.aux && cgraph_propagate_frequency (order[i]))
1117 for (e = order[i]->callees; e; e = e->next_callee)
1118 if (e->callee->local.local && !e->callee->symbol.aux)
1120 something_changed = true;
1121 e->callee->symbol.aux = (void *)1;
1124 order[i]->symbol.aux = NULL;
1127 free (order);
1128 return 0;
1131 static bool
1132 gate_ipa_profile (void)
1134 return flag_ipa_profile;
1137 struct ipa_opt_pass_d pass_ipa_profile =
1140 IPA_PASS,
1141 "profile_estimate", /* name */
1142 OPTGROUP_NONE, /* optinfo_flags */
1143 gate_ipa_profile, /* gate */
1144 ipa_profile, /* execute */
1145 NULL, /* sub */
1146 NULL, /* next */
1147 0, /* static_pass_number */
1148 TV_IPA_PROFILE, /* tv_id */
1149 0, /* properties_required */
1150 0, /* properties_provided */
1151 0, /* properties_destroyed */
1152 0, /* todo_flags_start */
1153 0 /* todo_flags_finish */
1155 NULL, /* generate_summary */
1156 NULL, /* write_summary */
1157 NULL, /* read_summary */
1158 NULL, /* write_optimization_summary */
1159 NULL, /* read_optimization_summary */
1160 NULL, /* stmt_fixup */
1161 0, /* TODOs */
1162 NULL, /* function_transform */
1163 NULL /* variable_transform */
1166 /* Generate and emit a static constructor or destructor. WHICH must
1167 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1168 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1169 initialization priority for this constructor or destructor.
1171 FINAL specify whether the externally visible name for collect2 should
1172 be produced. */
1174 static void
1175 cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
1177 static int counter = 0;
1178 char which_buf[16];
1179 tree decl, name, resdecl;
1181 /* The priority is encoded in the constructor or destructor name.
1182 collect2 will sort the names and arrange that they are called at
1183 program startup. */
1184 if (final)
1185 sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
1186 else
1187 /* Proudce sane name but one not recognizable by collect2, just for the
1188 case we fail to inline the function. */
1189 sprintf (which_buf, "sub_%c_%.5d_%d", which, priority, counter++);
1190 name = get_file_function_name (which_buf);
1192 decl = build_decl (input_location, FUNCTION_DECL, name,
1193 build_function_type_list (void_type_node, NULL_TREE));
1194 current_function_decl = decl;
1196 resdecl = build_decl (input_location,
1197 RESULT_DECL, NULL_TREE, void_type_node);
1198 DECL_ARTIFICIAL (resdecl) = 1;
1199 DECL_RESULT (decl) = resdecl;
1200 DECL_CONTEXT (resdecl) = decl;
1202 allocate_struct_function (decl, false);
1204 TREE_STATIC (decl) = 1;
1205 TREE_USED (decl) = 1;
1206 DECL_ARTIFICIAL (decl) = 1;
1207 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1208 DECL_SAVED_TREE (decl) = body;
1209 if (!targetm.have_ctors_dtors && final)
1211 TREE_PUBLIC (decl) = 1;
1212 DECL_PRESERVE_P (decl) = 1;
1214 DECL_UNINLINABLE (decl) = 1;
1216 DECL_INITIAL (decl) = make_node (BLOCK);
1217 TREE_USED (DECL_INITIAL (decl)) = 1;
1219 DECL_SOURCE_LOCATION (decl) = input_location;
1220 cfun->function_end_locus = input_location;
1222 switch (which)
1224 case 'I':
1225 DECL_STATIC_CONSTRUCTOR (decl) = 1;
1226 decl_init_priority_insert (decl, priority);
1227 break;
1228 case 'D':
1229 DECL_STATIC_DESTRUCTOR (decl) = 1;
1230 decl_fini_priority_insert (decl, priority);
1231 break;
1232 default:
1233 gcc_unreachable ();
1236 gimplify_function_tree (decl);
1238 cgraph_add_new_function (decl, false);
1240 set_cfun (NULL);
1241 current_function_decl = NULL;
1244 /* Generate and emit a static constructor or destructor. WHICH must
1245 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1246 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1247 initialization priority for this constructor or destructor. */
1249 void
1250 cgraph_build_static_cdtor (char which, tree body, int priority)
1252 cgraph_build_static_cdtor_1 (which, body, priority, false);
1255 /* A vector of FUNCTION_DECLs declared as static constructors. */
1256 static vec<tree> static_ctors;
1257 /* A vector of FUNCTION_DECLs declared as static destructors. */
1258 static vec<tree> static_dtors;
1260 /* When target does not have ctors and dtors, we call all constructor
1261 and destructor by special initialization/destruction function
1262 recognized by collect2.
1264 When we are going to build this function, collect all constructors and
1265 destructors and turn them into normal functions. */
1267 static void
1268 record_cdtor_fn (struct cgraph_node *node)
1270 if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
1271 static_ctors.safe_push (node->symbol.decl);
1272 if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
1273 static_dtors.safe_push (node->symbol.decl);
1274 node = cgraph_get_node (node->symbol.decl);
1275 DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl) = 1;
1278 /* Define global constructors/destructor functions for the CDTORS, of
1279 which they are LEN. The CDTORS are sorted by initialization
1280 priority. If CTOR_P is true, these are constructors; otherwise,
1281 they are destructors. */
1283 static void
1284 build_cdtor (bool ctor_p, vec<tree> cdtors)
1286 size_t i,j;
1287 size_t len = cdtors.length ();
1289 i = 0;
1290 while (i < len)
1292 tree body;
1293 tree fn;
1294 priority_type priority;
1296 priority = 0;
1297 body = NULL_TREE;
1298 j = i;
1301 priority_type p;
1302 fn = cdtors[j];
1303 p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
1304 if (j == i)
1305 priority = p;
1306 else if (p != priority)
1307 break;
1308 j++;
1310 while (j < len);
1312 /* When there is only one cdtor and target supports them, do nothing. */
1313 if (j == i + 1
1314 && targetm.have_ctors_dtors)
1316 i++;
1317 continue;
1319 /* Find the next batch of constructors/destructors with the same
1320 initialization priority. */
1321 for (;i < j; i++)
1323 tree call;
1324 fn = cdtors[i];
1325 call = build_call_expr (fn, 0);
1326 if (ctor_p)
1327 DECL_STATIC_CONSTRUCTOR (fn) = 0;
1328 else
1329 DECL_STATIC_DESTRUCTOR (fn) = 0;
1330 /* We do not want to optimize away pure/const calls here.
1331 When optimizing, these should be already removed, when not
1332 optimizing, we want user to be able to breakpoint in them. */
1333 TREE_SIDE_EFFECTS (call) = 1;
1334 append_to_statement_list (call, &body);
1336 gcc_assert (body != NULL_TREE);
1337 /* Generate a function to call all the function of like
1338 priority. */
1339 cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true);
1343 /* Comparison function for qsort. P1 and P2 are actually of type
1344 "tree *" and point to static constructors. DECL_INIT_PRIORITY is
1345 used to determine the sort order. */
1347 static int
1348 compare_ctor (const void *p1, const void *p2)
1350 tree f1;
1351 tree f2;
1352 int priority1;
1353 int priority2;
1355 f1 = *(const tree *)p1;
1356 f2 = *(const tree *)p2;
1357 priority1 = DECL_INIT_PRIORITY (f1);
1358 priority2 = DECL_INIT_PRIORITY (f2);
1360 if (priority1 < priority2)
1361 return -1;
1362 else if (priority1 > priority2)
1363 return 1;
1364 else
1365 /* Ensure a stable sort. Constructors are executed in backwarding
1366 order to make LTO initialize braries first. */
1367 return DECL_UID (f2) - DECL_UID (f1);
1370 /* Comparison function for qsort. P1 and P2 are actually of type
1371 "tree *" and point to static destructors. DECL_FINI_PRIORITY is
1372 used to determine the sort order. */
1374 static int
1375 compare_dtor (const void *p1, const void *p2)
1377 tree f1;
1378 tree f2;
1379 int priority1;
1380 int priority2;
1382 f1 = *(const tree *)p1;
1383 f2 = *(const tree *)p2;
1384 priority1 = DECL_FINI_PRIORITY (f1);
1385 priority2 = DECL_FINI_PRIORITY (f2);
1387 if (priority1 < priority2)
1388 return -1;
1389 else if (priority1 > priority2)
1390 return 1;
1391 else
1392 /* Ensure a stable sort. */
1393 return DECL_UID (f1) - DECL_UID (f2);
1396 /* Generate functions to call static constructors and destructors
1397 for targets that do not support .ctors/.dtors sections. These
1398 functions have magic names which are detected by collect2. */
1400 static void
1401 build_cdtor_fns (void)
1403 if (!static_ctors.is_empty ())
1405 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1406 static_ctors.qsort (compare_ctor);
1407 build_cdtor (/*ctor_p=*/true, static_ctors);
1410 if (!static_dtors.is_empty ())
1412 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1413 static_dtors.qsort (compare_dtor);
1414 build_cdtor (/*ctor_p=*/false, static_dtors);
1418 /* Look for constructors and destructors and produce function calling them.
1419 This is needed for targets not supporting ctors or dtors, but we perform the
1420 transformation also at linktime to merge possibly numerous
1421 constructors/destructors into single function to improve code locality and
1422 reduce size. */
1424 static unsigned int
1425 ipa_cdtor_merge (void)
1427 struct cgraph_node *node;
1428 FOR_EACH_DEFINED_FUNCTION (node)
1429 if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
1430 || DECL_STATIC_DESTRUCTOR (node->symbol.decl))
1431 record_cdtor_fn (node);
1432 build_cdtor_fns ();
1433 static_ctors.release ();
1434 static_dtors.release ();
1435 return 0;
1438 /* Perform the pass when we have no ctors/dtors support
1439 or at LTO time to merge multiple constructors into single
1440 function. */
1442 static bool
1443 gate_ipa_cdtor_merge (void)
1445 return !targetm.have_ctors_dtors || (optimize && in_lto_p);
1448 struct ipa_opt_pass_d pass_ipa_cdtor_merge =
1451 IPA_PASS,
1452 "cdtor", /* name */
1453 OPTGROUP_NONE, /* optinfo_flags */
1454 gate_ipa_cdtor_merge, /* gate */
1455 ipa_cdtor_merge, /* execute */
1456 NULL, /* sub */
1457 NULL, /* next */
1458 0, /* static_pass_number */
1459 TV_CGRAPHOPT, /* tv_id */
1460 0, /* properties_required */
1461 0, /* properties_provided */
1462 0, /* properties_destroyed */
1463 0, /* todo_flags_start */
1464 0 /* todo_flags_finish */
1466 NULL, /* generate_summary */
1467 NULL, /* write_summary */
1468 NULL, /* read_summary */
1469 NULL, /* write_optimization_summary */
1470 NULL, /* read_optimization_summary */
1471 NULL, /* stmt_fixup */
1472 0, /* TODOs */
1473 NULL, /* function_transform */
1474 NULL /* variable_transform */