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
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
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/>. */
22 #include "coretypes.h"
25 #include "tree-pass.h"
29 #include "pointer-set.h"
31 #include "tree-iterator.h"
32 #include "ipa-utils.h"
33 #include "pointer-set.h"
34 #include "ipa-inline.h"
35 #include "hash-table.h"
36 #include "tree-inline.h"
39 #include "lto-streamer.h"
40 #include "data-streamer.h"
42 /* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
45 cgraph_non_local_node_p_1 (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
47 /* FIXME: Aliases can be local, but i386 gets thunks wrong then. */
48 return !(cgraph_only_called_directly_or_aliased_p (node
)
49 && !ipa_ref_has_aliases_p (&node
->symbol
.ref_list
)
50 && node
->symbol
.definition
51 && !DECL_EXTERNAL (node
->symbol
.decl
)
52 && !node
->symbol
.externally_visible
53 && !node
->symbol
.used_from_other_partition
54 && !node
->symbol
.in_other_partition
);
57 /* Return true when function can be marked local. */
60 cgraph_local_node_p (struct cgraph_node
*node
)
62 struct cgraph_node
*n
= cgraph_function_or_thunk_node (node
, NULL
);
64 /* FIXME: thunks can be considered local, but we need prevent i386
65 from attempting to change calling convention of them. */
68 return !cgraph_for_node_and_aliases (n
,
69 cgraph_non_local_node_p_1
, NULL
, true);
73 /* Return true when NODE has ADDR reference. */
76 has_addr_references_p (struct cgraph_node
*node
,
77 void *data ATTRIBUTE_UNUSED
)
82 for (i
= 0; ipa_ref_list_referring_iterate (&node
->symbol
.ref_list
,
84 if (ref
->use
== IPA_REF_ADDR
)
89 /* Look for all functions inlined to NODE and update their inlined_to pointers
93 update_inlined_to_pointer (struct cgraph_node
*node
, struct cgraph_node
*inlined_to
)
95 struct cgraph_edge
*e
;
96 for (e
= node
->callees
; e
; e
= e
->next_callee
)
97 if (e
->callee
->global
.inlined_to
)
99 e
->callee
->global
.inlined_to
= inlined_to
;
100 update_inlined_to_pointer (e
->callee
, inlined_to
);
104 /* Add symtab NODE to queue starting at FIRST.
106 The queue is linked via AUX pointers and terminated by pointer to 1.
107 We enqueue nodes at two occasions: when we find them reachable or when we find
108 their bodies needed for further clonning. In the second case we mark them
109 by pointer to 2 after processing so they are re-queue when they become
113 enqueue_node (symtab_node node
, symtab_node
*first
,
114 struct pointer_set_t
*reachable
)
116 /* Node is still in queue; do nothing. */
117 if (node
->symbol
.aux
&& node
->symbol
.aux
!= (void *) 2)
119 /* Node was already processed as unreachable, re-enqueue
120 only if it became reachable now. */
121 if (node
->symbol
.aux
== (void *)2 && !pointer_set_contains (reachable
, node
))
123 node
->symbol
.aux
= *first
;
127 /* Process references. */
130 process_references (struct ipa_ref_list
*list
,
132 bool before_inlining_p
,
133 struct pointer_set_t
*reachable
)
137 for (i
= 0; ipa_ref_list_reference_iterate (list
, i
, ref
); i
++)
139 symtab_node node
= ref
->referred
;
141 if (node
->symbol
.definition
&& !node
->symbol
.in_other_partition
142 && ((!DECL_EXTERNAL (node
->symbol
.decl
) || node
->symbol
.alias
)
143 || (before_inlining_p
144 /* We use variable constructors during late complation for
145 constant folding. Keep references alive so partitioning
146 knows about potential references. */
147 || (TREE_CODE (node
->symbol
.decl
) == VAR_DECL
149 && ctor_for_folding (node
->symbol
.decl
)
150 != error_mark_node
))))
151 pointer_set_insert (reachable
, node
);
152 enqueue_node ((symtab_node
) node
, first
, reachable
);
157 /* Perform reachability analysis and reclaim all unreachable nodes.
159 The algorithm is basically mark&sweep but with some extra refinements:
161 - reachable extern inline functions needs special handling; the bodies needs
162 to stay in memory until inlining in hope that they will be inlined.
163 After inlining we release their bodies and turn them into unanalyzed
164 nodes even when they are reachable.
166 BEFORE_INLINING_P specify whether we are before or after inlining.
168 - virtual functions are kept in callgraph even if they seem unreachable in
169 hope calls to them will be devirtualized.
171 Again we remove them after inlining. In late optimization some
172 devirtualization may happen, but it is not importnat since we won't inline
173 the call. In theory early opts and IPA should work out all important cases.
175 - virtual clones needs bodies of their origins for later materialization;
176 this means that we want to keep the body even if the origin is unreachable
177 otherwise. To avoid origin from sitting in the callgraph and being
178 walked by IPA passes, we turn them into unanalyzed nodes with body
181 We maintain set of function declaration where body needs to stay in
182 body_needed_for_clonning
184 Inline clones represent special case: their declaration match the
185 declaration of origin and cgraph_remove_node already knows how to
186 reshape callgraph and preserve body when offline copy of function or
187 inline clone is being removed.
189 - C++ virtual tables keyed to other unit are represented as DECL_EXTERNAL
190 variables with DECL_INITIAL set. We finalize these and keep reachable
191 ones around for constant folding purposes. After inlining we however
192 stop walking their references to let everything static referneced by them
193 to be removed when it is otherwise unreachable.
195 We maintain queue of both reachable symbols (i.e. defined symbols that needs
196 to stay) and symbols that are in boundary (i.e. external symbols referenced
197 by reachable symbols or origins of clones). The queue is represented
198 as linked list by AUX pointer terminated by 1.
200 A the end we keep all reachable symbols. For symbols in boundary we always
201 turn definition into a declaration, but we may keep function body around
202 based on body_needed_for_clonning
204 All symbols that enter the queue have AUX pointer non-zero and are in the
205 boundary. Pointer set REACHABLE is used to track reachable symbols.
207 Every symbol can be visited twice - once as part of boundary and once
208 as real reachable symbol. enqueue_node needs to decide whether the
209 node needs to be re-queued for second processing. For this purpose
210 we set AUX pointer of processed symbols in the boundary to constant 2. */
213 symtab_remove_unreachable_nodes (bool before_inlining_p
, FILE *file
)
215 symtab_node first
= (symtab_node
) (void *) 1;
216 struct cgraph_node
*node
, *next
;
217 struct varpool_node
*vnode
, *vnext
;
218 bool changed
= false;
219 struct pointer_set_t
*reachable
= pointer_set_create ();
220 struct pointer_set_t
*body_needed_for_clonning
= pointer_set_create ();
222 #ifdef ENABLE_CHECKING
226 fprintf (file
, "\nReclaiming functions:");
227 #ifdef ENABLE_CHECKING
228 FOR_EACH_FUNCTION (node
)
229 gcc_assert (!node
->symbol
.aux
);
230 FOR_EACH_VARIABLE (vnode
)
231 gcc_assert (!vnode
->symbol
.aux
);
233 /* Mark functions whose bodies are obviously needed.
234 This is mostly when they can be referenced externally. Inline clones
235 are special since their declarations are shared with master clone and thus
236 cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them. */
237 FOR_EACH_FUNCTION (node
)
239 node
->used_as_abstract_origin
= false;
240 if (node
->symbol
.definition
241 && !node
->global
.inlined_to
242 && !node
->symbol
.in_other_partition
243 && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node
)
244 /* Keep around virtual functions for possible devirtualization. */
245 || (before_inlining_p
246 && DECL_VIRTUAL_P (node
->symbol
.decl
))))
248 gcc_assert (!node
->global
.inlined_to
);
249 pointer_set_insert (reachable
, node
);
250 enqueue_node ((symtab_node
)node
, &first
, reachable
);
253 gcc_assert (!node
->symbol
.aux
);
256 /* Mark variables that are obviously needed. */
257 FOR_EACH_DEFINED_VARIABLE (vnode
)
258 if (!varpool_can_remove_if_no_refs (vnode
)
259 && !vnode
->symbol
.in_other_partition
)
261 pointer_set_insert (reachable
, vnode
);
262 enqueue_node ((symtab_node
)vnode
, &first
, reachable
);
265 /* Perform reachability analysis. */
266 while (first
!= (symtab_node
) (void *) 1)
268 bool in_boundary_p
= !pointer_set_contains (reachable
, first
);
269 symtab_node node
= first
;
271 first
= (symtab_node
)first
->symbol
.aux
;
273 /* If we are processing symbol in boundary, mark its AUX pointer for
274 possible later re-processing in enqueue_node. */
276 node
->symbol
.aux
= (void *)2;
279 if (DECL_ABSTRACT_ORIGIN (node
->symbol
.decl
))
281 struct cgraph_node
*origin_node
282 = cgraph_get_create_real_symbol_node (DECL_ABSTRACT_ORIGIN (node
->symbol
.decl
));
283 origin_node
->used_as_abstract_origin
= true;
284 enqueue_node ((symtab_node
) origin_node
, &first
, reachable
);
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
)
291 for (next
= node
->symbol
.same_comdat_group
;
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. */
308 struct cgraph_edge
*e
;
309 for (e
= cnode
->callees
; e
; e
= e
->next_callee
)
311 if (e
->callee
->symbol
.definition
312 && !e
->callee
->symbol
.in_other_partition
313 && (!e
->inline_failed
314 || !DECL_EXTERNAL (e
->callee
->symbol
.decl
)
315 || e
->callee
->symbol
.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
->global
.inlined_to
)
324 pointer_set_insert (body_needed_for_clonning
, cnode
->symbol
.decl
);
326 /* For non-inline clones, force their origins to the boundary and ensure
327 that body is not removed. */
328 while (cnode
->clone_of
)
330 bool noninline
= cnode
->clone_of
->symbol
.decl
!= cnode
->symbol
.decl
;
331 cnode
= cnode
->clone_of
;
334 pointer_set_insert (body_needed_for_clonning
, cnode
->symbol
.decl
);
335 enqueue_node ((symtab_node
)cnode
, &first
, reachable
);
340 /* When we see constructor of external variable, keep referred nodes in the
341 boundary. This will also hold initializers of the external vars NODE
343 varpool_node
*vnode
= dyn_cast
<varpool_node
> (node
);
345 && DECL_EXTERNAL (node
->symbol
.decl
)
346 && !vnode
->symbol
.alias
350 for (int i
= 0; ipa_ref_list_reference_iterate (&node
->symbol
.ref_list
, i
, ref
); i
++)
351 enqueue_node (ref
->referred
, &first
, reachable
);
355 /* Remove unreachable functions. */
356 for (node
= cgraph_first_function (); node
; node
= next
)
358 next
= cgraph_next_function (node
);
360 /* If node is not needed at all, remove it. */
361 if (!node
->symbol
.aux
)
364 fprintf (file
, " %s", cgraph_node_name (node
));
365 cgraph_remove_node (node
);
368 /* If node is unreachable, remove its body. */
369 else if (!pointer_set_contains (reachable
, node
))
371 if (!pointer_set_contains (body_needed_for_clonning
, node
->symbol
.decl
))
372 cgraph_release_function_body (node
);
373 else if (!node
->clone_of
)
374 gcc_assert (DECL_RESULT (node
->symbol
.decl
));
375 if (node
->symbol
.definition
)
378 fprintf (file
, " %s", cgraph_node_name (node
));
379 cgraph_reset_node (node
);
384 gcc_assert (node
->clone_of
|| !cgraph_function_with_gimple_body_p (node
)
385 || DECL_RESULT (node
->symbol
.decl
));
388 /* Inline clones might be kept around so their materializing allows further
389 cloning. If the function the clone is inlined into is removed, we need
390 to turn it into normal cone. */
391 FOR_EACH_FUNCTION (node
)
393 if (node
->global
.inlined_to
396 gcc_assert (node
->clones
);
397 node
->global
.inlined_to
= NULL
;
398 update_inlined_to_pointer (node
, node
);
400 node
->symbol
.aux
= NULL
;
403 /* Remove unreachable variables. */
405 fprintf (file
, "\nReclaiming variables:");
406 for (vnode
= varpool_first_variable (); vnode
; vnode
= vnext
)
408 vnext
= varpool_next_variable (vnode
);
409 if (!vnode
->symbol
.aux
410 /* For can_refer_decl_in_current_unit_p we want to track for
411 all external variables if they are defined in other partition
413 && (!flag_ltrans
|| !DECL_EXTERNAL (vnode
->symbol
.decl
)))
416 fprintf (file
, " %s", varpool_node_name (vnode
));
417 varpool_remove_node (vnode
);
420 else if (!pointer_set_contains (reachable
, vnode
))
423 if (vnode
->symbol
.definition
)
426 fprintf (file
, " %s", varpool_node_name (vnode
));
429 vnode
->symbol
.definition
= false;
430 vnode
->symbol
.analyzed
= false;
431 vnode
->symbol
.aux
= NULL
;
433 /* Keep body if it may be useful for constant folding. */
434 if ((init
= ctor_for_folding (vnode
->symbol
.decl
)) == error_mark_node
)
435 varpool_remove_initializer (vnode
);
437 DECL_INITIAL (vnode
->symbol
.decl
) = init
;
438 ipa_remove_all_references (&vnode
->symbol
.ref_list
);
441 vnode
->symbol
.aux
= NULL
;
444 pointer_set_destroy (reachable
);
445 pointer_set_destroy (body_needed_for_clonning
);
447 /* Now update address_taken flags and try to promote functions to be local. */
449 fprintf (file
, "\nClearing address taken flags:");
450 FOR_EACH_DEFINED_FUNCTION (node
)
451 if (node
->symbol
.address_taken
452 && !node
->symbol
.used_from_other_partition
)
454 if (!cgraph_for_node_and_aliases (node
, has_addr_references_p
, NULL
, true))
457 fprintf (file
, " %s", cgraph_node_name (node
));
458 node
->symbol
.address_taken
= false;
460 if (cgraph_local_node_p (node
))
462 node
->local
.local
= true;
464 fprintf (file
, " (local)");
469 fprintf (file
, "\n");
471 #ifdef ENABLE_CHECKING
475 /* If we removed something, perhaps profile could be improved. */
476 if (changed
&& optimize
&& inline_edge_summary_vec
.exists ())
477 FOR_EACH_DEFINED_FUNCTION (node
)
478 cgraph_propagate_frequency (node
);
483 /* Discover variables that have no longer address taken or that are read only
484 and update their flags.
486 FIXME: This can not be done in between gimplify and omp_expand since
487 readonly flag plays role on what is shared and what is not. Currently we do
488 this transformation as part of whole program visibility and re-do at
489 ipa-reference pass (to take into account clonning), but it would
490 make sense to do it before early optimizations. */
493 ipa_discover_readonly_nonaddressable_vars (void)
495 struct varpool_node
*vnode
;
497 fprintf (dump_file
, "Clearing variable flags:");
498 FOR_EACH_VARIABLE (vnode
)
499 if (vnode
->symbol
.definition
&& varpool_all_refs_explicit_p (vnode
)
500 && (TREE_ADDRESSABLE (vnode
->symbol
.decl
)
501 || !TREE_READONLY (vnode
->symbol
.decl
)))
503 bool written
= false;
504 bool address_taken
= false;
507 for (i
= 0; ipa_ref_list_referring_iterate (&vnode
->symbol
.ref_list
,
509 && (!written
|| !address_taken
); i
++)
513 address_taken
= true;
521 if (TREE_ADDRESSABLE (vnode
->symbol
.decl
) && !address_taken
)
524 fprintf (dump_file
, " %s (addressable)", varpool_node_name (vnode
));
525 TREE_ADDRESSABLE (vnode
->symbol
.decl
) = 0;
527 if (!TREE_READONLY (vnode
->symbol
.decl
) && !address_taken
&& !written
528 /* Making variable in explicit section readonly can cause section
530 See e.g. gcc.c-torture/compile/pr23237.c */
531 && DECL_SECTION_NAME (vnode
->symbol
.decl
) == NULL
)
534 fprintf (dump_file
, " %s (read-only)", varpool_node_name (vnode
));
535 TREE_READONLY (vnode
->symbol
.decl
) = 1;
539 fprintf (dump_file
, "\n");
542 /* Return true when there is a reference to node and it is not vtable. */
544 address_taken_from_non_vtable_p (symtab_node node
)
548 for (i
= 0; ipa_ref_list_referring_iterate (&node
->symbol
.ref_list
,
550 if (ref
->use
== IPA_REF_ADDR
)
552 struct varpool_node
*node
;
553 if (is_a
<cgraph_node
> (ref
->referring
))
555 node
= ipa_ref_referring_varpool_node (ref
);
556 if (!DECL_VIRTUAL_P (node
->symbol
.decl
))
562 /* A helper for comdat_can_be_unshared_p. */
565 comdat_can_be_unshared_p_1 (symtab_node node
)
567 /* When address is taken, we don't know if equality comparison won't
568 break eventually. Exception are virutal functions and vtables,
569 where this is not possible by language standard. */
570 if (!DECL_VIRTUAL_P (node
->symbol
.decl
)
571 && address_taken_from_non_vtable_p (node
))
574 /* If the symbol is used in some weird way, better to not touch it. */
575 if (node
->symbol
.force_output
)
578 /* Explicit instantiations needs to be output when possibly
580 if (node
->symbol
.forced_by_abi
581 && TREE_PUBLIC (node
->symbol
.decl
)
582 && (node
->symbol
.resolution
!= LDPR_PREVAILING_DEF_IRONLY
583 && !flag_whole_program
))
586 /* Non-readonly and volatile variables can not be duplicated. */
587 if (is_a
<varpool_node
> (node
)
588 && (!TREE_READONLY (node
->symbol
.decl
)
589 || TREE_THIS_VOLATILE (node
->symbol
.decl
)))
594 /* COMDAT functions must be shared only if they have address taken,
595 otherwise we can produce our own private implementation with
597 Return true when turning COMDAT functoin static can not lead to wrong
598 code when the resulting object links with a library defining same COMDAT.
600 Virtual functions do have their addresses taken from the vtables,
601 but in C++ there is no way to compare their addresses for equality. */
604 comdat_can_be_unshared_p (symtab_node node
)
606 if (!comdat_can_be_unshared_p_1 (node
))
608 if (node
->symbol
.same_comdat_group
)
612 /* If more than one function is in the same COMDAT group, it must
613 be shared even if just one function in the comdat group has
615 for (next
= node
->symbol
.same_comdat_group
;
616 next
!= node
; next
= next
->symbol
.same_comdat_group
)
617 if (!comdat_can_be_unshared_p_1 (next
))
623 /* Return true when function NODE should be considered externally visible. */
626 cgraph_externally_visible_p (struct cgraph_node
*node
,
629 if (!node
->symbol
.definition
)
631 if (!TREE_PUBLIC (node
->symbol
.decl
)
632 || DECL_EXTERNAL (node
->symbol
.decl
))
635 /* Do not try to localize built-in functions yet. One of problems is that we
636 end up mangling their asm for WHOPR that makes it impossible to call them
637 using the implicit built-in declarations anymore. Similarly this enables
638 us to remove them as unreachable before actual calls may appear during
639 expansion or folding. */
640 if (DECL_BUILT_IN (node
->symbol
.decl
))
643 /* If linker counts on us, we must preserve the function. */
644 if (symtab_used_from_object_file_p ((symtab_node
) node
))
646 if (DECL_PRESERVE_P (node
->symbol
.decl
))
648 if (lookup_attribute ("externally_visible",
649 DECL_ATTRIBUTES (node
->symbol
.decl
)))
651 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
652 && lookup_attribute ("dllexport",
653 DECL_ATTRIBUTES (node
->symbol
.decl
)))
655 if (node
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
)
657 /* When doing LTO or whole program, we can bring COMDAT functoins static.
658 This improves code quality and we know we will duplicate them at most twice
659 (in the case that we are not using plugin and link with object file
660 implementing same COMDAT) */
661 if ((in_lto_p
|| whole_program
)
662 && DECL_COMDAT (node
->symbol
.decl
)
663 && comdat_can_be_unshared_p ((symtab_node
) node
))
666 /* When doing link time optimizations, hidden symbols become local. */
668 && (DECL_VISIBILITY (node
->symbol
.decl
) == VISIBILITY_HIDDEN
669 || DECL_VISIBILITY (node
->symbol
.decl
) == VISIBILITY_INTERNAL
)
670 /* Be sure that node is defined in IR file, not in other object
671 file. In that case we don't set used_from_other_object_file. */
672 && node
->symbol
.definition
)
674 else if (!whole_program
)
677 if (MAIN_NAME_P (DECL_NAME (node
->symbol
.decl
)))
683 /* Return true when variable VNODE should be considered externally visible. */
686 varpool_externally_visible_p (struct varpool_node
*vnode
)
688 if (DECL_EXTERNAL (vnode
->symbol
.decl
))
691 if (!TREE_PUBLIC (vnode
->symbol
.decl
))
694 /* If linker counts on us, we must preserve the function. */
695 if (symtab_used_from_object_file_p ((symtab_node
) vnode
))
698 if (DECL_HARD_REGISTER (vnode
->symbol
.decl
))
700 if (DECL_PRESERVE_P (vnode
->symbol
.decl
))
702 if (lookup_attribute ("externally_visible",
703 DECL_ATTRIBUTES (vnode
->symbol
.decl
)))
705 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
706 && lookup_attribute ("dllexport",
707 DECL_ATTRIBUTES (vnode
->symbol
.decl
)))
710 /* See if we have linker information about symbol not being used or
711 if we need to make guess based on the declaration.
713 Even if the linker clams the symbol is unused, never bring internal
714 symbols that are declared by user as used or externally visible.
715 This is needed for i.e. references from asm statements. */
716 if (symtab_used_from_object_file_p ((symtab_node
) vnode
))
718 if (vnode
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
)
721 /* As a special case, the COMDAT virtual tables can be unshared.
722 In LTO mode turn vtables into static variables. The variable is readonly,
723 so this does not enable more optimization, but referring static var
724 is faster for dynamic linking. Also this match logic hidding vtables
725 from LTO symbol tables. */
726 if ((in_lto_p
|| flag_whole_program
)
727 && DECL_COMDAT (vnode
->symbol
.decl
)
728 && comdat_can_be_unshared_p ((symtab_node
) vnode
))
731 /* When doing link time optimizations, hidden symbols become local. */
733 && (DECL_VISIBILITY (vnode
->symbol
.decl
) == VISIBILITY_HIDDEN
734 || DECL_VISIBILITY (vnode
->symbol
.decl
) == VISIBILITY_INTERNAL
)
735 /* Be sure that node is defined in IR file, not in other object
736 file. In that case we don't set used_from_other_object_file. */
737 && vnode
->symbol
.definition
)
739 else if (!flag_whole_program
)
742 /* Do not attempt to privatize COMDATS by default.
743 This would break linking with C++ libraries sharing
746 FIXME: We can do so for readonly vars with no address taken and
747 possibly also for vtables since no direct pointer comparsion is done.
748 It might be interesting to do so to reduce linking overhead. */
749 if (DECL_COMDAT (vnode
->symbol
.decl
) || DECL_WEAK (vnode
->symbol
.decl
))
754 /* Mark visibility of all functions.
756 A local function is one whose calls can occur only in the current
757 compilation unit and all its calls are explicit, so we can change
758 its calling convention. We simply mark all static functions whose
759 address is not taken as local.
761 We also change the TREE_PUBLIC flag of all declarations that are public
762 in language point of view but we want to overwrite this default
763 via visibilities for the backend point of view. */
766 function_and_variable_visibility (bool whole_program
)
768 struct cgraph_node
*node
;
769 struct varpool_node
*vnode
;
771 /* All aliases should be procssed at this point. */
772 gcc_checking_assert (!alias_pairs
|| !alias_pairs
->length());
774 FOR_EACH_FUNCTION (node
)
776 int flags
= flags_from_decl_or_type (node
->symbol
.decl
);
778 /* Optimize away PURE and CONST constructors and destructors. */
780 && (flags
& (ECF_CONST
| ECF_PURE
))
781 && !(flags
& ECF_LOOPING_CONST_OR_PURE
))
783 DECL_STATIC_CONSTRUCTOR (node
->symbol
.decl
) = 0;
784 DECL_STATIC_DESTRUCTOR (node
->symbol
.decl
) = 0;
787 /* Frontends and alias code marks nodes as needed before parsing is finished.
788 We may end up marking as node external nodes where this flag is meaningless
790 if (DECL_EXTERNAL (node
->symbol
.decl
) || !node
->symbol
.definition
)
792 node
->symbol
.force_output
= 0;
793 node
->symbol
.forced_by_abi
= 0;
796 /* C++ FE on lack of COMDAT support create local COMDAT functions
797 (that ought to be shared but can not due to object format
798 limitations). It is necessary to keep the flag to make rest of C++ FE
799 happy. Clear the flag here to avoid confusion in middle-end. */
800 if (DECL_COMDAT (node
->symbol
.decl
) && !TREE_PUBLIC (node
->symbol
.decl
))
801 DECL_COMDAT (node
->symbol
.decl
) = 0;
803 /* For external decls stop tracking same_comdat_group. It doesn't matter
804 what comdat group they are in when they won't be emitted in this TU. */
805 if (node
->symbol
.same_comdat_group
&& DECL_EXTERNAL (node
->symbol
.decl
))
807 #ifdef ENABLE_CHECKING
810 for (n
= node
->symbol
.same_comdat_group
;
811 n
!= (symtab_node
)node
;
812 n
= n
->symbol
.same_comdat_group
)
813 /* If at least one of same comdat group functions is external,
814 all of them have to be, otherwise it is a front-end bug. */
815 gcc_assert (DECL_EXTERNAL (n
->symbol
.decl
));
817 symtab_dissolve_same_comdat_group_list ((symtab_node
) node
);
819 gcc_assert ((!DECL_WEAK (node
->symbol
.decl
)
820 && !DECL_COMDAT (node
->symbol
.decl
))
821 || TREE_PUBLIC (node
->symbol
.decl
)
822 || node
->symbol
.weakref
823 || DECL_EXTERNAL (node
->symbol
.decl
));
824 if (cgraph_externally_visible_p (node
, whole_program
))
826 gcc_assert (!node
->global
.inlined_to
);
827 node
->symbol
.externally_visible
= true;
831 node
->symbol
.externally_visible
= false;
832 node
->symbol
.forced_by_abi
= false;
834 if (!node
->symbol
.externally_visible
835 && node
->symbol
.definition
&& !node
->symbol
.weakref
836 && !DECL_EXTERNAL (node
->symbol
.decl
))
838 gcc_assert (whole_program
|| in_lto_p
839 || !TREE_PUBLIC (node
->symbol
.decl
));
840 node
->symbol
.unique_name
= ((node
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
841 || node
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY_EXP
)
842 && TREE_PUBLIC (node
->symbol
.decl
));
843 symtab_make_decl_local (node
->symbol
.decl
);
844 node
->symbol
.resolution
= LDPR_PREVAILING_DEF_IRONLY
;
845 if (node
->symbol
.same_comdat_group
)
846 /* cgraph_externally_visible_p has already checked all other nodes
847 in the group and they will all be made local. We need to
848 dissolve the group at once so that the predicate does not
850 symtab_dissolve_same_comdat_group_list ((symtab_node
) node
);
853 if (node
->thunk
.thunk_p
854 && TREE_PUBLIC (node
->symbol
.decl
))
856 struct cgraph_node
*decl_node
= node
;
858 decl_node
= cgraph_function_node (decl_node
->callees
->callee
, NULL
);
860 /* Thunks have the same visibility as function they are attached to.
861 Make sure the C++ front end set this up properly. */
862 if (DECL_ONE_ONLY (decl_node
->symbol
.decl
))
864 gcc_checking_assert (DECL_COMDAT (node
->symbol
.decl
)
865 == DECL_COMDAT (decl_node
->symbol
.decl
));
866 gcc_checking_assert (DECL_COMDAT_GROUP (node
->symbol
.decl
)
867 == DECL_COMDAT_GROUP (decl_node
->symbol
.decl
));
868 gcc_checking_assert (node
->symbol
.same_comdat_group
);
870 if (DECL_EXTERNAL (decl_node
->symbol
.decl
))
871 DECL_EXTERNAL (node
->symbol
.decl
) = 1;
874 FOR_EACH_DEFINED_FUNCTION (node
)
875 node
->local
.local
= cgraph_local_node_p (node
);
876 FOR_EACH_VARIABLE (vnode
)
878 /* weak flag makes no sense on local variables. */
879 gcc_assert (!DECL_WEAK (vnode
->symbol
.decl
)
880 || vnode
->symbol
.weakref
881 || TREE_PUBLIC (vnode
->symbol
.decl
)
882 || DECL_EXTERNAL (vnode
->symbol
.decl
));
883 /* In several cases declarations can not be common:
885 - when declaration has initializer
887 - when it has specific section
888 - when it resides in non-generic address space.
889 - if declaration is local, it will get into .local common section
890 so common flag is not needed. Frontends still produce these in
891 certain cases, such as for:
893 static int a __attribute__ ((common))
895 Canonicalize things here and clear the redundant flag. */
896 if (DECL_COMMON (vnode
->symbol
.decl
)
897 && (!(TREE_PUBLIC (vnode
->symbol
.decl
)
898 || DECL_EXTERNAL (vnode
->symbol
.decl
))
899 || (DECL_INITIAL (vnode
->symbol
.decl
)
900 && DECL_INITIAL (vnode
->symbol
.decl
) != error_mark_node
)
901 || DECL_WEAK (vnode
->symbol
.decl
)
902 || DECL_SECTION_NAME (vnode
->symbol
.decl
) != NULL
903 || ! (ADDR_SPACE_GENERIC_P
904 (TYPE_ADDR_SPACE (TREE_TYPE (vnode
->symbol
.decl
))))))
905 DECL_COMMON (vnode
->symbol
.decl
) = 0;
907 FOR_EACH_DEFINED_VARIABLE (vnode
)
909 if (!vnode
->symbol
.definition
)
911 if (varpool_externally_visible_p (vnode
))
912 vnode
->symbol
.externally_visible
= true;
915 vnode
->symbol
.externally_visible
= false;
916 vnode
->symbol
.forced_by_abi
= false;
918 if (!vnode
->symbol
.externally_visible
919 && !vnode
->symbol
.weakref
)
921 gcc_assert (in_lto_p
|| whole_program
|| !TREE_PUBLIC (vnode
->symbol
.decl
));
922 symtab_make_decl_local (vnode
->symbol
.decl
);
923 vnode
->symbol
.unique_name
= ((vnode
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
924 || vnode
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY_EXP
)
925 && TREE_PUBLIC (vnode
->symbol
.decl
));
926 if (vnode
->symbol
.same_comdat_group
)
927 symtab_dissolve_same_comdat_group_list ((symtab_node
) vnode
);
928 vnode
->symbol
.resolution
= LDPR_PREVAILING_DEF_IRONLY
;
934 fprintf (dump_file
, "\nMarking local functions:");
935 FOR_EACH_DEFINED_FUNCTION (node
)
936 if (node
->local
.local
)
937 fprintf (dump_file
, " %s", cgraph_node_name (node
));
938 fprintf (dump_file
, "\n\n");
939 fprintf (dump_file
, "\nMarking externally visible functions:");
940 FOR_EACH_DEFINED_FUNCTION (node
)
941 if (node
->symbol
.externally_visible
)
942 fprintf (dump_file
, " %s", cgraph_node_name (node
));
943 fprintf (dump_file
, "\n\n");
944 fprintf (dump_file
, "\nMarking externally visible variables:");
945 FOR_EACH_DEFINED_VARIABLE (vnode
)
946 if (vnode
->symbol
.externally_visible
)
947 fprintf (dump_file
, " %s", varpool_node_name (vnode
));
948 fprintf (dump_file
, "\n\n");
950 cgraph_function_flags_ready
= true;
954 /* Local function pass handling visibilities. This happens before LTO streaming
955 so in particular -fwhole-program should be ignored at this level. */
958 local_function_and_variable_visibility (void)
960 return function_and_variable_visibility (flag_whole_program
&& !flag_lto
);
963 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility
=
967 "visibility", /* name */
968 OPTGROUP_NONE
, /* optinfo_flags */
970 local_function_and_variable_visibility
,/* execute */
973 0, /* static_pass_number */
974 TV_CGRAPHOPT
, /* tv_id */
975 0, /* properties_required */
976 0, /* properties_provided */
977 0, /* properties_destroyed */
978 0, /* todo_flags_start */
979 TODO_remove_functions
| TODO_dump_symtab
/* todo_flags_finish */
983 /* Free inline summary. */
986 free_inline_summary (void)
988 inline_free_summary ();
992 struct simple_ipa_opt_pass pass_ipa_free_inline_summary
=
996 "*free_inline_summary", /* name */
997 OPTGROUP_NONE
, /* optinfo_flags */
999 free_inline_summary
, /* execute */
1002 0, /* static_pass_number */
1003 TV_IPA_FREE_INLINE_SUMMARY
, /* tv_id */
1004 0, /* properties_required */
1005 0, /* properties_provided */
1006 0, /* properties_destroyed */
1007 0, /* todo_flags_start */
1008 0 /* todo_flags_finish */
1012 /* Do not re-run on ltrans stage. */
1015 gate_whole_program_function_and_variable_visibility (void)
1017 return !flag_ltrans
;
1020 /* Bring functionss local at LTO time with -fwhole-program. */
1023 whole_program_function_and_variable_visibility (void)
1025 function_and_variable_visibility (flag_whole_program
);
1027 ipa_discover_readonly_nonaddressable_vars ();
1031 struct ipa_opt_pass_d pass_ipa_whole_program_visibility
=
1035 "whole-program", /* name */
1036 OPTGROUP_NONE
, /* optinfo_flags */
1037 gate_whole_program_function_and_variable_visibility
,/* gate */
1038 whole_program_function_and_variable_visibility
,/* execute */
1041 0, /* static_pass_number */
1042 TV_CGRAPHOPT
, /* tv_id */
1043 0, /* properties_required */
1044 0, /* properties_provided */
1045 0, /* properties_destroyed */
1046 0, /* todo_flags_start */
1047 TODO_remove_functions
| TODO_dump_symtab
/* todo_flags_finish */
1049 NULL
, /* generate_summary */
1050 NULL
, /* write_summary */
1051 NULL
, /* read_summary */
1052 NULL
, /* write_optimization_summary */
1053 NULL
, /* read_optimization_summary */
1054 NULL
, /* stmt_fixup */
1056 NULL
, /* function_transform */
1057 NULL
, /* variable_transform */
1060 /* Entry in the histogram. */
1062 struct histogram_entry
1069 /* Histogram of profile values.
1070 The histogram is represented as an ordered vector of entries allocated via
1071 histogram_pool. During construction a separate hashtable is kept to lookup
1072 duplicate entries. */
1074 vec
<histogram_entry
*> histogram
;
1075 static alloc_pool histogram_pool
;
1077 /* Hashtable support for storing SSA names hashed by their SSA_NAME_VAR. */
1079 struct histogram_hash
: typed_noop_remove
<histogram_entry
>
1081 typedef histogram_entry value_type
;
1082 typedef histogram_entry compare_type
;
1083 static inline hashval_t
hash (const value_type
*);
1084 static inline int equal (const value_type
*, const compare_type
*);
1088 histogram_hash::hash (const histogram_entry
*val
)
1094 histogram_hash::equal (const histogram_entry
*val
, const histogram_entry
*val2
)
1096 return val
->count
== val2
->count
;
1099 /* Account TIME and SIZE executed COUNT times into HISTOGRAM.
1100 HASHTABLE is the on-side hash kept to avoid duplicates. */
1103 account_time_size (hash_table
<histogram_hash
> hashtable
,
1104 vec
<histogram_entry
*> &histogram
,
1105 gcov_type count
, int time
, int size
)
1107 histogram_entry key
= {count
, 0, 0};
1108 histogram_entry
**val
= hashtable
.find_slot (&key
, INSERT
);
1112 *val
= (histogram_entry
*) pool_alloc (histogram_pool
);
1114 histogram
.safe_push (*val
);
1116 (*val
)->time
+= time
;
1117 (*val
)->size
+= size
;
1121 cmp_counts (const void *v1
, const void *v2
)
1123 const histogram_entry
*h1
= *(const histogram_entry
* const *)v1
;
1124 const histogram_entry
*h2
= *(const histogram_entry
* const *)v2
;
1125 if (h1
->count
< h2
->count
)
1127 if (h1
->count
> h2
->count
)
1132 /* Dump HISTOGRAM to FILE. */
1135 dump_histogram (FILE *file
, vec
<histogram_entry
*> histogram
)
1138 gcov_type overall_time
= 0, cumulated_time
= 0, cumulated_size
= 0, overall_size
= 0;
1140 fprintf (dump_file
, "Histogram:\n");
1141 for (i
= 0; i
< histogram
.length (); i
++)
1143 overall_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1144 overall_size
+= histogram
[i
]->size
;
1150 for (i
= 0; i
< histogram
.length (); i
++)
1152 cumulated_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1153 cumulated_size
+= histogram
[i
]->size
;
1154 fprintf (file
, " "HOST_WIDEST_INT_PRINT_DEC
": time:%i (%2.2f) size:%i (%2.2f)\n",
1155 (HOST_WIDEST_INT
) histogram
[i
]->count
,
1157 cumulated_time
* 100.0 / overall_time
,
1159 cumulated_size
* 100.0 / overall_size
);
1163 /* Collect histogram from CFG profiles. */
1166 ipa_profile_generate_summary (void)
1168 struct cgraph_node
*node
;
1169 gimple_stmt_iterator gsi
;
1170 hash_table
<histogram_hash
> hashtable
;
1173 hashtable
.create (10);
1174 histogram_pool
= create_alloc_pool ("IPA histogram", sizeof (struct histogram_entry
),
1177 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
1178 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->symbol
.decl
))
1182 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1184 time
+= estimate_num_insns (gsi_stmt (gsi
), &eni_time_weights
);
1185 size
+= estimate_num_insns (gsi_stmt (gsi
), &eni_size_weights
);
1187 account_time_size (hashtable
, histogram
, bb
->count
, time
, size
);
1189 hashtable
.dispose ();
1190 histogram
.qsort (cmp_counts
);
1193 /* Serialize the ipa info for lto. */
1196 ipa_profile_write_summary (void)
1198 struct lto_simple_output_block
*ob
1199 = lto_create_simple_output_block (LTO_section_ipa_profile
);
1202 streamer_write_uhwi_stream (ob
->main_stream
, histogram
.length());
1203 for (i
= 0; i
< histogram
.length (); i
++)
1205 streamer_write_gcov_count_stream (ob
->main_stream
, histogram
[i
]->count
);
1206 streamer_write_uhwi_stream (ob
->main_stream
, histogram
[i
]->time
);
1207 streamer_write_uhwi_stream (ob
->main_stream
, histogram
[i
]->size
);
1209 lto_destroy_simple_output_block (ob
);
1212 /* Deserialize the ipa info for lto. */
1215 ipa_profile_read_summary (void)
1217 struct lto_file_decl_data
** file_data_vec
1218 = lto_get_file_decl_data ();
1219 struct lto_file_decl_data
* file_data
;
1220 hash_table
<histogram_hash
> hashtable
;
1223 hashtable
.create (10);
1224 histogram_pool
= create_alloc_pool ("IPA histogram", sizeof (struct histogram_entry
),
1227 while ((file_data
= file_data_vec
[j
++]))
1231 struct lto_input_block
*ib
1232 = lto_create_simple_input_block (file_data
,
1233 LTO_section_ipa_profile
,
1237 unsigned int num
= streamer_read_uhwi (ib
);
1239 for (n
= 0; n
< num
; n
++)
1241 gcov_type count
= streamer_read_gcov_count (ib
);
1242 int time
= streamer_read_uhwi (ib
);
1243 int size
= streamer_read_uhwi (ib
);
1244 account_time_size (hashtable
, histogram
,
1247 lto_destroy_simple_input_block (file_data
,
1248 LTO_section_ipa_profile
,
1252 hashtable
.dispose ();
1253 histogram
.qsort (cmp_counts
);
1256 /* Simple ipa profile pass propagating frequencies across the callgraph. */
1261 struct cgraph_node
**order
= XCNEWVEC (struct cgraph_node
*, cgraph_n_nodes
);
1262 struct cgraph_edge
*e
;
1264 bool something_changed
= false;
1266 gcov_type overall_time
= 0, cutoff
= 0, cumulated
= 0, overall_size
= 0;
1269 dump_histogram (dump_file
, histogram
);
1270 for (i
= 0; i
< (int)histogram
.length (); i
++)
1272 overall_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1273 overall_size
+= histogram
[i
]->size
;
1277 gcov_type threshold
;
1279 gcc_assert (overall_size
);
1282 gcov_type min
, cumulated_time
= 0, cumulated_size
= 0;
1284 fprintf (dump_file
, "Overall time: "HOST_WIDEST_INT_PRINT_DEC
"\n",
1285 (HOST_WIDEST_INT
)overall_time
);
1286 min
= get_hot_bb_threshold ();
1287 for (i
= 0; i
< (int)histogram
.length () && histogram
[i
]->count
>= min
;
1290 cumulated_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1291 cumulated_size
+= histogram
[i
]->size
;
1293 fprintf (dump_file
, "GCOV min count: "HOST_WIDEST_INT_PRINT_DEC
1294 " Time:%3.2f%% Size:%3.2f%%\n",
1295 (HOST_WIDEST_INT
)min
,
1296 cumulated_time
* 100.0 / overall_time
,
1297 cumulated_size
* 100.0 / overall_size
);
1299 cutoff
= (overall_time
* PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE
) + 500) / 1000;
1301 for (i
= 0; cumulated
< cutoff
; i
++)
1303 cumulated
+= histogram
[i
]->count
* histogram
[i
]->time
;
1304 threshold
= histogram
[i
]->count
;
1310 gcov_type cumulated_time
= 0, cumulated_size
= 0;
1313 i
< (int)histogram
.length () && histogram
[i
]->count
>= threshold
;
1316 cumulated_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1317 cumulated_size
+= histogram
[i
]->size
;
1319 fprintf (dump_file
, "Determined min count: "HOST_WIDEST_INT_PRINT_DEC
1320 " Time:%3.2f%% Size:%3.2f%%\n",
1321 (HOST_WIDEST_INT
)threshold
,
1322 cumulated_time
* 100.0 / overall_time
,
1323 cumulated_size
* 100.0 / overall_size
);
1325 if (threshold
> get_hot_bb_threshold ()
1329 fprintf (dump_file
, "Threshold updated.\n");
1330 set_hot_bb_threshold (threshold
);
1333 histogram
.release();
1334 free_alloc_pool (histogram_pool
);
1336 order_pos
= ipa_reverse_postorder (order
);
1337 for (i
= order_pos
- 1; i
>= 0; i
--)
1339 if (order
[i
]->local
.local
&& cgraph_propagate_frequency (order
[i
]))
1341 for (e
= order
[i
]->callees
; e
; e
= e
->next_callee
)
1342 if (e
->callee
->local
.local
&& !e
->callee
->symbol
.aux
)
1344 something_changed
= true;
1345 e
->callee
->symbol
.aux
= (void *)1;
1348 order
[i
]->symbol
.aux
= NULL
;
1351 while (something_changed
)
1353 something_changed
= false;
1354 for (i
= order_pos
- 1; i
>= 0; i
--)
1356 if (order
[i
]->symbol
.aux
&& cgraph_propagate_frequency (order
[i
]))
1358 for (e
= order
[i
]->callees
; e
; e
= e
->next_callee
)
1359 if (e
->callee
->local
.local
&& !e
->callee
->symbol
.aux
)
1361 something_changed
= true;
1362 e
->callee
->symbol
.aux
= (void *)1;
1365 order
[i
]->symbol
.aux
= NULL
;
1373 gate_ipa_profile (void)
1375 return flag_ipa_profile
;
1378 struct ipa_opt_pass_d pass_ipa_profile
=
1382 "profile_estimate", /* name */
1383 OPTGROUP_NONE
, /* optinfo_flags */
1384 gate_ipa_profile
, /* gate */
1385 ipa_profile
, /* execute */
1388 0, /* static_pass_number */
1389 TV_IPA_PROFILE
, /* tv_id */
1390 0, /* properties_required */
1391 0, /* properties_provided */
1392 0, /* properties_destroyed */
1393 0, /* todo_flags_start */
1394 0 /* todo_flags_finish */
1396 ipa_profile_generate_summary
, /* generate_summary */
1397 ipa_profile_write_summary
, /* write_summary */
1398 ipa_profile_read_summary
, /* read_summary */
1399 NULL
, /* write_optimization_summary */
1400 NULL
, /* read_optimization_summary */
1401 NULL
, /* stmt_fixup */
1403 NULL
, /* function_transform */
1404 NULL
/* variable_transform */
1407 /* Generate and emit a static constructor or destructor. WHICH must
1408 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1409 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1410 initialization priority for this constructor or destructor.
1412 FINAL specify whether the externally visible name for collect2 should
1416 cgraph_build_static_cdtor_1 (char which
, tree body
, int priority
, bool final
)
1418 static int counter
= 0;
1420 tree decl
, name
, resdecl
;
1422 /* The priority is encoded in the constructor or destructor name.
1423 collect2 will sort the names and arrange that they are called at
1426 sprintf (which_buf
, "%c_%.5d_%d", which
, priority
, counter
++);
1428 /* Proudce sane name but one not recognizable by collect2, just for the
1429 case we fail to inline the function. */
1430 sprintf (which_buf
, "sub_%c_%.5d_%d", which
, priority
, counter
++);
1431 name
= get_file_function_name (which_buf
);
1433 decl
= build_decl (input_location
, FUNCTION_DECL
, name
,
1434 build_function_type_list (void_type_node
, NULL_TREE
));
1435 current_function_decl
= decl
;
1437 resdecl
= build_decl (input_location
,
1438 RESULT_DECL
, NULL_TREE
, void_type_node
);
1439 DECL_ARTIFICIAL (resdecl
) = 1;
1440 DECL_RESULT (decl
) = resdecl
;
1441 DECL_CONTEXT (resdecl
) = decl
;
1443 allocate_struct_function (decl
, false);
1445 TREE_STATIC (decl
) = 1;
1446 TREE_USED (decl
) = 1;
1447 DECL_ARTIFICIAL (decl
) = 1;
1448 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl
) = 1;
1449 DECL_SAVED_TREE (decl
) = body
;
1450 if (!targetm
.have_ctors_dtors
&& final
)
1452 TREE_PUBLIC (decl
) = 1;
1453 DECL_PRESERVE_P (decl
) = 1;
1455 DECL_UNINLINABLE (decl
) = 1;
1457 DECL_INITIAL (decl
) = make_node (BLOCK
);
1458 TREE_USED (DECL_INITIAL (decl
)) = 1;
1460 DECL_SOURCE_LOCATION (decl
) = input_location
;
1461 cfun
->function_end_locus
= input_location
;
1466 DECL_STATIC_CONSTRUCTOR (decl
) = 1;
1467 decl_init_priority_insert (decl
, priority
);
1470 DECL_STATIC_DESTRUCTOR (decl
) = 1;
1471 decl_fini_priority_insert (decl
, priority
);
1477 gimplify_function_tree (decl
);
1479 cgraph_add_new_function (decl
, false);
1482 current_function_decl
= NULL
;
1485 /* Generate and emit a static constructor or destructor. WHICH must
1486 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1487 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1488 initialization priority for this constructor or destructor. */
1491 cgraph_build_static_cdtor (char which
, tree body
, int priority
)
1493 cgraph_build_static_cdtor_1 (which
, body
, priority
, false);
1496 /* A vector of FUNCTION_DECLs declared as static constructors. */
1497 static vec
<tree
> static_ctors
;
1498 /* A vector of FUNCTION_DECLs declared as static destructors. */
1499 static vec
<tree
> static_dtors
;
1501 /* When target does not have ctors and dtors, we call all constructor
1502 and destructor by special initialization/destruction function
1503 recognized by collect2.
1505 When we are going to build this function, collect all constructors and
1506 destructors and turn them into normal functions. */
1509 record_cdtor_fn (struct cgraph_node
*node
)
1511 if (DECL_STATIC_CONSTRUCTOR (node
->symbol
.decl
))
1512 static_ctors
.safe_push (node
->symbol
.decl
);
1513 if (DECL_STATIC_DESTRUCTOR (node
->symbol
.decl
))
1514 static_dtors
.safe_push (node
->symbol
.decl
);
1515 node
= cgraph_get_node (node
->symbol
.decl
);
1516 DECL_DISREGARD_INLINE_LIMITS (node
->symbol
.decl
) = 1;
1519 /* Define global constructors/destructor functions for the CDTORS, of
1520 which they are LEN. The CDTORS are sorted by initialization
1521 priority. If CTOR_P is true, these are constructors; otherwise,
1522 they are destructors. */
1525 build_cdtor (bool ctor_p
, vec
<tree
> cdtors
)
1528 size_t len
= cdtors
.length ();
1535 priority_type priority
;
1544 p
= ctor_p
? DECL_INIT_PRIORITY (fn
) : DECL_FINI_PRIORITY (fn
);
1547 else if (p
!= priority
)
1553 /* When there is only one cdtor and target supports them, do nothing. */
1555 && targetm
.have_ctors_dtors
)
1560 /* Find the next batch of constructors/destructors with the same
1561 initialization priority. */
1566 call
= build_call_expr (fn
, 0);
1568 DECL_STATIC_CONSTRUCTOR (fn
) = 0;
1570 DECL_STATIC_DESTRUCTOR (fn
) = 0;
1571 /* We do not want to optimize away pure/const calls here.
1572 When optimizing, these should be already removed, when not
1573 optimizing, we want user to be able to breakpoint in them. */
1574 TREE_SIDE_EFFECTS (call
) = 1;
1575 append_to_statement_list (call
, &body
);
1577 gcc_assert (body
!= NULL_TREE
);
1578 /* Generate a function to call all the function of like
1580 cgraph_build_static_cdtor_1 (ctor_p
? 'I' : 'D', body
, priority
, true);
1584 /* Comparison function for qsort. P1 and P2 are actually of type
1585 "tree *" and point to static constructors. DECL_INIT_PRIORITY is
1586 used to determine the sort order. */
1589 compare_ctor (const void *p1
, const void *p2
)
1596 f1
= *(const tree
*)p1
;
1597 f2
= *(const tree
*)p2
;
1598 priority1
= DECL_INIT_PRIORITY (f1
);
1599 priority2
= DECL_INIT_PRIORITY (f2
);
1601 if (priority1
< priority2
)
1603 else if (priority1
> priority2
)
1606 /* Ensure a stable sort. Constructors are executed in backwarding
1607 order to make LTO initialize braries first. */
1608 return DECL_UID (f2
) - DECL_UID (f1
);
1611 /* Comparison function for qsort. P1 and P2 are actually of type
1612 "tree *" and point to static destructors. DECL_FINI_PRIORITY is
1613 used to determine the sort order. */
1616 compare_dtor (const void *p1
, const void *p2
)
1623 f1
= *(const tree
*)p1
;
1624 f2
= *(const tree
*)p2
;
1625 priority1
= DECL_FINI_PRIORITY (f1
);
1626 priority2
= DECL_FINI_PRIORITY (f2
);
1628 if (priority1
< priority2
)
1630 else if (priority1
> priority2
)
1633 /* Ensure a stable sort. */
1634 return DECL_UID (f1
) - DECL_UID (f2
);
1637 /* Generate functions to call static constructors and destructors
1638 for targets that do not support .ctors/.dtors sections. These
1639 functions have magic names which are detected by collect2. */
1642 build_cdtor_fns (void)
1644 if (!static_ctors
.is_empty ())
1646 gcc_assert (!targetm
.have_ctors_dtors
|| in_lto_p
);
1647 static_ctors
.qsort (compare_ctor
);
1648 build_cdtor (/*ctor_p=*/true, static_ctors
);
1651 if (!static_dtors
.is_empty ())
1653 gcc_assert (!targetm
.have_ctors_dtors
|| in_lto_p
);
1654 static_dtors
.qsort (compare_dtor
);
1655 build_cdtor (/*ctor_p=*/false, static_dtors
);
1659 /* Look for constructors and destructors and produce function calling them.
1660 This is needed for targets not supporting ctors or dtors, but we perform the
1661 transformation also at linktime to merge possibly numerous
1662 constructors/destructors into single function to improve code locality and
1666 ipa_cdtor_merge (void)
1668 struct cgraph_node
*node
;
1669 FOR_EACH_DEFINED_FUNCTION (node
)
1670 if (DECL_STATIC_CONSTRUCTOR (node
->symbol
.decl
)
1671 || DECL_STATIC_DESTRUCTOR (node
->symbol
.decl
))
1672 record_cdtor_fn (node
);
1674 static_ctors
.release ();
1675 static_dtors
.release ();
1679 /* Perform the pass when we have no ctors/dtors support
1680 or at LTO time to merge multiple constructors into single
1684 gate_ipa_cdtor_merge (void)
1686 return !targetm
.have_ctors_dtors
|| (optimize
&& in_lto_p
);
1689 struct ipa_opt_pass_d pass_ipa_cdtor_merge
=
1694 OPTGROUP_NONE
, /* optinfo_flags */
1695 gate_ipa_cdtor_merge
, /* gate */
1696 ipa_cdtor_merge
, /* execute */
1699 0, /* static_pass_number */
1700 TV_CGRAPHOPT
, /* tv_id */
1701 0, /* properties_required */
1702 0, /* properties_provided */
1703 0, /* properties_destroyed */
1704 0, /* todo_flags_start */
1705 0 /* todo_flags_finish */
1707 NULL
, /* generate_summary */
1708 NULL
, /* write_summary */
1709 NULL
, /* read_summary */
1710 NULL
, /* write_optimization_summary */
1711 NULL
, /* read_optimization_summary */
1712 NULL
, /* stmt_fixup */
1714 NULL
, /* function_transform */
1715 NULL
/* variable_transform */