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 (in_lto_p
|| DECL_RESULT (node
->symbol
.decl
));
375 if (node
->symbol
.definition
)
378 fprintf (file
, " %s", cgraph_node_name (node
));
379 node
->symbol
.analyzed
= false;
380 node
->symbol
.definition
= false;
381 node
->symbol
.cpp_implicit_alias
= false;
382 node
->symbol
.alias
= false;
383 node
->symbol
.weakref
= false;
384 if (!node
->symbol
.in_other_partition
)
385 node
->local
.local
= false;
386 cgraph_node_remove_callees (node
);
387 ipa_remove_all_references (&node
->symbol
.ref_list
);
392 gcc_assert (node
->clone_of
|| !cgraph_function_with_gimple_body_p (node
)
393 || in_lto_p
|| DECL_RESULT (node
->symbol
.decl
));
396 /* Inline clones might be kept around so their materializing allows further
397 cloning. If the function the clone is inlined into is removed, we need
398 to turn it into normal cone. */
399 FOR_EACH_FUNCTION (node
)
401 if (node
->global
.inlined_to
404 gcc_assert (node
->clones
);
405 node
->global
.inlined_to
= NULL
;
406 update_inlined_to_pointer (node
, node
);
408 node
->symbol
.aux
= NULL
;
411 /* Remove unreachable variables. */
413 fprintf (file
, "\nReclaiming variables:");
414 for (vnode
= varpool_first_variable (); vnode
; vnode
= vnext
)
416 vnext
= varpool_next_variable (vnode
);
417 if (!vnode
->symbol
.aux
418 /* For can_refer_decl_in_current_unit_p we want to track for
419 all external variables if they are defined in other partition
421 && (!flag_ltrans
|| !DECL_EXTERNAL (vnode
->symbol
.decl
)))
424 fprintf (file
, " %s", varpool_node_name (vnode
));
425 varpool_remove_node (vnode
);
428 else if (!pointer_set_contains (reachable
, vnode
))
431 if (vnode
->symbol
.definition
)
434 fprintf (file
, " %s", varpool_node_name (vnode
));
437 vnode
->symbol
.definition
= false;
438 vnode
->symbol
.analyzed
= false;
439 vnode
->symbol
.aux
= NULL
;
441 /* Keep body if it may be useful for constant folding. */
442 if ((init
= ctor_for_folding (vnode
->symbol
.decl
)) == error_mark_node
)
443 varpool_remove_initializer (vnode
);
445 DECL_INITIAL (vnode
->symbol
.decl
) = init
;
446 ipa_remove_all_references (&vnode
->symbol
.ref_list
);
449 vnode
->symbol
.aux
= NULL
;
452 pointer_set_destroy (reachable
);
453 pointer_set_destroy (body_needed_for_clonning
);
455 /* Now update address_taken flags and try to promote functions to be local. */
457 fprintf (file
, "\nClearing address taken flags:");
458 FOR_EACH_DEFINED_FUNCTION (node
)
459 if (node
->symbol
.address_taken
460 && !node
->symbol
.used_from_other_partition
)
462 if (!cgraph_for_node_and_aliases (node
, has_addr_references_p
, NULL
, true))
465 fprintf (file
, " %s", cgraph_node_name (node
));
466 node
->symbol
.address_taken
= false;
468 if (cgraph_local_node_p (node
))
470 node
->local
.local
= true;
472 fprintf (file
, " (local)");
477 fprintf (file
, "\n");
479 #ifdef ENABLE_CHECKING
483 /* If we removed something, perhaps profile could be improved. */
484 if (changed
&& optimize
&& inline_edge_summary_vec
.exists ())
485 FOR_EACH_DEFINED_FUNCTION (node
)
486 cgraph_propagate_frequency (node
);
491 /* Discover variables that have no longer address taken or that are read only
492 and update their flags.
494 FIXME: This can not be done in between gimplify and omp_expand since
495 readonly flag plays role on what is shared and what is not. Currently we do
496 this transformation as part of whole program visibility and re-do at
497 ipa-reference pass (to take into account clonning), but it would
498 make sense to do it before early optimizations. */
501 ipa_discover_readonly_nonaddressable_vars (void)
503 struct varpool_node
*vnode
;
505 fprintf (dump_file
, "Clearing variable flags:");
506 FOR_EACH_VARIABLE (vnode
)
507 if (vnode
->symbol
.definition
&& varpool_all_refs_explicit_p (vnode
)
508 && (TREE_ADDRESSABLE (vnode
->symbol
.decl
)
509 || !TREE_READONLY (vnode
->symbol
.decl
)))
511 bool written
= false;
512 bool address_taken
= false;
515 for (i
= 0; ipa_ref_list_referring_iterate (&vnode
->symbol
.ref_list
,
517 && (!written
|| !address_taken
); i
++)
521 address_taken
= true;
529 if (TREE_ADDRESSABLE (vnode
->symbol
.decl
) && !address_taken
)
532 fprintf (dump_file
, " %s (addressable)", varpool_node_name (vnode
));
533 TREE_ADDRESSABLE (vnode
->symbol
.decl
) = 0;
535 if (!TREE_READONLY (vnode
->symbol
.decl
) && !address_taken
&& !written
536 /* Making variable in explicit section readonly can cause section
538 See e.g. gcc.c-torture/compile/pr23237.c */
539 && DECL_SECTION_NAME (vnode
->symbol
.decl
) == NULL
)
542 fprintf (dump_file
, " %s (read-only)", varpool_node_name (vnode
));
543 TREE_READONLY (vnode
->symbol
.decl
) = 1;
547 fprintf (dump_file
, "\n");
550 /* Return true when there is a reference to node and it is not vtable. */
552 address_taken_from_non_vtable_p (symtab_node node
)
556 for (i
= 0; ipa_ref_list_referring_iterate (&node
->symbol
.ref_list
,
558 if (ref
->use
== IPA_REF_ADDR
)
560 struct varpool_node
*node
;
561 if (is_a
<cgraph_node
> (ref
->referring
))
563 node
= ipa_ref_referring_varpool_node (ref
);
564 if (!DECL_VIRTUAL_P (node
->symbol
.decl
))
570 /* A helper for comdat_can_be_unshared_p. */
573 comdat_can_be_unshared_p_1 (symtab_node node
)
575 /* When address is taken, we don't know if equality comparison won't
576 break eventually. Exception are virutal functions and vtables,
577 where this is not possible by language standard. */
578 if (!DECL_VIRTUAL_P (node
->symbol
.decl
)
579 && address_taken_from_non_vtable_p (node
))
582 /* If the symbol is used in some weird way, better to not touch it. */
583 if (node
->symbol
.force_output
)
586 /* Explicit instantiations needs to be output when possibly
588 if (node
->symbol
.forced_by_abi
589 && TREE_PUBLIC (node
->symbol
.decl
)
590 && (node
->symbol
.resolution
!= LDPR_PREVAILING_DEF_IRONLY
591 && !flag_whole_program
))
594 /* Non-readonly and volatile variables can not be duplicated. */
595 if (is_a
<varpool_node
> (node
)
596 && (!TREE_READONLY (node
->symbol
.decl
)
597 || TREE_THIS_VOLATILE (node
->symbol
.decl
)))
602 /* COMDAT functions must be shared only if they have address taken,
603 otherwise we can produce our own private implementation with
605 Return true when turning COMDAT functoin static can not lead to wrong
606 code when the resulting object links with a library defining same COMDAT.
608 Virtual functions do have their addresses taken from the vtables,
609 but in C++ there is no way to compare their addresses for equality. */
612 comdat_can_be_unshared_p (symtab_node node
)
614 if (!comdat_can_be_unshared_p_1 (node
))
616 if (node
->symbol
.same_comdat_group
)
620 /* If more than one function is in the same COMDAT group, it must
621 be shared even if just one function in the comdat group has
623 for (next
= node
->symbol
.same_comdat_group
;
624 next
!= node
; next
= next
->symbol
.same_comdat_group
)
625 if (!comdat_can_be_unshared_p_1 (next
))
631 /* Return true when function NODE should be considered externally visible. */
634 cgraph_externally_visible_p (struct cgraph_node
*node
,
637 if (!node
->symbol
.definition
)
639 if (!TREE_PUBLIC (node
->symbol
.decl
)
640 || DECL_EXTERNAL (node
->symbol
.decl
))
643 /* Do not try to localize built-in functions yet. One of problems is that we
644 end up mangling their asm for WHOPR that makes it impossible to call them
645 using the implicit built-in declarations anymore. Similarly this enables
646 us to remove them as unreachable before actual calls may appear during
647 expansion or folding. */
648 if (DECL_BUILT_IN (node
->symbol
.decl
))
651 /* If linker counts on us, we must preserve the function. */
652 if (symtab_used_from_object_file_p ((symtab_node
) node
))
654 if (DECL_PRESERVE_P (node
->symbol
.decl
))
656 if (lookup_attribute ("externally_visible",
657 DECL_ATTRIBUTES (node
->symbol
.decl
)))
659 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
660 && lookup_attribute ("dllexport",
661 DECL_ATTRIBUTES (node
->symbol
.decl
)))
663 if (node
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
)
665 /* When doing LTO or whole program, we can bring COMDAT functoins static.
666 This improves code quality and we know we will duplicate them at most twice
667 (in the case that we are not using plugin and link with object file
668 implementing same COMDAT) */
669 if ((in_lto_p
|| whole_program
)
670 && DECL_COMDAT (node
->symbol
.decl
)
671 && comdat_can_be_unshared_p ((symtab_node
) node
))
674 /* When doing link time optimizations, hidden symbols become local. */
676 && (DECL_VISIBILITY (node
->symbol
.decl
) == VISIBILITY_HIDDEN
677 || DECL_VISIBILITY (node
->symbol
.decl
) == VISIBILITY_INTERNAL
)
678 /* Be sure that node is defined in IR file, not in other object
679 file. In that case we don't set used_from_other_object_file. */
680 && node
->symbol
.definition
)
682 else if (!whole_program
)
685 if (MAIN_NAME_P (DECL_NAME (node
->symbol
.decl
)))
691 /* Return true when variable VNODE should be considered externally visible. */
694 varpool_externally_visible_p (struct varpool_node
*vnode
)
696 if (DECL_EXTERNAL (vnode
->symbol
.decl
))
699 if (!TREE_PUBLIC (vnode
->symbol
.decl
))
702 /* If linker counts on us, we must preserve the function. */
703 if (symtab_used_from_object_file_p ((symtab_node
) vnode
))
706 if (DECL_HARD_REGISTER (vnode
->symbol
.decl
))
708 if (DECL_PRESERVE_P (vnode
->symbol
.decl
))
710 if (lookup_attribute ("externally_visible",
711 DECL_ATTRIBUTES (vnode
->symbol
.decl
)))
713 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
714 && lookup_attribute ("dllexport",
715 DECL_ATTRIBUTES (vnode
->symbol
.decl
)))
718 /* See if we have linker information about symbol not being used or
719 if we need to make guess based on the declaration.
721 Even if the linker clams the symbol is unused, never bring internal
722 symbols that are declared by user as used or externally visible.
723 This is needed for i.e. references from asm statements. */
724 if (symtab_used_from_object_file_p ((symtab_node
) vnode
))
726 if (vnode
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
)
729 /* As a special case, the COMDAT virtual tables can be unshared.
730 In LTO mode turn vtables into static variables. The variable is readonly,
731 so this does not enable more optimization, but referring static var
732 is faster for dynamic linking. Also this match logic hidding vtables
733 from LTO symbol tables. */
734 if ((in_lto_p
|| flag_whole_program
)
735 && DECL_COMDAT (vnode
->symbol
.decl
)
736 && comdat_can_be_unshared_p ((symtab_node
) vnode
))
739 /* When doing link time optimizations, hidden symbols become local. */
741 && (DECL_VISIBILITY (vnode
->symbol
.decl
) == VISIBILITY_HIDDEN
742 || DECL_VISIBILITY (vnode
->symbol
.decl
) == VISIBILITY_INTERNAL
)
743 /* Be sure that node is defined in IR file, not in other object
744 file. In that case we don't set used_from_other_object_file. */
745 && vnode
->symbol
.definition
)
747 else if (!flag_whole_program
)
750 /* Do not attempt to privatize COMDATS by default.
751 This would break linking with C++ libraries sharing
754 FIXME: We can do so for readonly vars with no address taken and
755 possibly also for vtables since no direct pointer comparsion is done.
756 It might be interesting to do so to reduce linking overhead. */
757 if (DECL_COMDAT (vnode
->symbol
.decl
) || DECL_WEAK (vnode
->symbol
.decl
))
762 /* Return true if reference to NODE can be replaced by a local alias.
763 Local aliases save dynamic linking overhead and enable more optimizations.
767 can_replace_by_local_alias (symtab_node node
)
769 return (symtab_node_availability (node
) > AVAIL_OVERWRITABLE
770 && !DECL_EXTERNAL (node
->symbol
.decl
)
771 && (!DECL_ONE_ONLY (node
->symbol
.decl
)
772 || node
->symbol
.resolution
== LDPR_PREVAILING_DEF
773 || node
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
774 || node
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY_EXP
));
777 /* Mark visibility of all functions.
779 A local function is one whose calls can occur only in the current
780 compilation unit and all its calls are explicit, so we can change
781 its calling convention. We simply mark all static functions whose
782 address is not taken as local.
784 We also change the TREE_PUBLIC flag of all declarations that are public
785 in language point of view but we want to overwrite this default
786 via visibilities for the backend point of view. */
789 function_and_variable_visibility (bool whole_program
)
791 struct cgraph_node
*node
;
792 struct varpool_node
*vnode
;
794 /* All aliases should be procssed at this point. */
795 gcc_checking_assert (!alias_pairs
|| !alias_pairs
->length());
797 FOR_EACH_FUNCTION (node
)
799 int flags
= flags_from_decl_or_type (node
->symbol
.decl
);
801 /* Optimize away PURE and CONST constructors and destructors. */
803 && (flags
& (ECF_CONST
| ECF_PURE
))
804 && !(flags
& ECF_LOOPING_CONST_OR_PURE
))
806 DECL_STATIC_CONSTRUCTOR (node
->symbol
.decl
) = 0;
807 DECL_STATIC_DESTRUCTOR (node
->symbol
.decl
) = 0;
810 /* Frontends and alias code marks nodes as needed before parsing is finished.
811 We may end up marking as node external nodes where this flag is meaningless
813 if (DECL_EXTERNAL (node
->symbol
.decl
) || !node
->symbol
.definition
)
815 node
->symbol
.force_output
= 0;
816 node
->symbol
.forced_by_abi
= 0;
819 /* C++ FE on lack of COMDAT support create local COMDAT functions
820 (that ought to be shared but can not due to object format
821 limitations). It is necessary to keep the flag to make rest of C++ FE
822 happy. Clear the flag here to avoid confusion in middle-end. */
823 if (DECL_COMDAT (node
->symbol
.decl
) && !TREE_PUBLIC (node
->symbol
.decl
))
824 DECL_COMDAT (node
->symbol
.decl
) = 0;
826 /* For external decls stop tracking same_comdat_group. It doesn't matter
827 what comdat group they are in when they won't be emitted in this TU. */
828 if (node
->symbol
.same_comdat_group
&& DECL_EXTERNAL (node
->symbol
.decl
))
830 #ifdef ENABLE_CHECKING
833 for (n
= node
->symbol
.same_comdat_group
;
834 n
!= (symtab_node
)node
;
835 n
= n
->symbol
.same_comdat_group
)
836 /* If at least one of same comdat group functions is external,
837 all of them have to be, otherwise it is a front-end bug. */
838 gcc_assert (DECL_EXTERNAL (n
->symbol
.decl
));
840 symtab_dissolve_same_comdat_group_list ((symtab_node
) node
);
842 gcc_assert ((!DECL_WEAK (node
->symbol
.decl
)
843 && !DECL_COMDAT (node
->symbol
.decl
))
844 || TREE_PUBLIC (node
->symbol
.decl
)
845 || node
->symbol
.weakref
846 || DECL_EXTERNAL (node
->symbol
.decl
));
847 if (cgraph_externally_visible_p (node
, whole_program
))
849 gcc_assert (!node
->global
.inlined_to
);
850 node
->symbol
.externally_visible
= true;
854 node
->symbol
.externally_visible
= false;
855 node
->symbol
.forced_by_abi
= false;
857 if (!node
->symbol
.externally_visible
858 && node
->symbol
.definition
&& !node
->symbol
.weakref
859 && !DECL_EXTERNAL (node
->symbol
.decl
))
861 gcc_assert (whole_program
|| in_lto_p
862 || !TREE_PUBLIC (node
->symbol
.decl
));
863 node
->symbol
.unique_name
= ((node
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
864 || node
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY_EXP
)
865 && TREE_PUBLIC (node
->symbol
.decl
));
866 symtab_make_decl_local (node
->symbol
.decl
);
867 node
->symbol
.resolution
= LDPR_PREVAILING_DEF_IRONLY
;
868 if (node
->symbol
.same_comdat_group
)
869 /* cgraph_externally_visible_p has already checked all other nodes
870 in the group and they will all be made local. We need to
871 dissolve the group at once so that the predicate does not
873 symtab_dissolve_same_comdat_group_list ((symtab_node
) node
);
876 if (node
->thunk
.thunk_p
877 && TREE_PUBLIC (node
->symbol
.decl
))
879 struct cgraph_node
*decl_node
= node
;
881 decl_node
= cgraph_function_node (decl_node
->callees
->callee
, NULL
);
883 /* Thunks have the same visibility as function they are attached to.
884 Make sure the C++ front end set this up properly. */
885 if (DECL_ONE_ONLY (decl_node
->symbol
.decl
))
887 gcc_checking_assert (DECL_COMDAT (node
->symbol
.decl
)
888 == DECL_COMDAT (decl_node
->symbol
.decl
));
889 gcc_checking_assert (DECL_COMDAT_GROUP (node
->symbol
.decl
)
890 == DECL_COMDAT_GROUP (decl_node
->symbol
.decl
));
891 gcc_checking_assert (node
->symbol
.same_comdat_group
);
893 if (DECL_EXTERNAL (decl_node
->symbol
.decl
))
894 DECL_EXTERNAL (node
->symbol
.decl
) = 1;
897 FOR_EACH_DEFINED_FUNCTION (node
)
899 node
->local
.local
|= cgraph_local_node_p (node
);
901 /* If we know that function can not be overwritten by a different semantics
902 and moreover its section can not be discarded, replace all direct calls
903 by calls to an nonoverwritable alias. This make dynamic linking
904 cheaper and enable more optimization.
906 TODO: We can also update virtual tables. */
907 if (node
->callers
&& can_replace_by_local_alias ((symtab_node
)node
))
909 struct cgraph_node
*alias
= cgraph (symtab_nonoverwritable_alias ((symtab_node
) node
));
913 while (node
->callers
)
915 struct cgraph_edge
*e
= node
->callers
;
917 cgraph_redirect_edge_callee (e
, alias
);
920 push_cfun (DECL_STRUCT_FUNCTION (e
->caller
->symbol
.decl
));
921 cgraph_redirect_edge_call_stmt_to_callee (e
);
928 FOR_EACH_VARIABLE (vnode
)
930 /* weak flag makes no sense on local variables. */
931 gcc_assert (!DECL_WEAK (vnode
->symbol
.decl
)
932 || vnode
->symbol
.weakref
933 || TREE_PUBLIC (vnode
->symbol
.decl
)
934 || DECL_EXTERNAL (vnode
->symbol
.decl
));
935 /* In several cases declarations can not be common:
937 - when declaration has initializer
939 - when it has specific section
940 - when it resides in non-generic address space.
941 - if declaration is local, it will get into .local common section
942 so common flag is not needed. Frontends still produce these in
943 certain cases, such as for:
945 static int a __attribute__ ((common))
947 Canonicalize things here and clear the redundant flag. */
948 if (DECL_COMMON (vnode
->symbol
.decl
)
949 && (!(TREE_PUBLIC (vnode
->symbol
.decl
)
950 || DECL_EXTERNAL (vnode
->symbol
.decl
))
951 || (DECL_INITIAL (vnode
->symbol
.decl
)
952 && DECL_INITIAL (vnode
->symbol
.decl
) != error_mark_node
)
953 || DECL_WEAK (vnode
->symbol
.decl
)
954 || DECL_SECTION_NAME (vnode
->symbol
.decl
) != NULL
955 || ! (ADDR_SPACE_GENERIC_P
956 (TYPE_ADDR_SPACE (TREE_TYPE (vnode
->symbol
.decl
))))))
957 DECL_COMMON (vnode
->symbol
.decl
) = 0;
959 FOR_EACH_DEFINED_VARIABLE (vnode
)
961 if (!vnode
->symbol
.definition
)
963 if (varpool_externally_visible_p (vnode
))
964 vnode
->symbol
.externally_visible
= true;
967 vnode
->symbol
.externally_visible
= false;
968 vnode
->symbol
.forced_by_abi
= false;
970 if (!vnode
->symbol
.externally_visible
971 && !vnode
->symbol
.weakref
)
973 gcc_assert (in_lto_p
|| whole_program
|| !TREE_PUBLIC (vnode
->symbol
.decl
));
974 symtab_make_decl_local (vnode
->symbol
.decl
);
975 vnode
->symbol
.unique_name
= ((vnode
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY
976 || vnode
->symbol
.resolution
== LDPR_PREVAILING_DEF_IRONLY_EXP
)
977 && TREE_PUBLIC (vnode
->symbol
.decl
));
978 if (vnode
->symbol
.same_comdat_group
)
979 symtab_dissolve_same_comdat_group_list ((symtab_node
) vnode
);
980 vnode
->symbol
.resolution
= LDPR_PREVAILING_DEF_IRONLY
;
986 fprintf (dump_file
, "\nMarking local functions:");
987 FOR_EACH_DEFINED_FUNCTION (node
)
988 if (node
->local
.local
)
989 fprintf (dump_file
, " %s", cgraph_node_name (node
));
990 fprintf (dump_file
, "\n\n");
991 fprintf (dump_file
, "\nMarking externally visible functions:");
992 FOR_EACH_DEFINED_FUNCTION (node
)
993 if (node
->symbol
.externally_visible
)
994 fprintf (dump_file
, " %s", cgraph_node_name (node
));
995 fprintf (dump_file
, "\n\n");
996 fprintf (dump_file
, "\nMarking externally visible variables:");
997 FOR_EACH_DEFINED_VARIABLE (vnode
)
998 if (vnode
->symbol
.externally_visible
)
999 fprintf (dump_file
, " %s", varpool_node_name (vnode
));
1000 fprintf (dump_file
, "\n\n");
1002 cgraph_function_flags_ready
= true;
1006 /* Local function pass handling visibilities. This happens before LTO streaming
1007 so in particular -fwhole-program should be ignored at this level. */
1010 local_function_and_variable_visibility (void)
1012 return function_and_variable_visibility (flag_whole_program
&& !flag_lto
);
1015 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility
=
1019 "visibility", /* name */
1020 OPTGROUP_NONE
, /* optinfo_flags */
1022 local_function_and_variable_visibility
,/* execute */
1025 0, /* static_pass_number */
1026 TV_CGRAPHOPT
, /* tv_id */
1027 0, /* properties_required */
1028 0, /* properties_provided */
1029 0, /* properties_destroyed */
1030 0, /* todo_flags_start */
1031 TODO_remove_functions
| TODO_dump_symtab
/* todo_flags_finish */
1035 /* Free inline summary. */
1038 free_inline_summary (void)
1040 inline_free_summary ();
1044 struct simple_ipa_opt_pass pass_ipa_free_inline_summary
=
1048 "*free_inline_summary", /* name */
1049 OPTGROUP_NONE
, /* optinfo_flags */
1051 free_inline_summary
, /* execute */
1054 0, /* static_pass_number */
1055 TV_IPA_FREE_INLINE_SUMMARY
, /* tv_id */
1056 0, /* properties_required */
1057 0, /* properties_provided */
1058 0, /* properties_destroyed */
1059 0, /* todo_flags_start */
1060 0 /* todo_flags_finish */
1064 /* Do not re-run on ltrans stage. */
1067 gate_whole_program_function_and_variable_visibility (void)
1069 return !flag_ltrans
;
1072 /* Bring functionss local at LTO time with -fwhole-program. */
1075 whole_program_function_and_variable_visibility (void)
1077 function_and_variable_visibility (flag_whole_program
);
1079 ipa_discover_readonly_nonaddressable_vars ();
1083 struct ipa_opt_pass_d pass_ipa_whole_program_visibility
=
1087 "whole-program", /* name */
1088 OPTGROUP_NONE
, /* optinfo_flags */
1089 gate_whole_program_function_and_variable_visibility
,/* gate */
1090 whole_program_function_and_variable_visibility
,/* execute */
1093 0, /* static_pass_number */
1094 TV_CGRAPHOPT
, /* tv_id */
1095 0, /* properties_required */
1096 0, /* properties_provided */
1097 0, /* properties_destroyed */
1098 0, /* todo_flags_start */
1099 TODO_remove_functions
| TODO_dump_symtab
/* todo_flags_finish */
1101 NULL
, /* generate_summary */
1102 NULL
, /* write_summary */
1103 NULL
, /* read_summary */
1104 NULL
, /* write_optimization_summary */
1105 NULL
, /* read_optimization_summary */
1106 NULL
, /* stmt_fixup */
1108 NULL
, /* function_transform */
1109 NULL
, /* variable_transform */
1112 /* Entry in the histogram. */
1114 struct histogram_entry
1121 /* Histogram of profile values.
1122 The histogram is represented as an ordered vector of entries allocated via
1123 histogram_pool. During construction a separate hashtable is kept to lookup
1124 duplicate entries. */
1126 vec
<histogram_entry
*> histogram
;
1127 static alloc_pool histogram_pool
;
1129 /* Hashtable support for storing SSA names hashed by their SSA_NAME_VAR. */
1131 struct histogram_hash
: typed_noop_remove
<histogram_entry
>
1133 typedef histogram_entry value_type
;
1134 typedef histogram_entry compare_type
;
1135 static inline hashval_t
hash (const value_type
*);
1136 static inline int equal (const value_type
*, const compare_type
*);
1140 histogram_hash::hash (const histogram_entry
*val
)
1146 histogram_hash::equal (const histogram_entry
*val
, const histogram_entry
*val2
)
1148 return val
->count
== val2
->count
;
1151 /* Account TIME and SIZE executed COUNT times into HISTOGRAM.
1152 HASHTABLE is the on-side hash kept to avoid duplicates. */
1155 account_time_size (hash_table
<histogram_hash
> hashtable
,
1156 vec
<histogram_entry
*> &histogram
,
1157 gcov_type count
, int time
, int size
)
1159 histogram_entry key
= {count
, 0, 0};
1160 histogram_entry
**val
= hashtable
.find_slot (&key
, INSERT
);
1164 *val
= (histogram_entry
*) pool_alloc (histogram_pool
);
1166 histogram
.safe_push (*val
);
1168 (*val
)->time
+= time
;
1169 (*val
)->size
+= size
;
1173 cmp_counts (const void *v1
, const void *v2
)
1175 const histogram_entry
*h1
= *(const histogram_entry
* const *)v1
;
1176 const histogram_entry
*h2
= *(const histogram_entry
* const *)v2
;
1177 if (h1
->count
< h2
->count
)
1179 if (h1
->count
> h2
->count
)
1184 /* Dump HISTOGRAM to FILE. */
1187 dump_histogram (FILE *file
, vec
<histogram_entry
*> histogram
)
1190 gcov_type overall_time
= 0, cumulated_time
= 0, cumulated_size
= 0, overall_size
= 0;
1192 fprintf (dump_file
, "Histogram:\n");
1193 for (i
= 0; i
< histogram
.length (); i
++)
1195 overall_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1196 overall_size
+= histogram
[i
]->size
;
1202 for (i
= 0; i
< histogram
.length (); i
++)
1204 cumulated_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1205 cumulated_size
+= histogram
[i
]->size
;
1206 fprintf (file
, " "HOST_WIDEST_INT_PRINT_DEC
": time:%i (%2.2f) size:%i (%2.2f)\n",
1207 (HOST_WIDEST_INT
) histogram
[i
]->count
,
1209 cumulated_time
* 100.0 / overall_time
,
1211 cumulated_size
* 100.0 / overall_size
);
1215 /* Collect histogram from CFG profiles. */
1218 ipa_profile_generate_summary (void)
1220 struct cgraph_node
*node
;
1221 gimple_stmt_iterator gsi
;
1222 hash_table
<histogram_hash
> hashtable
;
1225 hashtable
.create (10);
1226 histogram_pool
= create_alloc_pool ("IPA histogram", sizeof (struct histogram_entry
),
1229 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node
)
1230 FOR_EACH_BB_FN (bb
, DECL_STRUCT_FUNCTION (node
->symbol
.decl
))
1234 for (gsi
= gsi_start_bb (bb
); !gsi_end_p (gsi
); gsi_next (&gsi
))
1236 time
+= estimate_num_insns (gsi_stmt (gsi
), &eni_time_weights
);
1237 size
+= estimate_num_insns (gsi_stmt (gsi
), &eni_size_weights
);
1239 account_time_size (hashtable
, histogram
, bb
->count
, time
, size
);
1241 hashtable
.dispose ();
1242 histogram
.qsort (cmp_counts
);
1245 /* Serialize the ipa info for lto. */
1248 ipa_profile_write_summary (void)
1250 struct lto_simple_output_block
*ob
1251 = lto_create_simple_output_block (LTO_section_ipa_profile
);
1254 streamer_write_uhwi_stream (ob
->main_stream
, histogram
.length());
1255 for (i
= 0; i
< histogram
.length (); i
++)
1257 streamer_write_gcov_count_stream (ob
->main_stream
, histogram
[i
]->count
);
1258 streamer_write_uhwi_stream (ob
->main_stream
, histogram
[i
]->time
);
1259 streamer_write_uhwi_stream (ob
->main_stream
, histogram
[i
]->size
);
1261 lto_destroy_simple_output_block (ob
);
1264 /* Deserialize the ipa info for lto. */
1267 ipa_profile_read_summary (void)
1269 struct lto_file_decl_data
** file_data_vec
1270 = lto_get_file_decl_data ();
1271 struct lto_file_decl_data
* file_data
;
1272 hash_table
<histogram_hash
> hashtable
;
1275 hashtable
.create (10);
1276 histogram_pool
= create_alloc_pool ("IPA histogram", sizeof (struct histogram_entry
),
1279 while ((file_data
= file_data_vec
[j
++]))
1283 struct lto_input_block
*ib
1284 = lto_create_simple_input_block (file_data
,
1285 LTO_section_ipa_profile
,
1289 unsigned int num
= streamer_read_uhwi (ib
);
1291 for (n
= 0; n
< num
; n
++)
1293 gcov_type count
= streamer_read_gcov_count (ib
);
1294 int time
= streamer_read_uhwi (ib
);
1295 int size
= streamer_read_uhwi (ib
);
1296 account_time_size (hashtable
, histogram
,
1299 lto_destroy_simple_input_block (file_data
,
1300 LTO_section_ipa_profile
,
1304 hashtable
.dispose ();
1305 histogram
.qsort (cmp_counts
);
1308 /* Simple ipa profile pass propagating frequencies across the callgraph. */
1313 struct cgraph_node
**order
= XCNEWVEC (struct cgraph_node
*, cgraph_n_nodes
);
1314 struct cgraph_edge
*e
;
1316 bool something_changed
= false;
1318 gcov_type overall_time
= 0, cutoff
= 0, cumulated
= 0, overall_size
= 0;
1321 dump_histogram (dump_file
, histogram
);
1322 for (i
= 0; i
< (int)histogram
.length (); i
++)
1324 overall_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1325 overall_size
+= histogram
[i
]->size
;
1329 gcov_type threshold
;
1331 gcc_assert (overall_size
);
1334 gcov_type min
, cumulated_time
= 0, cumulated_size
= 0;
1336 fprintf (dump_file
, "Overall time: "HOST_WIDEST_INT_PRINT_DEC
"\n",
1337 (HOST_WIDEST_INT
)overall_time
);
1338 min
= get_hot_bb_threshold ();
1339 for (i
= 0; i
< (int)histogram
.length () && histogram
[i
]->count
>= min
;
1342 cumulated_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1343 cumulated_size
+= histogram
[i
]->size
;
1345 fprintf (dump_file
, "GCOV min count: "HOST_WIDEST_INT_PRINT_DEC
1346 " Time:%3.2f%% Size:%3.2f%%\n",
1347 (HOST_WIDEST_INT
)min
,
1348 cumulated_time
* 100.0 / overall_time
,
1349 cumulated_size
* 100.0 / overall_size
);
1351 cutoff
= (overall_time
* PARAM_VALUE (HOT_BB_COUNT_WS_PERMILLE
) + 500) / 1000;
1353 for (i
= 0; cumulated
< cutoff
; i
++)
1355 cumulated
+= histogram
[i
]->count
* histogram
[i
]->time
;
1356 threshold
= histogram
[i
]->count
;
1362 gcov_type cumulated_time
= 0, cumulated_size
= 0;
1365 i
< (int)histogram
.length () && histogram
[i
]->count
>= threshold
;
1368 cumulated_time
+= histogram
[i
]->count
* histogram
[i
]->time
;
1369 cumulated_size
+= histogram
[i
]->size
;
1371 fprintf (dump_file
, "Determined min count: "HOST_WIDEST_INT_PRINT_DEC
1372 " Time:%3.2f%% Size:%3.2f%%\n",
1373 (HOST_WIDEST_INT
)threshold
,
1374 cumulated_time
* 100.0 / overall_time
,
1375 cumulated_size
* 100.0 / overall_size
);
1377 if (threshold
> get_hot_bb_threshold ()
1381 fprintf (dump_file
, "Threshold updated.\n");
1382 set_hot_bb_threshold (threshold
);
1385 histogram
.release();
1386 free_alloc_pool (histogram_pool
);
1388 order_pos
= ipa_reverse_postorder (order
);
1389 for (i
= order_pos
- 1; i
>= 0; i
--)
1391 if (order
[i
]->local
.local
&& cgraph_propagate_frequency (order
[i
]))
1393 for (e
= order
[i
]->callees
; e
; e
= e
->next_callee
)
1394 if (e
->callee
->local
.local
&& !e
->callee
->symbol
.aux
)
1396 something_changed
= true;
1397 e
->callee
->symbol
.aux
= (void *)1;
1400 order
[i
]->symbol
.aux
= NULL
;
1403 while (something_changed
)
1405 something_changed
= false;
1406 for (i
= order_pos
- 1; i
>= 0; i
--)
1408 if (order
[i
]->symbol
.aux
&& cgraph_propagate_frequency (order
[i
]))
1410 for (e
= order
[i
]->callees
; e
; e
= e
->next_callee
)
1411 if (e
->callee
->local
.local
&& !e
->callee
->symbol
.aux
)
1413 something_changed
= true;
1414 e
->callee
->symbol
.aux
= (void *)1;
1417 order
[i
]->symbol
.aux
= NULL
;
1425 gate_ipa_profile (void)
1427 return flag_ipa_profile
;
1430 struct ipa_opt_pass_d pass_ipa_profile
=
1434 "profile_estimate", /* name */
1435 OPTGROUP_NONE
, /* optinfo_flags */
1436 gate_ipa_profile
, /* gate */
1437 ipa_profile
, /* execute */
1440 0, /* static_pass_number */
1441 TV_IPA_PROFILE
, /* tv_id */
1442 0, /* properties_required */
1443 0, /* properties_provided */
1444 0, /* properties_destroyed */
1445 0, /* todo_flags_start */
1446 0 /* todo_flags_finish */
1448 ipa_profile_generate_summary
, /* generate_summary */
1449 ipa_profile_write_summary
, /* write_summary */
1450 ipa_profile_read_summary
, /* read_summary */
1451 NULL
, /* write_optimization_summary */
1452 NULL
, /* read_optimization_summary */
1453 NULL
, /* stmt_fixup */
1455 NULL
, /* function_transform */
1456 NULL
/* variable_transform */
1459 /* Generate and emit a static constructor or destructor. WHICH must
1460 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1461 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1462 initialization priority for this constructor or destructor.
1464 FINAL specify whether the externally visible name for collect2 should
1468 cgraph_build_static_cdtor_1 (char which
, tree body
, int priority
, bool final
)
1470 static int counter
= 0;
1472 tree decl
, name
, resdecl
;
1474 /* The priority is encoded in the constructor or destructor name.
1475 collect2 will sort the names and arrange that they are called at
1478 sprintf (which_buf
, "%c_%.5d_%d", which
, priority
, counter
++);
1480 /* Proudce sane name but one not recognizable by collect2, just for the
1481 case we fail to inline the function. */
1482 sprintf (which_buf
, "sub_%c_%.5d_%d", which
, priority
, counter
++);
1483 name
= get_file_function_name (which_buf
);
1485 decl
= build_decl (input_location
, FUNCTION_DECL
, name
,
1486 build_function_type_list (void_type_node
, NULL_TREE
));
1487 current_function_decl
= decl
;
1489 resdecl
= build_decl (input_location
,
1490 RESULT_DECL
, NULL_TREE
, void_type_node
);
1491 DECL_ARTIFICIAL (resdecl
) = 1;
1492 DECL_RESULT (decl
) = resdecl
;
1493 DECL_CONTEXT (resdecl
) = decl
;
1495 allocate_struct_function (decl
, false);
1497 TREE_STATIC (decl
) = 1;
1498 TREE_USED (decl
) = 1;
1499 DECL_ARTIFICIAL (decl
) = 1;
1500 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl
) = 1;
1501 DECL_SAVED_TREE (decl
) = body
;
1502 if (!targetm
.have_ctors_dtors
&& final
)
1504 TREE_PUBLIC (decl
) = 1;
1505 DECL_PRESERVE_P (decl
) = 1;
1507 DECL_UNINLINABLE (decl
) = 1;
1509 DECL_INITIAL (decl
) = make_node (BLOCK
);
1510 TREE_USED (DECL_INITIAL (decl
)) = 1;
1512 DECL_SOURCE_LOCATION (decl
) = input_location
;
1513 cfun
->function_end_locus
= input_location
;
1518 DECL_STATIC_CONSTRUCTOR (decl
) = 1;
1519 decl_init_priority_insert (decl
, priority
);
1522 DECL_STATIC_DESTRUCTOR (decl
) = 1;
1523 decl_fini_priority_insert (decl
, priority
);
1529 gimplify_function_tree (decl
);
1531 cgraph_add_new_function (decl
, false);
1534 current_function_decl
= NULL
;
1537 /* Generate and emit a static constructor or destructor. WHICH must
1538 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1539 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1540 initialization priority for this constructor or destructor. */
1543 cgraph_build_static_cdtor (char which
, tree body
, int priority
)
1545 cgraph_build_static_cdtor_1 (which
, body
, priority
, false);
1548 /* A vector of FUNCTION_DECLs declared as static constructors. */
1549 static vec
<tree
> static_ctors
;
1550 /* A vector of FUNCTION_DECLs declared as static destructors. */
1551 static vec
<tree
> static_dtors
;
1553 /* When target does not have ctors and dtors, we call all constructor
1554 and destructor by special initialization/destruction function
1555 recognized by collect2.
1557 When we are going to build this function, collect all constructors and
1558 destructors and turn them into normal functions. */
1561 record_cdtor_fn (struct cgraph_node
*node
)
1563 if (DECL_STATIC_CONSTRUCTOR (node
->symbol
.decl
))
1564 static_ctors
.safe_push (node
->symbol
.decl
);
1565 if (DECL_STATIC_DESTRUCTOR (node
->symbol
.decl
))
1566 static_dtors
.safe_push (node
->symbol
.decl
);
1567 node
= cgraph_get_node (node
->symbol
.decl
);
1568 DECL_DISREGARD_INLINE_LIMITS (node
->symbol
.decl
) = 1;
1571 /* Define global constructors/destructor functions for the CDTORS, of
1572 which they are LEN. The CDTORS are sorted by initialization
1573 priority. If CTOR_P is true, these are constructors; otherwise,
1574 they are destructors. */
1577 build_cdtor (bool ctor_p
, vec
<tree
> cdtors
)
1580 size_t len
= cdtors
.length ();
1587 priority_type priority
;
1596 p
= ctor_p
? DECL_INIT_PRIORITY (fn
) : DECL_FINI_PRIORITY (fn
);
1599 else if (p
!= priority
)
1605 /* When there is only one cdtor and target supports them, do nothing. */
1607 && targetm
.have_ctors_dtors
)
1612 /* Find the next batch of constructors/destructors with the same
1613 initialization priority. */
1618 call
= build_call_expr (fn
, 0);
1620 DECL_STATIC_CONSTRUCTOR (fn
) = 0;
1622 DECL_STATIC_DESTRUCTOR (fn
) = 0;
1623 /* We do not want to optimize away pure/const calls here.
1624 When optimizing, these should be already removed, when not
1625 optimizing, we want user to be able to breakpoint in them. */
1626 TREE_SIDE_EFFECTS (call
) = 1;
1627 append_to_statement_list (call
, &body
);
1629 gcc_assert (body
!= NULL_TREE
);
1630 /* Generate a function to call all the function of like
1632 cgraph_build_static_cdtor_1 (ctor_p
? 'I' : 'D', body
, priority
, true);
1636 /* Comparison function for qsort. P1 and P2 are actually of type
1637 "tree *" and point to static constructors. DECL_INIT_PRIORITY is
1638 used to determine the sort order. */
1641 compare_ctor (const void *p1
, const void *p2
)
1648 f1
= *(const tree
*)p1
;
1649 f2
= *(const tree
*)p2
;
1650 priority1
= DECL_INIT_PRIORITY (f1
);
1651 priority2
= DECL_INIT_PRIORITY (f2
);
1653 if (priority1
< priority2
)
1655 else if (priority1
> priority2
)
1658 /* Ensure a stable sort. Constructors are executed in backwarding
1659 order to make LTO initialize braries first. */
1660 return DECL_UID (f2
) - DECL_UID (f1
);
1663 /* Comparison function for qsort. P1 and P2 are actually of type
1664 "tree *" and point to static destructors. DECL_FINI_PRIORITY is
1665 used to determine the sort order. */
1668 compare_dtor (const void *p1
, const void *p2
)
1675 f1
= *(const tree
*)p1
;
1676 f2
= *(const tree
*)p2
;
1677 priority1
= DECL_FINI_PRIORITY (f1
);
1678 priority2
= DECL_FINI_PRIORITY (f2
);
1680 if (priority1
< priority2
)
1682 else if (priority1
> priority2
)
1685 /* Ensure a stable sort. */
1686 return DECL_UID (f1
) - DECL_UID (f2
);
1689 /* Generate functions to call static constructors and destructors
1690 for targets that do not support .ctors/.dtors sections. These
1691 functions have magic names which are detected by collect2. */
1694 build_cdtor_fns (void)
1696 if (!static_ctors
.is_empty ())
1698 gcc_assert (!targetm
.have_ctors_dtors
|| in_lto_p
);
1699 static_ctors
.qsort (compare_ctor
);
1700 build_cdtor (/*ctor_p=*/true, static_ctors
);
1703 if (!static_dtors
.is_empty ())
1705 gcc_assert (!targetm
.have_ctors_dtors
|| in_lto_p
);
1706 static_dtors
.qsort (compare_dtor
);
1707 build_cdtor (/*ctor_p=*/false, static_dtors
);
1711 /* Look for constructors and destructors and produce function calling them.
1712 This is needed for targets not supporting ctors or dtors, but we perform the
1713 transformation also at linktime to merge possibly numerous
1714 constructors/destructors into single function to improve code locality and
1718 ipa_cdtor_merge (void)
1720 struct cgraph_node
*node
;
1721 FOR_EACH_DEFINED_FUNCTION (node
)
1722 if (DECL_STATIC_CONSTRUCTOR (node
->symbol
.decl
)
1723 || DECL_STATIC_DESTRUCTOR (node
->symbol
.decl
))
1724 record_cdtor_fn (node
);
1726 static_ctors
.release ();
1727 static_dtors
.release ();
1731 /* Perform the pass when we have no ctors/dtors support
1732 or at LTO time to merge multiple constructors into single
1736 gate_ipa_cdtor_merge (void)
1738 return !targetm
.have_ctors_dtors
|| (optimize
&& in_lto_p
);
1741 struct ipa_opt_pass_d pass_ipa_cdtor_merge
=
1746 OPTGROUP_NONE
, /* optinfo_flags */
1747 gate_ipa_cdtor_merge
, /* gate */
1748 ipa_cdtor_merge
, /* execute */
1751 0, /* static_pass_number */
1752 TV_CGRAPHOPT
, /* tv_id */
1753 0, /* properties_required */
1754 0, /* properties_provided */
1755 0, /* properties_destroyed */
1756 0, /* todo_flags_start */
1757 0 /* todo_flags_finish */
1759 NULL
, /* generate_summary */
1760 NULL
, /* write_summary */
1761 NULL
, /* read_summary */
1762 NULL
, /* write_optimization_summary */
1763 NULL
, /* read_optimization_summary */
1764 NULL
, /* stmt_fixup */
1766 NULL
, /* function_transform */
1767 NULL
/* variable_transform */