lto-symtab.c (lto_cgraph_replace_node): Do not call mark_reahcable_node.
[gcc.git] / gcc / ipa.c
1 /* Basic IPA optimizations and utilities.
2 Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
3 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "cgraph.h"
26 #include "tree-pass.h"
27 #include "timevar.h"
28 #include "gimple.h"
29 #include "ggc.h"
30 #include "flags.h"
31 #include "pointer-set.h"
32 #include "target.h"
33 #include "tree-iterator.h"
34 #include "ipa-utils.h"
35 #include "pointer-set.h"
36
37 /* Look for all functions inlined to NODE and update their inlined_to pointers
38 to INLINED_TO. */
39
40 static void
41 update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
42 {
43 struct cgraph_edge *e;
44 for (e = node->callees; e; e = e->next_callee)
45 if (e->callee->global.inlined_to)
46 {
47 e->callee->global.inlined_to = inlined_to;
48 update_inlined_to_pointer (e->callee, inlined_to);
49 }
50 }
51
52 /* Add cgraph NODE to queue starting at FIRST.
53
54 The queue is linked via AUX pointers and terminated by pointer to 1.
55 We enqueue nodes at two occasions: when we find them reachable or when we find
56 their bodies needed for further clonning. In the second case we mark them
57 by pointer to 2 after processing so they are re-queue when they become
58 reachable. */
59
60 static void
61 enqueue_cgraph_node (struct cgraph_node *node, struct cgraph_node **first,
62 struct pointer_set_t *reachable)
63 {
64 /* Node is still in queue; do nothing. */
65 if (node->symbol.aux && node->symbol.aux != (void *) 2)
66 return;
67 /* Node was already processed as unreachable, re-enqueue
68 only if it became reachable now. */
69 if (node->symbol.aux == (void *)2 && !pointer_set_contains (reachable, node))
70 return;
71 node->symbol.aux = *first;
72 *first = node;
73 }
74
75 /* Add varpool NODE to queue starting at FIRST. */
76
77 static void
78 enqueue_varpool_node (struct varpool_node *node, struct varpool_node **first)
79 {
80 node->symbol.aux = *first;
81 *first = node;
82 }
83
84 /* Process references. */
85
86 static void
87 process_references (struct ipa_ref_list *list,
88 struct cgraph_node **first,
89 struct varpool_node **first_varpool,
90 bool before_inlining_p,
91 struct pointer_set_t *reachable)
92 {
93 int i;
94 struct ipa_ref *ref;
95 for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++)
96 {
97 if (symtab_function_p (ref->referred))
98 {
99 struct cgraph_node *node = ipa_ref_node (ref);
100 if (node->analyzed
101 && (!DECL_EXTERNAL (node->symbol.decl)
102 || node->alias
103 || before_inlining_p))
104 pointer_set_insert (reachable, node);
105 enqueue_cgraph_node (node, first, reachable);
106 }
107 else
108 {
109 struct varpool_node *node = ipa_ref_varpool_node (ref);
110 if (!pointer_set_insert (reachable, node))
111 enqueue_varpool_node (node, first_varpool);
112 }
113 }
114 }
115
116
117 /* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
118
119 static bool
120 cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
121 {
122 /* FIXME: Aliases can be local, but i386 gets thunks wrong then. */
123 return !(cgraph_only_called_directly_or_aliased_p (node)
124 && !ipa_ref_has_aliases_p (&node->symbol.ref_list)
125 && node->analyzed
126 && !DECL_EXTERNAL (node->symbol.decl)
127 && !node->symbol.externally_visible
128 && !node->symbol.used_from_other_partition
129 && !node->symbol.in_other_partition);
130 }
131
132 /* Return true when function can be marked local. */
133
134 static bool
135 cgraph_local_node_p (struct cgraph_node *node)
136 {
137 struct cgraph_node *n = cgraph_function_or_thunk_node (node, NULL);
138
139 /* FIXME: thunks can be considered local, but we need prevent i386
140 from attempting to change calling convention of them. */
141 if (n->thunk.thunk_p)
142 return false;
143 return !cgraph_for_node_and_aliases (n,
144 cgraph_non_local_node_p_1, NULL, true);
145
146 }
147
148 /* Return true when NODE has ADDR reference. */
149
150 static bool
151 has_addr_references_p (struct cgraph_node *node,
152 void *data ATTRIBUTE_UNUSED)
153 {
154 int i;
155 struct ipa_ref *ref;
156
157 for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
158 i, ref); i++)
159 if (ref->use == IPA_REF_ADDR)
160 return true;
161 return false;
162 }
163
164 /* Perform reachability analysis and reclaim all unreachable nodes.
165 If BEFORE_INLINING_P is true this function is called before inlining
166 decisions has been made. If BEFORE_INLINING_P is false this function also
167 removes unneeded bodies of extern inline functions. */
168
169 bool
170 cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
171 {
172 struct cgraph_node *first = (struct cgraph_node *) (void *) 1;
173 struct varpool_node *first_varpool = (struct varpool_node *) (void *) 1;
174 struct cgraph_node *node, *next;
175 struct varpool_node *vnode, *vnext;
176 bool changed = false;
177 struct pointer_set_t *reachable = pointer_set_create ();
178
179 #ifdef ENABLE_CHECKING
180 verify_symtab ();
181 #endif
182 if (file)
183 fprintf (file, "\nReclaiming functions:");
184 #ifdef ENABLE_CHECKING
185 FOR_EACH_FUNCTION (node)
186 gcc_assert (!node->symbol.aux);
187 FOR_EACH_VARIABLE (vnode)
188 gcc_assert (!vnode->symbol.aux);
189 #endif
190 /* Mark functions whose bodies are obviously needed.
191 This is mostly when they can be referenced externally. Inline clones
192 are special since their declarations are shared with master clone and thus
193 cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them. */
194 FOR_EACH_FUNCTION (node)
195 if (node->analyzed && !node->global.inlined_to
196 && (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
197 /* Keep around virtual functions for possible devirtualization. */
198 || (before_inlining_p
199 && DECL_VIRTUAL_P (node->symbol.decl)
200 && (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl)))))
201 {
202 gcc_assert (!node->global.inlined_to);
203 enqueue_cgraph_node (node, &first, reachable);
204 pointer_set_insert (reachable, node);
205 }
206 else
207 gcc_assert (!node->symbol.aux);
208
209 /* Mark variables that are obviously needed. */
210 FOR_EACH_VARIABLE (vnode)
211 {
212 if ((vnode->analyzed || vnode->symbol.force_output)
213 && !varpool_can_remove_if_no_refs (vnode))
214 {
215 pointer_set_insert (reachable, vnode);
216 enqueue_varpool_node (vnode, &first_varpool);
217 }
218 }
219
220 /* Perform reachability analysis. As a special case do not consider
221 extern inline functions not inlined as live because we won't output
222 them at all.
223
224 We maintain two worklist, one for cgraph nodes other for varpools and
225 are finished once both are empty. */
226
227 while (first != (struct cgraph_node *) (void *) 1
228 || first_varpool != (struct varpool_node *) (void *) 1)
229 {
230 if (first != (struct cgraph_node *) (void *) 1)
231 {
232 struct cgraph_edge *e;
233 node = first;
234 first = (struct cgraph_node *) first->symbol.aux;
235 if (!pointer_set_contains (reachable, node))
236 node->symbol.aux = (void *)2;
237 /* If we found this node reachable, first mark on the callees
238 reachable too, unless they are direct calls to extern inline functions
239 we decided to not inline. */
240 else
241 {
242 for (e = node->callees; e; e = e->next_callee)
243 {
244 if (node->analyzed
245 && (!e->inline_failed
246 || !DECL_EXTERNAL (e->callee->symbol.decl)
247 || node->alias
248 || before_inlining_p))
249 pointer_set_insert (reachable, e->callee);
250 enqueue_cgraph_node (e->callee, &first, reachable);
251 }
252 process_references (&node->symbol.ref_list, &first,
253 &first_varpool, before_inlining_p,
254 reachable);
255
256 /* If any function in a comdat group is reachable, force
257 all other functions in the same comdat group to be
258 also reachable. */
259 if (node->symbol.same_comdat_group
260 && !node->global.inlined_to)
261 {
262 for (next = cgraph (node->symbol.same_comdat_group);
263 next != node;
264 next = cgraph (next->symbol.same_comdat_group))
265 if (!pointer_set_insert (reachable, next))
266 enqueue_cgraph_node (next, &first, reachable);
267 }
268 }
269
270 /* We can freely remove inline clones even if they are cloned, however if
271 function is clone of real clone, we must keep it around in order to
272 make materialize_clones produce function body with the changes
273 applied. */
274 while (node->clone_of && !node->clone_of->symbol.aux
275 && !gimple_has_body_p (node->symbol.decl))
276 {
277 bool noninline = node->clone_of->symbol.decl != node->symbol.decl;
278 node = node->clone_of;
279 if (noninline && !pointer_set_insert (reachable, node) && !node->symbol.aux)
280 {
281 enqueue_cgraph_node (node, &first, reachable);
282 break;
283 }
284 }
285 }
286 if (first_varpool != (struct varpool_node *) (void *) 1)
287 {
288 vnode = first_varpool;
289 first_varpool = (struct varpool_node *)first_varpool->symbol.aux;
290 vnode->symbol.aux = NULL;
291 process_references (&vnode->symbol.ref_list, &first,
292 &first_varpool, before_inlining_p,
293 reachable);
294 /* If any function in a comdat group is reachable, force
295 all other functions in the same comdat group to be
296 also reachable. */
297 if (vnode->symbol.same_comdat_group)
298 {
299 struct varpool_node *next;
300 for (next = varpool (vnode->symbol.same_comdat_group);
301 next != vnode;
302 next = varpool (next->symbol.same_comdat_group))
303 if (!pointer_set_insert (reachable, next))
304 enqueue_varpool_node (next, &first_varpool);
305 }
306 }
307 }
308
309 /* Remove unreachable nodes.
310
311 Completely unreachable functions can be fully removed from the callgraph.
312 Extern inline functions that we decided to not inline need to become unanalyzed nodes of
313 callgraph (so we still have edges to them). We remove function body then.
314
315 Also we need to care functions that are unreachable but we need to keep them around
316 for later clonning. In this case we also turn them to unanalyzed nodes, but
317 keep the body around. */
318 for (node = cgraph_first_function (); node; node = next)
319 {
320 next = cgraph_next_function (node);
321 if (node->symbol.aux && !pointer_set_contains (reachable, node))
322 {
323 cgraph_node_remove_callees (node);
324 ipa_remove_all_references (&node->symbol.ref_list);
325 node->analyzed = false;
326 }
327 if (!node->symbol.aux)
328 {
329 struct cgraph_edge *e;
330 bool found = false;
331 int i;
332 struct ipa_ref *ref;
333
334 node->global.inlined_to = NULL;
335 if (file)
336 fprintf (file, " %s", cgraph_node_name (node));
337 /* See if there is reachable caller. */
338 for (e = node->callers; e && !found; e = e->next_caller)
339 if (pointer_set_contains (reachable, e->caller))
340 found = true;
341 for (i = 0; (ipa_ref_list_referring_iterate (&node->symbol.ref_list,
342 i, ref)
343 && !found); i++)
344 if (pointer_set_contains (reachable, ref->referring))
345 found = true;
346
347 /* If so, we need to keep node in the callgraph. */
348 if (found)
349 {
350 if (node->analyzed)
351 {
352 struct cgraph_node *clone;
353
354 /* If there are still clones, we must keep body around.
355 Otherwise we can just remove the body but keep the clone. */
356 for (clone = node->clones; clone;
357 clone = clone->next_sibling_clone)
358 if (clone->symbol.aux)
359 break;
360 if (!clone)
361 {
362 cgraph_release_function_body (node);
363 if (node->prev_sibling_clone)
364 node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
365 else if (node->clone_of)
366 node->clone_of->clones = node->next_sibling_clone;
367 if (node->next_sibling_clone)
368 node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
369 if (node->clone_of)
370 node->former_clone_of = node->clone_of->symbol.decl;
371 node->clone_of = NULL;
372 node->next_sibling_clone = NULL;
373 node->prev_sibling_clone = NULL;
374 }
375 else
376 gcc_assert (!clone->symbol.in_other_partition);
377 node->analyzed = false;
378 changed = true;
379 cgraph_node_remove_callees (node);
380 ipa_remove_all_references (&node->symbol.ref_list);
381 }
382 }
383 else
384 {
385 cgraph_remove_node (node);
386 changed = true;
387 }
388 }
389 }
390 FOR_EACH_FUNCTION (node)
391 {
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 if (node->global.inlined_to
396 && !node->callers)
397 {
398 gcc_assert (node->clones);
399 node->global.inlined_to = NULL;
400 update_inlined_to_pointer (node, node);
401 }
402 node->symbol.aux = NULL;
403 }
404
405 if (file)
406 fprintf (file, "\n");
407
408 if (file)
409 fprintf (file, "Reclaiming variables:");
410 for (vnode = varpool_first_variable (); vnode; vnode = vnext)
411 {
412 vnext = varpool_next_variable (vnode);
413 if (!pointer_set_contains (reachable, vnode))
414 {
415 if (file)
416 fprintf (file, " %s", varpool_node_name (vnode));
417 varpool_remove_node (vnode);
418 changed = true;
419 }
420 }
421
422 /* Now update address_taken flags and try to promote functions to be local. */
423
424 if (file)
425 fprintf (file, "\nClearing address taken flags:");
426 FOR_EACH_DEFINED_FUNCTION (node)
427 if (node->symbol.address_taken
428 && !node->symbol.used_from_other_partition)
429 {
430 if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true))
431 {
432 if (file)
433 fprintf (file, " %s", cgraph_node_name (node));
434 node->symbol.address_taken = false;
435 changed = true;
436 if (cgraph_local_node_p (node))
437 {
438 node->local.local = true;
439 if (file)
440 fprintf (file, " (local)");
441 }
442 }
443 }
444 if (file)
445 fprintf (file, "\n");
446
447 /* Rest of transformations are undesirable at -O0. */
448 if (!optimize)
449 return changed;
450
451 #ifdef ENABLE_CHECKING
452 verify_symtab ();
453 #endif
454
455 /* Reclaim alias pairs for functions that have disappeared from the
456 call graph. */
457 remove_unreachable_alias_pairs ();
458 pointer_set_destroy (reachable);
459
460 return changed;
461 }
462
463 /* Discover variables that have no longer address taken or that are read only
464 and update their flags.
465
466 FIXME: This can not be done in between gimplify and omp_expand since
467 readonly flag plays role on what is shared and what is not. Currently we do
468 this transformation as part of whole program visibility and re-do at
469 ipa-reference pass (to take into account clonning), but it would
470 make sense to do it before early optimizations. */
471
472 void
473 ipa_discover_readonly_nonaddressable_vars (void)
474 {
475 struct varpool_node *vnode;
476 if (dump_file)
477 fprintf (dump_file, "Clearing variable flags:");
478 FOR_EACH_VARIABLE (vnode)
479 if (vnode->finalized && varpool_all_refs_explicit_p (vnode)
480 && (TREE_ADDRESSABLE (vnode->symbol.decl)
481 || !TREE_READONLY (vnode->symbol.decl)))
482 {
483 bool written = false;
484 bool address_taken = false;
485 int i;
486 struct ipa_ref *ref;
487 for (i = 0; ipa_ref_list_referring_iterate (&vnode->symbol.ref_list,
488 i, ref)
489 && (!written || !address_taken); i++)
490 switch (ref->use)
491 {
492 case IPA_REF_ADDR:
493 address_taken = true;
494 break;
495 case IPA_REF_LOAD:
496 break;
497 case IPA_REF_STORE:
498 written = true;
499 break;
500 }
501 if (TREE_ADDRESSABLE (vnode->symbol.decl) && !address_taken)
502 {
503 if (dump_file)
504 fprintf (dump_file, " %s (addressable)", varpool_node_name (vnode));
505 TREE_ADDRESSABLE (vnode->symbol.decl) = 0;
506 }
507 if (!TREE_READONLY (vnode->symbol.decl) && !address_taken && !written
508 /* Making variable in explicit section readonly can cause section
509 type conflict.
510 See e.g. gcc.c-torture/compile/pr23237.c */
511 && DECL_SECTION_NAME (vnode->symbol.decl) == NULL)
512 {
513 if (dump_file)
514 fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
515 TREE_READONLY (vnode->symbol.decl) = 1;
516 }
517 }
518 if (dump_file)
519 fprintf (dump_file, "\n");
520 }
521
522 /* Return true when there is a reference to node and it is not vtable. */
523 static bool
524 cgraph_address_taken_from_non_vtable_p (struct cgraph_node *node)
525 {
526 int i;
527 struct ipa_ref *ref;
528 for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list,
529 i, ref); i++)
530 if (ref->use == IPA_REF_ADDR)
531 {
532 struct varpool_node *node;
533 if (symtab_function_p (ref->referring))
534 return true;
535 node = ipa_ref_referring_varpool_node (ref);
536 if (!DECL_VIRTUAL_P (node->symbol.decl))
537 return true;
538 }
539 return false;
540 }
541
542 /* COMDAT functions must be shared only if they have address taken,
543 otherwise we can produce our own private implementation with
544 -fwhole-program.
545 Return true when turning COMDAT functoin static can not lead to wrong
546 code when the resulting object links with a library defining same COMDAT.
547
548 Virtual functions do have their addresses taken from the vtables,
549 but in C++ there is no way to compare their addresses for equality. */
550
551 bool
552 cgraph_comdat_can_be_unshared_p (struct cgraph_node *node)
553 {
554 if ((cgraph_address_taken_from_non_vtable_p (node)
555 && !DECL_VIRTUAL_P (node->symbol.decl))
556 || !node->analyzed)
557 return false;
558 if (node->symbol.same_comdat_group)
559 {
560 struct cgraph_node *next;
561
562 /* If more than one function is in the same COMDAT group, it must
563 be shared even if just one function in the comdat group has
564 address taken. */
565 for (next = cgraph (node->symbol.same_comdat_group);
566 next != node; next = cgraph (next->symbol.same_comdat_group))
567 if (cgraph_address_taken_from_non_vtable_p (next)
568 && !DECL_VIRTUAL_P (next->symbol.decl))
569 return false;
570 }
571 return true;
572 }
573
574 /* Return true when function NODE should be considered externally visible. */
575
576 static bool
577 cgraph_externally_visible_p (struct cgraph_node *node,
578 bool whole_program, bool aliased)
579 {
580 if (!node->local.finalized)
581 return false;
582 if (!DECL_COMDAT (node->symbol.decl)
583 && (!TREE_PUBLIC (node->symbol.decl)
584 || DECL_EXTERNAL (node->symbol.decl)))
585 return false;
586
587 /* Do not even try to be smart about aliased nodes. Until we properly
588 represent everything by same body alias, these are just evil. */
589 if (aliased)
590 return true;
591
592 /* Do not try to localize built-in functions yet. One of problems is that we
593 end up mangling their asm for WHOPR that makes it impossible to call them
594 using the implicit built-in declarations anymore. Similarly this enables
595 us to remove them as unreachable before actual calls may appear during
596 expansion or folding. */
597 if (DECL_BUILT_IN (node->symbol.decl))
598 return true;
599
600 /* If linker counts on us, we must preserve the function. */
601 if (cgraph_used_from_object_file_p (node))
602 return true;
603 if (DECL_PRESERVE_P (node->symbol.decl))
604 return true;
605 if (lookup_attribute ("externally_visible",
606 DECL_ATTRIBUTES (node->symbol.decl)))
607 return true;
608 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
609 && lookup_attribute ("dllexport",
610 DECL_ATTRIBUTES (node->symbol.decl)))
611 return true;
612 if (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
613 return false;
614 /* When doing LTO or whole program, we can bring COMDAT functoins static.
615 This improves code quality and we know we will duplicate them at most twice
616 (in the case that we are not using plugin and link with object file
617 implementing same COMDAT) */
618 if ((in_lto_p || whole_program)
619 && DECL_COMDAT (node->symbol.decl)
620 && cgraph_comdat_can_be_unshared_p (node))
621 return false;
622
623 /* When doing link time optimizations, hidden symbols become local. */
624 if (in_lto_p
625 && (DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_HIDDEN
626 || DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL)
627 /* Be sure that node is defined in IR file, not in other object
628 file. In that case we don't set used_from_other_object_file. */
629 && node->analyzed)
630 ;
631 else if (!whole_program)
632 return true;
633
634 if (MAIN_NAME_P (DECL_NAME (node->symbol.decl)))
635 return true;
636
637 return false;
638 }
639
640 /* Return true when variable VNODE should be considered externally visible. */
641
642 bool
643 varpool_externally_visible_p (struct varpool_node *vnode, bool aliased)
644 {
645 /* Do not touch weakrefs; while they are not externally visible,
646 dropping their DECL_EXTERNAL flags confuse most
647 of code handling them. */
648 if (vnode->alias && DECL_EXTERNAL (vnode->symbol.decl))
649 return true;
650
651 if (!DECL_COMDAT (vnode->symbol.decl) && !TREE_PUBLIC (vnode->symbol.decl))
652 return false;
653
654 /* Do not even try to be smart about aliased nodes. Until we properly
655 represent everything by same body alias, these are just evil. */
656 if (aliased)
657 return true;
658
659 /* If linker counts on us, we must preserve the function. */
660 if (varpool_used_from_object_file_p (vnode))
661 return true;
662
663 if (DECL_HARD_REGISTER (vnode->symbol.decl))
664 return true;
665 if (DECL_PRESERVE_P (vnode->symbol.decl))
666 return true;
667 if (lookup_attribute ("externally_visible",
668 DECL_ATTRIBUTES (vnode->symbol.decl)))
669 return true;
670 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
671 && lookup_attribute ("dllexport",
672 DECL_ATTRIBUTES (vnode->symbol.decl)))
673 return true;
674
675 /* See if we have linker information about symbol not being used or
676 if we need to make guess based on the declaration.
677
678 Even if the linker clams the symbol is unused, never bring internal
679 symbols that are declared by user as used or externally visible.
680 This is needed for i.e. references from asm statements. */
681 if (varpool_used_from_object_file_p (vnode))
682 return true;
683 if (vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY)
684 return false;
685
686 /* As a special case, the COMDAT virutal tables can be unshared.
687 In LTO mode turn vtables into static variables. The variable is readonly,
688 so this does not enable more optimization, but referring static var
689 is faster for dynamic linking. Also this match logic hidding vtables
690 from LTO symbol tables. */
691 if ((in_lto_p || flag_whole_program)
692 && !vnode->symbol.force_output
693 && DECL_COMDAT (vnode->symbol.decl) && DECL_VIRTUAL_P (vnode->symbol.decl))
694 return false;
695
696 /* When doing link time optimizations, hidden symbols become local. */
697 if (in_lto_p
698 && (DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_HIDDEN
699 || DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL)
700 /* Be sure that node is defined in IR file, not in other object
701 file. In that case we don't set used_from_other_object_file. */
702 && vnode->finalized)
703 ;
704 else if (!flag_whole_program)
705 return true;
706
707 /* Do not attempt to privatize COMDATS by default.
708 This would break linking with C++ libraries sharing
709 inline definitions.
710
711 FIXME: We can do so for readonly vars with no address taken and
712 possibly also for vtables since no direct pointer comparsion is done.
713 It might be interesting to do so to reduce linking overhead. */
714 if (DECL_COMDAT (vnode->symbol.decl) || DECL_WEAK (vnode->symbol.decl))
715 return true;
716 return false;
717 }
718
719 /* Dissolve the same_comdat_group list in which NODE resides. */
720
721 static void
722 dissolve_same_comdat_group_list (symtab_node node)
723 {
724 symtab_node n = node, next;
725 do
726 {
727 next = n->symbol.same_comdat_group;
728 n->symbol.same_comdat_group = NULL;
729 n = next;
730 }
731 while (n != node);
732 }
733
734 /* Mark visibility of all functions.
735
736 A local function is one whose calls can occur only in the current
737 compilation unit and all its calls are explicit, so we can change
738 its calling convention. We simply mark all static functions whose
739 address is not taken as local.
740
741 We also change the TREE_PUBLIC flag of all declarations that are public
742 in language point of view but we want to overwrite this default
743 via visibilities for the backend point of view. */
744
745 static unsigned int
746 function_and_variable_visibility (bool whole_program)
747 {
748 struct cgraph_node *node;
749 struct varpool_node *vnode;
750 struct pointer_set_t *aliased_nodes = pointer_set_create ();
751 struct pointer_set_t *aliased_vnodes = pointer_set_create ();
752 unsigned i;
753 alias_pair *p;
754
755 /* Discover aliased nodes. */
756 FOR_EACH_VEC_ELT (alias_pair, alias_pairs, i, p)
757 {
758 if (dump_file)
759 fprintf (dump_file, "Alias %s->%s",
760 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (p->decl)),
761 IDENTIFIER_POINTER (p->target));
762
763 if ((node = cgraph_node_for_asm (p->target)) != NULL
764 && !DECL_EXTERNAL (node->symbol.decl))
765 {
766 if (!node->analyzed)
767 continue;
768 cgraph_mark_force_output_node (node);
769 pointer_set_insert (aliased_nodes, node);
770 if (dump_file)
771 fprintf (dump_file, " node %s/%i",
772 cgraph_node_name (node), node->uid);
773 }
774 else if ((vnode = varpool_node_for_asm (p->target)) != NULL
775 && !DECL_EXTERNAL (vnode->symbol.decl))
776 {
777 vnode->symbol.force_output = 1;
778 pointer_set_insert (aliased_vnodes, vnode);
779 if (dump_file)
780 fprintf (dump_file, " varpool node %s",
781 varpool_node_name (vnode));
782 }
783 if (dump_file)
784 fprintf (dump_file, "\n");
785 }
786
787 FOR_EACH_FUNCTION (node)
788 {
789 int flags = flags_from_decl_or_type (node->symbol.decl);
790
791 /* Optimize away PURE and CONST constructors and destructors. */
792 if (optimize
793 && (flags & (ECF_CONST | ECF_PURE))
794 && !(flags & ECF_LOOPING_CONST_OR_PURE))
795 {
796 DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0;
797 DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0;
798 }
799
800 /* Frontends and alias code marks nodes as needed before parsing is finished.
801 We may end up marking as node external nodes where this flag is meaningless
802 strip it. */
803 if (node->symbol.force_output
804 && (DECL_EXTERNAL (node->symbol.decl) || !node->analyzed))
805 node->symbol.force_output = 0;
806
807 /* C++ FE on lack of COMDAT support create local COMDAT functions
808 (that ought to be shared but can not due to object format
809 limitations). It is neccesary to keep the flag to make rest of C++ FE
810 happy. Clear the flag here to avoid confusion in middle-end. */
811 if (DECL_COMDAT (node->symbol.decl) && !TREE_PUBLIC (node->symbol.decl))
812 DECL_COMDAT (node->symbol.decl) = 0;
813 /* For external decls stop tracking same_comdat_group, it doesn't matter
814 what comdat group they are in when they won't be emitted in this TU,
815 and simplifies later passes. */
816 if (node->symbol.same_comdat_group && DECL_EXTERNAL (node->symbol.decl))
817 {
818 #ifdef ENABLE_CHECKING
819 symtab_node n;
820
821 for (n = node->symbol.same_comdat_group;
822 n != (symtab_node)node;
823 n = n->symbol.same_comdat_group)
824 /* If at least one of same comdat group functions is external,
825 all of them have to be, otherwise it is a front-end bug. */
826 gcc_assert (DECL_EXTERNAL (n->symbol.decl));
827 #endif
828 dissolve_same_comdat_group_list ((symtab_node) node);
829 }
830 gcc_assert ((!DECL_WEAK (node->symbol.decl)
831 && !DECL_COMDAT (node->symbol.decl))
832 || TREE_PUBLIC (node->symbol.decl)
833 || DECL_EXTERNAL (node->symbol.decl));
834 if (cgraph_externally_visible_p (node, whole_program,
835 pointer_set_contains (aliased_nodes,
836 node)))
837 {
838 gcc_assert (!node->global.inlined_to);
839 node->symbol.externally_visible = true;
840 }
841 else
842 node->symbol.externally_visible = false;
843 if (!node->symbol.externally_visible && node->analyzed
844 && !DECL_EXTERNAL (node->symbol.decl))
845 {
846 gcc_assert (whole_program || in_lto_p
847 || !TREE_PUBLIC (node->symbol.decl));
848 cgraph_make_decl_local (node->symbol.decl);
849 node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
850 if (node->symbol.same_comdat_group)
851 /* cgraph_externally_visible_p has already checked all other nodes
852 in the group and they will all be made local. We need to
853 dissolve the group at once so that the predicate does not
854 segfault though. */
855 dissolve_same_comdat_group_list ((symtab_node) node);
856 }
857
858 if (node->thunk.thunk_p
859 && TREE_PUBLIC (node->symbol.decl))
860 {
861 struct cgraph_node *decl_node = node;
862
863 decl_node = cgraph_function_node (decl_node->callees->callee, NULL);
864
865 /* Thunks have the same visibility as function they are attached to.
866 Make sure the C++ front end set this up properly. */
867 if (DECL_ONE_ONLY (decl_node->symbol.decl))
868 {
869 gcc_checking_assert (DECL_COMDAT (node->symbol.decl)
870 == DECL_COMDAT (decl_node->symbol.decl));
871 gcc_checking_assert (DECL_COMDAT_GROUP (node->symbol.decl)
872 == DECL_COMDAT_GROUP (decl_node->symbol.decl));
873 gcc_checking_assert (node->symbol.same_comdat_group);
874 }
875 if (DECL_EXTERNAL (decl_node->symbol.decl))
876 DECL_EXTERNAL (node->symbol.decl) = 1;
877 }
878 }
879 FOR_EACH_DEFINED_FUNCTION (node)
880 node->local.local = cgraph_local_node_p (node);
881 FOR_EACH_VARIABLE (vnode)
882 {
883 /* weak flag makes no sense on local variables. */
884 gcc_assert (!DECL_WEAK (vnode->symbol.decl)
885 || TREE_PUBLIC (vnode->symbol.decl)
886 || DECL_EXTERNAL (vnode->symbol.decl));
887 /* In several cases declarations can not be common:
888
889 - when declaration has initializer
890 - when it is in weak
891 - when it has specific section
892 - when it resides in non-generic address space.
893 - if declaration is local, it will get into .local common section
894 so common flag is not needed. Frontends still produce these in
895 certain cases, such as for:
896
897 static int a __attribute__ ((common))
898
899 Canonicalize things here and clear the redundant flag. */
900 if (DECL_COMMON (vnode->symbol.decl)
901 && (!(TREE_PUBLIC (vnode->symbol.decl)
902 || DECL_EXTERNAL (vnode->symbol.decl))
903 || (DECL_INITIAL (vnode->symbol.decl)
904 && DECL_INITIAL (vnode->symbol.decl) != error_mark_node)
905 || DECL_WEAK (vnode->symbol.decl)
906 || DECL_SECTION_NAME (vnode->symbol.decl) != NULL
907 || ! (ADDR_SPACE_GENERIC_P
908 (TYPE_ADDR_SPACE (TREE_TYPE (vnode->symbol.decl))))))
909 DECL_COMMON (vnode->symbol.decl) = 0;
910 }
911 FOR_EACH_DEFINED_VARIABLE (vnode)
912 {
913 if (!vnode->finalized)
914 continue;
915 if (varpool_externally_visible_p
916 (vnode,
917 pointer_set_contains (aliased_vnodes, vnode)))
918 vnode->symbol.externally_visible = true;
919 else
920 vnode->symbol.externally_visible = false;
921 if (!vnode->symbol.externally_visible)
922 {
923 gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl));
924 cgraph_make_decl_local (vnode->symbol.decl);
925 if (vnode->symbol.same_comdat_group)
926 dissolve_same_comdat_group_list ((symtab_node) vnode);
927 vnode->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY;
928 }
929 gcc_assert (TREE_STATIC (vnode->symbol.decl));
930 }
931 pointer_set_destroy (aliased_nodes);
932 pointer_set_destroy (aliased_vnodes);
933
934 if (dump_file)
935 {
936 fprintf (dump_file, "\nMarking local functions:");
937 FOR_EACH_DEFINED_FUNCTION (node)
938 if (node->local.local)
939 fprintf (dump_file, " %s", cgraph_node_name (node));
940 fprintf (dump_file, "\n\n");
941 fprintf (dump_file, "\nMarking externally visible functions:");
942 FOR_EACH_DEFINED_FUNCTION (node)
943 if (node->symbol.externally_visible)
944 fprintf (dump_file, " %s", cgraph_node_name (node));
945 fprintf (dump_file, "\n\n");
946 fprintf (dump_file, "\nMarking externally visible variables:");
947 FOR_EACH_DEFINED_VARIABLE (vnode)
948 if (vnode->symbol.externally_visible)
949 fprintf (dump_file, " %s", varpool_node_name (vnode));
950 fprintf (dump_file, "\n\n");
951 }
952 cgraph_function_flags_ready = true;
953 return 0;
954 }
955
956 /* Local function pass handling visibilities. This happens before LTO streaming
957 so in particular -fwhole-program should be ignored at this level. */
958
959 static unsigned int
960 local_function_and_variable_visibility (void)
961 {
962 return function_and_variable_visibility (flag_whole_program && !flag_lto);
963 }
964
965 struct simple_ipa_opt_pass pass_ipa_function_and_variable_visibility =
966 {
967 {
968 SIMPLE_IPA_PASS,
969 "visibility", /* name */
970 NULL, /* gate */
971 local_function_and_variable_visibility,/* execute */
972 NULL, /* sub */
973 NULL, /* next */
974 0, /* static_pass_number */
975 TV_CGRAPHOPT, /* tv_id */
976 0, /* properties_required */
977 0, /* properties_provided */
978 0, /* properties_destroyed */
979 0, /* todo_flags_start */
980 TODO_remove_functions | TODO_dump_symtab
981 | TODO_ggc_collect /* todo_flags_finish */
982 }
983 };
984
985 /* Do not re-run on ltrans stage. */
986
987 static bool
988 gate_whole_program_function_and_variable_visibility (void)
989 {
990 return !flag_ltrans;
991 }
992
993 /* Bring functionss local at LTO time whith -fwhole-program. */
994
995 static unsigned int
996 whole_program_function_and_variable_visibility (void)
997 {
998 function_and_variable_visibility (flag_whole_program);
999 if (optimize)
1000 ipa_discover_readonly_nonaddressable_vars ();
1001 return 0;
1002 }
1003
1004 struct ipa_opt_pass_d pass_ipa_whole_program_visibility =
1005 {
1006 {
1007 IPA_PASS,
1008 "whole-program", /* name */
1009 gate_whole_program_function_and_variable_visibility,/* gate */
1010 whole_program_function_and_variable_visibility,/* execute */
1011 NULL, /* sub */
1012 NULL, /* next */
1013 0, /* static_pass_number */
1014 TV_CGRAPHOPT, /* tv_id */
1015 0, /* properties_required */
1016 0, /* properties_provided */
1017 0, /* properties_destroyed */
1018 0, /* todo_flags_start */
1019 TODO_remove_functions | TODO_dump_symtab
1020 | TODO_ggc_collect /* todo_flags_finish */
1021 },
1022 NULL, /* generate_summary */
1023 NULL, /* write_summary */
1024 NULL, /* read_summary */
1025 NULL, /* write_optimization_summary */
1026 NULL, /* read_optimization_summary */
1027 NULL, /* stmt_fixup */
1028 0, /* TODOs */
1029 NULL, /* function_transform */
1030 NULL, /* variable_transform */
1031 };
1032
1033
1034 /* Simple ipa profile pass propagating frequencies across the callgraph. */
1035
1036 static unsigned int
1037 ipa_profile (void)
1038 {
1039 struct cgraph_node **order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1040 struct cgraph_edge *e;
1041 int order_pos;
1042 bool something_changed = false;
1043 int i;
1044
1045 order_pos = ipa_reverse_postorder (order);
1046 for (i = order_pos - 1; i >= 0; i--)
1047 {
1048 if (order[i]->local.local && cgraph_propagate_frequency (order[i]))
1049 {
1050 for (e = order[i]->callees; e; e = e->next_callee)
1051 if (e->callee->local.local && !e->callee->symbol.aux)
1052 {
1053 something_changed = true;
1054 e->callee->symbol.aux = (void *)1;
1055 }
1056 }
1057 order[i]->symbol.aux = NULL;
1058 }
1059
1060 while (something_changed)
1061 {
1062 something_changed = false;
1063 for (i = order_pos - 1; i >= 0; i--)
1064 {
1065 if (order[i]->symbol.aux && cgraph_propagate_frequency (order[i]))
1066 {
1067 for (e = order[i]->callees; e; e = e->next_callee)
1068 if (e->callee->local.local && !e->callee->symbol.aux)
1069 {
1070 something_changed = true;
1071 e->callee->symbol.aux = (void *)1;
1072 }
1073 }
1074 order[i]->symbol.aux = NULL;
1075 }
1076 }
1077 free (order);
1078 return 0;
1079 }
1080
1081 static bool
1082 gate_ipa_profile (void)
1083 {
1084 return flag_ipa_profile;
1085 }
1086
1087 struct ipa_opt_pass_d pass_ipa_profile =
1088 {
1089 {
1090 IPA_PASS,
1091 "profile_estimate", /* name */
1092 gate_ipa_profile, /* gate */
1093 ipa_profile, /* execute */
1094 NULL, /* sub */
1095 NULL, /* next */
1096 0, /* static_pass_number */
1097 TV_IPA_PROFILE, /* tv_id */
1098 0, /* properties_required */
1099 0, /* properties_provided */
1100 0, /* properties_destroyed */
1101 0, /* todo_flags_start */
1102 0 /* todo_flags_finish */
1103 },
1104 NULL, /* generate_summary */
1105 NULL, /* write_summary */
1106 NULL, /* read_summary */
1107 NULL, /* write_optimization_summary */
1108 NULL, /* read_optimization_summary */
1109 NULL, /* stmt_fixup */
1110 0, /* TODOs */
1111 NULL, /* function_transform */
1112 NULL /* variable_transform */
1113 };
1114
1115 /* Generate and emit a static constructor or destructor. WHICH must
1116 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1117 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1118 initialization priority for this constructor or destructor.
1119
1120 FINAL specify whether the externally visible name for collect2 should
1121 be produced. */
1122
1123 static void
1124 cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final)
1125 {
1126 static int counter = 0;
1127 char which_buf[16];
1128 tree decl, name, resdecl;
1129
1130 /* The priority is encoded in the constructor or destructor name.
1131 collect2 will sort the names and arrange that they are called at
1132 program startup. */
1133 if (final)
1134 sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
1135 else
1136 /* Proudce sane name but one not recognizable by collect2, just for the
1137 case we fail to inline the function. */
1138 sprintf (which_buf, "sub_%c_%.5d_%d", which, priority, counter++);
1139 name = get_file_function_name (which_buf);
1140
1141 decl = build_decl (input_location, FUNCTION_DECL, name,
1142 build_function_type_list (void_type_node, NULL_TREE));
1143 current_function_decl = decl;
1144
1145 resdecl = build_decl (input_location,
1146 RESULT_DECL, NULL_TREE, void_type_node);
1147 DECL_ARTIFICIAL (resdecl) = 1;
1148 DECL_RESULT (decl) = resdecl;
1149 DECL_CONTEXT (resdecl) = decl;
1150
1151 allocate_struct_function (decl, false);
1152
1153 TREE_STATIC (decl) = 1;
1154 TREE_USED (decl) = 1;
1155 DECL_ARTIFICIAL (decl) = 1;
1156 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1157 DECL_SAVED_TREE (decl) = body;
1158 if (!targetm.have_ctors_dtors && final)
1159 {
1160 TREE_PUBLIC (decl) = 1;
1161 DECL_PRESERVE_P (decl) = 1;
1162 }
1163 DECL_UNINLINABLE (decl) = 1;
1164
1165 DECL_INITIAL (decl) = make_node (BLOCK);
1166 TREE_USED (DECL_INITIAL (decl)) = 1;
1167
1168 DECL_SOURCE_LOCATION (decl) = input_location;
1169 cfun->function_end_locus = input_location;
1170
1171 switch (which)
1172 {
1173 case 'I':
1174 DECL_STATIC_CONSTRUCTOR (decl) = 1;
1175 decl_init_priority_insert (decl, priority);
1176 break;
1177 case 'D':
1178 DECL_STATIC_DESTRUCTOR (decl) = 1;
1179 decl_fini_priority_insert (decl, priority);
1180 break;
1181 default:
1182 gcc_unreachable ();
1183 }
1184
1185 gimplify_function_tree (decl);
1186
1187 cgraph_add_new_function (decl, false);
1188
1189 set_cfun (NULL);
1190 current_function_decl = NULL;
1191 }
1192
1193 /* Generate and emit a static constructor or destructor. WHICH must
1194 be one of 'I' (for a constructor) or 'D' (for a destructor). BODY
1195 is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the
1196 initialization priority for this constructor or destructor. */
1197
1198 void
1199 cgraph_build_static_cdtor (char which, tree body, int priority)
1200 {
1201 cgraph_build_static_cdtor_1 (which, body, priority, false);
1202 }
1203
1204 /* A vector of FUNCTION_DECLs declared as static constructors. */
1205 static VEC(tree, heap) *static_ctors;
1206 /* A vector of FUNCTION_DECLs declared as static destructors. */
1207 static VEC(tree, heap) *static_dtors;
1208
1209 /* When target does not have ctors and dtors, we call all constructor
1210 and destructor by special initialization/destruction function
1211 recognized by collect2.
1212
1213 When we are going to build this function, collect all constructors and
1214 destructors and turn them into normal functions. */
1215
1216 static void
1217 record_cdtor_fn (struct cgraph_node *node)
1218 {
1219 if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl))
1220 VEC_safe_push (tree, heap, static_ctors, node->symbol.decl);
1221 if (DECL_STATIC_DESTRUCTOR (node->symbol.decl))
1222 VEC_safe_push (tree, heap, static_dtors, node->symbol.decl);
1223 node = cgraph_get_node (node->symbol.decl);
1224 DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl) = 1;
1225 }
1226
1227 /* Define global constructors/destructor functions for the CDTORS, of
1228 which they are LEN. The CDTORS are sorted by initialization
1229 priority. If CTOR_P is true, these are constructors; otherwise,
1230 they are destructors. */
1231
1232 static void
1233 build_cdtor (bool ctor_p, VEC (tree, heap) *cdtors)
1234 {
1235 size_t i,j;
1236 size_t len = VEC_length (tree, cdtors);
1237
1238 i = 0;
1239 while (i < len)
1240 {
1241 tree body;
1242 tree fn;
1243 priority_type priority;
1244
1245 priority = 0;
1246 body = NULL_TREE;
1247 j = i;
1248 do
1249 {
1250 priority_type p;
1251 fn = VEC_index (tree, cdtors, j);
1252 p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
1253 if (j == i)
1254 priority = p;
1255 else if (p != priority)
1256 break;
1257 j++;
1258 }
1259 while (j < len);
1260
1261 /* When there is only one cdtor and target supports them, do nothing. */
1262 if (j == i + 1
1263 && targetm.have_ctors_dtors)
1264 {
1265 i++;
1266 continue;
1267 }
1268 /* Find the next batch of constructors/destructors with the same
1269 initialization priority. */
1270 for (;i < j; i++)
1271 {
1272 tree call;
1273 fn = VEC_index (tree, cdtors, i);
1274 call = build_call_expr (fn, 0);
1275 if (ctor_p)
1276 DECL_STATIC_CONSTRUCTOR (fn) = 0;
1277 else
1278 DECL_STATIC_DESTRUCTOR (fn) = 0;
1279 /* We do not want to optimize away pure/const calls here.
1280 When optimizing, these should be already removed, when not
1281 optimizing, we want user to be able to breakpoint in them. */
1282 TREE_SIDE_EFFECTS (call) = 1;
1283 append_to_statement_list (call, &body);
1284 }
1285 gcc_assert (body != NULL_TREE);
1286 /* Generate a function to call all the function of like
1287 priority. */
1288 cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true);
1289 }
1290 }
1291
1292 /* Comparison function for qsort. P1 and P2 are actually of type
1293 "tree *" and point to static constructors. DECL_INIT_PRIORITY is
1294 used to determine the sort order. */
1295
1296 static int
1297 compare_ctor (const void *p1, const void *p2)
1298 {
1299 tree f1;
1300 tree f2;
1301 int priority1;
1302 int priority2;
1303
1304 f1 = *(const tree *)p1;
1305 f2 = *(const tree *)p2;
1306 priority1 = DECL_INIT_PRIORITY (f1);
1307 priority2 = DECL_INIT_PRIORITY (f2);
1308
1309 if (priority1 < priority2)
1310 return -1;
1311 else if (priority1 > priority2)
1312 return 1;
1313 else
1314 /* Ensure a stable sort. Constructors are executed in backwarding
1315 order to make LTO initialize braries first. */
1316 return DECL_UID (f2) - DECL_UID (f1);
1317 }
1318
1319 /* Comparison function for qsort. P1 and P2 are actually of type
1320 "tree *" and point to static destructors. DECL_FINI_PRIORITY is
1321 used to determine the sort order. */
1322
1323 static int
1324 compare_dtor (const void *p1, const void *p2)
1325 {
1326 tree f1;
1327 tree f2;
1328 int priority1;
1329 int priority2;
1330
1331 f1 = *(const tree *)p1;
1332 f2 = *(const tree *)p2;
1333 priority1 = DECL_FINI_PRIORITY (f1);
1334 priority2 = DECL_FINI_PRIORITY (f2);
1335
1336 if (priority1 < priority2)
1337 return -1;
1338 else if (priority1 > priority2)
1339 return 1;
1340 else
1341 /* Ensure a stable sort. */
1342 return DECL_UID (f1) - DECL_UID (f2);
1343 }
1344
1345 /* Generate functions to call static constructors and destructors
1346 for targets that do not support .ctors/.dtors sections. These
1347 functions have magic names which are detected by collect2. */
1348
1349 static void
1350 build_cdtor_fns (void)
1351 {
1352 if (!VEC_empty (tree, static_ctors))
1353 {
1354 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1355 VEC_qsort (tree, static_ctors, compare_ctor);
1356 build_cdtor (/*ctor_p=*/true, static_ctors);
1357 }
1358
1359 if (!VEC_empty (tree, static_dtors))
1360 {
1361 gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1362 VEC_qsort (tree, static_dtors, compare_dtor);
1363 build_cdtor (/*ctor_p=*/false, static_dtors);
1364 }
1365 }
1366
1367 /* Look for constructors and destructors and produce function calling them.
1368 This is needed for targets not supporting ctors or dtors, but we perform the
1369 transformation also at linktime to merge possibly numberous
1370 constructors/destructors into single function to improve code locality and
1371 reduce size. */
1372
1373 static unsigned int
1374 ipa_cdtor_merge (void)
1375 {
1376 struct cgraph_node *node;
1377 FOR_EACH_DEFINED_FUNCTION (node)
1378 if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)
1379 || DECL_STATIC_DESTRUCTOR (node->symbol.decl))
1380 record_cdtor_fn (node);
1381 build_cdtor_fns ();
1382 VEC_free (tree, heap, static_ctors);
1383 VEC_free (tree, heap, static_dtors);
1384 return 0;
1385 }
1386
1387 /* Perform the pass when we have no ctors/dtors support
1388 or at LTO time to merge multiple constructors into single
1389 function. */
1390
1391 static bool
1392 gate_ipa_cdtor_merge (void)
1393 {
1394 return !targetm.have_ctors_dtors || (optimize && in_lto_p);
1395 }
1396
1397 struct ipa_opt_pass_d pass_ipa_cdtor_merge =
1398 {
1399 {
1400 IPA_PASS,
1401 "cdtor", /* name */
1402 gate_ipa_cdtor_merge, /* gate */
1403 ipa_cdtor_merge, /* execute */
1404 NULL, /* sub */
1405 NULL, /* next */
1406 0, /* static_pass_number */
1407 TV_CGRAPHOPT, /* tv_id */
1408 0, /* properties_required */
1409 0, /* properties_provided */
1410 0, /* properties_destroyed */
1411 0, /* todo_flags_start */
1412 0 /* todo_flags_finish */
1413 },
1414 NULL, /* generate_summary */
1415 NULL, /* write_summary */
1416 NULL, /* read_summary */
1417 NULL, /* write_optimization_summary */
1418 NULL, /* read_optimization_summary */
1419 NULL, /* stmt_fixup */
1420 0, /* TODOs */
1421 NULL, /* function_transform */
1422 NULL /* variable_transform */
1423 };