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_DEFINED_FUNCTION (node
)
238 if (!node
->global
.inlined_to
239 && !node
->symbol
.in_other_partition
240 && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node
)
241 /* Keep around virtual functions for possible devirtualization. */
242 || (before_inlining_p
243 && DECL_VIRTUAL_P (node
->symbol
.decl
))))
245 gcc_assert (!node
->global
.inlined_to
);
246 pointer_set_insert (reachable
, node
);
247 enqueue_node ((symtab_node
)node
, &first
, reachable
);
250 gcc_assert (!node
->symbol
.aux
);
252 /* Mark variables that are obviously needed. */
253 FOR_EACH_DEFINED_VARIABLE (vnode
)
254 if (!varpool_can_remove_if_no_refs (vnode
)
255 && !vnode
->symbol
.in_other_partition
)
257 pointer_set_insert (reachable
, vnode
);
258 enqueue_node ((symtab_node
)vnode
, &first
, reachable
);
261 /* Perform reachability analysis. */
262 while (first
!= (symtab_node
) (void *) 1)
264 bool in_boundary_p
= !pointer_set_contains (reachable
, first
);
265 symtab_node node
= first
;
267 first
= (symtab_node
)first
->symbol
.aux
;
269 /* If we are processing symbol in boundary, mark its AUX pointer for
270 possible later re-processing in enqueue_node. */
272 node
->symbol
.aux
= (void *)2;
275 /* If any symbol in a comdat group is reachable, force
276 all other in the same comdat group to be also reachable. */
277 if (node
->symbol
.same_comdat_group
)
280 for (next
= node
->symbol
.same_comdat_group
;
282 next
= next
->symbol
.same_comdat_group
)
283 if (!pointer_set_insert (reachable
, next
))
284 enqueue_node ((symtab_node
) next
, &first
, reachable
);
286 /* Mark references as reachable. */
287 process_references (&node
->symbol
.ref_list
, &first
,
288 before_inlining_p
, reachable
);
291 if (cgraph_node
*cnode
= dyn_cast
<cgraph_node
> (node
))
293 /* Mark the callees reachable unless they are direct calls to extern
294 inline functions we decided to not inline. */
297 struct cgraph_edge
*e
;
298 for (e
= cnode
->callees
; e
; e
= e
->next_callee
)
300 if (e
->callee
->symbol
.definition
301 && !e
->callee
->symbol
.in_other_partition
302 && (!e
->inline_failed
303 || !DECL_EXTERNAL (e
->callee
->symbol
.decl
)
304 || e
->callee
->symbol
.alias
305 || before_inlining_p
))
306 pointer_set_insert (reachable
, e
->callee
);
307 enqueue_node ((symtab_node
) e
->callee
, &first
, reachable
);
310 /* When inline clone exists, mark body to be preserved so when removing
311 offline copy of the function we don't kill it. */
312 if (cnode
->global
.inlined_to
)
313 pointer_set_insert (body_needed_for_clonning
, cnode
->symbol
.decl
);
315 /* For non-inline clones, force their origins to the boundary and ensure
316 that body is not removed. */
317 while (cnode
->clone_of
)
319 bool noninline
= cnode
->clone_of
->symbol
.decl
!= cnode
->symbol
.decl
;
320 cnode
= cnode
->clone_of
;
323 pointer_set_insert (body_needed_for_clonning
, cnode
->symbol
.decl
);
324 enqueue_node ((symtab_node
)cnode
, &first
, reachable
);
329 /* When we see constructor of external variable, keep referred nodes in the
330 boundary. This will also hold initializers of the external vars NODE
332 varpool_node
*vnode
= dyn_cast
<varpool_node
> (node
);
334 && DECL_EXTERNAL (node
->symbol
.decl
)
335 && !vnode
->symbol
.alias
339 for (int i
= 0; ipa_ref_list_reference_iterate (&node
->symbol
.ref_list
, i
, ref
); i
++)
340 enqueue_node (ref
->referred
, &first
, reachable
);
344 /* Remove unreachable functions. */
345 for (node
= cgraph_first_function (); node
; node
= next
)
347 next
= cgraph_next_function (node
);
349 /* If node is not needed at all, remove it. */
350 if (!node
->symbol
.aux
)
353 fprintf (file
, " %s", cgraph_node_name (node
));
354 cgraph_remove_node (node
);
357 /* If node is unreachable, remove its body. */
358 else if (!pointer_set_contains (reachable
, node
))
360 if (!pointer_set_contains (body_needed_for_clonning
, node
->symbol
.decl
))
361 cgraph_release_function_body (node
);
362 else if (!node
->clone_of
)
363 gcc_assert (DECL_RESULT (node
->symbol
.decl
));
364 if (node
->symbol
.definition
)
367 fprintf (file
, " %s", cgraph_node_name (node
));
368 cgraph_reset_node (node
);
373 gcc_assert (node
->clone_of
|| !cgraph_function_with_gimple_body_p (node
)
374 || DECL_RESULT (node
->symbol
.decl
));
377 /* Inline clones might be kept around so their materializing allows further
378 cloning. If the function the clone is inlined into is removed, we need
379 to turn it into normal cone. */
380 FOR_EACH_FUNCTION (node
)
382 if (node
->global
.inlined_to
385 gcc_assert (node
->clones
);
386 node
->global
.inlined_to
= NULL
;
387 update_inlined_to_pointer (node
, node
);
389 node
->symbol
.aux
= NULL
;
392 /* Remove unreachable variables. */
394 fprintf (file
, "\nReclaiming variables:");
395 for (vnode
= varpool_first_variable (); vnode
; vnode
= vnext
)
397 vnext
= varpool_next_variable (vnode
);
398 if (!vnode
->symbol
.aux
399 /* For can_refer_decl_in_current_unit_p we want to track for
400 all external variables if they are defined in other partition
402 && (!flag_ltrans
|| !DECL_EXTERNAL (vnode
->symbol
.decl
)))
405 fprintf (file
, " %s", varpool_node_name (vnode
));
406 varpool_remove_node (vnode
);
409 else if (!pointer_set_contains (reachable
, vnode
))
412 if (vnode
->symbol
.definition
)
415 fprintf (file
, " %s", varpool_node_name (vnode
));
418 vnode
->symbol
.definition
= false;
419 vnode
->symbol
.analyzed
= false;
420 vnode
->symbol
.aux
= NULL
;
422 /* Keep body if it may be useful for constant folding. */
423 if ((init
= ctor_for_folding (vnode
->symbol
.decl
)) == error_mark_node
)
424 varpool_remove_initializer (vnode
);
426 DECL_INITIAL (vnode
->symbol
.decl
) = init
;
427 ipa_remove_all_references (&vnode
->symbol
.ref_list
);
430 vnode
->symbol
.aux
= NULL
;
433 pointer_set_destroy (reachable
);
434 pointer_set_destroy (body_needed_for_clonning
);
436 /* Now update address_taken flags and try to promote functions to be local. */
438 fprintf (file
, "\nClearing address taken flags:");
439 FOR_EACH_DEFINED_FUNCTION (node
)
440 if (node
->symbol
.address_taken
441 && !node
->symbol
.used_from_other_partition
)
443 if (!cgraph_for_node_and_aliases (node
, has_addr_references_p
, NULL
, true))
446 fprintf (file
, " %s", cgraph_node_name (node
));
447 node
->symbol
.address_taken
= false;
449 if (cgraph_local_node_p (node
))
451 node
->local
.local
= true;
453 fprintf (file
, " (local)");
458 fprintf (file
, "\n");
460 #ifdef ENABLE_CHECKING
464 /* If we removed something, perhaps profile could be improved. */
465 if (changed
&& optimize
&& inline_edge_summary_vec
.exists ())
466 FOR_EACH_DEFINED_FUNCTION (node
)
467 cgraph_propagate_frequency (node
);
472 /* Discover variables that have no longer address taken or that are read only
473 and update their flags.
475 FIXME: This can not be done in between gimplify and omp_expand since
476 readonly flag plays role on what is shared and what is not. Currently we do
477 this transformation as part of whole program visibility and re-do at
478 ipa-reference pass (to take into account clonning), but it would
479 make sense to do it before early optimizations. */
482 ipa_discover_readonly_nonaddressable_vars (void)
484 struct varpool_node
*vnode
;
486 fprintf (dump_file
, "Clearing variable flags:");
487 FOR_EACH_VARIABLE (vnode
)
488 if (vnode
->symbol
.definition
&& varpool_all_refs_explicit_p (vnode
)
489 && (TREE_ADDRESSABLE (vnode
->symbol
.decl
)
490 || !TREE_READONLY (vnode
->symbol
.decl
)))
492 bool written
= false;
493 bool address_taken
= false;
496 for (i
= 0; ipa_ref_list_referring_iterate (&vnode
->symbol
.ref_list
,
498 && (!written
|| !address_taken
); i
++)
502 address_taken
= true;
510 if (TREE_ADDRESSABLE (vnode
->symbol
.decl
) && !address_taken
)
513 fprintf (dump_file
, " %s (addressable)", varpool_node_name (vnode
));
514 TREE_ADDRESSABLE (vnode
->symbol
.decl
) = 0;
516 if (!TREE_READONLY (vnode
->symbol
.decl
) && !address_taken
&& !written
517 /* Making variable in explicit section readonly can cause section
519 See e.g. gcc.c-torture/compile/pr23237.c */
520 && DECL_SECTION_NAME (vnode
->symbol
.decl
) == NULL
)
523 fprintf (dump_file
, " %s (read-only)", varpool_node_name (vnode
));
524 TREE_READONLY (vnode
->symbol
.decl
) = 1;
528 fprintf (dump_file
, "\n");
531 /* Return true when there is a reference to node and it is not vtable. */
533 address_taken_from_non_vtable_p (symtab_node node
)
537 for (i
= 0; ipa_ref_list_referring_iterate (&node
->symbol
.ref_list
,
539 if (ref
->use
== IPA_REF_ADDR
)
541 struct varpool_node
*node
;
542 if (is_a
<cgraph_node
> (ref
->referring
))
544 node
= ipa_ref_referring_varpool_node (ref
);
545 if (!DECL_VIRTUAL_P (node
->symbol
.decl
))
551 /* A helper for comdat_can_be_unshared_p. */
554 comdat_can_be_unshared_p_1 (symtab_node node
)
556 /* When address is taken, we don't know if equality comparison won't
557 break eventually. Exception are virutal functions and vtables,
558 where this is not possible by language standard. */
559 if (!DECL_VIRTUAL_P (node
->symbol
.decl
)
560 && address_taken_from_non_vtable_p (node
))
563 /* If the symbol is used in some weird way, better to not touch it. */
564 if (node
->symbol
.force_output
)
567 /* Explicit instantiations needs to be output when possibly
569 if (node
->symbol
.forced_by_abi
570 && TREE_PUBLIC (node
->symbol
.decl
)
571 && (node
->symbol
.resolution
!= LDPR_PREVAILING_DEF_IRONLY
572 && !flag_whole_program
))
575 /* Non-readonly and volatile variables can not be duplicated. */
576 if (is_a
<varpool_node
> (node
)
577 && (!TREE_READONLY (node
->symbol
.decl
)
578 || TREE_THIS_VOLATILE (node
->symbol
.decl
)))
583 /* COMDAT functions must be shared only if they have address taken,
584 otherwise we can produce our own private implementation with
586 Return true when turning COMDAT functoin static can not lead to wrong
587 code when the resulting object links with a library defining same COMDAT.
589 Virtual functions do have their addresses taken from the vtables,
590 but in C++ there is no way to compare their addresses for equality. */
593 comdat_can_be_unshared_p (symtab_node node
)
595 if (!comdat_can_be_unshared_p_1 (node
))
597 if (node
->symbol
.same_comdat_group
)
601 /* If more than one function is in the same COMDAT group, it must
602 be shared even if just one function in the comdat group has
604 for (next
= node
->symbol
.same_comdat_group
;
605 next
!= node
; next
= next
->symbol
.same_comdat_group
)
606 if (!comdat_can_be_unshared_p_1 (next
))
612 /* Return true when function NODE should be considered externally visible. */
615 cgraph_externally_visible_p (struct cgraph_node
*node
,
618 if (!node
->symbol
.definition
)
620 if (!TREE_PUBLIC (node
->symbol
.decl
)
621 || DECL_EXTERNAL (node
->symbol
.decl
))
624 /* Do not try to localize built-in functions yet. One of problems is that we
625 end up mangling their asm for WHOPR that makes it impossible to call them
626 using the implicit built-in declarations anymore. Similarly this enables
627 us to remove them as unreachable before actual calls may appear during
628 expansion or folding. */
629 if (DECL_BUILT_IN (node
->symbol
.decl
))
632 /* If linker counts on us, we must preserve the function. */
633 if (symtab_used_from_object_file_p ((symtab_node
) node
))
635 if (DECL_PRESERVE_P (node
->symbol
.decl
))
637 if (lookup_attribute ("externally_visible",
638 DECL_ATTRIBUTES (node
->symbol
.decl
)))
640 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
641 && lookup_attribute ("dllexport",
642 DECL_ATTRIBUTES (node
->symbol
.decl
)))
644 if (node
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
)
646 /* When doing LTO or whole program, we can bring COMDAT functoins static.
647 This improves code quality and we know we will duplicate them at most twice
648 (in the case that we are not using plugin and link with object file
649 implementing same COMDAT) */
650 if ((in_lto_p
|| whole_program
)
651 && DECL_COMDAT (node
->symbol
.decl
)
652 && comdat_can_be_unshared_p ((symtab_node
) node
))
655 /* When doing link time optimizations, hidden symbols become local. */
657 && (DECL_VISIBILITY (node
->symbol
.decl
) == VISIBILITY_HIDDEN
658 || DECL_VISIBILITY (node
->symbol
.decl
) == VISIBILITY_INTERNAL
)
659 /* Be sure that node is defined in IR file, not in other object
660 file. In that case we don't set used_from_other_object_file. */
661 && node
->symbol
.definition
)
663 else if (!whole_program
)
666 if (MAIN_NAME_P (DECL_NAME (node
->symbol
.decl
)))
672 /* Return true when variable VNODE should be considered externally visible. */
675 varpool_externally_visible_p (struct varpool_node
*vnode
)
677 if (DECL_EXTERNAL (vnode
->symbol
.decl
))
680 if (!TREE_PUBLIC (vnode
->symbol
.decl
))
683 /* If linker counts on us, we must preserve the function. */
684 if (symtab_used_from_object_file_p ((symtab_node
) vnode
))
687 if (DECL_HARD_REGISTER (vnode
->symbol
.decl
))
689 if (DECL_PRESERVE_P (vnode
->symbol
.decl
))
691 if (lookup_attribute ("externally_visible",
692 DECL_ATTRIBUTES (vnode
->symbol
.decl
)))
694 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
695 && lookup_attribute ("dllexport",
696 DECL_ATTRIBUTES (vnode
->symbol
.decl
)))
699 /* See if we have linker information about symbol not being used or
700 if we need to make guess based on the declaration.
702 Even if the linker clams the symbol is unused, never bring internal
703 symbols that are declared by user as used or externally visible.
704 This is needed for i.e. references from asm statements. */
705 if (symtab_used_from_object_file_p ((symtab_node
) vnode
))
707 if (vnode
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
)
710 /* As a special case, the COMDAT virtual tables can be unshared.
711 In LTO mode turn vtables into static variables. The variable is readonly,
712 so this does not enable more optimization, but referring static var
713 is faster for dynamic linking. Also this match logic hidding vtables
714 from LTO symbol tables. */
715 if ((in_lto_p
|| flag_whole_program
)
716 && DECL_COMDAT (vnode
->symbol
.decl
)
717 && comdat_can_be_unshared_p ((symtab_node
) vnode
))
720 /* When doing link time optimizations, hidden symbols become local. */
722 && (DECL_VISIBILITY (vnode
->symbol
.decl
) == VISIBILITY_HIDDEN
723 || DECL_VISIBILITY (vnode
->symbol
.decl
) == VISIBILITY_INTERNAL
)
724 /* Be sure that node is defined in IR file, not in other object
725 file. In that case we don't set used_from_other_object_file. */
726 && vnode
->symbol
.definition
)
728 else if (!flag_whole_program
)
731 /* Do not attempt to privatize COMDATS by default.
732 This would break linking with C++ libraries sharing
735 FIXME: We can do so for readonly vars with no address taken and
736 possibly also for vtables since no direct pointer comparsion is done.
737 It might be interesting to do so to reduce linking overhead. */
738 if (DECL_COMDAT (vnode
->symbol
.decl
) || DECL_WEAK (vnode
->symbol
.decl
))
743 /* Mark visibility of all functions.
745 A local function is one whose calls can occur only in the current
746 compilation unit and all its calls are explicit, so we can change
747 its calling convention. We simply mark all static functions whose
748 address is not taken as local.
750 We also change the TREE_PUBLIC flag of all declarations that are public
751 in language point of view but we want to overwrite this default
752 via visibilities for the backend point of view. */
755 function_and_variable_visibility (bool whole_program
)
757 struct cgraph_node
*node
;
758 struct varpool_node
*vnode
;
760 /* All aliases should be procssed at this point. */
761 gcc_checking_assert (!alias_pairs
|| !alias_pairs
->length());
763 FOR_EACH_FUNCTION (node
)
765 int flags
= flags_from_decl_or_type (node
->symbol
.decl
);
767 /* Optimize away PURE and CONST constructors and destructors. */
769 && (flags
& (ECF_CONST
| ECF_PURE
))
770 && !(flags
& ECF_LOOPING_CONST_OR_PURE
))
772 DECL_STATIC_CONSTRUCTOR (node
->symbol
.decl
) = 0;
773 DECL_STATIC_DESTRUCTOR (node
->symbol
.decl
) = 0;
776 /* Frontends and alias code marks nodes as needed before parsing is finished.
777 We may end up marking as node external nodes where this flag is meaningless
779 if (DECL_EXTERNAL (node
->symbol
.decl
) || !node
->symbol
.definition
)
781 node
->symbol
.force_output
= 0;
782 node
->symbol
.forced_by_abi
= 0;
785 /* C++ FE on lack of COMDAT support create local COMDAT functions
786 (that ought to be shared but can not due to object format
787 limitations). It is necessary to keep the flag to make rest of C++ FE
788 happy. Clear the flag here to avoid confusion in middle-end. */
789 if (DECL_COMDAT (node
->symbol
.decl
) && !TREE_PUBLIC (node
->symbol
.decl
))
790 DECL_COMDAT (node
->symbol
.decl
) = 0;
792 /* For external decls stop tracking same_comdat_group. It doesn't matter
793 what comdat group they are in when they won't be emitted in this TU. */
794 if (node
->symbol
.same_comdat_group
&& DECL_EXTERNAL (node
->symbol
.decl
))
796 #ifdef ENABLE_CHECKING
799 for (n
= node
->symbol
.same_comdat_group
;
800 n
!= (symtab_node
)node
;
801 n
= n
->symbol
.same_comdat_group
)
802 /* If at least one of same comdat group functions is external,
803 all of them have to be, otherwise it is a front-end bug. */
804 gcc_assert (DECL_EXTERNAL (n
->symbol
.decl
));
806 symtab_dissolve_same_comdat_group_list ((symtab_node
) node
);
808 gcc_assert ((!DECL_WEAK (node
->symbol
.decl
)
809 && !DECL_COMDAT (node
->symbol
.decl
))
810 || TREE_PUBLIC (node
->symbol
.decl
)
811 || node
->symbol
.weakref
812 || DECL_EXTERNAL (node
->symbol
.decl
));
813 if (cgraph_externally_visible_p (node
, whole_program
))
815 gcc_assert (!node
->global
.inlined_to
);
816 node
->symbol
.externally_visible
= true;
820 node
->symbol
.externally_visible
= false;
821 node
->symbol
.forced_by_abi
= false;
823 if (!node
->symbol
.externally_visible
824 && node
->symbol
.definition
&& !node
->symbol
.weakref
825 && !DECL_EXTERNAL (node
->symbol
.decl
))
827 gcc_assert (whole_program
|| in_lto_p
828 || !TREE_PUBLIC (node
->symbol
.decl
));
829 node
->symbol
.unique_name
= ((node
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
830 || node
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY_EXP
)
831 && TREE_PUBLIC (node
->symbol
.decl
));
832 symtab_make_decl_local (node
->symbol
.decl
);
833 node
->symbol
.resolution
= LDPR_PREVAILING_DEF_IRONLY
;
834 if (node
->symbol
.same_comdat_group
)
835 /* cgraph_externally_visible_p has already checked all other nodes
836 in the group and they will all be made local. We need to
837 dissolve the group at once so that the predicate does not
839 symtab_dissolve_same_comdat_group_list ((symtab_node
) node
);
842 if (node
->thunk
.thunk_p
843 && TREE_PUBLIC (node
->symbol
.decl
))
845 struct cgraph_node
*decl_node
= node
;
847 decl_node
= cgraph_function_node (decl_node
->callees
->callee
, NULL
);
849 /* Thunks have the same visibility as function they are attached to.
850 Make sure the C++ front end set this up properly. */
851 if (DECL_ONE_ONLY (decl_node
->symbol
.decl
))
853 gcc_checking_assert (DECL_COMDAT (node
->symbol
.decl
)
854 == DECL_COMDAT (decl_node
->symbol
.decl
));
855 gcc_checking_assert (DECL_COMDAT_GROUP (node
->symbol
.decl
)
856 == DECL_COMDAT_GROUP (decl_node
->symbol
.decl
));
857 gcc_checking_assert (node
->symbol
.same_comdat_group
);
859 if (DECL_EXTERNAL (decl_node
->symbol
.decl
))
860 DECL_EXTERNAL (node
->symbol
.decl
) = 1;
863 FOR_EACH_DEFINED_FUNCTION (node
)
864 node
->local
.local
= cgraph_local_node_p (node
);
865 FOR_EACH_VARIABLE (vnode
)
867 /* weak flag makes no sense on local variables. */
868 gcc_assert (!DECL_WEAK (vnode
->symbol
.decl
)
869 || vnode
->symbol
.weakref
870 || TREE_PUBLIC (vnode
->symbol
.decl
)
871 || DECL_EXTERNAL (vnode
->symbol
.decl
));
872 /* In several cases declarations can not be common:
874 - when declaration has initializer
876 - when it has specific section
877 - when it resides in non-generic address space.
878 - if declaration is local, it will get into .local common section
879 so common flag is not needed. Frontends still produce these in
880 certain cases, such as for:
882 static int a __attribute__ ((common))
884 Canonicalize things here and clear the redundant flag. */
885 if (DECL_COMMON (vnode
->symbol
.decl
)
886 && (!(TREE_PUBLIC (vnode
->symbol
.decl
)
887 || DECL_EXTERNAL (vnode
->symbol
.decl
))
888 || (DECL_INITIAL (vnode
->symbol
.decl
)
889 && DECL_INITIAL (vnode
->symbol
.decl
) != error_mark_node
)
890 || DECL_WEAK (vnode
->symbol
.decl
)
891 || DECL_SECTION_NAME (vnode
->symbol
.decl
) != NULL
892 || ! (ADDR_SPACE_GENERIC_P
893 (TYPE_ADDR_SPACE (TREE_TYPE (vnode
->symbol
.decl
))))))
894 DECL_COMMON (vnode
->symbol
.decl
) = 0;
896 FOR_EACH_DEFINED_VARIABLE (vnode
)
898 if (!vnode
->symbol
.definition
)
900 if (varpool_externally_visible_p (vnode
))
901 vnode
->symbol
.externally_visible
= true;
904 vnode
->symbol
.externally_visible
= false;
905 vnode
->symbol
.forced_by_abi
= false;
907 if (!vnode
->symbol
.externally_visible
908 && !vnode
->symbol
.weakref
)
910 gcc_assert (in_lto_p
|| whole_program
|| !TREE_PUBLIC (vnode
->symbol
.decl
));
911 symtab_make_decl_local (vnode
->symbol
.decl
);
912 vnode
->symbol
.unique_name
= ((vnode
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
913 || vnode
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY_EXP
)
914 && TREE_PUBLIC (vnode
->symbol
.decl
));
915 if (vnode
->symbol
.same_comdat_group
)
916 symtab_dissolve_same_comdat_group_list ((symtab_node
) vnode
);
917 vnode
->symbol
.resolution
= LDPR_PREVAILING_DEF_IRONLY
;
923 fprintf (dump_file
, "\nMarking local functions:");
924 FOR_EACH_DEFINED_FUNCTION (node
)
925 if (node
->local
.local
)
926 fprintf (dump_file
, " %s", cgraph_node_name (node
));
927 fprintf (dump_file
, "\n\n");
928 fprintf (dump_file
, "\nMarking externally visible functions:");
929 FOR_EACH_DEFINED_FUNCTION (node
)
930 if (node
->symbol
.externally_visible
)
931 fprintf (dump_file
, " %s", cgraph_node_name (node
));
932 fprintf (dump_file
, "\n\n");
933 fprintf (dump_file
, "\nMarking externally visible variables:");
934 FOR_EACH_DEFINED_VARIABLE (vnode
)
935 if (vnode
->symbol
.externally_visible
)
936 fprintf (dump_file
, " %s", varpool_node_name (vnode
));
937 fprintf (dump_file
, "\n\n");
939 cgraph_function_flags_ready
= true;
943 /* Local function pass handling visibilities. This happens before LTO streaming
944 so in particular -fwhole-program should be ignored at this level. */
947 local_function_and_variable_visibility (void)
949 return function_and_variable_visibility (flag_whole_program
&& !flag_lto
);
952 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility
=
956 "visibility", /* name */
957 OPTGROUP_NONE
, /* optinfo_flags */
959 local_function_and_variable_visibility
,/* execute */
962 0, /* static_pass_number */
963 TV_CGRAPHOPT
, /* tv_id */
964 0, /* properties_required */
965 0, /* properties_provided */
966 0, /* properties_destroyed */
967 0, /* todo_flags_start */
968 TODO_remove_functions
| TODO_dump_symtab
/* todo_flags_finish */
972 /* Free inline summary. */
975 free_inline_summary (void)
977 inline_free_summary ();
981 struct simple_ipa_opt_pass pass_ipa_free_inline_summary
=
985 "*free_inline_summary", /* name */
986 OPTGROUP_NONE
, /* optinfo_flags */
988 free_inline_summary
, /* execute */
991 0, /* static_pass_number */
992 TV_IPA_FREE_INLINE_SUMMARY
, /* tv_id */
993 0, /* properties_required */
994 0, /* properties_provided */
995 0, /* properties_destroyed */
996 0, /* todo_flags_start */
997 0 /* todo_flags_finish */
1001 /* Do not re-run on ltrans stage. */
1004 gate_whole_program_function_and_variable_visibility (void)
1006 return !flag_ltrans
;
1009 /* Bring functionss local at LTO time with -fwhole-program. */
1012 whole_program_function_and_variable_visibility (void)
1014 function_and_variable_visibility (flag_whole_program
);
1016 ipa_discover_readonly_nonaddressable_vars ();
1020 struct ipa_opt_pass_d pass_ipa_whole_program_visibility
=
1024 "whole-program", /* name */
1025 OPTGROUP_NONE
, /* optinfo_flags */
1026 gate_whole_program_function_and_variable_visibility
,/* gate */
1027 whole_program_function_and_variable_visibility
,/* execute */
1030 0, /* static_pass_number */
1031 TV_CGRAPHOPT
, /* tv_id */
1032 0, /* properties_required */
1033 0, /* properties_provided */
1034 0, /* properties_destroyed */
1035 0, /* todo_flags_start */
1036 TODO_remove_functions
| TODO_dump_symtab
/* todo_flags_finish */
1038 NULL
, /* generate_summary */
1039 NULL
, /* write_summary */
1040 NULL
, /* read_summary */
1041 NULL
, /* write_optimization_summary */
1042 NULL
, /* read_optimization_summary */
1043 NULL
, /* stmt_fixup */
1045 NULL
, /* function_transform */
1046 NULL
, /* variable_transform */
1049 /* Entry in the histogram. */
1051 struct histogram_entry
1058 /* Histogram of profile values.
1059 The histogram is represented as an ordered vector of entries allocated via
1060 histogram_pool. During construction a separate hashtable is kept to lookup
1061 duplicate entries. */
1063 vec
<histogram_entry
*> histogram
;
1064 static alloc_pool histogram_pool
;
1066 /* Hashtable support for storing SSA names hashed by their SSA_NAME_VAR. */
1068 struct histogram_hash
: typed_noop_remove
<histogram_entry
>
1070 typedef histogram_entry value_type
;
1071 typedef histogram_entry compare_type
;
1072 static inline hashval_t
hash (const value_type
*);
1073 static inline int equal (const value_type
*, const compare_type
*);
1077 histogram_hash::hash (const histogram_entry
*val
)
1083 histogram_hash::equal (const histogram_entry
*val
, const histogram_entry
*val2
)
1085 return val
->count
== val2
->count
;
1088 /* Account TIME and SIZE executed COUNT times into HISTOGRAM.
1089 HASHTABLE is the on-side hash kept to avoid duplicates. */
1092 account_time_size (hash_table
<histogram_hash
> hashtable
,
1093 vec
<histogram_entry
*> &histogram
,
1094 gcov_type count
, int time
, int size
)
1096 histogram_entry key
= {count
, 0, 0};
1097 histogram_entry
**val
= hashtable
.find_slot (&key
, INSERT
);
1101 *val
= (histogram_entry
*) pool_alloc (histogram_pool
);
1103 histogram
.safe_push (*val
);
1105 (*val
)->time
+= time
;
1106 (*val
)->size
+= size
;
1110 cmp_counts (const void *v1
, const void *v2
)
1112 const histogram_entry
*h1
= *(const histogram_entry
* const *)v1
;
1113 const histogram_entry
*h2
= *(const histogram_entry
* const *)v2
;
1114 if (h1
->count
< h2
->count
)
1116 if (h1
->count
> h2
->count
)
1121 /* Dump HISTOGRAM to FILE. */
1124 dump_histogram (FILE *file
, vec
<histogram_entry
*> histogram
)
1127 gcov_type overall_time
= 0, cumulated_time
= 0, cumulated_size
= 0, overall_size
= 0;
1129 fprintf (dump_file
, "Histogram:\n");
1130 for (i
= 0; i
< histogram
.length (); i
++)
1132 overall_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1133 overall_size
+= histogram
[i
]->size
;
1139 for (i
= 0; i
< histogram
.length (); i
++)
1141 cumulated_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1142 cumulated_size
+= histogram
[i
]->size
;
1143 fprintf (file
, " "HOST_WIDEST_INT_PRINT_DEC
": time:%i (%2.2f) size:%i (%2.2f)\n",
1144 (HOST_WIDEST_INT
) histogram
[i
]->count
,
1146 cumulated_time
* 100.0 / overall_time
,
1148 cumulated_size
* 100.0 / overall_size
);
1152 /* Collect histogram from CFG profiles. */
1155 ipa_profile_generate_summary (void)
1157 struct cgraph_node
*node
;
1158 gimple_stmt_iterator gsi
;
1159 hash_table
<histogram_hash
> hashtable
;
1162 hashtable
.create (10);
1163 histogram_pool
= create_alloc_pool ("IPA histogram", sizeof (struct histogram_entry
),
1166 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
1167 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->symbol
.decl
))
1171 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1173 time
+= estimate_num_insns (gsi_stmt (gsi
), &eni_time_weights
);
1174 size
+= estimate_num_insns (gsi_stmt (gsi
), &eni_size_weights
);
1176 account_time_size (hashtable
, histogram
, bb
->count
, time
, size
);
1178 hashtable
.dispose ();
1179 histogram
.qsort (cmp_counts
);
1182 /* Serialize the ipa info for lto. */
1185 ipa_profile_write_summary (void)
1187 struct lto_simple_output_block
*ob
1188 = lto_create_simple_output_block (LTO_section_ipa_profile
);
1191 streamer_write_uhwi_stream (ob
->main_stream
, histogram
.length());
1192 for (i
= 0; i
< histogram
.length (); i
++)
1194 streamer_write_gcov_count_stream (ob
->main_stream
, histogram
[i
]->count
);
1195 streamer_write_uhwi_stream (ob
->main_stream
, histogram
[i
]->time
);
1196 streamer_write_uhwi_stream (ob
->main_stream
, histogram
[i
]->size
);
1198 lto_destroy_simple_output_block (ob
);
1201 /* Deserialize the ipa info for lto. */
1204 ipa_profile_read_summary (void)
1206 struct lto_file_decl_data
** file_data_vec
1207 = lto_get_file_decl_data ();
1208 struct lto_file_decl_data
* file_data
;
1209 hash_table
<histogram_hash
> hashtable
;
1212 hashtable
.create (10);
1213 histogram_pool
= create_alloc_pool ("IPA histogram", sizeof (struct histogram_entry
),
1216 while ((file_data
= file_data_vec
[j
++]))
1220 struct lto_input_block
*ib
1221 = lto_create_simple_input_block (file_data
,
1222 LTO_section_ipa_profile
,
1226 unsigned int num
= streamer_read_uhwi (ib
);
1228 for (n
= 0; n
< num
; n
++)
1230 gcov_type count
= streamer_read_gcov_count (ib
);
1231 int time
= streamer_read_uhwi (ib
);
1232 int size
= streamer_read_uhwi (ib
);
1233 account_time_size (hashtable
, histogram
,
1236 lto_destroy_simple_input_block (file_data
,
1237 LTO_section_ipa_profile
,
1241 hashtable
.dispose ();
1242 histogram
.qsort (cmp_counts
);
1245 /* Simple ipa profile pass propagating frequencies across the callgraph. */
1250 struct cgraph_node
**order
= XCNEWVEC (struct cgraph_node
*, cgraph_n_nodes
);
1251 struct cgraph_edge
*e
;
1253 bool something_changed
= false;
1255 gcov_type overall_time
= 0, cutoff
= 0, cumulated
= 0, overall_size
= 0;
1258 dump_histogram (dump_file
, histogram
);
1259 for (i
= 0; i
< (int)histogram
.length (); i
++)
1261 overall_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1262 overall_size
+= histogram
[i
]->size
;
1266 gcov_type threshold
;
1268 gcc_assert (overall_size
);
1271 gcov_type min
, cumulated_time
= 0, cumulated_size
= 0;
1273 fprintf (dump_file
, "Overall time: "HOST_WIDEST_INT_PRINT_DEC
"\n",
1274 (HOST_WIDEST_INT
)overall_time
);
1275 min
= get_hot_bb_threshold ();
1276 for (i
= 0; i
< (int)histogram
.length () && histogram
[i
]->count
>= min
;
1279 cumulated_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1280 cumulated_size
+= histogram
[i
]->size
;
1282 fprintf (dump_file
, "GCOV min count: "HOST_WIDEST_INT_PRINT_DEC
1283 " Time:%3.2f%% Size:%3.2f%%\n",
1284 (HOST_WIDEST_INT
)min
,
1285 cumulated_time
* 100.0 / overall_time
,
1286 cumulated_size
* 100.0 / overall_size
);
1288 cutoff
= (overall_time
* PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE
) + 500) / 1000;
1290 for (i
= 0; cumulated
< cutoff
; i
++)
1292 cumulated
+= histogram
[i
]->count
* histogram
[i
]->time
;
1293 threshold
= histogram
[i
]->count
;
1299 gcov_type cumulated_time
= 0, cumulated_size
= 0;
1302 i
< (int)histogram
.length () && histogram
[i
]->count
>= threshold
;
1305 cumulated_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1306 cumulated_size
+= histogram
[i
]->size
;
1308 fprintf (dump_file
, "Determined min count: "HOST_WIDEST_INT_PRINT_DEC
1309 " Time:%3.2f%% Size:%3.2f%%\n",
1310 (HOST_WIDEST_INT
)threshold
,
1311 cumulated_time
* 100.0 / overall_time
,
1312 cumulated_size
* 100.0 / overall_size
);
1314 if (threshold
> get_hot_bb_threshold ()
1318 fprintf (dump_file
, "Threshold updated.\n");
1319 set_hot_bb_threshold (threshold
);
1322 histogram
.release();
1323 free_alloc_pool (histogram_pool
);
1325 order_pos
= ipa_reverse_postorder (order
);
1326 for (i
= order_pos
- 1; i
>= 0; i
--)
1328 if (order
[i
]->local
.local
&& cgraph_propagate_frequency (order
[i
]))
1330 for (e
= order
[i
]->callees
; e
; e
= e
->next_callee
)
1331 if (e
->callee
->local
.local
&& !e
->callee
->symbol
.aux
)
1333 something_changed
= true;
1334 e
->callee
->symbol
.aux
= (void *)1;
1337 order
[i
]->symbol
.aux
= NULL
;
1340 while (something_changed
)
1342 something_changed
= false;
1343 for (i
= order_pos
- 1; i
>= 0; i
--)
1345 if (order
[i
]->symbol
.aux
&& cgraph_propagate_frequency (order
[i
]))
1347 for (e
= order
[i
]->callees
; e
; e
= e
->next_callee
)
1348 if (e
->callee
->local
.local
&& !e
->callee
->symbol
.aux
)
1350 something_changed
= true;
1351 e
->callee
->symbol
.aux
= (void *)1;
1354 order
[i
]->symbol
.aux
= NULL
;
1362 gate_ipa_profile (void)
1364 return flag_ipa_profile
;
1367 struct ipa_opt_pass_d pass_ipa_profile
=
1371 "profile_estimate", /* name */
1372 OPTGROUP_NONE
, /* optinfo_flags */
1373 gate_ipa_profile
, /* gate */
1374 ipa_profile
, /* execute */
1377 0, /* static_pass_number */
1378 TV_IPA_PROFILE
, /* tv_id */
1379 0, /* properties_required */
1380 0, /* properties_provided */
1381 0, /* properties_destroyed */
1382 0, /* todo_flags_start */
1383 0 /* todo_flags_finish */
1385 ipa_profile_generate_summary
, /* generate_summary */
1386 ipa_profile_write_summary
, /* write_summary */
1387 ipa_profile_read_summary
, /* read_summary */
1388 NULL
, /* write_optimization_summary */
1389 NULL
, /* read_optimization_summary */
1390 NULL
, /* stmt_fixup */
1392 NULL
, /* function_transform */
1393 NULL
/* variable_transform */
1396 /* Generate and emit a static constructor or destructor. WHICH must
1397 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1398 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1399 initialization priority for this constructor or destructor.
1401 FINAL specify whether the externally visible name for collect2 should
1405 cgraph_build_static_cdtor_1 (char which
, tree body
, int priority
, bool final
)
1407 static int counter
= 0;
1409 tree decl
, name
, resdecl
;
1411 /* The priority is encoded in the constructor or destructor name.
1412 collect2 will sort the names and arrange that they are called at
1415 sprintf (which_buf
, "%c_%.5d_%d", which
, priority
, counter
++);
1417 /* Proudce sane name but one not recognizable by collect2, just for the
1418 case we fail to inline the function. */
1419 sprintf (which_buf
, "sub_%c_%.5d_%d", which
, priority
, counter
++);
1420 name
= get_file_function_name (which_buf
);
1422 decl
= build_decl (input_location
, FUNCTION_DECL
, name
,
1423 build_function_type_list (void_type_node
, NULL_TREE
));
1424 current_function_decl
= decl
;
1426 resdecl
= build_decl (input_location
,
1427 RESULT_DECL
, NULL_TREE
, void_type_node
);
1428 DECL_ARTIFICIAL (resdecl
) = 1;
1429 DECL_RESULT (decl
) = resdecl
;
1430 DECL_CONTEXT (resdecl
) = decl
;
1432 allocate_struct_function (decl
, false);
1434 TREE_STATIC (decl
) = 1;
1435 TREE_USED (decl
) = 1;
1436 DECL_ARTIFICIAL (decl
) = 1;
1437 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl
) = 1;
1438 DECL_SAVED_TREE (decl
) = body
;
1439 if (!targetm
.have_ctors_dtors
&& final
)
1441 TREE_PUBLIC (decl
) = 1;
1442 DECL_PRESERVE_P (decl
) = 1;
1444 DECL_UNINLINABLE (decl
) = 1;
1446 DECL_INITIAL (decl
) = make_node (BLOCK
);
1447 TREE_USED (DECL_INITIAL (decl
)) = 1;
1449 DECL_SOURCE_LOCATION (decl
) = input_location
;
1450 cfun
->function_end_locus
= input_location
;
1455 DECL_STATIC_CONSTRUCTOR (decl
) = 1;
1456 decl_init_priority_insert (decl
, priority
);
1459 DECL_STATIC_DESTRUCTOR (decl
) = 1;
1460 decl_fini_priority_insert (decl
, priority
);
1466 gimplify_function_tree (decl
);
1468 cgraph_add_new_function (decl
, false);
1471 current_function_decl
= NULL
;
1474 /* Generate and emit a static constructor or destructor. WHICH must
1475 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1476 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1477 initialization priority for this constructor or destructor. */
1480 cgraph_build_static_cdtor (char which
, tree body
, int priority
)
1482 cgraph_build_static_cdtor_1 (which
, body
, priority
, false);
1485 /* A vector of FUNCTION_DECLs declared as static constructors. */
1486 static vec
<tree
> static_ctors
;
1487 /* A vector of FUNCTION_DECLs declared as static destructors. */
1488 static vec
<tree
> static_dtors
;
1490 /* When target does not have ctors and dtors, we call all constructor
1491 and destructor by special initialization/destruction function
1492 recognized by collect2.
1494 When we are going to build this function, collect all constructors and
1495 destructors and turn them into normal functions. */
1498 record_cdtor_fn (struct cgraph_node
*node
)
1500 if (DECL_STATIC_CONSTRUCTOR (node
->symbol
.decl
))
1501 static_ctors
.safe_push (node
->symbol
.decl
);
1502 if (DECL_STATIC_DESTRUCTOR (node
->symbol
.decl
))
1503 static_dtors
.safe_push (node
->symbol
.decl
);
1504 node
= cgraph_get_node (node
->symbol
.decl
);
1505 DECL_DISREGARD_INLINE_LIMITS (node
->symbol
.decl
) = 1;
1508 /* Define global constructors/destructor functions for the CDTORS, of
1509 which they are LEN. The CDTORS are sorted by initialization
1510 priority. If CTOR_P is true, these are constructors; otherwise,
1511 they are destructors. */
1514 build_cdtor (bool ctor_p
, vec
<tree
> cdtors
)
1517 size_t len
= cdtors
.length ();
1524 priority_type priority
;
1533 p
= ctor_p
? DECL_INIT_PRIORITY (fn
) : DECL_FINI_PRIORITY (fn
);
1536 else if (p
!= priority
)
1542 /* When there is only one cdtor and target supports them, do nothing. */
1544 && targetm
.have_ctors_dtors
)
1549 /* Find the next batch of constructors/destructors with the same
1550 initialization priority. */
1555 call
= build_call_expr (fn
, 0);
1557 DECL_STATIC_CONSTRUCTOR (fn
) = 0;
1559 DECL_STATIC_DESTRUCTOR (fn
) = 0;
1560 /* We do not want to optimize away pure/const calls here.
1561 When optimizing, these should be already removed, when not
1562 optimizing, we want user to be able to breakpoint in them. */
1563 TREE_SIDE_EFFECTS (call
) = 1;
1564 append_to_statement_list (call
, &body
);
1566 gcc_assert (body
!= NULL_TREE
);
1567 /* Generate a function to call all the function of like
1569 cgraph_build_static_cdtor_1 (ctor_p
? 'I' : 'D', body
, priority
, true);
1573 /* Comparison function for qsort. P1 and P2 are actually of type
1574 "tree *" and point to static constructors. DECL_INIT_PRIORITY is
1575 used to determine the sort order. */
1578 compare_ctor (const void *p1
, const void *p2
)
1585 f1
= *(const tree
*)p1
;
1586 f2
= *(const tree
*)p2
;
1587 priority1
= DECL_INIT_PRIORITY (f1
);
1588 priority2
= DECL_INIT_PRIORITY (f2
);
1590 if (priority1
< priority2
)
1592 else if (priority1
> priority2
)
1595 /* Ensure a stable sort. Constructors are executed in backwarding
1596 order to make LTO initialize braries first. */
1597 return DECL_UID (f2
) - DECL_UID (f1
);
1600 /* Comparison function for qsort. P1 and P2 are actually of type
1601 "tree *" and point to static destructors. DECL_FINI_PRIORITY is
1602 used to determine the sort order. */
1605 compare_dtor (const void *p1
, const void *p2
)
1612 f1
= *(const tree
*)p1
;
1613 f2
= *(const tree
*)p2
;
1614 priority1
= DECL_FINI_PRIORITY (f1
);
1615 priority2
= DECL_FINI_PRIORITY (f2
);
1617 if (priority1
< priority2
)
1619 else if (priority1
> priority2
)
1622 /* Ensure a stable sort. */
1623 return DECL_UID (f1
) - DECL_UID (f2
);
1626 /* Generate functions to call static constructors and destructors
1627 for targets that do not support .ctors/.dtors sections. These
1628 functions have magic names which are detected by collect2. */
1631 build_cdtor_fns (void)
1633 if (!static_ctors
.is_empty ())
1635 gcc_assert (!targetm
.have_ctors_dtors
|| in_lto_p
);
1636 static_ctors
.qsort (compare_ctor
);
1637 build_cdtor (/*ctor_p=*/true, static_ctors
);
1640 if (!static_dtors
.is_empty ())
1642 gcc_assert (!targetm
.have_ctors_dtors
|| in_lto_p
);
1643 static_dtors
.qsort (compare_dtor
);
1644 build_cdtor (/*ctor_p=*/false, static_dtors
);
1648 /* Look for constructors and destructors and produce function calling them.
1649 This is needed for targets not supporting ctors or dtors, but we perform the
1650 transformation also at linktime to merge possibly numerous
1651 constructors/destructors into single function to improve code locality and
1655 ipa_cdtor_merge (void)
1657 struct cgraph_node
*node
;
1658 FOR_EACH_DEFINED_FUNCTION (node
)
1659 if (DECL_STATIC_CONSTRUCTOR (node
->symbol
.decl
)
1660 || DECL_STATIC_DESTRUCTOR (node
->symbol
.decl
))
1661 record_cdtor_fn (node
);
1663 static_ctors
.release ();
1664 static_dtors
.release ();
1668 /* Perform the pass when we have no ctors/dtors support
1669 or at LTO time to merge multiple constructors into single
1673 gate_ipa_cdtor_merge (void)
1675 return !targetm
.have_ctors_dtors
|| (optimize
&& in_lto_p
);
1678 struct ipa_opt_pass_d pass_ipa_cdtor_merge
=
1683 OPTGROUP_NONE
, /* optinfo_flags */
1684 gate_ipa_cdtor_merge
, /* gate */
1685 ipa_cdtor_merge
, /* execute */
1688 0, /* static_pass_number */
1689 TV_CGRAPHOPT
, /* tv_id */
1690 0, /* properties_required */
1691 0, /* properties_provided */
1692 0, /* properties_destroyed */
1693 0, /* todo_flags_start */
1694 0 /* todo_flags_finish */
1696 NULL
, /* generate_summary */
1697 NULL
, /* write_summary */
1698 NULL
, /* read_summary */
1699 NULL
, /* write_optimization_summary */
1700 NULL
, /* read_optimization_summary */
1701 NULL
, /* stmt_fixup */
1703 NULL
, /* function_transform */
1704 NULL
/* variable_transform */