Line data Source code
1 : /* Basic IPA optimizations and utilities.
2 : Copyright (C) 2003-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 : #include "config.h"
21 : #include "system.h"
22 : #include "coretypes.h"
23 : #include "backend.h"
24 : #include "target.h"
25 : #include "tree.h"
26 : #include "gimple.h"
27 : #include "alloc-pool.h"
28 : #include "tree-pass.h"
29 : #include "stringpool.h"
30 : #include "cgraph.h"
31 : #include "gimplify.h"
32 : #include "tree-iterator.h"
33 : #include "ipa-utils.h"
34 : #include "symbol-summary.h"
35 : #include "tree-vrp.h"
36 : #include "sreal.h"
37 : #include "ipa-cp.h"
38 : #include "ipa-prop.h"
39 : #include "ipa-fnsummary.h"
40 : #include "dbgcnt.h"
41 : #include "debug.h"
42 : #include "attribs.h"
43 :
44 : /* Return true when NODE has ADDR reference. */
45 :
46 : static bool
47 3363856 : has_addr_references_p (struct cgraph_node *node,
48 : void *)
49 : {
50 3363856 : int i;
51 3363856 : struct ipa_ref *ref = NULL;
52 :
53 3470236 : for (i = 0; node->iterate_referring (i, ref); i++)
54 3371899 : if (ref->use == IPA_REF_ADDR)
55 : return true;
56 : return false;
57 : }
58 :
59 : /* Return true when NODE can be target of an indirect call. */
60 :
61 : static bool
62 548 : is_indirect_call_target_p (struct cgraph_node *node, void *)
63 : {
64 548 : return node->indirect_call_target;
65 : }
66 :
67 : /* Look for all functions inlined to NODE and update their inlined_to pointers
68 : to INLINED_TO. */
69 :
70 : static void
71 0 : update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined_to)
72 : {
73 0 : struct cgraph_edge *e;
74 0 : for (e = node->callees; e; e = e->next_callee)
75 0 : if (e->callee->inlined_to)
76 : {
77 0 : e->callee->inlined_to = inlined_to;
78 0 : update_inlined_to_pointer (e->callee, inlined_to);
79 : }
80 0 : }
81 :
82 : /* Add symtab NODE to queue starting at FIRST.
83 :
84 : The queue is linked via AUX pointers and terminated by pointer to 1.
85 : We enqueue nodes at two occasions: when we find them reachable or when we find
86 : their bodies needed for further cloning. In the second case we mark them
87 : by pointer to 2 after processing so they are re-queue when they become
88 : reachable. */
89 :
90 : static void
91 146095114 : enqueue_node (symtab_node *node, symtab_node **first,
92 : hash_set<symtab_node *> *reachable)
93 : {
94 : /* Node is still in queue; do nothing. */
95 146095114 : if (node->aux && node->aux != (void *) 2)
96 : return;
97 : /* Node was already processed as unreachable, re-enqueue
98 : only if it became reachable now. */
99 81449258 : if (node->aux == (void *)2 && !reachable->contains (node))
100 : return;
101 51140050 : node->aux = *first;
102 51140050 : *first = node;
103 : }
104 :
105 : /* Return true if NODE may get inlined later.
106 : This is used to keep DECL_EXTERNAL function bodies around long enough
107 : so inliner can process them. */
108 :
109 : static bool
110 1759744 : possible_inline_candidate_p (symtab_node *node)
111 : {
112 1759744 : if (symtab->state >= IPA_SSA_AFTER_INLINING)
113 : return false;
114 1683628 : cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
115 1650405 : if (!cnode)
116 : return false;
117 1650405 : if (DECL_UNINLINABLE (cnode->decl))
118 : return false;
119 1647444 : if (opt_for_fn (cnode->decl, optimize))
120 : return true;
121 2240 : if (symtab->state >= IPA_SSA)
122 : return false;
123 1828 : return lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl));
124 : }
125 :
126 : /* Process references. */
127 :
128 : static void
129 37298929 : process_references (symtab_node *snode,
130 : symtab_node **first,
131 : hash_set<symtab_node *> *reachable)
132 : {
133 37298929 : int i;
134 37298929 : struct ipa_ref *ref = NULL;
135 105903509 : for (i = 0; snode->iterate_reference (i, ref); i++)
136 : {
137 68604580 : symtab_node *node = ref->referred;
138 68604580 : symtab_node *body = node->ultimate_alias_target ();
139 :
140 49563508 : if (node->definition && !node->in_other_partition
141 118168002 : && ((!DECL_EXTERNAL (node->decl) || node->alias)
142 99851 : || (possible_inline_candidate_p (node)
143 : /* We use variable constructors during late compilation for
144 : constant folding. Keep references alive so partitioning
145 : knows about potential references. */
146 38173 : || (VAR_P (node->decl)
147 33223 : && (flag_wpa
148 33223 : || flag_incremental_link
149 : == INCREMENTAL_LINK_LTO)
150 0 : && dyn_cast <varpool_node *> (node)
151 0 : ->ctor_useable_for_folding_p ()))))
152 : {
153 : /* Be sure that we will not optimize out alias target
154 : body. */
155 49525249 : if (DECL_EXTERNAL (node->decl)
156 80920 : && node->alias
157 49544491 : && symtab->state < IPA_SSA_AFTER_INLINING)
158 11234 : reachable->add (body);
159 49525249 : reachable->add (node);
160 : }
161 68604580 : enqueue_node (node, first, reachable);
162 : }
163 37298929 : }
164 :
165 : /* EDGE is an polymorphic call. If BEFORE_INLINING_P is set, mark
166 : all its potential targets as reachable to permit later inlining if
167 : devirtualization happens. After inlining still keep their declarations
168 : around, so we can devirtualize to a direct call.
169 :
170 : Also try to make trivial devirtualization when no or only one target is
171 : possible. */
172 :
173 : static void
174 175496 : walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
175 : struct cgraph_edge *edge,
176 : symtab_node **first,
177 : hash_set<symtab_node *> *reachable)
178 : {
179 175496 : unsigned int i;
180 175496 : void *cache_token;
181 175496 : bool final;
182 175496 : vec <cgraph_node *>targets
183 : = possible_polymorphic_call_targets
184 175496 : (edge, &final, &cache_token);
185 :
186 175496 : if (cache_token != NULL && !reachable_call_targets->add (cache_token))
187 : {
188 219429 : for (i = 0; i < targets.length (); i++)
189 : {
190 129922 : struct cgraph_node *n = targets[i];
191 :
192 : /* Do not bother to mark virtual methods in anonymous namespace;
193 : either we will find use of virtual table defining it, or it is
194 : unused. */
195 129922 : if (TREE_CODE (TREE_TYPE (n->decl)) == METHOD_TYPE
196 253433 : && type_in_anonymous_namespace_p
197 123511 : (TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl))))
198 4820 : continue;
199 :
200 125102 : n->indirect_call_target = true;
201 125102 : symtab_node *body = n->function_symbol ();
202 :
203 : /* Prior inlining, keep alive bodies of possible targets for
204 : devirtualization. */
205 125102 : if (n->definition
206 125102 : && (possible_inline_candidate_p (body)
207 93298 : && opt_for_fn (body->decl, flag_devirtualize)))
208 : {
209 : /* Be sure that we will not optimize out alias target
210 : body. */
211 93298 : if (DECL_EXTERNAL (n->decl)
212 2823 : && n->alias
213 93298 : && symtab->state < IPA_SSA_AFTER_INLINING)
214 0 : reachable->add (body);
215 93298 : reachable->add (n);
216 : }
217 : /* Even after inlining we want to keep the possible targets in the
218 : boundary, so late passes can still produce direct call even if
219 : the chance for inlining is lost. */
220 125102 : enqueue_node (n, first, reachable);
221 : }
222 : }
223 :
224 : /* Very trivial devirtualization; when the type is
225 : final or anonymous (so we know all its derivation)
226 : and there is only one possible virtual call target,
227 : make the edge direct. */
228 175496 : if (final)
229 : {
230 357 : if (targets.length () <= 1 && dbg_cnt (devirt))
231 : {
232 57 : cgraph_node *target, *node = edge->caller;
233 57 : if (targets.length () == 1)
234 51 : target = targets[0];
235 : else
236 6 : target = cgraph_node::get_create (builtin_decl_unreachable ());
237 :
238 57 : if (dump_enabled_p ())
239 : {
240 0 : dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, edge->call_stmt,
241 : "devirtualizing call in %s to %s\n",
242 0 : edge->caller->dump_name (),
243 : target->dump_name ());
244 : }
245 57 : edge = cgraph_edge::make_direct (edge, target);
246 57 : if (ipa_fn_summaries)
247 0 : ipa_update_overall_fn_summary (node->inlined_to
248 : ? node->inlined_to : node);
249 57 : else if (edge->call_stmt)
250 57 : cgraph_edge::redirect_call_stmt_to_callee (edge);
251 : }
252 : }
253 175496 : }
254 :
255 : /* Perform reachability analysis and reclaim all unreachable nodes.
256 :
257 : The algorithm is basically mark&sweep but with some extra refinements:
258 :
259 : - reachable extern inline functions needs special handling; the bodies needs
260 : to stay in memory until inlining in hope that they will be inlined.
261 : After inlining we release their bodies and turn them into unanalyzed
262 : nodes even when they are reachable.
263 :
264 : - virtual functions are kept in callgraph even if they seem unreachable in
265 : hope calls to them will be devirtualized.
266 :
267 : Again we remove them after inlining. In late optimization some
268 : devirtualization may happen, but it is not important since we won't inline
269 : the call. In theory early opts and IPA should work out all important cases.
270 :
271 : - virtual clones needs bodies of their origins for later materialization;
272 : this means that we want to keep the body even if the origin is unreachable
273 : otherwise. To avoid origin from sitting in the callgraph and being
274 : walked by IPA passes, we turn them into unanalyzed nodes with body
275 : defined.
276 :
277 : We maintain set of function declaration where body needs to stay in
278 : body_needed_for_clonning
279 :
280 : Inline clones represent special case: their declaration match the
281 : declaration of origin and cgraph_remove_node already knows how to
282 : reshape callgraph and preserve body when offline copy of function or
283 : inline clone is being removed.
284 :
285 : - C++ virtual tables keyed to other unit are represented as DECL_EXTERNAL
286 : variables with DECL_INITIAL set. We finalize these and keep reachable
287 : ones around for constant folding purposes. After inlining we however
288 : stop walking their references to let everything static referenced by them
289 : to be removed when it is otherwise unreachable.
290 :
291 : We maintain queue of both reachable symbols (i.e. defined symbols that needs
292 : to stay) and symbols that are in boundary (i.e. external symbols referenced
293 : by reachable symbols or origins of clones). The queue is represented
294 : as linked list by AUX pointer terminated by 1.
295 :
296 : At the end we keep all reachable symbols. For symbols in boundary we always
297 : turn definition into a declaration, but we may keep function body around
298 : based on body_needed_for_clonning
299 :
300 : All symbols that enter the queue have AUX pointer non-zero and are in the
301 : boundary. Pointer set REACHABLE is used to track reachable symbols.
302 :
303 : Every symbol can be visited twice - once as part of boundary and once
304 : as real reachable symbol. enqueue_node needs to decide whether the
305 : node needs to be re-queued for second processing. For this purpose
306 : we set AUX pointer of processed symbols in the boundary to constant 2. */
307 :
308 : bool
309 1502140 : symbol_table::remove_unreachable_nodes (FILE *file)
310 : {
311 1502140 : symtab_node *first = (symtab_node *) (void *) 1;
312 1502140 : symtab_node *snode;
313 1502140 : struct cgraph_node *node, *next;
314 1502140 : varpool_node *vnode, *vnext;
315 1502140 : bool changed = false;
316 1502140 : hash_set<symtab_node *> reachable;
317 1502140 : hash_set<tree> body_needed_for_clonning;
318 1502140 : hash_set<void *> reachable_call_targets;
319 :
320 1502140 : timevar_push (TV_IPA_UNREACHABLE);
321 1502140 : build_type_inheritance_graph ();
322 1502140 : if (file)
323 701 : fprintf (file, "\nReclaiming functions:");
324 1502140 : if (flag_checking)
325 : {
326 30509704 : FOR_EACH_FUNCTION (node)
327 29007665 : gcc_assert (!node->aux);
328 23957402 : FOR_EACH_VARIABLE (vnode)
329 22455363 : gcc_assert (!vnode->aux);
330 : }
331 : /* Mark functions whose bodies are obviously needed.
332 : This is mostly when they can be referenced externally. Inline clones
333 : are special since their declarations are shared with master clone and thus
334 : cgraph_can_remove_if_no_direct_calls_and_refs_p should not be called on them. */
335 30510128 : FOR_EACH_FUNCTION (node)
336 : {
337 29007988 : node->used_as_abstract_origin = false;
338 29007988 : node->indirect_call_target = false;
339 29007988 : if (node->definition
340 17302374 : && !node->inlined_to
341 14876268 : && !node->in_other_partition
342 43883990 : && !node->can_remove_if_no_direct_calls_and_refs_p ())
343 : {
344 7854678 : gcc_assert (!node->inlined_to);
345 7854678 : reachable.add (node);
346 7854678 : enqueue_node (node, &first, &reachable);
347 : }
348 : else
349 21153310 : gcc_assert (!node->aux);
350 : }
351 :
352 : /* Mark variables that are obviously needed. */
353 21869772 : FOR_EACH_DEFINED_VARIABLE (vnode)
354 20367632 : if (!vnode->can_remove_if_no_refs_p()
355 20367632 : && !vnode->in_other_partition)
356 : {
357 10169061 : reachable.add (vnode);
358 10169061 : enqueue_node (vnode, &first, &reachable);
359 : }
360 :
361 : /* Declarations or symbols in other partitions are also needed if referenced
362 : from asm. */
363 52965911 : FOR_EACH_SYMBOL (snode)
364 51463771 : if (snode->ref_by_asm)
365 763 : enqueue_node (snode, &first, &reachable);
366 :
367 : /* Perform reachability analysis. */
368 52642190 : while (first != (symtab_node *) (void *) 1)
369 : {
370 51140050 : bool in_boundary_p = !reachable.contains (first);
371 51140050 : symtab_node *node = first;
372 :
373 51140050 : first = (symtab_node *)first->aux;
374 :
375 : /* If we are processing symbol in boundary, mark its AUX pointer for
376 : possible later re-processing in enqueue_node. */
377 51140050 : if (in_boundary_p)
378 : {
379 13841121 : node->aux = (void *)2;
380 13841121 : if (node->alias && node->analyzed)
381 4190 : enqueue_node (node->get_alias_target (), &first, &reachable);
382 : }
383 : else
384 : {
385 37298929 : if (TREE_CODE (node->decl) == FUNCTION_DECL
386 37298929 : && DECL_ABSTRACT_ORIGIN (node->decl))
387 : {
388 3388527 : struct cgraph_node *origin_node
389 3388527 : = cgraph_node::get (DECL_ABSTRACT_ORIGIN (node->decl));
390 3388527 : if (origin_node && !origin_node->used_as_abstract_origin)
391 : {
392 396736 : origin_node->used_as_abstract_origin = true;
393 396736 : gcc_assert (!origin_node->prev_sibling_clone);
394 396736 : gcc_assert (!origin_node->next_sibling_clone);
395 626829 : for (cgraph_node *n = origin_node->clones; n;
396 230093 : n = n->next_sibling_clone)
397 230093 : if (n->decl == DECL_ABSTRACT_ORIGIN (node->decl))
398 196628 : n->used_as_abstract_origin = true;
399 : }
400 : }
401 : /* If any non-external and non-local symbol in a comdat group is
402 : reachable, force all externally visible symbols in the same comdat
403 : group to be reachable as well. Comdat-local symbols
404 : can be discarded if all uses were inlined. */
405 37298929 : if (node->same_comdat_group
406 1640621 : && node->externally_visible
407 38912704 : && !DECL_EXTERNAL (node->decl))
408 : {
409 1613775 : symtab_node *next;
410 1613775 : for (next = node->same_comdat_group;
411 4879996 : next != node;
412 3266221 : next = next->same_comdat_group)
413 6532442 : if (!next->comdat_local_p ()
414 3194675 : && !DECL_EXTERNAL (next->decl)
415 3194672 : && !reachable.add (next))
416 769485 : enqueue_node (next, &first, &reachable);
417 : }
418 : /* Mark references as reachable. */
419 37298929 : process_references (node, &first, &reachable);
420 : }
421 :
422 51140050 : if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
423 : {
424 : /* Mark the callees reachable unless they are direct calls to extern
425 : inline functions we decided to not inline. */
426 28729954 : if (!in_boundary_p)
427 : {
428 16975953 : struct cgraph_edge *e;
429 : /* Keep alive possible targets for devirtualization. */
430 16975953 : if (opt_for_fn (cnode->decl, optimize)
431 16975953 : && opt_for_fn (cnode->decl, flag_devirtualize))
432 : {
433 14022970 : struct cgraph_edge *next;
434 15187678 : for (e = cnode->indirect_calls; e; e = next)
435 : {
436 1164708 : next = e->next_callee;
437 2329416 : if (usable_polymorphic_info_p (e->indirect_info))
438 175496 : walk_polymorphic_call_targets (&reachable_call_targets,
439 : e, &first, &reachable);
440 : }
441 : }
442 :
443 74450846 : for (e = cnode->callees; e; e = e->next_callee)
444 : {
445 57474893 : symtab_node *body = e->callee->function_symbol ();
446 57474893 : if (e->callee->definition
447 22790353 : && !e->callee->in_other_partition
448 80265102 : && (!e->inline_failed
449 20384854 : || !DECL_EXTERNAL (e->callee->decl)
450 1742194 : || e->callee->alias
451 1555358 : || possible_inline_candidate_p (e->callee)))
452 : {
453 : /* Be sure that we will not optimize out alias target
454 : body. */
455 22726761 : if (DECL_EXTERNAL (e->callee->decl)
456 1921032 : && e->callee->alias
457 22913597 : && symtab->state < IPA_SSA_AFTER_INLINING)
458 185236 : reachable.add (body);
459 22726761 : reachable.add (e->callee);
460 : }
461 57474893 : enqueue_node (e->callee, &first, &reachable);
462 : }
463 :
464 : /* When inline clone exists, mark body to be preserved so when removing
465 : offline copy of the function we don't kill it. */
466 16975953 : if (cnode->inlined_to)
467 2405355 : body_needed_for_clonning.add (cnode->decl);
468 :
469 : /* For non-inline clones, force their origins to the boundary and ensure
470 : that body is not removed. */
471 20375125 : while (cnode->clone_of)
472 : {
473 3399172 : bool noninline = cnode->clone_of->decl != cnode->decl;
474 3399172 : cnode = cnode->clone_of;
475 3399172 : if (noninline)
476 : {
477 987666 : body_needed_for_clonning.add (cnode->decl);
478 987666 : enqueue_node (cnode, &first, &reachable);
479 : }
480 : }
481 :
482 : }
483 11754001 : else if (cnode->thunk)
484 45 : enqueue_node (cnode->callees->callee, &first, &reachable);
485 :
486 : /* A reference to the default node implies use of all the other
487 : versions (they get used in the function resolver made later
488 : in multiple_target.cc) */
489 28729954 : cgraph_function_version_info *node_v = cnode->function_version ();
490 28729954 : if (node_v && is_function_default_version (node->decl))
491 4709 : for (cgraph_function_version_info *fvi = node_v->next; fvi;
492 3600 : fvi = fvi->next)
493 3600 : enqueue_node (fvi->this_node, &first, &reachable);
494 :
495 : /* If any reachable function has simd clones, mark them as
496 : reachable as well. */
497 28729954 : if (cnode->simd_clones)
498 : {
499 : cgraph_node *next;
500 0 : for (next = cnode->simd_clones;
501 0 : next;
502 0 : next = next->simdclone->next_clone)
503 0 : if (in_boundary_p
504 0 : || !reachable.add (next))
505 0 : enqueue_node (next, &first, &reachable);
506 : }
507 : }
508 : /* When we see constructor of external variable, keep referred nodes in the
509 : boundary. This will also hold initializers of the external vars NODE
510 : refers to. */
511 51140050 : varpool_node *vnode = dyn_cast <varpool_node *> (node);
512 51140050 : if (vnode
513 22410096 : && DECL_EXTERNAL (node->decl)
514 2086869 : && !vnode->alias
515 : && in_boundary_p)
516 : {
517 2187918 : struct ipa_ref *ref = NULL;
518 54830108 : for (int i = 0; node->iterate_reference (i, ref); i++)
519 101051 : enqueue_node (ref->referred, &first, &reachable);
520 : }
521 : }
522 :
523 : /* Remove unreachable functions. */
524 30515505 : for (node = first_function (); node; node = next)
525 : {
526 29013365 : next = next_function (node);
527 :
528 : /* If node is not needed at all, remove it. */
529 29013365 : if (!node->aux)
530 : {
531 289492 : if (file)
532 91 : fprintf (file, " %s", node->dump_name ());
533 289492 : node->remove ();
534 289492 : changed = true;
535 : }
536 : /* If node is unreachable, remove its body. */
537 28723873 : else if (!reachable.contains (node))
538 : {
539 : /* We keep definitions of thunks and aliases in the boundary so
540 : we can walk to the ultimate alias targets and function symbols
541 : reliably. */
542 11747920 : if (node->alias || node->thunk)
543 : ;
544 11743390 : else if (!body_needed_for_clonning.contains (node->decl))
545 : {
546 : /* Make the node a non-clone so that we do not attempt to
547 : materialize it later. */
548 11338979 : if (node->clone_of)
549 0 : node->remove_from_clone_tree ();
550 11338979 : node->release_body ();
551 : }
552 404411 : else if (!node->clone_of)
553 393392 : gcc_assert (in_lto_p || DECL_RESULT (node->decl));
554 11747920 : if (node->definition && !node->alias && !node->thunk)
555 : {
556 164157 : if (file)
557 183 : fprintf (file, " %s", node->dump_name ());
558 164157 : node->body_removed = true;
559 164157 : node->analyzed = false;
560 164157 : node->definition = false;
561 164157 : node->cpp_implicit_alias = false;
562 164157 : node->alias = false;
563 164157 : node->transparent_alias = false;
564 164157 : node->thunk = false;
565 164157 : node->weakref = false;
566 : /* After early inlining we drop always_inline attributes on
567 : bodies of functions that are still referenced (have their
568 : address taken). */
569 164157 : DECL_ATTRIBUTES (node->decl)
570 164157 : = remove_attribute ("always_inline",
571 164157 : DECL_ATTRIBUTES (node->decl));
572 164157 : if (!node->in_other_partition)
573 163973 : node->local = false;
574 164157 : node->remove_callees ();
575 164157 : node->remove_all_references ();
576 164157 : changed = true;
577 : }
578 : }
579 : else
580 16975953 : gcc_assert (node->clone_of || !node->has_gimple_body_p ()
581 : || in_lto_p || DECL_RESULT (node->decl));
582 : }
583 :
584 : /* Inline clones might be kept around so their materializing allows further
585 : cloning. If the function the clone is inlined into is removed, we need
586 : to turn it into normal cone. */
587 30226013 : FOR_EACH_FUNCTION (node)
588 : {
589 28723873 : if (node->inlined_to
590 2405355 : && !node->callers)
591 : {
592 0 : gcc_assert (node->clones);
593 0 : node->inlined_to = NULL;
594 0 : update_inlined_to_pointer (node, node);
595 : }
596 28723873 : node->aux = NULL;
597 : }
598 :
599 : /* Remove unreachable variables. */
600 1502140 : if (file)
601 701 : fprintf (file, "\nReclaiming variables:");
602 23957923 : for (vnode = first_variable (); vnode; vnode = vnext)
603 : {
604 22455783 : vnext = next_variable (vnode);
605 22455783 : if (!vnode->aux
606 : /* For can_refer_decl_in_current_unit_p we want to track for
607 : all external variables if they are defined in other partition
608 : or not. */
609 22455783 : && (!flag_ltrans || !DECL_EXTERNAL (vnode->decl)))
610 : {
611 45650 : struct ipa_ref *ref = NULL;
612 :
613 : /* First remove the aliases, so varpool::remove can possibly lookup
614 : the constructor and save it for future use. */
615 45650 : while (vnode->iterate_direct_aliases (0, ref))
616 : {
617 0 : if (file)
618 0 : fprintf (file, " %s", ref->referred->dump_name ());
619 0 : ref->referring->remove ();
620 : }
621 45650 : if (file)
622 1 : fprintf (file, " %s", vnode->dump_name ());
623 45650 : vnext = next_variable (vnode);
624 : /* Signal removal to the debug machinery. */
625 45650 : if (! flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
626 : {
627 43309 : vnode->definition = false;
628 43309 : (*debug_hooks->late_global_decl) (vnode->decl);
629 : }
630 45650 : vnode->remove ();
631 45650 : changed = true;
632 : }
633 22410133 : else if (!reachable.contains (vnode) && !vnode->alias)
634 : {
635 2086945 : tree init;
636 2086945 : if (vnode->definition)
637 : {
638 17385 : if (file)
639 0 : fprintf (file, " %s", vnode->dump_name ());
640 : changed = true;
641 : }
642 : /* Keep body if it may be useful for constant folding. */
643 2082041 : if ((flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
644 4168932 : || ((init = ctor_for_folding (vnode->decl)) == error_mark_node))
645 2001519 : vnode->remove_initializer ();
646 : else
647 85426 : DECL_INITIAL (vnode->decl) = init;
648 2086945 : vnode->body_removed = true;
649 2086945 : vnode->definition = false;
650 2086945 : vnode->analyzed = false;
651 2086945 : vnode->aux = NULL;
652 :
653 2086945 : vnode->remove_from_same_comdat_group ();
654 :
655 2086945 : vnode->remove_all_references ();
656 : }
657 : else
658 20323188 : vnode->aux = NULL;
659 : }
660 :
661 : /* Now update address_taken flags and try to promote functions to be local. */
662 1502140 : if (file)
663 701 : fprintf (file, "\nClearing address taken flags:");
664 18481956 : FOR_EACH_DEFINED_FUNCTION (node)
665 16979816 : if (node->address_taken
666 3289225 : && !node->used_from_other_partition)
667 : {
668 3289079 : if (!node->call_for_symbol_and_aliases
669 3289079 : (has_addr_references_p, NULL, true))
670 : {
671 23560 : if (file)
672 0 : fprintf (file, " %s", node->dump_name ());
673 23560 : node->address_taken = false;
674 23560 : changed = true;
675 23560 : if (node->local_p ()
676 : /* Virtual functions may be kept in cgraph just because
677 : of possible later devirtualization. Do not mark them as
678 : local too early so we won't optimize them out before
679 : we are done with polymorphic call analysis. */
680 23560 : && (symtab->state >= IPA_SSA_AFTER_INLINING
681 548 : || !node->call_for_symbol_and_aliases
682 548 : (is_indirect_call_target_p, NULL, true)))
683 : {
684 554 : node->local = true;
685 554 : if (file)
686 0 : fprintf (file, " (local)");
687 : }
688 : }
689 : }
690 1502140 : if (file)
691 701 : fprintf (file, "\n");
692 :
693 1502140 : symtab_node::checking_verify_symtab_nodes ();
694 :
695 : /* If we removed something, perhaps profile could be improved. */
696 1502140 : if (changed && (optimize || in_lto_p) && ipa_call_summaries)
697 4283319 : FOR_EACH_DEFINED_FUNCTION (node)
698 4211420 : ipa_propagate_frequency (node);
699 :
700 1502140 : timevar_pop (TV_IPA_UNREACHABLE);
701 1502140 : return changed;
702 1502140 : }
703 :
704 : /* Process references to VNODE and set flags WRITTEN, ADDRESS_TAKEN, READ
705 : as needed, also clear EXPLICIT_REFS if the references to given variable
706 : do not need to be explicit. */
707 :
708 : void
709 5434466 : process_references (varpool_node *vnode,
710 : bool *written, bool *address_taken,
711 : bool *read, bool *explicit_refs)
712 : {
713 5434466 : int i;
714 5434466 : struct ipa_ref *ref;
715 :
716 5434466 : if (!vnode->all_refs_explicit_p ()
717 5434466 : || TREE_THIS_VOLATILE (vnode->decl))
718 2948746 : *explicit_refs = false;
719 :
720 9568473 : for (i = 0; vnode->iterate_referring (i, ref)
721 9568473 : && *explicit_refs && (!*written || !*address_taken || !*read); i++)
722 4134007 : switch (ref->use)
723 : {
724 2796551 : case IPA_REF_ADDR:
725 2796551 : *address_taken = true;
726 2796551 : break;
727 730972 : case IPA_REF_LOAD:
728 730972 : *read = true;
729 730972 : break;
730 593874 : case IPA_REF_STORE:
731 593874 : *written = true;
732 593874 : break;
733 12610 : case IPA_REF_ALIAS:
734 12610 : process_references (dyn_cast<varpool_node *> (ref->referring), written,
735 : address_taken, read, explicit_refs);
736 12610 : break;
737 : }
738 5434466 : }
739 :
740 : /* Set TREE_READONLY bit. */
741 :
742 : bool
743 80166 : set_readonly_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
744 : {
745 80166 : TREE_READONLY (vnode->decl) = true;
746 80166 : return false;
747 : }
748 :
749 : /* Set writeonly bit and clear the initializer, since it will not be needed. */
750 :
751 : bool
752 26210 : set_writeonly_bit (varpool_node *vnode, void *data)
753 : {
754 26210 : vnode->writeonly = true;
755 26210 : if (optimize || in_lto_p)
756 : {
757 26210 : DECL_INITIAL (vnode->decl) = NULL;
758 26210 : if (!vnode->alias)
759 : {
760 26210 : if (vnode->num_references ())
761 213 : *(bool *)data = true;
762 26210 : vnode->remove_all_references ();
763 : }
764 : }
765 26210 : return false;
766 : }
767 :
768 : /* Clear addressale bit of VNODE. */
769 :
770 : bool
771 179456 : clear_addressable_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
772 : {
773 179456 : vnode->address_taken = false;
774 179456 : TREE_ADDRESSABLE (vnode->decl) = 0;
775 179456 : return false;
776 : }
777 :
778 : /* Discover variables that have no longer address taken, are read-only or
779 : write-only and update their flags.
780 :
781 : Return true when unreachable symbol removal should be done.
782 :
783 : FIXME: This cannot be done in between gimplify and omp_expand since
784 : readonly flag plays role on what is shared and what is not. Currently we do
785 : this transformation as part of whole program visibility and re-do at
786 : ipa-reference pass (to take into account cloning), but it would
787 : make sense to do it before early optimizations. */
788 :
789 : bool
790 311430 : ipa_discover_variable_flags (void)
791 : {
792 311430 : if (!flag_ipa_reference_addressable)
793 : return false;
794 :
795 307557 : bool remove_p = false;
796 307557 : varpool_node *vnode;
797 307557 : if (dump_file)
798 73 : fprintf (dump_file, "Clearing variable flags:");
799 5742528 : FOR_EACH_VARIABLE (vnode)
800 5434971 : if (!vnode->alias
801 5434971 : && (TREE_ADDRESSABLE (vnode->decl)
802 2382914 : || !vnode->writeonly
803 26136 : || !TREE_READONLY (vnode->decl)))
804 : {
805 5421856 : bool written = false;
806 5421856 : bool address_taken = false;
807 5421856 : bool read = false;
808 5421856 : bool explicit_refs = true;
809 :
810 5421856 : process_references (vnode, &written, &address_taken, &read,
811 : &explicit_refs);
812 5421856 : if (!explicit_refs)
813 2948746 : continue;
814 2473110 : if (!address_taken)
815 : {
816 168021 : if (TREE_ADDRESSABLE (vnode->decl) && dump_file)
817 0 : fprintf (dump_file, " %s (non-addressable)",
818 : vnode->dump_name ());
819 168021 : vnode->call_for_symbol_and_aliases (clear_addressable_bit, NULL,
820 : true);
821 : }
822 168021 : if (!address_taken && !written
823 : /* Making variable in explicit section readonly can cause section
824 : type conflict.
825 : See e.g. gcc.c-torture/compile/pr23237.c */
826 2541875 : && vnode->get_section () == NULL)
827 : {
828 68735 : if (!TREE_READONLY (vnode->decl) && dump_file)
829 3 : fprintf (dump_file, " %s (read-only)", vnode->dump_name ());
830 68735 : vnode->call_for_symbol_and_aliases (set_readonly_bit, NULL, true);
831 : }
832 2473110 : if (!vnode->writeonly && !read && !address_taken && written)
833 : {
834 26210 : if (dump_file)
835 0 : fprintf (dump_file, " %s (write-only)", vnode->dump_name ());
836 26210 : vnode->call_for_symbol_and_aliases (set_writeonly_bit, &remove_p,
837 : true);
838 : }
839 : }
840 307557 : if (dump_file)
841 73 : fprintf (dump_file, "\n");
842 307557 : return remove_p;
843 : }
844 :
845 : /* Generate and emit a static constructor or destructor. WHICH must
846 : be one of 'I' (for a constructor), 'D' (for a destructor).
847 : BODY is a STATEMENT_LIST containing GENERIC
848 : statements. PRIORITY is the initialization priority for this
849 : constructor or destructor.
850 :
851 : FINAL specify whether the externally visible name for collect2 should
852 : be produced. */
853 :
854 : static tree
855 4881 : cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final,
856 : tree optimization,
857 : tree target)
858 : {
859 4881 : static int counter = 0;
860 4881 : char which_buf[16];
861 4881 : tree decl, name, resdecl;
862 :
863 : /* The priority is encoded in the constructor or destructor name.
864 : collect2 will sort the names and arrange that they are called at
865 : program startup. */
866 4881 : if (!targetm.have_ctors_dtors && final)
867 : {
868 0 : sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
869 0 : name = get_file_function_name (which_buf);
870 : }
871 : else
872 : {
873 : /* Proudce sane name but one not recognizable by collect2, just for the
874 : case we fail to inline the function. */
875 4881 : sprintf (which_buf, "_sub_%c_%.5d_%d", which, priority, counter++);
876 4881 : name = get_identifier (which_buf);
877 : }
878 :
879 4881 : decl = build_decl (input_location, FUNCTION_DECL, name,
880 : build_function_type_list (void_type_node, NULL_TREE));
881 4881 : current_function_decl = decl;
882 :
883 4881 : resdecl = build_decl (input_location,
884 : RESULT_DECL, NULL_TREE, void_type_node);
885 4881 : DECL_ARTIFICIAL (resdecl) = 1;
886 4881 : DECL_RESULT (decl) = resdecl;
887 4881 : DECL_CONTEXT (resdecl) = decl;
888 :
889 4881 : allocate_struct_function (decl, false);
890 :
891 4881 : TREE_STATIC (decl) = 1;
892 4881 : TREE_USED (decl) = 1;
893 4881 : DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl) = optimization;
894 4881 : DECL_FUNCTION_SPECIFIC_TARGET (decl) = target;
895 4881 : DECL_ARTIFICIAL (decl) = 1;
896 4881 : DECL_IGNORED_P (decl) = 1;
897 4881 : DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
898 4881 : DECL_SAVED_TREE (decl) = body;
899 4881 : if (!targetm.have_ctors_dtors && final)
900 : {
901 0 : TREE_PUBLIC (decl) = 1;
902 0 : DECL_PRESERVE_P (decl) = 1;
903 : }
904 4881 : DECL_UNINLINABLE (decl) = 1;
905 :
906 4881 : DECL_INITIAL (decl) = make_node (BLOCK);
907 4881 : BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
908 4881 : TREE_USED (DECL_INITIAL (decl)) = 1;
909 :
910 4881 : DECL_SOURCE_LOCATION (decl) = input_location;
911 4881 : cfun->function_end_locus = input_location;
912 :
913 4881 : switch (which)
914 : {
915 3337 : case 'I':
916 3337 : DECL_STATIC_CONSTRUCTOR (decl) = 1;
917 3337 : decl_init_priority_insert (decl, priority);
918 3337 : break;
919 1544 : case 'D':
920 1544 : DECL_STATIC_DESTRUCTOR (decl) = 1;
921 1544 : decl_fini_priority_insert (decl, priority);
922 1544 : break;
923 0 : default:
924 0 : gcc_unreachable ();
925 : }
926 :
927 4881 : gimplify_function_tree (decl);
928 :
929 4881 : cgraph_node::add_new_function (decl, false);
930 :
931 4881 : set_cfun (NULL);
932 4881 : current_function_decl = NULL;
933 4881 : return decl;
934 : }
935 :
936 : /* Generate and emit a static constructor or destructor. WHICH must
937 : be one of 'I' (for a constructor) or 'D' (for a destructor).
938 : BODY is a STATEMENT_LIST containing GENERIC
939 : statements. PRIORITY is the initialization priority for this
940 : constructor or destructor. */
941 :
942 : void
943 4873 : cgraph_build_static_cdtor (char which, tree body, int priority)
944 : {
945 : /* FIXME: We should be able to
946 : gcc_assert (!in_lto_p);
947 : because at LTO time the global options are not safe to use.
948 : Unfortunately ASAN finish_file will produce constructors late and they
949 : may lead to surprises. */
950 4873 : cgraph_build_static_cdtor_1 (which, body, priority, false,
951 : optimization_default_node,
952 : target_option_default_node);
953 4873 : }
954 :
955 : /* When target does not have ctors and dtors, we call all constructor
956 : and destructor by special initialization/destruction function
957 : recognized by collect2.
958 :
959 : When we are going to build this function, collect all constructors and
960 : destructors and turn them into normal functions. */
961 :
962 : static void
963 106 : record_cdtor_fn (struct cgraph_node *node, vec<tree> *ctors, vec<tree> *dtors)
964 : {
965 106 : if (DECL_STATIC_CONSTRUCTOR (node->decl))
966 80 : ctors->safe_push (node->decl);
967 106 : if (DECL_STATIC_DESTRUCTOR (node->decl))
968 30 : dtors->safe_push (node->decl);
969 106 : node = cgraph_node::get (node->decl);
970 106 : DECL_DISREGARD_INLINE_LIMITS (node->decl) = 1;
971 106 : }
972 :
973 : /* Define global constructors/destructor functions for the CDTORS, of
974 : which they are LEN. The CDTORS are sorted by initialization
975 : priority. If CTOR_P is true, these are constructors; otherwise,
976 : they are destructors. */
977 :
978 : static void
979 78 : build_cdtor (bool ctor_p, const vec<tree> &cdtors)
980 : {
981 78 : size_t i,j;
982 78 : size_t len = cdtors.length ();
983 :
984 78 : i = 0;
985 180 : while (i < len)
986 : {
987 102 : tree body;
988 102 : tree fn;
989 102 : priority_type priority;
990 :
991 102 : priority = 0;
992 102 : body = NULL_TREE;
993 102 : j = i;
994 134 : do
995 : {
996 134 : priority_type p;
997 134 : fn = cdtors[j];
998 134 : p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
999 134 : if (j == i)
1000 : priority = p;
1001 32 : else if (p != priority)
1002 : break;
1003 110 : j++;
1004 : }
1005 110 : while (j < len);
1006 :
1007 : /* When there is only one cdtor and target supports them, do nothing. */
1008 102 : if (j == i + 1
1009 94 : && targetm.have_ctors_dtors)
1010 : {
1011 94 : i++;
1012 94 : continue;
1013 : }
1014 : /* Find the next batch of constructors/destructors with the same
1015 : initialization priority. */
1016 24 : for (;i < j; i++)
1017 : {
1018 16 : tree call;
1019 16 : fn = cdtors[i];
1020 16 : call = build_call_expr (fn, 0);
1021 16 : if (ctor_p)
1022 8 : DECL_STATIC_CONSTRUCTOR (fn) = 0;
1023 : else
1024 8 : DECL_STATIC_DESTRUCTOR (fn) = 0;
1025 : /* We do not want to optimize away pure/const calls here.
1026 : When optimizing, these should be already removed, when not
1027 : optimizing, we want user to be able to breakpoint in them. */
1028 16 : TREE_SIDE_EFFECTS (call) = 1;
1029 16 : append_to_statement_list (call, &body);
1030 : }
1031 8 : gcc_assert (body != NULL_TREE);
1032 : /* Generate a function to call all the function of like
1033 : priority. */
1034 16 : cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true,
1035 8 : DECL_FUNCTION_SPECIFIC_OPTIMIZATION (cdtors[0]),
1036 8 : DECL_FUNCTION_SPECIFIC_TARGET (cdtors[0]));
1037 : }
1038 78 : }
1039 :
1040 : /* Helper functions for build_cxa_dtor_registrations ().
1041 : Build a decl for __cxa_atexit (). */
1042 :
1043 : static tree
1044 0 : build_cxa_atexit_decl ()
1045 : {
1046 : /* The parameter to "__cxa_atexit" is "void (*)(void *)". */
1047 0 : tree fn_type = build_function_type_list (void_type_node,
1048 : ptr_type_node, NULL_TREE);
1049 0 : tree fn_ptr_type = build_pointer_type (fn_type);
1050 : /* The declaration for `__cxa_atexit' is:
1051 : int __cxa_atexit (void (*)(void *), void *, void *). */
1052 0 : const char *name = "__cxa_atexit";
1053 0 : tree cxa_name = get_identifier (name);
1054 0 : fn_type = build_function_type_list (integer_type_node, fn_ptr_type,
1055 : ptr_type_node, ptr_type_node, NULL_TREE);
1056 0 : tree atexit_fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1057 : cxa_name, fn_type);
1058 0 : SET_DECL_ASSEMBLER_NAME (atexit_fndecl, cxa_name);
1059 0 : DECL_VISIBILITY (atexit_fndecl) = VISIBILITY_DEFAULT;
1060 0 : DECL_VISIBILITY_SPECIFIED (atexit_fndecl) = true;
1061 0 : set_call_expr_flags (atexit_fndecl, ECF_LEAF | ECF_NOTHROW);
1062 0 : TREE_PUBLIC (atexit_fndecl) = true;
1063 0 : DECL_EXTERNAL (atexit_fndecl) = true;
1064 0 : DECL_ARTIFICIAL (atexit_fndecl) = true;
1065 0 : return atexit_fndecl;
1066 : }
1067 :
1068 : /* Build a decl for __dso_handle. */
1069 :
1070 : static tree
1071 0 : build_dso_handle_decl ()
1072 : {
1073 : /* Declare the __dso_handle variable. */
1074 0 : tree dso_handle_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1075 : get_identifier ("__dso_handle"),
1076 : ptr_type_node);
1077 0 : TREE_PUBLIC (dso_handle_decl) = true;
1078 0 : DECL_EXTERNAL (dso_handle_decl) = true;
1079 0 : DECL_ARTIFICIAL (dso_handle_decl) = true;
1080 : #ifdef HAVE_GAS_HIDDEN
1081 0 : if (dso_handle_decl != error_mark_node)
1082 : {
1083 0 : DECL_VISIBILITY (dso_handle_decl) = VISIBILITY_HIDDEN;
1084 0 : DECL_VISIBILITY_SPECIFIED (dso_handle_decl) = true;
1085 : }
1086 : #endif
1087 0 : return dso_handle_decl;
1088 : }
1089 :
1090 : /* This builds one or more constructor functions that register DTORs with
1091 : __cxa_atexit (). Within a priority level, DTORs are registered in TU
1092 : order - which means that they will run in reverse TU order from cxa_atexit.
1093 : This is the same behavior as using a .fini / .mod_term_funcs section.
1094 : As the functions are built, they are appended to the CTORs vector. */
1095 :
1096 : static void
1097 0 : build_cxa_dtor_registrations (const vec<tree> &dtors, vec<tree> *ctors)
1098 : {
1099 0 : size_t i,j;
1100 0 : size_t len = dtors.length ();
1101 :
1102 0 : location_t sav_loc = input_location;
1103 0 : input_location = UNKNOWN_LOCATION;
1104 :
1105 0 : tree atexit_fndecl = build_cxa_atexit_decl ();
1106 0 : tree dso_handle_decl = build_dso_handle_decl ();
1107 :
1108 : /* We want &__dso_handle. */
1109 0 : tree dso_ptr = build1_loc (UNKNOWN_LOCATION, ADDR_EXPR,
1110 : ptr_type_node, dso_handle_decl);
1111 :
1112 0 : i = 0;
1113 0 : while (i < len)
1114 : {
1115 0 : priority_type priority = 0;
1116 0 : tree body = NULL_TREE;
1117 0 : j = i;
1118 0 : do
1119 : {
1120 0 : priority_type p;
1121 0 : tree fn = dtors[j];
1122 0 : p = DECL_FINI_PRIORITY (fn);
1123 0 : if (j == i)
1124 : priority = p;
1125 0 : else if (p != priority)
1126 : break;
1127 0 : j++;
1128 : }
1129 0 : while (j < len);
1130 :
1131 : /* Find the next batch of destructors with the same initialization
1132 : priority. */
1133 0 : for (;i < j; i++)
1134 : {
1135 0 : tree fn = dtors[i];
1136 0 : DECL_STATIC_DESTRUCTOR (fn) = 0;
1137 0 : tree dtor_ptr = build1_loc (UNKNOWN_LOCATION, ADDR_EXPR,
1138 : ptr_type_node, fn);
1139 0 : tree call_cxa_atexit
1140 0 : = build_call_expr_loc (UNKNOWN_LOCATION, atexit_fndecl, 3,
1141 : dtor_ptr, null_pointer_node, dso_ptr);
1142 0 : TREE_SIDE_EFFECTS (call_cxa_atexit) = 1;
1143 0 : append_to_statement_list (call_cxa_atexit, &body);
1144 : }
1145 :
1146 0 : gcc_assert (body != NULL_TREE);
1147 : /* Generate a function to register the DTORs at this priority. */
1148 0 : tree new_ctor
1149 0 : = cgraph_build_static_cdtor_1 ('I', body, priority, true,
1150 0 : DECL_FUNCTION_SPECIFIC_OPTIMIZATION (dtors[0]),
1151 0 : DECL_FUNCTION_SPECIFIC_TARGET (dtors[0]));
1152 : /* Add this to the list of ctors. */
1153 0 : ctors->safe_push (new_ctor);
1154 : }
1155 0 : input_location = sav_loc;
1156 0 : }
1157 :
1158 : /* Comparison function for qsort. P1 and P2 are actually of type
1159 : "tree *" and point to static constructors. DECL_INIT_PRIORITY is
1160 : used to determine the sort order. */
1161 :
1162 : static int
1163 96 : compare_ctor (const void *p1, const void *p2)
1164 : {
1165 96 : tree f1;
1166 96 : tree f2;
1167 96 : int priority1;
1168 96 : int priority2;
1169 :
1170 96 : f1 = *(const tree *)p1;
1171 96 : f2 = *(const tree *)p2;
1172 96 : priority1 = DECL_INIT_PRIORITY (f1);
1173 96 : priority2 = DECL_INIT_PRIORITY (f2);
1174 :
1175 96 : if (priority1 < priority2)
1176 : return -1;
1177 40 : else if (priority1 > priority2)
1178 : return 1;
1179 : else
1180 : /* Ensure a stable sort. Constructors are executed in backwarding
1181 : order to make LTO initialize braries first. */
1182 16 : return DECL_UID (f2) - DECL_UID (f1);
1183 : }
1184 :
1185 : /* Comparison function for qsort. P1 and P2 are actually of type
1186 : "tree *" and point to static destructors. DECL_FINI_PRIORITY is
1187 : used to determine the sort order. */
1188 :
1189 : static int
1190 96 : compare_dtor (const void *p1, const void *p2)
1191 : {
1192 96 : tree f1;
1193 96 : tree f2;
1194 96 : int priority1;
1195 96 : int priority2;
1196 :
1197 96 : f1 = *(const tree *)p1;
1198 96 : f2 = *(const tree *)p2;
1199 96 : priority1 = DECL_FINI_PRIORITY (f1);
1200 96 : priority2 = DECL_FINI_PRIORITY (f2);
1201 :
1202 96 : if (priority1 < priority2)
1203 : return -1;
1204 40 : else if (priority1 > priority2)
1205 : return 1;
1206 : else
1207 : /* Ensure a stable sort - into TU order. */
1208 16 : return DECL_UID (f1) - DECL_UID (f2);
1209 : }
1210 :
1211 : /* Comparison function for qsort. P1 and P2 are of type "tree *" and point to
1212 : a pair of static constructors or destructors. We first sort on the basis of
1213 : priority and then into TU order (on the strict assumption that DECL_UIDs are
1214 : ordered in the same way as the original functions). ???: this seems quite
1215 : fragile. */
1216 :
1217 : static int
1218 0 : compare_cdtor_tu_order (const void *p1, const void *p2)
1219 : {
1220 0 : tree f1;
1221 0 : tree f2;
1222 0 : int priority1;
1223 0 : int priority2;
1224 :
1225 0 : f1 = *(const tree *)p1;
1226 0 : f2 = *(const tree *)p2;
1227 : /* We process the DTORs first, and then remove their flag, so this order
1228 : allows for functions that are declared as both CTOR and DTOR. */
1229 0 : if (DECL_STATIC_DESTRUCTOR (f1))
1230 : {
1231 0 : gcc_checking_assert (DECL_STATIC_DESTRUCTOR (f2));
1232 0 : priority1 = DECL_FINI_PRIORITY (f1);
1233 0 : priority2 = DECL_FINI_PRIORITY (f2);
1234 : }
1235 : else
1236 : {
1237 0 : priority1 = DECL_INIT_PRIORITY (f1);
1238 0 : priority2 = DECL_INIT_PRIORITY (f2);
1239 : }
1240 :
1241 0 : if (priority1 < priority2)
1242 : return -1;
1243 0 : else if (priority1 > priority2)
1244 : return 1;
1245 : else
1246 : /* For equal priority, sort into the order of definition in the TU. */
1247 0 : return DECL_UID (f1) - DECL_UID (f2);
1248 : }
1249 :
1250 : /* Generate functions to call static constructors and destructors
1251 : for targets that do not support .ctors/.dtors sections. These
1252 : functions have magic names which are detected by collect2. */
1253 :
1254 : static void
1255 12431 : build_cdtor_fns (vec<tree> *ctors, vec<tree> *dtors)
1256 : {
1257 12431 : if (!ctors->is_empty ())
1258 : {
1259 64 : gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1260 64 : ctors->qsort (compare_ctor);
1261 64 : build_cdtor (/*ctor_p=*/true, *ctors);
1262 : }
1263 :
1264 12431 : if (!dtors->is_empty ())
1265 : {
1266 14 : gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1267 14 : dtors->qsort (compare_dtor);
1268 14 : build_cdtor (/*ctor_p=*/false, *dtors);
1269 : }
1270 12431 : }
1271 :
1272 : /* Generate new CTORs to register static destructors with __cxa_atexit and add
1273 : them to the existing list of CTORs; we then process the revised CTORs list.
1274 :
1275 : We sort the DTORs into priority and then TU order, this means that they are
1276 : registered in that order with __cxa_atexit () and therefore will be run in
1277 : the reverse order.
1278 :
1279 : Likewise, CTORs are sorted into priority and then TU order, which means that
1280 : they will run in that order.
1281 :
1282 : This matches the behavior of using init/fini or mod_init_func/mod_term_func
1283 : sections. */
1284 :
1285 : static void
1286 0 : build_cxa_atexit_fns (vec<tree> *ctors, vec<tree> *dtors)
1287 : {
1288 0 : if (!dtors->is_empty ())
1289 : {
1290 0 : gcc_assert (targetm.dtors_from_cxa_atexit);
1291 0 : dtors->qsort (compare_cdtor_tu_order);
1292 0 : build_cxa_dtor_registrations (*dtors, ctors);
1293 : }
1294 :
1295 0 : if (!ctors->is_empty ())
1296 : {
1297 0 : gcc_assert (targetm.dtors_from_cxa_atexit);
1298 0 : ctors->qsort (compare_cdtor_tu_order);
1299 0 : build_cdtor (/*ctor_p=*/true, *ctors);
1300 : }
1301 0 : }
1302 :
1303 : /* Look for constructors and destructors and produce function calling them.
1304 : This is needed for targets not supporting ctors or dtors, but we perform the
1305 : transformation also at linktime to merge possibly numerous
1306 : constructors/destructors into single function to improve code locality and
1307 : reduce size. */
1308 :
1309 : static unsigned int
1310 12431 : ipa_cdtor_merge (void)
1311 : {
1312 : /* A vector of FUNCTION_DECLs declared as static constructors. */
1313 12431 : auto_vec<tree, 20> ctors;
1314 : /* A vector of FUNCTION_DECLs declared as static destructors. */
1315 12431 : auto_vec<tree, 20> dtors;
1316 12431 : struct cgraph_node *node;
1317 91932 : FOR_EACH_DEFINED_FUNCTION (node)
1318 79501 : if (DECL_STATIC_CONSTRUCTOR (node->decl)
1319 79501 : || DECL_STATIC_DESTRUCTOR (node->decl))
1320 106 : record_cdtor_fn (node, &ctors, &dtors);
1321 12431 : if (targetm.dtors_from_cxa_atexit)
1322 0 : build_cxa_atexit_fns (&ctors, &dtors);
1323 : else
1324 12431 : build_cdtor_fns (&ctors, &dtors);
1325 12431 : return 0;
1326 12431 : }
1327 :
1328 : namespace {
1329 :
1330 : const pass_data pass_data_ipa_cdtor_merge =
1331 : {
1332 : IPA_PASS, /* type */
1333 : "cdtor", /* name */
1334 : OPTGROUP_NONE, /* optinfo_flags */
1335 : TV_CGRAPHOPT, /* tv_id */
1336 : 0, /* properties_required */
1337 : 0, /* properties_provided */
1338 : 0, /* properties_destroyed */
1339 : 0, /* todo_flags_start */
1340 : 0, /* todo_flags_finish */
1341 : };
1342 :
1343 : class pass_ipa_cdtor_merge : public ipa_opt_pass_d
1344 : {
1345 : public:
1346 294587 : pass_ipa_cdtor_merge (gcc::context *ctxt)
1347 : : ipa_opt_pass_d (pass_data_ipa_cdtor_merge, ctxt,
1348 : NULL, /* generate_summary */
1349 : NULL, /* write_summary */
1350 : NULL, /* read_summary */
1351 : NULL, /* write_optimization_summary */
1352 : NULL, /* read_optimization_summary */
1353 : NULL, /* stmt_fixup */
1354 : 0, /* function_transform_todo_flags_start */
1355 : NULL, /* function_transform */
1356 294587 : NULL) /* variable_transform */
1357 294587 : {}
1358 :
1359 : /* opt_pass methods: */
1360 : bool gate (function *) final override;
1361 12431 : unsigned int execute (function *) final override
1362 : {
1363 12431 : return ipa_cdtor_merge ();
1364 : }
1365 :
1366 : }; // class pass_ipa_cdtor_merge
1367 :
1368 : bool
1369 579649 : pass_ipa_cdtor_merge::gate (function *)
1370 : {
1371 : /* Perform the pass when we have no ctors/dtors support
1372 : or at LTO time to merge multiple constructors into single
1373 : function. */
1374 579649 : return !targetm.have_ctors_dtors || in_lto_p || targetm.dtors_from_cxa_atexit;
1375 : }
1376 :
1377 : } // anon namespace
1378 :
1379 : ipa_opt_pass_d *
1380 294587 : make_pass_ipa_cdtor_merge (gcc::context *ctxt)
1381 : {
1382 294587 : return new pass_ipa_cdtor_merge (ctxt);
1383 : }
1384 :
1385 : /* Invalid pointer representing BOTTOM for single user dataflow. */
1386 : #define BOTTOM ((cgraph_node *)(size_t) 2)
1387 :
1388 : /* Meet operation for single user dataflow.
1389 : Here we want to associate variables with single function that may access it.
1390 :
1391 : FUNCTION is current single user of a variable, VAR is variable that uses it.
1392 : Latttice is stored in SINGLE_USER_MAP.
1393 :
1394 : We represent:
1395 : - TOP by no entry in SIGNLE_USER_MAP
1396 : - BOTTOM by BOTTOM in AUX pointer (to save lookups)
1397 : - known single user by cgraph pointer in SINGLE_USER_MAP. */
1398 :
1399 : cgraph_node *
1400 3449538 : meet (cgraph_node *function, varpool_node *var,
1401 : hash_map<varpool_node *, cgraph_node *> &single_user_map)
1402 : {
1403 3449538 : struct cgraph_node *user, **f;
1404 :
1405 3449538 : if (var->aux == BOTTOM)
1406 : return BOTTOM;
1407 :
1408 2462906 : f = single_user_map.get (var);
1409 2462906 : if (!f)
1410 : return function;
1411 1004060 : user = *f;
1412 1004060 : if (!function)
1413 : return user;
1414 981240 : else if (function != user)
1415 : return BOTTOM;
1416 : else
1417 977398 : return function;
1418 : }
1419 :
1420 : /* Propagation step of single-use dataflow.
1421 :
1422 : Check all uses of VNODE and see if they are used by single function FUNCTION.
1423 : SINGLE_USER_MAP represents the dataflow lattice. */
1424 :
1425 : cgraph_node *
1426 1807036 : propagate_single_user (varpool_node *vnode, cgraph_node *function,
1427 : hash_map<varpool_node *, cgraph_node *> &single_user_map)
1428 : {
1429 1807036 : int i;
1430 1807036 : struct ipa_ref *ref;
1431 :
1432 1807036 : gcc_assert (!vnode->externally_visible);
1433 :
1434 : /* If node is an alias, first meet with its target. */
1435 1807036 : if (vnode->alias)
1436 17219 : function = meet (function, vnode->get_alias_target (), single_user_map);
1437 :
1438 : /* Check all users and see if they correspond to a single function. */
1439 5872995 : for (i = 0; vnode->iterate_referring (i, ref) && function != BOTTOM; i++)
1440 : {
1441 8131918 : struct cgraph_node *cnode = dyn_cast <cgraph_node *> (ref->referring);
1442 4065959 : if (cnode)
1443 : {
1444 633640 : if (cnode->inlined_to)
1445 93282 : cnode = cnode->inlined_to;
1446 633640 : if (!function)
1447 : function = cnode;
1448 319115 : else if (function != cnode)
1449 25493 : function = BOTTOM;
1450 : }
1451 : else
1452 6864638 : function = meet (function, dyn_cast <varpool_node *> (ref->referring),
1453 : single_user_map);
1454 : }
1455 1807036 : return function;
1456 : }
1457 :
1458 : /* Pass setting used_by_single_function flag.
1459 : This flag is set on variable when there is only one function that may
1460 : possibly refer to it. */
1461 :
1462 : static unsigned int
1463 237284 : ipa_single_use (void)
1464 : {
1465 237284 : varpool_node *first = (varpool_node *) (void *) 1;
1466 237284 : varpool_node *var;
1467 237284 : hash_map<varpool_node *, cgraph_node *> single_user_map;
1468 :
1469 3130703 : FOR_EACH_DEFINED_VARIABLE (var)
1470 2893419 : if (!var->all_refs_explicit_p ())
1471 : var->aux = BOTTOM;
1472 : else
1473 : {
1474 : /* Enqueue symbol for dataflow. */
1475 1319521 : var->aux = first;
1476 1319521 : first = var;
1477 : }
1478 :
1479 : /* The actual dataflow. */
1480 :
1481 2044320 : while (first != (void *) 1)
1482 : {
1483 1807036 : cgraph_node *user, *orig_user, **f;
1484 :
1485 1807036 : var = first;
1486 1807036 : first = (varpool_node *)first->aux;
1487 :
1488 1807036 : f = single_user_map.get (var);
1489 1807036 : if (f)
1490 29711 : orig_user = *f;
1491 : else
1492 : orig_user = NULL;
1493 1807036 : user = propagate_single_user (var, orig_user, single_user_map);
1494 :
1495 1807036 : gcc_checking_assert (var->aux != BOTTOM);
1496 :
1497 : /* If user differs, enqueue all references. */
1498 1807036 : if (user != orig_user)
1499 : {
1500 1325805 : unsigned int i;
1501 1325805 : ipa_ref *ref;
1502 :
1503 1325805 : single_user_map.put (var, user);
1504 :
1505 : /* Enqueue all aliases for re-processing. */
1506 2665956 : for (i = 0; var->iterate_direct_aliases (i, ref); i++)
1507 14346 : if (!ref->referring->aux)
1508 : {
1509 4324 : ref->referring->aux = first;
1510 14346 : first = dyn_cast <varpool_node *> (ref->referring);
1511 : }
1512 : /* Enqueue all users for re-processing. */
1513 5272062 : for (i = 0; var->iterate_reference (i, ref); i++)
1514 1310226 : if (!ref->referred->aux
1515 736562 : && ref->referred->definition
1516 2529979 : && is_a <varpool_node *> (ref->referred))
1517 : {
1518 483191 : ref->referred->aux = first;
1519 1310226 : first = dyn_cast <varpool_node *> (ref->referred);
1520 : }
1521 :
1522 : /* If user is BOTTOM, just punt on this var. */
1523 1325805 : if (user == BOTTOM)
1524 : var->aux = BOTTOM;
1525 : else
1526 309838 : var->aux = NULL;
1527 : }
1528 : else
1529 481231 : var->aux = NULL;
1530 : }
1531 :
1532 3130703 : FOR_EACH_DEFINED_VARIABLE (var)
1533 : {
1534 2893419 : if (var->aux != BOTTOM)
1535 : {
1536 : /* Not having the single user known means that the VAR is
1537 : unreachable. Either someone forgot to remove unreachable
1538 : variables or the reachability here is wrong. */
1539 :
1540 303554 : gcc_checking_assert (single_user_map.get (var));
1541 :
1542 303554 : if (dump_file)
1543 : {
1544 10 : fprintf (dump_file, "Variable %s is used by single function\n",
1545 : var->dump_name ());
1546 : }
1547 303554 : var->used_by_single_function = true;
1548 : }
1549 2893419 : var->aux = NULL;
1550 : }
1551 237284 : return 0;
1552 237284 : }
1553 :
1554 : namespace {
1555 :
1556 : const pass_data pass_data_ipa_single_use =
1557 : {
1558 : IPA_PASS, /* type */
1559 : "single-use", /* name */
1560 : OPTGROUP_NONE, /* optinfo_flags */
1561 : TV_CGRAPHOPT, /* tv_id */
1562 : 0, /* properties_required */
1563 : 0, /* properties_provided */
1564 : 0, /* properties_destroyed */
1565 : 0, /* todo_flags_start */
1566 : 0, /* todo_flags_finish */
1567 : };
1568 :
1569 : class pass_ipa_single_use : public ipa_opt_pass_d
1570 : {
1571 : public:
1572 294587 : pass_ipa_single_use (gcc::context *ctxt)
1573 : : ipa_opt_pass_d (pass_data_ipa_single_use, ctxt,
1574 : NULL, /* generate_summary */
1575 : NULL, /* write_summary */
1576 : NULL, /* read_summary */
1577 : NULL, /* write_optimization_summary */
1578 : NULL, /* read_optimization_summary */
1579 : NULL, /* stmt_fixup */
1580 : 0, /* function_transform_todo_flags_start */
1581 : NULL, /* function_transform */
1582 294587 : NULL) /* variable_transform */
1583 294587 : {}
1584 :
1585 : /* opt_pass methods: */
1586 237284 : unsigned int execute (function *) final override { return ipa_single_use (); }
1587 :
1588 : }; // class pass_ipa_single_use
1589 :
1590 : } // anon namespace
1591 :
1592 : ipa_opt_pass_d *
1593 294587 : make_pass_ipa_single_use (gcc::context *ctxt)
1594 : {
1595 294587 : return new pass_ipa_single_use (ctxt);
1596 : }
1597 :
|