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