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