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