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