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