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