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