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