Merge trunk version 202159 into gupc branch.
[official-gcc.git] / gcc / ipa.c
blobb1759ae876cb1d30605d459181057115cf5e44b9
1 /* Basic IPA optimizations and utilities.
2 Copyright (C) 2003-2013 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "tm.h"
24 #include "cgraph.h"
25 #include "tree-pass.h"
26 #include "gimple.h"
27 #include "ggc.h"
28 #include "flags.h"
29 #include "pointer-set.h"
30 #include "target.h"
31 #include "tree-iterator.h"
32 #include "ipa-utils.h"
33 #include "ipa-inline.h"
34 #include "tree-inline.h"
35 #include "profile.h"
36 #include "params.h"
38 /* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
40 static bool
41 cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
43 /* FIXME: Aliases can be local, but i386 gets thunks wrong then. */
44 return !(cgraph_only_called_directly_or_aliased_p (node)
45 && !ipa_ref_has_aliases_p (&node->symbol.ref_list)
46 && node->symbol.definition
47 && !DECL_EXTERNAL (node->symbol.decl)
48 && !node->symbol.externally_visible
49 && !node->symbol.used_from_other_partition
50 && !node->symbol.in_other_partition);
53 /* Return true when function can be marked local. */
55 static bool
56 cgraph_local_node_p (struct cgraph_node *node)
58 struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);
60 /* FIXME: thunks can be considered local, but we need prevent i386
61 from attempting to change calling convention of them. */
62 if (n->thunk.thunk_p)
63 return false;
64 return !cgraph_for_node_and_aliases (n,
65 cgraph_non_local_node_p_1, NULL, true);
69 /* Return true when NODE has ADDR reference. */
71 static bool
72 has_addr_references_p (struct cgraph_node *node,
73 void *data ATTRIBUTE_UNUSED)
75 int i;
76 struct ipa_ref *ref;
78 for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
79 i, ref); i++)
80 if (ref->use == IPA_REF_ADDR)
81 return true;
82 return false;
85 /* Look for all functions inlined to NODE and update their inlined_to pointers
86 to INLINED_TO. */
88 static void
89 update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
91 struct cgraph_edge *e;
92 for (e = node->callees; e; e = e->next_callee)
93 if (e->callee->global.inlined_to)
95 e->callee->global.inlined_to = inlined_to;
96 update_inlined_to_pointer (e->callee, inlined_to);
100 /* Add symtab NODE to queue starting at FIRST.
102 The queue is linked via AUX pointers and terminated by pointer to 1.
103 We enqueue nodes at two occasions: when we find them reachable or when we find
104 their bodies needed for further clonning. In the second case we mark them
105 by pointer to 2 after processing so they are re-queue when they become
106 reachable. */
108 static void
109 enqueue_node (symtab_node node, symtab_node *first,
110 struct pointer_set_t *reachable)
112 /* Node is still in queue; do nothing. */
113 if (node->symbol.aux && node->symbol.aux != (void *) 2)
114 return;
115 /* Node was already processed as unreachable, re-enqueue
116 only if it became reachable now. */
117 if (node->symbol.aux == (void *)2 && !pointer_set_contains (reachable, node))
118 return;
119 node->symbol.aux = *first;
120 *first = node;
123 /* Process references. */
125 static void
126 process_references (struct ipa_ref_list *list,
127 symtab_node *first,
128 bool before_inlining_p,
129 struct pointer_set_t *reachable)
131 int i;
132 struct ipa_ref *ref;
133 for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
135 symtab_node node = ref->referred;
137 if (node->symbol.definition && !node->symbol.in_other_partition
138 && ((!DECL_EXTERNAL (node->symbol.decl) || node->symbol.alias)
139 || (before_inlining_p
140 /* We use variable constructors during late complation for
141 constant folding. Keep references alive so partitioning
142 knows about potential references. */
143 || (TREE_CODE (node->symbol.decl) == VAR_DECL
144 && flag_wpa
145 && ctor_for_folding (node->symbol.decl)
146 != error_mark_node))))
147 pointer_set_insert (reachable, node);
148 enqueue_node ((symtab_node) node, first, reachable);
153 /* Perform reachability analysis and reclaim all unreachable nodes.
155 The algorithm is basically mark&sweep but with some extra refinements:
157 - reachable extern inline functions needs special handling; the bodies needs
158 to stay in memory until inlining in hope that they will be inlined.
159 After inlining we release their bodies and turn them into unanalyzed
160 nodes even when they are reachable.
162 BEFORE_INLINING_P specify whether we are before or after inlining.
164 - virtual functions are kept in callgraph even if they seem unreachable in
165 hope calls to them will be devirtualized.
167 Again we remove them after inlining. In late optimization some
168 devirtualization may happen, but it is not importnat since we won't inline
169 the call. In theory early opts and IPA should work out all important cases.
171 - virtual clones needs bodies of their origins for later materialization;
172 this means that we want to keep the body even if the origin is unreachable
173 otherwise. To avoid origin from sitting in the callgraph and being
174 walked by IPA passes, we turn them into unanalyzed nodes with body
175 defined.
177 We maintain set of function declaration where body needs to stay in
178 body_needed_for_clonning
180 Inline clones represent special case: their declaration match the
181 declaration of origin and cgraph_remove_node already knows how to
182 reshape callgraph and preserve body when offline copy of function or
183 inline clone is being removed.
185 - C++ virtual tables keyed to other unit are represented as DECL_EXTERNAL
186 variables with DECL_INITIAL set. We finalize these and keep reachable
187 ones around for constant folding purposes. After inlining we however
188 stop walking their references to let everything static referneced by them
189 to be removed when it is otherwise unreachable.
191 We maintain queue of both reachable symbols (i.e. defined symbols that needs
192 to stay) and symbols that are in boundary (i.e. external symbols referenced
193 by reachable symbols or origins of clones). The queue is represented
194 as linked list by AUX pointer terminated by 1.
196 A the end we keep all reachable symbols. For symbols in boundary we always
197 turn definition into a declaration, but we may keep function body around
198 based on body_needed_for_clonning
200 All symbols that enter the queue have AUX pointer non-zero and are in the
201 boundary. Pointer set REACHABLE is used to track reachable symbols.
203 Every symbol can be visited twice - once as part of boundary and once
204 as real reachable symbol. enqueue_node needs to decide whether the
205 node needs to be re-queued for second processing. For this purpose
206 we set AUX pointer of processed symbols in the boundary to constant 2. */
208 bool
209 symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
211 symtab_node first = (symtab_node) (void *) 1;
212 struct cgraph_node *node, *next;
213 struct varpool_node *vnode, *vnext;
214 bool changed = false;
215 struct pointer_set_t *reachable = pointer_set_create ();
216 struct pointer_set_t *body_needed_for_clonning = pointer_set_create ();
218 #ifdef ENABLE_CHECKING
219 verify_symtab ();
220 #endif
221 if (file)
222 fprintf (file, "\nReclaiming functions:");
223 #ifdef ENABLE_CHECKING
224 FOR_EACH_FUNCTION (node)
225 gcc_assert (!node->symbol.aux);
226 FOR_EACH_VARIABLE (vnode)
227 gcc_assert (!vnode->symbol.aux);
228 #endif
229 /* Mark functions whose bodies are obviously needed.
230 This is mostly when they can be referenced externally. Inline clones
231 are special since their declarations are shared with master clone and thus
232 cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them. */
233 FOR_EACH_FUNCTION (node)
235 node->used_as_abstract_origin = false;
236 if (node->symbol.definition
237 && !node->global.inlined_to
238 && !node->symbol.in_other_partition
239 && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
240 /* Keep around virtual functions for possible devirtualization. */
241 || (before_inlining_p
242 && DECL_VIRTUAL_P (node->symbol.decl))))
244 gcc_assert (!node->global.inlined_to);
245 pointer_set_insert (reachable, node);
246 enqueue_node ((symtab_node)node, &first, reachable);
248 else
249 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. */
271 if (in_boundary_p)
272 node->symbol.aux = (void *)2;
273 else
275 if (DECL_ABSTRACT_ORIGIN (node->symbol.decl))
277 struct cgraph_node *origin_node
278 = cgraph_get_create_real_symbol_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl));
279 origin_node->used_as_abstract_origin = true;
280 enqueue_node ((symtab_node) origin_node, &first, reachable);
282 /* If any symbol in a comdat group is reachable, force
283 all other in the same comdat group to be also reachable. */
284 if (node->symbol.same_comdat_group)
286 symtab_node next;
287 for (next = node->symbol.same_comdat_group;
288 next != node;
289 next = next->symbol.same_comdat_group)
290 if (!pointer_set_insert (reachable, next))
291 enqueue_node ((symtab_node) next, &first, reachable);
293 /* Mark references as reachable. */
294 process_references (&node->symbol.ref_list, &first,
295 before_inlining_p, reachable);
298 if (cgraph_node *cnode = dyn_cast <cgraph_node> (node))
300 /* Mark the callees reachable unless they are direct calls to extern
301 inline functions we decided to not inline. */
302 if (!in_boundary_p)
304 struct cgraph_edge *e;
305 for (e = cnode->callees; e; e = e->next_callee)
307 if (e->callee->symbol.definition
308 && !e->callee->symbol.in_other_partition
309 && (!e->inline_failed
310 || !DECL_EXTERNAL (e->callee->symbol.decl)
311 || e->callee->symbol.alias
312 || before_inlining_p))
313 pointer_set_insert (reachable, e->callee);
314 enqueue_node ((symtab_node) e->callee, &first, reachable);
317 /* When inline clone exists, mark body to be preserved so when removing
318 offline copy of the function we don't kill it. */
319 if (cnode->global.inlined_to)
320 pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
322 /* For non-inline clones, force their origins to the boundary and ensure
323 that body is not removed. */
324 while (cnode->clone_of)
326 bool noninline = cnode->clone_of->symbol.decl != cnode->symbol.decl;
327 cnode = cnode->clone_of;
328 if (noninline)
330 pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl);
331 enqueue_node ((symtab_node)cnode, &first, reachable);
336 /* When we see constructor of external variable, keep referred nodes in the
337 boundary. This will also hold initializers of the external vars NODE
338 refers to. */
339 varpool_node *vnode = dyn_cast <varpool_node> (node);
340 if (vnode
341 && DECL_EXTERNAL (node->symbol.decl)
342 && !vnode->symbol.alias
343 && in_boundary_p)
345 struct ipa_ref *ref;
346 for (int i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++)
347 enqueue_node (ref->referred, &first, reachable);
351 /* Remove unreachable functions. */
352 for (node = cgraph_first_function (); node; node = next)
354 next = cgraph_next_function (node);
356 /* If node is not needed at all, remove it. */
357 if (!node->symbol.aux)
359 if (file)
360 fprintf (file, " %s", cgraph_node_name (node));
361 cgraph_remove_node (node);
362 changed = true;
364 /* If node is unreachable, remove its body. */
365 else if (!pointer_set_contains (reachable, node))
367 if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl))
368 cgraph_release_function_body (node);
369 else if (!node->clone_of)
370 gcc_assert (in_lto_p || DECL_RESULT (node->symbol.decl));
371 if (node->symbol.definition)
373 if (file)
374 fprintf (file, " %s", cgraph_node_name (node));
375 node->symbol.analyzed = false;
376 node->symbol.definition = false;
377 node->symbol.cpp_implicit_alias = false;
378 node->symbol.alias = false;
379 node->symbol.weakref = false;
380 if (!node->symbol.in_other_partition)
381 node->local.local = false;
382 cgraph_node_remove_callees (node);
383 ipa_remove_all_references (&node->symbol.ref_list);
384 changed = true;
387 else
388 gcc_assert (node->clone_of || !cgraph_function_with_gimple_body_p (node)
389 || in_lto_p || DECL_RESULT (node->symbol.decl));
392 /* Inline clones might be kept around so their materializing allows further
393 cloning. If the function the clone is inlined into is removed, we need
394 to turn it into normal cone. */
395 FOR_EACH_FUNCTION (node)
397 if (node->global.inlined_to
398 && !node->callers)
400 gcc_assert (node->clones);
401 node->global.inlined_to = NULL;
402 update_inlined_to_pointer (node, node);
404 node->symbol.aux = NULL;
407 /* Remove unreachable variables. */
408 if (file)
409 fprintf (file, "\nReclaiming variables:");
410 for (vnode = varpool_first_variable (); vnode; vnode = vnext)
412 vnext = varpool_next_variable (vnode);
413 if (!vnode->symbol.aux
414 /* For can_refer_decl_in_current_unit_p we want to track for
415 all external variables if they are defined in other partition
416 or not. */
417 && (!flag_ltrans || !DECL_EXTERNAL (vnode->symbol.decl)))
419 if (file)
420 fprintf (file, " %s", varpool_node_name (vnode));
421 varpool_remove_node (vnode);
422 changed = true;
424 else if (!pointer_set_contains (reachable, vnode))
426 tree init;
427 if (vnode->symbol.definition)
429 if (file)
430 fprintf (file, " %s", varpool_node_name (vnode));
431 changed = true;
433 vnode->symbol.definition = false;
434 vnode->symbol.analyzed = false;
435 vnode->symbol.aux = NULL;
437 /* Keep body if it may be useful for constant folding. */
438 if ((init = ctor_for_folding (vnode->symbol.decl)) == error_mark_node)
439 varpool_remove_initializer (vnode);
440 else
441 DECL_INITIAL (vnode->symbol.decl) = init;
442 ipa_remove_all_references (&vnode->symbol.ref_list);
444 else
445 vnode->symbol.aux = NULL;
448 pointer_set_destroy (reachable);
449 pointer_set_destroy (body_needed_for_clonning);
451 /* Now update address_taken flags and try to promote functions to be local. */
452 if (file)
453 fprintf (file, "\nClearing address taken flags:");
454 FOR_EACH_DEFINED_FUNCTION (node)
455 if (node->symbol.address_taken
456 && !node->symbol.used_from_other_partition)
458 if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true))
460 if (file)
461 fprintf (file, " %s", cgraph_node_name (node));
462 node->symbol.address_taken = false;
463 changed = true;
464 if (cgraph_local_node_p (node))
466 node->local.local = true;
467 if (file)
468 fprintf (file, " (local)");
472 if (file)
473 fprintf (file, "\n");
475 #ifdef ENABLE_CHECKING
476 verify_symtab ();
477 #endif
479 /* If we removed something, perhaps profile could be improved. */
480 if (changed && optimize && inline_edge_summary_vec.exists ())
481 FOR_EACH_DEFINED_FUNCTION (node)
482 ipa_propagate_frequency (node);
484 return changed;
487 /* Discover variables that have no longer address taken or that are read only
488 and update their flags.
490 FIXME: This can not be done in between gimplify and omp_expand since
491 readonly flag plays role on what is shared and what is not. Currently we do
492 this transformation as part of whole program visibility and re-do at
493 ipa-reference pass (to take into account clonning), but it would
494 make sense to do it before early optimizations. */
496 void
497 ipa_discover_readonly_nonaddressable_vars (void)
499 struct varpool_node *vnode;
500 if (dump_file)
501 fprintf (dump_file, "Clearing variable flags:");
502 FOR_EACH_VARIABLE (vnode)
503 if (vnode->symbol.definition && varpool_all_refs_explicit_p (vnode)
504 && (TREE_ADDRESSABLE (vnode->symbol.decl)
505 || !TREE_READONLY (vnode->symbol.decl)))
507 bool written = false;
508 bool address_taken = false;
509 int i;
510 struct ipa_ref *ref;
511 for (i = 0; ipa_ref_list_referring_iterate (&vnode->symbol.ref_list,
512 i, ref)
513 && (!written || !address_taken); i++)
514 switch (ref->use)
516 case IPA_REF_ADDR:
517 address_taken = true;
518 break;
519 case IPA_REF_LOAD:
520 break;
521 case IPA_REF_STORE:
522 written = true;
523 break;
525 if (TREE_ADDRESSABLE (vnode->symbol.decl) && !address_taken)
527 if (dump_file)
528 fprintf (dump_file, " %s (addressable)", varpool_node_name (vnode));
529 TREE_ADDRESSABLE (vnode->symbol.decl) = 0;
531 if (!TREE_READONLY (vnode->symbol.decl) && !address_taken && !written
532 /* Making variable in explicit section readonly can cause section
533 type conflict.
534 See e.g. gcc.c-torture/compile/pr23237.c */
535 && DECL_SECTION_NAME (vnode->symbol.decl) == NULL)
537 if (dump_file)
538 fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
539 TREE_READONLY (vnode->symbol.decl) = 1;
542 if (dump_file)
543 fprintf (dump_file, "\n");
546 /* Return true when there is a reference to node and it is not vtable. */
547 static bool
548 address_taken_from_non_vtable_p (symtab_node node)
550 int i;
551 struct ipa_ref *ref;
552 for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
553 i, ref); i++)
554 if (ref->use == IPA_REF_ADDR)
556 struct varpool_node *node;
557 if (is_a <cgraph_node> (ref->referring))
558 return true;
559 node = ipa_ref_referring_varpool_node (ref);
560 if (!DECL_VIRTUAL_P (node->symbol.decl))
561 return true;
563 return false;
566 /* A helper for comdat_can_be_unshared_p. */
568 static bool
569 comdat_can_be_unshared_p_1 (symtab_node node)
571 /* When address is taken, we don't know if equality comparison won't
572 break eventually. Exception are virutal functions, C++
573 constructors/destructors and vtables, where this is not possible by
574 language standard. */
575 if (!DECL_VIRTUAL_P (node->symbol.decl)
576 && (TREE_CODE (node->symbol.decl) != FUNCTION_DECL
577 || (!DECL_CXX_CONSTRUCTOR_P (node->symbol.decl)
578 && !DECL_CXX_DESTRUCTOR_P (node->symbol.decl)))
579 && address_taken_from_non_vtable_p (node))
580 return false;
582 /* If the symbol is used in some weird way, better to not touch it. */
583 if (node->symbol.force_output)
584 return false;
586 /* Explicit instantiations needs to be output when possibly
587 used externally. */
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))
592 return false;
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)))
598 return false;
599 return true;
602 /* COMDAT functions must be shared only if they have address taken,
603 otherwise we can produce our own private implementation with
604 -fwhole-program.
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. */
611 static bool
612 comdat_can_be_unshared_p (symtab_node node)
614 if (!comdat_can_be_unshared_p_1 (node))
615 return false;
616 if (node->symbol.same_comdat_group)
618 symtab_node next;
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
622 address taken. */
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))
626 return false;
628 return true;
631 /* Return true when function NODE should be considered externally visible. */
633 static bool
634 cgraph_externally_visible_p (struct cgraph_node *node,
635 bool whole_program)
637 if (!node->symbol.definition)
638 return false;
639 if (!TREE_PUBLIC (node->symbol.decl)
640 || DECL_EXTERNAL (node->symbol.decl))
641 return false;
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))
649 return true;
651 /* If linker counts on us, we must preserve the function. */
652 if (symtab_used_from_object_file_p ((symtab_node) node))
653 return true;
654 if (DECL_PRESERVE_P (node->symbol.decl))
655 return true;
656 if (lookup_attribute ("externally_visible",
657 DECL_ATTRIBUTES (node->symbol.decl)))
658 return true;
659 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
660 && lookup_attribute ("dllexport",
661 DECL_ATTRIBUTES (node->symbol.decl)))
662 return true;
663 if (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
664 return false;
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))
672 return false;
674 /* When doing link time optimizations, hidden symbols become local. */
675 if (in_lto_p
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)
683 return true;
685 if (MAIN_NAME_P (DECL_NAME (node->symbol.decl)))
686 return true;
688 return false;
691 /* Return true when variable VNODE should be considered externally visible. */
693 bool
694 varpool_externally_visible_p (struct varpool_node *vnode)
696 if (DECL_EXTERNAL (vnode->symbol.decl))
697 return true;
699 if (!TREE_PUBLIC (vnode->symbol.decl))
700 return false;
702 /* If linker counts on us, we must preserve the function. */
703 if (symtab_used_from_object_file_p ((symtab_node) vnode))
704 return true;
706 if (DECL_HARD_REGISTER (vnode->symbol.decl))
707 return true;
708 if (DECL_PRESERVE_P (vnode->symbol.decl))
709 return true;
710 if (lookup_attribute ("externally_visible",
711 DECL_ATTRIBUTES (vnode->symbol.decl)))
712 return true;
713 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
714 && lookup_attribute ("dllexport",
715 DECL_ATTRIBUTES (vnode->symbol.decl)))
716 return true;
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))
725 return true;
726 if (vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
727 return false;
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))
737 return false;
739 /* When doing link time optimizations, hidden symbols become local. */
740 if (in_lto_p
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)
748 return true;
750 /* Do not attempt to privatize COMDATS by default.
751 This would break linking with C++ libraries sharing
752 inline definitions.
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))
758 return true;
759 return false;
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.
766 bool
767 can_replace_by_local_alias (symtab_node node)
769 return (symtab_node_availability (node) > AVAIL_OVERWRITABLE
770 && !symtab_can_be_discarded (node));
773 /* Mark visibility of all functions.
775 A local function is one whose calls can occur only in the current
776 compilation unit and all its calls are explicit, so we can change
777 its calling convention. We simply mark all static functions whose
778 address is not taken as local.
780 We also change the TREE_PUBLIC flag of all declarations that are public
781 in language point of view but we want to overwrite this default
782 via visibilities for the backend point of view. */
784 static unsigned int
785 function_and_variable_visibility (bool whole_program)
787 struct cgraph_node *node;
788 struct varpool_node *vnode;
790 /* All aliases should be procssed at this point. */
791 gcc_checking_assert (!alias_pairs || !alias_pairs->length());
793 FOR_EACH_FUNCTION (node)
795 int flags = flags_from_decl_or_type (node->symbol.decl);
797 /* Optimize away PURE and CONST constructors and destructors. */
798 if (optimize
799 && (flags & (ECF_CONST | ECF_PURE))
800 && !(flags & ECF_LOOPING_CONST_OR_PURE))
802 DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0;
803 DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0;
806 /* Frontends and alias code marks nodes as needed before parsing is finished.
807 We may end up marking as node external nodes where this flag is meaningless
808 strip it. */
809 if (DECL_EXTERNAL (node->symbol.decl) || !node->symbol.definition)
811 node->symbol.force_output = 0;
812 node->symbol.forced_by_abi = 0;
815 /* C++ FE on lack of COMDAT support create local COMDAT functions
816 (that ought to be shared but can not due to object format
817 limitations). It is necessary to keep the flag to make rest of C++ FE
818 happy. Clear the flag here to avoid confusion in middle-end. */
819 if (DECL_COMDAT (node->symbol.decl) && !TREE_PUBLIC (node->symbol.decl))
820 DECL_COMDAT (node->symbol.decl) = 0;
822 /* For external decls stop tracking same_comdat_group. It doesn't matter
823 what comdat group they are in when they won't be emitted in this TU. */
824 if (node->symbol.same_comdat_group && DECL_EXTERNAL (node->symbol.decl))
826 #ifdef ENABLE_CHECKING
827 symtab_node n;
829 for (n = node->symbol.same_comdat_group;
830 n != (symtab_node)node;
831 n = n->symbol.same_comdat_group)
832 /* If at least one of same comdat group functions is external,
833 all of them have to be, otherwise it is a front-end bug. */
834 gcc_assert (DECL_EXTERNAL (n->symbol.decl));
835 #endif
836 symtab_dissolve_same_comdat_group_list ((symtab_node) node);
838 gcc_assert ((!DECL_WEAK (node->symbol.decl)
839 && !DECL_COMDAT (node->symbol.decl))
840 || TREE_PUBLIC (node->symbol.decl)
841 || node->symbol.weakref
842 || DECL_EXTERNAL (node->symbol.decl));
843 if (cgraph_externally_visible_p (node, whole_program))
845 gcc_assert (!node->global.inlined_to);
846 node->symbol.externally_visible = true;
848 else
850 node->symbol.externally_visible = false;
851 node->symbol.forced_by_abi = false;
853 if (!node->symbol.externally_visible
854 && node->symbol.definition && !node->symbol.weakref
855 && !DECL_EXTERNAL (node->symbol.decl))
857 gcc_assert (whole_program || in_lto_p
858 || !TREE_PUBLIC (node->symbol.decl));
859 node->symbol.unique_name = ((node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
860 || node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
861 && TREE_PUBLIC (node->symbol.decl));
862 symtab_make_decl_local (node->symbol.decl);
863 node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
864 if (node->symbol.same_comdat_group)
865 /* cgraph_externally_visible_p has already checked all other nodes
866 in the group and they will all be made local. We need to
867 dissolve the group at once so that the predicate does not
868 segfault though. */
869 symtab_dissolve_same_comdat_group_list ((symtab_node) node);
872 if (node->thunk.thunk_p
873 && TREE_PUBLIC (node->symbol.decl))
875 struct cgraph_node *decl_node = node;
877 decl_node = cgraph_function_node (decl_node->callees->callee, NULL);
879 /* Thunks have the same visibility as function they are attached to.
880 Make sure the C++ front end set this up properly. */
881 if (DECL_ONE_ONLY (decl_node->symbol.decl))
883 gcc_checking_assert (DECL_COMDAT (node->symbol.decl)
884 == DECL_COMDAT (decl_node->symbol.decl));
885 gcc_checking_assert (DECL_COMDAT_GROUP (node->symbol.decl)
886 == DECL_COMDAT_GROUP (decl_node->symbol.decl));
887 gcc_checking_assert (node->symbol.same_comdat_group);
889 if (DECL_EXTERNAL (decl_node->symbol.decl))
890 DECL_EXTERNAL (node->symbol.decl) = 1;
893 FOR_EACH_DEFINED_FUNCTION (node)
895 node->local.local |= cgraph_local_node_p (node);
897 /* If we know that function can not be overwritten by a different semantics
898 and moreover its section can not be discarded, replace all direct calls
899 by calls to an nonoverwritable alias. This make dynamic linking
900 cheaper and enable more optimization.
902 TODO: We can also update virtual tables. */
903 if (node->callers && can_replace_by_local_alias ((symtab_node)node))
905 struct cgraph_node *alias = cgraph (symtab_nonoverwritable_alias ((symtab_node) node));
907 if (alias != node)
909 while (node->callers)
911 struct cgraph_edge *e = node->callers;
913 cgraph_redirect_edge_callee (e, alias);
914 if (gimple_has_body_p (e->caller->symbol.decl))
916 push_cfun (DECL_STRUCT_FUNCTION (e->caller->symbol.decl));
917 cgraph_redirect_edge_call_stmt_to_callee (e);
918 pop_cfun ();
924 FOR_EACH_VARIABLE (vnode)
926 /* weak flag makes no sense on local variables. */
927 gcc_assert (!DECL_WEAK (vnode->symbol.decl)
928 || vnode->symbol.weakref
929 || TREE_PUBLIC (vnode->symbol.decl)
930 || DECL_EXTERNAL (vnode->symbol.decl));
931 /* In several cases declarations can not be common:
933 - when declaration has initializer
934 - when it is in weak
935 - when it has specific section
936 - when it resides in non-generic address space.
937 - if declaration is local, it will get into .local common section
938 so common flag is not needed. Frontends still produce these in
939 certain cases, such as for:
941 static int a __attribute__ ((common))
943 Canonicalize things here and clear the redundant flag. */
944 if (DECL_COMMON (vnode->symbol.decl)
945 && (!(TREE_PUBLIC (vnode->symbol.decl)
946 || DECL_EXTERNAL (vnode->symbol.decl))
947 || (DECL_INITIAL (vnode->symbol.decl)
948 && DECL_INITIAL (vnode->symbol.decl) != error_mark_node)
949 || DECL_WEAK (vnode->symbol.decl)
950 || DECL_SECTION_NAME (vnode->symbol.decl) != NULL
951 || ! (ADDR_SPACE_GENERIC_P
952 (TYPE_ADDR_SPACE (TREE_TYPE (vnode->symbol.decl))))))
953 DECL_COMMON (vnode->symbol.decl) = 0;
955 FOR_EACH_DEFINED_VARIABLE (vnode)
957 if (!vnode->symbol.definition)
958 continue;
959 if (varpool_externally_visible_p (vnode))
960 vnode->symbol.externally_visible = true;
961 else
963 vnode->symbol.externally_visible = false;
964 vnode->symbol.forced_by_abi = false;
966 if (!vnode->symbol.externally_visible
967 && !vnode->symbol.weakref)
969 gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl));
970 vnode->symbol.unique_name = ((vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY
971 || vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
972 && TREE_PUBLIC (vnode->symbol.decl));
973 symtab_make_decl_local (vnode->symbol.decl);
974 if (vnode->symbol.same_comdat_group)
975 symtab_dissolve_same_comdat_group_list ((symtab_node) vnode);
976 vnode->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
980 if (dump_file)
982 fprintf (dump_file, "\nMarking local functions:");
983 FOR_EACH_DEFINED_FUNCTION (node)
984 if (node->local.local)
985 fprintf (dump_file, " %s", cgraph_node_name (node));
986 fprintf (dump_file, "\n\n");
987 fprintf (dump_file, "\nMarking externally visible functions:");
988 FOR_EACH_DEFINED_FUNCTION (node)
989 if (node->symbol.externally_visible)
990 fprintf (dump_file, " %s", cgraph_node_name (node));
991 fprintf (dump_file, "\n\n");
992 fprintf (dump_file, "\nMarking externally visible variables:");
993 FOR_EACH_DEFINED_VARIABLE (vnode)
994 if (vnode->symbol.externally_visible)
995 fprintf (dump_file, " %s", varpool_node_name (vnode));
996 fprintf (dump_file, "\n\n");
998 cgraph_function_flags_ready = true;
999 return 0;
1002 /* Local function pass handling visibilities. This happens before LTO streaming
1003 so in particular -fwhole-program should be ignored at this level. */
1005 static unsigned int
1006 local_function_and_variable_visibility (void)
1008 return function_and_variable_visibility (flag_whole_program && !flag_lto);
1011 namespace {
1013 const pass_data pass_data_ipa_function_and_variable_visibility =
1015 SIMPLE_IPA_PASS, /* type */
1016 "visibility", /* name */
1017 OPTGROUP_NONE, /* optinfo_flags */
1018 false, /* has_gate */
1019 true, /* has_execute */
1020 TV_CGRAPHOPT, /* tv_id */
1021 0, /* properties_required */
1022 0, /* properties_provided */
1023 0, /* properties_destroyed */
1024 0, /* todo_flags_start */
1025 ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
1028 class pass_ipa_function_and_variable_visibility : public simple_ipa_opt_pass
1030 public:
1031 pass_ipa_function_and_variable_visibility(gcc::context *ctxt)
1032 : simple_ipa_opt_pass(pass_data_ipa_function_and_variable_visibility, ctxt)
1035 /* opt_pass methods: */
1036 unsigned int execute () {
1037 return local_function_and_variable_visibility ();
1040 }; // class pass_ipa_function_and_variable_visibility
1042 } // anon namespace
1044 simple_ipa_opt_pass *
1045 make_pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
1047 return new pass_ipa_function_and_variable_visibility (ctxt);
1050 /* Free inline summary. */
1052 static unsigned
1053 free_inline_summary (void)
1055 inline_free_summary ();
1056 return 0;
1059 namespace {
1061 const pass_data pass_data_ipa_free_inline_summary =
1063 SIMPLE_IPA_PASS, /* type */
1064 "*free_inline_summary", /* name */
1065 OPTGROUP_NONE, /* optinfo_flags */
1066 false, /* has_gate */
1067 true, /* has_execute */
1068 TV_IPA_FREE_INLINE_SUMMARY, /* tv_id */
1069 0, /* properties_required */
1070 0, /* properties_provided */
1071 0, /* properties_destroyed */
1072 0, /* todo_flags_start */
1073 0, /* todo_flags_finish */
1076 class pass_ipa_free_inline_summary : public simple_ipa_opt_pass
1078 public:
1079 pass_ipa_free_inline_summary(gcc::context *ctxt)
1080 : simple_ipa_opt_pass(pass_data_ipa_free_inline_summary, ctxt)
1083 /* opt_pass methods: */
1084 unsigned int execute () { return free_inline_summary (); }
1086 }; // class pass_ipa_free_inline_summary
1088 } // anon namespace
1090 simple_ipa_opt_pass *
1091 make_pass_ipa_free_inline_summary (gcc::context *ctxt)
1093 return new pass_ipa_free_inline_summary (ctxt);
1096 /* Do not re-run on ltrans stage. */
1098 static bool
1099 gate_whole_program_function_and_variable_visibility (void)
1101 return !flag_ltrans;
1104 /* Bring functionss local at LTO time with -fwhole-program. */
1106 static unsigned int
1107 whole_program_function_and_variable_visibility (void)
1109 function_and_variable_visibility (flag_whole_program);
1110 if (optimize)
1111 ipa_discover_readonly_nonaddressable_vars ();
1112 return 0;
1115 namespace {
1117 const pass_data pass_data_ipa_whole_program_visibility =
1119 IPA_PASS, /* type */
1120 "whole-program", /* name */
1121 OPTGROUP_NONE, /* optinfo_flags */
1122 true, /* has_gate */
1123 true, /* has_execute */
1124 TV_CGRAPHOPT, /* tv_id */
1125 0, /* properties_required */
1126 0, /* properties_provided */
1127 0, /* properties_destroyed */
1128 0, /* todo_flags_start */
1129 ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
1132 class pass_ipa_whole_program_visibility : public ipa_opt_pass_d
1134 public:
1135 pass_ipa_whole_program_visibility(gcc::context *ctxt)
1136 : ipa_opt_pass_d(pass_data_ipa_whole_program_visibility, ctxt,
1137 NULL, /* generate_summary */
1138 NULL, /* write_summary */
1139 NULL, /* read_summary */
1140 NULL, /* write_optimization_summary */
1141 NULL, /* read_optimization_summary */
1142 NULL, /* stmt_fixup */
1143 0, /* function_transform_todo_flags_start */
1144 NULL, /* function_transform */
1145 NULL) /* variable_transform */
1148 /* opt_pass methods: */
1149 bool gate () {
1150 return gate_whole_program_function_and_variable_visibility ();
1152 unsigned int execute () {
1153 return whole_program_function_and_variable_visibility ();
1156 }; // class pass_ipa_whole_program_visibility
1158 } // anon namespace
1160 ipa_opt_pass_d *
1161 make_pass_ipa_whole_program_visibility (gcc::context *ctxt)
1163 return new pass_ipa_whole_program_visibility (ctxt);
1166 /* Generate and emit a static constructor or destructor. WHICH must
1167 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1168 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1169 initialization priority for this constructor or destructor.
1171 FINAL specify whether the externally visible name for collect2 should
1172 be produced. */
1174 static void
1175 cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
1177 static int counter = 0;
1178 char which_buf[16];
1179 tree decl, name, resdecl;
1181 /* The priority is encoded in the constructor or destructor name.
1182 collect2 will sort the names and arrange that they are called at
1183 program startup. */
1184 if (final)
1185 sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
1186 else
1187 /* Proudce sane name but one not recognizable by collect2, just for the
1188 case we fail to inline the function. */
1189 sprintf (which_buf, "sub_%c_%.5d_%d", which, priority, counter++);
1190 name = get_file_function_name (which_buf);
1192 decl = build_decl (input_location, FUNCTION_DECL, name,
1193 build_function_type_list (void_type_node, NULL_TREE));
1194 current_function_decl = decl;
1196 resdecl = build_decl (input_location,
1197 RESULT_DECL, NULL_TREE, void_type_node);
1198 DECL_ARTIFICIAL (resdecl) = 1;
1199 DECL_RESULT (decl) = resdecl;
1200 DECL_CONTEXT (resdecl) = decl;
1202 allocate_struct_function (decl, false);
1204 TREE_STATIC (decl) = 1;
1205 TREE_USED (decl) = 1;
1206 DECL_ARTIFICIAL (decl) = 1;
1207 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1208 DECL_SAVED_TREE (decl) = body;
1209 if (!targetm.have_ctors_dtors && final)
1211 TREE_PUBLIC (decl) = 1;
1212 DECL_PRESERVE_P (decl) = 1;
1214 DECL_UNINLINABLE (decl) = 1;
1216 DECL_INITIAL (decl) = make_node (BLOCK);
1217 TREE_USED (DECL_INITIAL (decl)) = 1;
1219 DECL_SOURCE_LOCATION (decl) = input_location;
1220 cfun->function_end_locus = input_location;
1222 switch (which)
1224 case 'I':
1225 DECL_STATIC_CONSTRUCTOR (decl) = 1;
1226 decl_init_priority_insert (decl, priority);
1227 break;
1228 case 'D':
1229 DECL_STATIC_DESTRUCTOR (decl) = 1;
1230 decl_fini_priority_insert (decl, priority);
1231 break;
1232 default:
1233 gcc_unreachable ();
1236 gimplify_function_tree (decl);
1238 cgraph_add_new_function (decl, false);
1240 set_cfun (NULL);
1241 current_function_decl = NULL;
1244 /* Generate and emit a static constructor or destructor. WHICH must
1245 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1246 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1247 initialization priority for this constructor or destructor. */
1249 void
1250 cgraph_build_static_cdtor (char which, tree body, int priority)
1252 cgraph_build_static_cdtor_1 (which, body, priority, false);
1255 /* A vector of FUNCTION_DECLs declared as static constructors. */
1256 static vec<tree> static_ctors;
1257 /* A vector of FUNCTION_DECLs declared as static destructors. */
1258 static vec<tree> static_dtors;
1260 /* When target does not have ctors and dtors, we call all constructor
1261 and destructor by special initialization/destruction function
1262 recognized by collect2.
1264 When we are going to build this function, collect all constructors and
1265 destructors and turn them into normal functions. */
1267 static void
1268 record_cdtor_fn (struct cgraph_node *node)
1270 if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
1271 static_ctors.safe_push (node->symbol.decl);
1272 if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
1273 static_dtors.safe_push (node->symbol.decl);
1274 node = cgraph_get_node (node->symbol.decl);
1275 DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl) = 1;
1278 /* Define global constructors/destructor functions for the CDTORS, of
1279 which they are LEN. The CDTORS are sorted by initialization
1280 priority. If CTOR_P is true, these are constructors; otherwise,
1281 they are destructors. */
1283 static void
1284 build_cdtor (bool ctor_p, vec<tree> cdtors)
1286 size_t i,j;
1287 size_t len = cdtors.length ();
1289 i = 0;
1290 while (i < len)
1292 tree body;
1293 tree fn;
1294 priority_type priority;
1296 priority = 0;
1297 body = NULL_TREE;
1298 j = i;
1301 priority_type p;
1302 fn = cdtors[j];
1303 p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
1304 if (j == i)
1305 priority = p;
1306 else if (p != priority)
1307 break;
1308 j++;
1310 while (j < len);
1312 /* When there is only one cdtor and target supports them, do nothing. */
1313 if (j == i + 1
1314 && targetm.have_ctors_dtors)
1316 i++;
1317 continue;
1319 /* Find the next batch of constructors/destructors with the same
1320 initialization priority. */
1321 for (;i < j; i++)
1323 tree call;
1324 fn = cdtors[i];
1325 call = build_call_expr (fn, 0);
1326 if (ctor_p)
1327 DECL_STATIC_CONSTRUCTOR (fn) = 0;
1328 else
1329 DECL_STATIC_DESTRUCTOR (fn) = 0;
1330 /* We do not want to optimize away pure/const calls here.
1331 When optimizing, these should be already removed, when not
1332 optimizing, we want user to be able to breakpoint in them. */
1333 TREE_SIDE_EFFECTS (call) = 1;
1334 append_to_statement_list (call, &body);
1336 gcc_assert (body != NULL_TREE);
1337 /* Generate a function to call all the function of like
1338 priority. */
1339 cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true);
1343 /* Comparison function for qsort. P1 and P2 are actually of type
1344 "tree *" and point to static constructors. DECL_INIT_PRIORITY is
1345 used to determine the sort order. */
1347 static int
1348 compare_ctor (const void *p1, const void *p2)
1350 tree f1;
1351 tree f2;
1352 int priority1;
1353 int priority2;
1355 f1 = *(const tree *)p1;
1356 f2 = *(const tree *)p2;
1357 priority1 = DECL_INIT_PRIORITY (f1);
1358 priority2 = DECL_INIT_PRIORITY (f2);
1360 if (priority1 < priority2)
1361 return -1;
1362 else if (priority1 > priority2)
1363 return 1;
1364 else
1365 /* Ensure a stable sort. Constructors are executed in backwarding
1366 order to make LTO initialize braries first. */
1367 return DECL_UID (f2) - DECL_UID (f1);
1370 /* Comparison function for qsort. P1 and P2 are actually of type
1371 "tree *" and point to static destructors. DECL_FINI_PRIORITY is
1372 used to determine the sort order. */
1374 static int
1375 compare_dtor (const void *p1, const void *p2)
1377 tree f1;
1378 tree f2;
1379 int priority1;
1380 int priority2;
1382 f1 = *(const tree *)p1;
1383 f2 = *(const tree *)p2;
1384 priority1 = DECL_FINI_PRIORITY (f1);
1385 priority2 = DECL_FINI_PRIORITY (f2);
1387 if (priority1 < priority2)
1388 return -1;
1389 else if (priority1 > priority2)
1390 return 1;
1391 else
1392 /* Ensure a stable sort. */
1393 return DECL_UID (f1) - DECL_UID (f2);
1396 /* Generate functions to call static constructors and destructors
1397 for targets that do not support .ctors/.dtors sections. These
1398 functions have magic names which are detected by collect2. */
1400 static void
1401 build_cdtor_fns (void)
1403 if (!static_ctors.is_empty ())
1405 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1406 static_ctors.qsort (compare_ctor);
1407 build_cdtor (/*ctor_p=*/true, static_ctors);
1410 if (!static_dtors.is_empty ())
1412 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1413 static_dtors.qsort (compare_dtor);
1414 build_cdtor (/*ctor_p=*/false, static_dtors);
1418 /* Look for constructors and destructors and produce function calling them.
1419 This is needed for targets not supporting ctors or dtors, but we perform the
1420 transformation also at linktime to merge possibly numerous
1421 constructors/destructors into single function to improve code locality and
1422 reduce size. */
1424 static unsigned int
1425 ipa_cdtor_merge (void)
1427 struct cgraph_node *node;
1428 FOR_EACH_DEFINED_FUNCTION (node)
1429 if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
1430 || DECL_STATIC_DESTRUCTOR (node->symbol.decl))
1431 record_cdtor_fn (node);
1432 build_cdtor_fns ();
1433 static_ctors.release ();
1434 static_dtors.release ();
1435 return 0;
1438 /* Perform the pass when we have no ctors/dtors support
1439 or at LTO time to merge multiple constructors into single
1440 function. */
1442 static bool
1443 gate_ipa_cdtor_merge (void)
1445 return !targetm.have_ctors_dtors || (optimize && in_lto_p);
1448 namespace {
1450 const pass_data pass_data_ipa_cdtor_merge =
1452 IPA_PASS, /* type */
1453 "cdtor", /* name */
1454 OPTGROUP_NONE, /* optinfo_flags */
1455 true, /* has_gate */
1456 true, /* has_execute */
1457 TV_CGRAPHOPT, /* tv_id */
1458 0, /* properties_required */
1459 0, /* properties_provided */
1460 0, /* properties_destroyed */
1461 0, /* todo_flags_start */
1462 0, /* todo_flags_finish */
1465 class pass_ipa_cdtor_merge : public ipa_opt_pass_d
1467 public:
1468 pass_ipa_cdtor_merge(gcc::context *ctxt)
1469 : ipa_opt_pass_d(pass_data_ipa_cdtor_merge, ctxt,
1470 NULL, /* generate_summary */
1471 NULL, /* write_summary */
1472 NULL, /* read_summary */
1473 NULL, /* write_optimization_summary */
1474 NULL, /* read_optimization_summary */
1475 NULL, /* stmt_fixup */
1476 0, /* function_transform_todo_flags_start */
1477 NULL, /* function_transform */
1478 NULL) /* variable_transform */
1481 /* opt_pass methods: */
1482 bool gate () { return gate_ipa_cdtor_merge (); }
1483 unsigned int execute () { return ipa_cdtor_merge (); }
1485 }; // class pass_ipa_cdtor_merge
1487 } // anon namespace
1489 ipa_opt_pass_d *
1490 make_pass_ipa_cdtor_merge (gcc::context *ctxt)
1492 return new pass_ipa_cdtor_merge (ctxt);