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