Branch data Line data Source code
1 : : /* Basic IPA optimizations and utilities.
2 : : Copyright (C) 2003-2025 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 : 3329233 : has_addr_references_p (struct cgraph_node *node,
49 : : void *)
50 : : {
51 : 3329233 : int i;
52 : 3329233 : struct ipa_ref *ref = NULL;
53 : :
54 : 3429469 : for (i = 0; node->iterate_referring (i, ref); i++)
55 : 3337636 : 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 : 493 : is_indirect_call_target_p (struct cgraph_node *node, void *)
64 : : {
65 : 493 : 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 : 143521433 : enqueue_node (symtab_node *node, symtab_node **first,
93 : : hash_set<symtab_node *> *reachable)
94 : : {
95 : : /* Node is still in queue; do nothing. */
96 : 143521433 : 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 : 79795563 : if (node->aux == (void *)2 && !reachable->contains (node))
101 : : return;
102 : 50369630 : node->aux = *first;
103 : 50369630 : *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 : 1376389 : possible_inline_candidate_p (symtab_node *node)
112 : : {
113 : 1376389 : if (symtab->state >= IPA_SSA_AFTER_INLINING)
114 : : return false;
115 : 1308823 : cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
116 : 1277848 : if (!cnode)
117 : : return false;
118 : 1277848 : if (DECL_UNINLINABLE (cnode->decl))
119 : : return false;
120 : 1275791 : if (opt_for_fn (cnode->decl, optimize))
121 : : return true;
122 : 1530 : if (symtab->state >= IPA_SSA)
123 : : return false;
124 : 1454 : return lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl));
125 : : }
126 : :
127 : : /* Process references. */
128 : :
129 : : static void
130 : 36758594 : process_references (symtab_node *snode,
131 : : symtab_node **first,
132 : : hash_set<symtab_node *> *reachable)
133 : : {
134 : 36758594 : int i;
135 : 36758594 : struct ipa_ref *ref = NULL;
136 : 104569797 : for (i = 0; snode->iterate_reference (i, ref); i++)
137 : : {
138 : 67811203 : symtab_node *node = ref->referred;
139 : 67811203 : symtab_node *body = node->ultimate_alias_target ();
140 : :
141 : 48909414 : if (node->definition && !node->in_other_partition
142 : 116720520 : && ((!DECL_EXTERNAL (node->decl) || node->alias)
143 : 89033 : || (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 : 34557 : || (VAR_P (node->decl)
148 : 30975 : && (flag_wpa
149 : 30975 : || 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 : 48874760 : if (DECL_EXTERNAL (node->decl)
157 : 55351 : && node->alias
158 : 48875635 : && symtab->state < IPA_SSA_AFTER_INLINING)
159 : 725 : reachable->add (body);
160 : 48874760 : reachable->add (node);
161 : : }
162 : 67811203 : enqueue_node (node, first, reachable);
163 : : }
164 : 36758594 : }
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 : 199824 : 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 : 199824 : unsigned int i;
181 : 199824 : void *cache_token;
182 : 199824 : bool final;
183 : 199824 : vec <cgraph_node *>targets
184 : : = possible_polymorphic_call_targets
185 : 199824 : (edge, &final, &cache_token);
186 : :
187 : 199824 : if (cache_token != NULL && !reachable_call_targets->add (cache_token))
188 : : {
189 : 245369 : for (i = 0; i < targets.length (); i++)
190 : : {
191 : 150471 : 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 : 150471 : if (TREE_CODE (TREE_TYPE (n->decl)) == METHOD_TYPE
197 : 294544 : && type_in_anonymous_namespace_p
198 : 144073 : (TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl))))
199 : 5621 : continue;
200 : :
201 : 144850 : n->indirect_call_target = true;
202 : 144850 : symtab_node *body = n->function_symbol ();
203 : :
204 : : /* Prior inlining, keep alive bodies of possible targets for
205 : : devirtualization. */
206 : 144850 : if (n->definition
207 : 144850 : && (possible_inline_candidate_p (body)
208 : 111365 : && opt_for_fn (body->decl, flag_devirtualize)))
209 : : {
210 : : /* Be sure that we will not optimize out alias target
211 : : body. */
212 : 111365 : if (DECL_EXTERNAL (n->decl)
213 : 2952 : && n->alias
214 : 111365 : && symtab->state < IPA_SSA_AFTER_INLINING)
215 : 0 : reachable->add (body);
216 : 111365 : 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 : 144850 : 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 : 199824 : if (final)
230 : : {
231 : 242 : if (targets.length () <= 1 && dbg_cnt (devirt))
232 : : {
233 : 14 : cgraph_node *target, *node = edge->caller;
234 : 14 : if (targets.length () == 1)
235 : 6 : target = targets[0];
236 : : else
237 : 8 : target = cgraph_node::get_create (builtin_decl_unreachable ());
238 : :
239 : 14 : 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 : 14 : edge = cgraph_edge::make_direct (edge, target);
247 : 14 : if (ipa_fn_summaries)
248 : 2 : ipa_update_overall_fn_summary (node->inlined_to
249 : : ? node->inlined_to : node);
250 : 12 : else if (edge->call_stmt)
251 : 12 : cgraph_edge::redirect_call_stmt_to_callee (edge);
252 : : }
253 : : }
254 : 199824 : }
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 : 1465955 : symbol_table::remove_unreachable_nodes (FILE *file)
311 : : {
312 : 1465955 : symtab_node *first = (symtab_node *) (void *) 1;
313 : 1465955 : struct cgraph_node *node, *next;
314 : 1465955 : varpool_node *vnode, *vnext;
315 : 1465955 : bool changed = false;
316 : 1465955 : hash_set<symtab_node *> reachable;
317 : 1465955 : hash_set<tree> body_needed_for_clonning;
318 : 1465955 : hash_set<void *> reachable_call_targets;
319 : :
320 : 1465955 : timevar_push (TV_IPA_UNREACHABLE);
321 : 1465955 : build_type_inheritance_graph ();
322 : 1465955 : if (file)
323 : 694 : fprintf (file, "\nReclaiming functions:");
324 : 1465955 : if (flag_checking)
325 : : {
326 : 59844656 : FOR_EACH_FUNCTION (node)
327 : 28456474 : gcc_assert (!node->aux);
328 : 45926826 : FOR_EACH_VARIABLE (vnode)
329 : 22230486 : 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 : 59845504 : FOR_EACH_FUNCTION (node)
336 : : {
337 : 28456797 : node->used_as_abstract_origin = false;
338 : 28456797 : node->indirect_call_target = false;
339 : 28456797 : if (node->definition
340 : 16953766 : && !node->inlined_to
341 : 14520553 : && !node->in_other_partition
342 : 42977115 : && !node->can_remove_if_no_direct_calls_and_refs_p ())
343 : : {
344 : 7676497 : gcc_assert (!node->inlined_to);
345 : 7676497 : reachable.add (node);
346 : 7676497 : enqueue_node (node, &first, &reachable);
347 : : }
348 : : else
349 : 20780300 : gcc_assert (!node->aux);
350 : : }
351 : :
352 : : /* Mark variables that are obviously needed. */
353 : 21623353 : FOR_EACH_DEFINED_VARIABLE (vnode)
354 : 20157398 : if (!vnode->can_remove_if_no_refs_p()
355 : 20157398 : && !vnode->in_other_partition)
356 : : {
357 : 10093247 : reachable.add (vnode);
358 : 10093247 : enqueue_node (vnode, &first, &reachable);
359 : : }
360 : :
361 : : /* Perform reachability analysis. */
362 : 51835585 : while (first != (symtab_node *) (void *) 1)
363 : : {
364 : 50369630 : bool in_boundary_p = !reachable.contains (first);
365 : 50369630 : symtab_node *node = first;
366 : :
367 : 50369630 : first = (symtab_node *)first->aux;
368 : :
369 : : /* If we are processing symbol in boundary, mark its AUX pointer for
370 : : possible later re-processing in enqueue_node. */
371 : 50369630 : if (in_boundary_p)
372 : : {
373 : 13611036 : node->aux = (void *)2;
374 : 13611036 : if (node->alias && node->analyzed)
375 : 3688 : enqueue_node (node->get_alias_target (), &first, &reachable);
376 : : }
377 : : else
378 : : {
379 : 36758594 : if (TREE_CODE (node->decl) == FUNCTION_DECL
380 : 36758594 : && DECL_ABSTRACT_ORIGIN (node->decl))
381 : : {
382 : 3402103 : struct cgraph_node *origin_node
383 : 3402103 : = cgraph_node::get (DECL_ABSTRACT_ORIGIN (node->decl));
384 : 3402103 : if (origin_node && !origin_node->used_as_abstract_origin)
385 : : {
386 : 399991 : origin_node->used_as_abstract_origin = true;
387 : 399991 : gcc_assert (!origin_node->prev_sibling_clone);
388 : 399991 : gcc_assert (!origin_node->next_sibling_clone);
389 : 670524 : for (cgraph_node *n = origin_node->clones; n;
390 : 270533 : n = n->next_sibling_clone)
391 : 270533 : if (n->decl == DECL_ABSTRACT_ORIGIN (node->decl))
392 : 240504 : n->used_as_abstract_origin = true;
393 : : }
394 : : }
395 : : /* If any non-external and non-local symbol in a comdat group is
396 : : reachable, force all externally visible symbols in the same comdat
397 : : group to be reachable as well. Comdat-local symbols
398 : : can be discarded if all uses were inlined. */
399 : 36758594 : if (node->same_comdat_group
400 : 1623511 : && node->externally_visible
401 : 38355344 : && !DECL_EXTERNAL (node->decl))
402 : : {
403 : 1596750 : symtab_node *next;
404 : 1596750 : for (next = node->same_comdat_group;
405 : 4837576 : next != node;
406 : 3240826 : next = next->same_comdat_group)
407 : 6481652 : if (!next->comdat_local_p ()
408 : 3171917 : && !DECL_EXTERNAL (next->decl)
409 : 3171914 : && !reachable.add (next))
410 : 759317 : enqueue_node (next, &first, &reachable);
411 : : }
412 : : /* Mark references as reachable. */
413 : 36758594 : process_references (node, &first, &reachable);
414 : : }
415 : :
416 : 50369630 : if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
417 : : {
418 : : /* Mark the callees reachable unless they are direct calls to extern
419 : : inline functions we decided to not inline. */
420 : 28182333 : if (!in_boundary_p)
421 : : {
422 : 16643728 : struct cgraph_edge *e;
423 : : /* Keep alive possible targets for devirtualization. */
424 : 16643728 : if (opt_for_fn (cnode->decl, optimize)
425 : 16643728 : && opt_for_fn (cnode->decl, flag_devirtualize))
426 : : {
427 : 13794267 : struct cgraph_edge *next;
428 : 14993938 : for (e = cnode->indirect_calls; e; e = next)
429 : : {
430 : 1199671 : next = e->next_callee;
431 : 1199671 : if (e->indirect_info->polymorphic)
432 : 199824 : walk_polymorphic_call_targets (&reachable_call_targets,
433 : : e, &first, &reachable);
434 : : }
435 : : }
436 : :
437 : : /* A reference to the default node implies use of all the other
438 : : versions (they get used in the function resolver made later
439 : : in multiple_target.cc) */
440 : 16643728 : cgraph_function_version_info *node_v = cnode->function_version ();
441 : 16643728 : if (node_v && is_function_default_version (node->decl))
442 : 963 : for (cgraph_function_version_info *fvi = node_v->next;
443 : 4066 : fvi;
444 : 3103 : fvi = fvi->next)
445 : 3103 : enqueue_node (fvi->this_node, &first, &reachable);
446 : :
447 : 72766535 : for (e = cnode->callees; e; e = e->next_callee)
448 : : {
449 : 56122807 : symtab_node *body = e->callee->function_symbol ();
450 : 56122807 : if (e->callee->definition
451 : 22382058 : && !e->callee->in_other_partition
452 : 78504742 : && (!e->inline_failed
453 : 19970448 : || !DECL_EXTERNAL (e->callee->decl)
454 : 1331997 : || e->callee->alias
455 : 1162466 : || possible_inline_candidate_p (e->callee)))
456 : : {
457 : : /* Be sure that we will not optimize out alias target
458 : : body. */
459 : 22329309 : if (DECL_EXTERNAL (e->callee->decl)
460 : 1497529 : && e->callee->alias
461 : 22498840 : && symtab->state < IPA_SSA_AFTER_INLINING)
462 : 168370 : reachable.add (body);
463 : 22329309 : reachable.add (e->callee);
464 : : }
465 : 56122807 : enqueue_node (e->callee, &first, &reachable);
466 : : }
467 : :
468 : : /* When inline clone exists, mark body to be preserved so when removing
469 : : offline copy of the function we don't kill it. */
470 : 16643728 : if (cnode->inlined_to)
471 : 2411487 : body_needed_for_clonning.add (cnode->decl);
472 : :
473 : : /* For non-inline clones, force their origins to the boundary and ensure
474 : : that body is not removed. */
475 : 19948627 : while (cnode->clone_of)
476 : : {
477 : 3304899 : bool noninline = cnode->clone_of->decl != cnode->decl;
478 : 3304899 : cnode = cnode->clone_of;
479 : 3304899 : if (noninline)
480 : : {
481 : 809098 : body_needed_for_clonning.add (cnode->decl);
482 : 809098 : enqueue_node (cnode, &first, &reachable);
483 : : }
484 : : }
485 : :
486 : : }
487 : 11538605 : else if (cnode->thunk)
488 : 42 : enqueue_node (cnode->callees->callee, &first, &reachable);
489 : :
490 : : /* If any reachable function has simd clones, mark them as
491 : : reachable as well. */
492 : 28182333 : if (cnode->simd_clones)
493 : : {
494 : : cgraph_node *next;
495 : 0 : for (next = cnode->simd_clones;
496 : 0 : next;
497 : 0 : next = next->simdclone->next_clone)
498 : 0 : if (in_boundary_p
499 : 0 : || !reachable.add (next))
500 : 0 : enqueue_node (next, &first, &reachable);
501 : : }
502 : : }
503 : : /* When we see constructor of external variable, keep referred nodes in the
504 : : boundary. This will also hold initializers of the external vars NODE
505 : : refers to. */
506 : 50369630 : varpool_node *vnode = dyn_cast <varpool_node *> (node);
507 : 50369630 : if (vnode
508 : 22187297 : && DECL_EXTERNAL (node->decl)
509 : 2072180 : && !vnode->alias
510 : : && in_boundary_p)
511 : : {
512 : 2169759 : struct ipa_ref *ref = NULL;
513 : 5707892 : for (int i = 0; node->iterate_reference (i, ref); i++)
514 : 97581 : enqueue_node (ref->referred, &first, &reachable);
515 : : }
516 : : }
517 : :
518 : : /* Remove unreachable functions. */
519 : 31394205 : for (node = first_function (); node; node = next)
520 : : {
521 : 28462295 : next = next_function (node);
522 : :
523 : : /* If node is not needed at all, remove it. */
524 : 28462295 : if (!node->aux)
525 : : {
526 : 286898 : if (file)
527 : 89 : fprintf (file, " %s", node->dump_name ());
528 : 286898 : node->remove ();
529 : 286898 : changed = true;
530 : : }
531 : : /* If node is unreachable, remove its body. */
532 : 28175397 : else if (!reachable.contains (node))
533 : : {
534 : : /* We keep definitions of thunks and aliases in the boundary so
535 : : we can walk to the ultimate alias targets and function symbols
536 : : reliably. */
537 : 11531669 : if (node->alias || node->thunk)
538 : : ;
539 : 11527425 : else if (!body_needed_for_clonning.contains (node->decl))
540 : : {
541 : : /* Make the node a non-clone so that we do not attempt to
542 : : materialize it later. */
543 : 11167662 : if (node->clone_of)
544 : 0 : node->remove_from_clone_tree ();
545 : 11167662 : node->release_body ();
546 : : }
547 : 359763 : else if (!node->clone_of)
548 : 348618 : gcc_assert (in_lto_p || DECL_RESULT (node->decl));
549 : 11531669 : if (node->definition && !node->alias && !node->thunk)
550 : : {
551 : 142579 : if (file)
552 : 179 : fprintf (file, " %s", node->dump_name ());
553 : 142579 : node->body_removed = true;
554 : 142579 : node->analyzed = false;
555 : 142579 : node->definition = false;
556 : 142579 : node->cpp_implicit_alias = false;
557 : 142579 : node->alias = false;
558 : 142579 : node->transparent_alias = false;
559 : 142579 : node->thunk = false;
560 : 142579 : node->weakref = false;
561 : : /* After early inlining we drop always_inline attributes on
562 : : bodies of functions that are still referenced (have their
563 : : address taken). */
564 : 142579 : DECL_ATTRIBUTES (node->decl)
565 : 142579 : = remove_attribute ("always_inline",
566 : 142579 : DECL_ATTRIBUTES (node->decl));
567 : 142579 : if (!node->in_other_partition)
568 : 142406 : node->local = false;
569 : 142579 : node->remove_callees ();
570 : 142579 : node->remove_all_references ();
571 : 142579 : changed = true;
572 : : }
573 : : }
574 : : else
575 : 16643728 : gcc_assert (node->clone_of || !node->has_gimple_body_p ()
576 : : || in_lto_p || DECL_RESULT (node->decl));
577 : : }
578 : :
579 : : /* Inline clones might be kept around so their materializing allows further
580 : : cloning. If the function the clone is inlined into is removed, we need
581 : : to turn it into normal cone. */
582 : 31107307 : FOR_EACH_FUNCTION (node)
583 : : {
584 : 28175397 : if (node->inlined_to
585 : 2411487 : && !node->callers)
586 : : {
587 : 0 : gcc_assert (node->clones);
588 : 0 : node->inlined_to = NULL;
589 : 0 : update_inlined_to_pointer (node, node);
590 : : }
591 : 28175397 : node->aux = NULL;
592 : : }
593 : :
594 : : /* Remove unreachable variables. */
595 : 1465955 : if (file)
596 : 694 : fprintf (file, "\nReclaiming variables:");
597 : 25162816 : for (vnode = first_variable (); vnode; vnode = vnext)
598 : : {
599 : 22230906 : vnext = next_variable (vnode);
600 : 22230906 : if (!vnode->aux
601 : : /* For can_refer_decl_in_current_unit_p we want to track for
602 : : all external variables if they are defined in other partition
603 : : or not. */
604 : 22230906 : && (!flag_ltrans || !DECL_EXTERNAL (vnode->decl)))
605 : : {
606 : 43558 : struct ipa_ref *ref = NULL;
607 : :
608 : : /* First remove the aliases, so varpool::remove can possibly lookup
609 : : the constructor and save it for future use. */
610 : 43558 : while (vnode->iterate_direct_aliases (0, ref))
611 : : {
612 : 0 : if (file)
613 : 0 : fprintf (file, " %s", ref->referred->dump_name ());
614 : 0 : ref->referring->remove ();
615 : : }
616 : 43558 : if (file)
617 : 1 : fprintf (file, " %s", vnode->dump_name ());
618 : 43558 : vnext = next_variable (vnode);
619 : : /* Signal removal to the debug machinery. */
620 : 43558 : if (! flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
621 : : {
622 : 41220 : vnode->definition = false;
623 : 41220 : (*debug_hooks->late_global_decl) (vnode->decl);
624 : : }
625 : 43558 : vnode->remove ();
626 : 43558 : changed = true;
627 : : }
628 : 22187348 : else if (!reachable.contains (vnode) && !vnode->alias)
629 : : {
630 : 2072270 : tree init;
631 : 2072270 : if (vnode->definition)
632 : : {
633 : 16069 : if (file)
634 : 0 : fprintf (file, " %s", vnode->dump_name ());
635 : : changed = true;
636 : : }
637 : : /* Keep body if it may be useful for constant folding. */
638 : 2067542 : if ((flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
639 : 4139752 : || ((init = ctor_for_folding (vnode->decl)) == error_mark_node))
640 : 1986047 : vnode->remove_initializer ();
641 : : else
642 : 86223 : DECL_INITIAL (vnode->decl) = init;
643 : 2072270 : vnode->body_removed = true;
644 : 2072270 : vnode->definition = false;
645 : 2072270 : vnode->analyzed = false;
646 : 2072270 : vnode->aux = NULL;
647 : :
648 : 2072270 : vnode->remove_from_same_comdat_group ();
649 : :
650 : 2072270 : vnode->remove_all_references ();
651 : : }
652 : : else
653 : 20115078 : vnode->aux = NULL;
654 : : }
655 : :
656 : : /* Now update address_taken flags and try to promote functions to be local. */
657 : 1465955 : if (file)
658 : 694 : fprintf (file, "\nClearing address taken flags:");
659 : 18113260 : FOR_EACH_DEFINED_FUNCTION (node)
660 : 16647305 : if (node->address_taken
661 : 3260306 : && !node->used_from_other_partition)
662 : : {
663 : 3260152 : if (!node->call_for_symbol_and_aliases
664 : 3260152 : (has_addr_references_p, NULL, true))
665 : : {
666 : 22752 : if (file)
667 : 0 : fprintf (file, " %s", node->dump_name ());
668 : 22752 : node->address_taken = false;
669 : 22752 : changed = true;
670 : 22752 : if (node->local_p ()
671 : : /* Virtual functions may be kept in cgraph just because
672 : : of possible later devirtualization. Do not mark them as
673 : : local too early so we won't optimize them out before
674 : : we are done with polymorphic call analysis. */
675 : 22752 : && (symtab->state >= IPA_SSA_AFTER_INLINING
676 : 493 : || !node->call_for_symbol_and_aliases
677 : 493 : (is_indirect_call_target_p, NULL, true)))
678 : : {
679 : 503 : node->local = true;
680 : 503 : if (file)
681 : 0 : fprintf (file, " (local)");
682 : : }
683 : : }
684 : : }
685 : 1465955 : if (file)
686 : 694 : fprintf (file, "\n");
687 : :
688 : 1465955 : symtab_node::checking_verify_symtab_nodes ();
689 : :
690 : : /* If we removed something, perhaps profile could be improved. */
691 : 1465955 : if (changed && (optimize || in_lto_p) && ipa_call_summaries)
692 : 4306560 : FOR_EACH_DEFINED_FUNCTION (node)
693 : 4237468 : ipa_propagate_frequency (node);
694 : :
695 : 1465955 : timevar_pop (TV_IPA_UNREACHABLE);
696 : 1465955 : return changed;
697 : 1465955 : }
698 : :
699 : : /* Process references to VNODE and set flags WRITTEN, ADDRESS_TAKEN, READ
700 : : as needed, also clear EXPLICIT_REFS if the references to given variable
701 : : do not need to be explicit. */
702 : :
703 : : void
704 : 5386575 : process_references (varpool_node *vnode,
705 : : bool *written, bool *address_taken,
706 : : bool *read, bool *explicit_refs)
707 : : {
708 : 5386575 : int i;
709 : 5386575 : struct ipa_ref *ref;
710 : :
711 : 5386575 : if (!vnode->all_refs_explicit_p ()
712 : 5386575 : || TREE_THIS_VOLATILE (vnode->decl))
713 : 2933586 : *explicit_refs = false;
714 : :
715 : 4017356 : for (i = 0; vnode->iterate_referring (i, ref)
716 : 9403931 : && *explicit_refs && (!*written || !*address_taken || !*read); i++)
717 : 4017356 : switch (ref->use)
718 : : {
719 : 2743145 : case IPA_REF_ADDR:
720 : 2743145 : *address_taken = true;
721 : 2743145 : break;
722 : 696126 : case IPA_REF_LOAD:
723 : 696126 : *read = true;
724 : 696126 : break;
725 : 565900 : case IPA_REF_STORE:
726 : 565900 : *written = true;
727 : 565900 : break;
728 : 12185 : case IPA_REF_ALIAS:
729 : 12185 : process_references (dyn_cast<varpool_node *> (ref->referring), written,
730 : : address_taken, read, explicit_refs);
731 : 12185 : break;
732 : : }
733 : 5386575 : }
734 : :
735 : : /* Set TREE_READONLY bit. */
736 : :
737 : : bool
738 : 77835 : set_readonly_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
739 : : {
740 : 77835 : TREE_READONLY (vnode->decl) = true;
741 : 77835 : return false;
742 : : }
743 : :
744 : : /* Set writeonly bit and clear the initalizer, since it will not be needed. */
745 : :
746 : : bool
747 : 25944 : set_writeonly_bit (varpool_node *vnode, void *data)
748 : : {
749 : 25944 : vnode->writeonly = true;
750 : 25944 : if (optimize || in_lto_p)
751 : : {
752 : 25944 : DECL_INITIAL (vnode->decl) = NULL;
753 : 25944 : if (!vnode->alias)
754 : : {
755 : 25944 : if (vnode->num_references ())
756 : 210 : *(bool *)data = true;
757 : 25944 : vnode->remove_all_references ();
758 : : }
759 : : }
760 : 25944 : return false;
761 : : }
762 : :
763 : : /* Clear addressale bit of VNODE. */
764 : :
765 : : bool
766 : 174714 : clear_addressable_bit (varpool_node *vnode, void *data ATTRIBUTE_UNUSED)
767 : : {
768 : 174714 : vnode->address_taken = false;
769 : 174714 : TREE_ADDRESSABLE (vnode->decl) = 0;
770 : 174714 : return false;
771 : : }
772 : :
773 : : /* Discover variables that have no longer address taken, are read-only or
774 : : write-only and update their flags.
775 : :
776 : : Return true when unreachable symbol removal should be done.
777 : :
778 : : FIXME: This cannot be done in between gimplify and omp_expand since
779 : : readonly flag plays role on what is shared and what is not. Currently we do
780 : : this transformation as part of whole program visibility and re-do at
781 : : ipa-reference pass (to take into account clonning), but it would
782 : : make sense to do it before early optimizations. */
783 : :
784 : : bool
785 : 303396 : ipa_discover_variable_flags (void)
786 : : {
787 : 303396 : if (!flag_ipa_reference_addressable)
788 : : return false;
789 : :
790 : 296897 : bool remove_p = false;
791 : 296897 : varpool_node *vnode;
792 : 296897 : if (dump_file)
793 : 73 : fprintf (dump_file, "Clearing variable flags:");
794 : 11367394 : FOR_EACH_VARIABLE (vnode)
795 : 5386800 : if (!vnode->alias
796 : 5386800 : && (TREE_ADDRESSABLE (vnode->decl)
797 : 2370920 : || !vnode->writeonly
798 : 25870 : || !TREE_READONLY (vnode->decl)))
799 : : {
800 : 5374390 : bool written = false;
801 : 5374390 : bool address_taken = false;
802 : 5374390 : bool read = false;
803 : 5374390 : bool explicit_refs = true;
804 : :
805 : 5374390 : process_references (vnode, &written, &address_taken, &read,
806 : : &explicit_refs);
807 : 5374390 : if (!explicit_refs)
808 : 2933586 : continue;
809 : 2440804 : if (!address_taken)
810 : : {
811 : 163497 : if (TREE_ADDRESSABLE (vnode->decl) && dump_file)
812 : 0 : fprintf (dump_file, " %s (non-addressable)",
813 : : vnode->dump_name ());
814 : 163497 : vnode->call_for_symbol_and_aliases (clear_addressable_bit, NULL,
815 : : true);
816 : : }
817 : 163497 : if (!address_taken && !written
818 : : /* Making variable in explicit section readonly can cause section
819 : : type conflict.
820 : : See e.g. gcc.c-torture/compile/pr23237.c */
821 : 2507456 : && vnode->get_section () == NULL)
822 : : {
823 : 66622 : if (!TREE_READONLY (vnode->decl) && dump_file)
824 : 3 : fprintf (dump_file, " %s (read-only)", vnode->dump_name ());
825 : 66622 : vnode->call_for_symbol_and_aliases (set_readonly_bit, NULL, true);
826 : : }
827 : 2440804 : if (!vnode->writeonly && !read && !address_taken && written)
828 : : {
829 : 25944 : if (dump_file)
830 : 0 : fprintf (dump_file, " %s (write-only)", vnode->dump_name ());
831 : 25944 : vnode->call_for_symbol_and_aliases (set_writeonly_bit, &remove_p,
832 : : true);
833 : : }
834 : : }
835 : 296897 : if (dump_file)
836 : 73 : fprintf (dump_file, "\n");
837 : 296897 : return remove_p;
838 : : }
839 : :
840 : : /* Generate and emit a static constructor or destructor. WHICH must
841 : : be one of 'I' (for a constructor), 'D' (for a destructor).
842 : : BODY is a STATEMENT_LIST containing GENERIC
843 : : statements. PRIORITY is the initialization priority for this
844 : : constructor or destructor.
845 : :
846 : : FINAL specify whether the externally visible name for collect2 should
847 : : be produced. */
848 : :
849 : : static tree
850 : 4946 : cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final,
851 : : tree optimization,
852 : : tree target)
853 : : {
854 : 4946 : static int counter = 0;
855 : 4946 : char which_buf[16];
856 : 4946 : tree decl, name, resdecl;
857 : :
858 : : /* The priority is encoded in the constructor or destructor name.
859 : : collect2 will sort the names and arrange that they are called at
860 : : program startup. */
861 : 4946 : if (!targetm.have_ctors_dtors && final)
862 : : {
863 : 0 : sprintf (which_buf, "%c_%.5d_%d", which, priority, counter++);
864 : 0 : name = get_file_function_name (which_buf);
865 : : }
866 : : else
867 : : {
868 : : /* Proudce sane name but one not recognizable by collect2, just for the
869 : : case we fail to inline the function. */
870 : 4946 : sprintf (which_buf, "_sub_%c_%.5d_%d", which, priority, counter++);
871 : 4946 : name = get_identifier (which_buf);
872 : : }
873 : :
874 : 4946 : decl = build_decl (input_location, FUNCTION_DECL, name,
875 : : build_function_type_list (void_type_node, NULL_TREE));
876 : 4946 : current_function_decl = decl;
877 : :
878 : 4946 : resdecl = build_decl (input_location,
879 : : RESULT_DECL, NULL_TREE, void_type_node);
880 : 4946 : DECL_ARTIFICIAL (resdecl) = 1;
881 : 4946 : DECL_RESULT (decl) = resdecl;
882 : 4946 : DECL_CONTEXT (resdecl) = decl;
883 : :
884 : 4946 : allocate_struct_function (decl, false);
885 : :
886 : 4946 : TREE_STATIC (decl) = 1;
887 : 4946 : TREE_USED (decl) = 1;
888 : 4946 : DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl) = optimization;
889 : 4946 : DECL_FUNCTION_SPECIFIC_TARGET (decl) = target;
890 : 4946 : DECL_ARTIFICIAL (decl) = 1;
891 : 4946 : DECL_IGNORED_P (decl) = 1;
892 : 4946 : DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
893 : 4946 : DECL_SAVED_TREE (decl) = body;
894 : 4946 : if (!targetm.have_ctors_dtors && final)
895 : : {
896 : 0 : TREE_PUBLIC (decl) = 1;
897 : 0 : DECL_PRESERVE_P (decl) = 1;
898 : : }
899 : 4946 : DECL_UNINLINABLE (decl) = 1;
900 : :
901 : 4946 : DECL_INITIAL (decl) = make_node (BLOCK);
902 : 4946 : BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
903 : 4946 : TREE_USED (DECL_INITIAL (decl)) = 1;
904 : :
905 : 4946 : DECL_SOURCE_LOCATION (decl) = input_location;
906 : 4946 : cfun->function_end_locus = input_location;
907 : :
908 : 4946 : switch (which)
909 : : {
910 : 3473 : case 'I':
911 : 3473 : DECL_STATIC_CONSTRUCTOR (decl) = 1;
912 : 3473 : decl_init_priority_insert (decl, priority);
913 : 3473 : break;
914 : 1473 : case 'D':
915 : 1473 : DECL_STATIC_DESTRUCTOR (decl) = 1;
916 : 1473 : decl_fini_priority_insert (decl, priority);
917 : 1473 : break;
918 : 0 : default:
919 : 0 : gcc_unreachable ();
920 : : }
921 : :
922 : 4946 : gimplify_function_tree (decl);
923 : :
924 : 4946 : cgraph_node::add_new_function (decl, false);
925 : :
926 : 4946 : set_cfun (NULL);
927 : 4946 : current_function_decl = NULL;
928 : 4946 : return decl;
929 : : }
930 : :
931 : : /* Generate and emit a static constructor or destructor. WHICH must
932 : : be one of 'I' (for a constructor) or 'D' (for a destructor).
933 : : BODY is a STATEMENT_LIST containing GENERIC
934 : : statements. PRIORITY is the initialization priority for this
935 : : constructor or destructor. */
936 : :
937 : : void
938 : 4938 : cgraph_build_static_cdtor (char which, tree body, int priority)
939 : : {
940 : : /* FIXME: We should be able to
941 : : gcc_assert (!in_lto_p);
942 : : because at LTO time the global options are not safe to use.
943 : : Unfortunately ASAN finish_file will produce constructors late and they
944 : : may lead to surprises. */
945 : 4938 : cgraph_build_static_cdtor_1 (which, body, priority, false,
946 : : optimization_default_node,
947 : : target_option_default_node);
948 : 4938 : }
949 : :
950 : : /* When target does not have ctors and dtors, we call all constructor
951 : : and destructor by special initialization/destruction function
952 : : recognized by collect2.
953 : :
954 : : When we are going to build this function, collect all constructors and
955 : : destructors and turn them into normal functions. */
956 : :
957 : : static void
958 : 100 : record_cdtor_fn (struct cgraph_node *node, vec<tree> *ctors, vec<tree> *dtors)
959 : : {
960 : 100 : if (DECL_STATIC_CONSTRUCTOR (node->decl))
961 : 75 : ctors->safe_push (node->decl);
962 : 100 : if (DECL_STATIC_DESTRUCTOR (node->decl))
963 : 29 : dtors->safe_push (node->decl);
964 : 100 : node = cgraph_node::get (node->decl);
965 : 100 : DECL_DISREGARD_INLINE_LIMITS (node->decl) = 1;
966 : 100 : }
967 : :
968 : : /* Define global constructors/destructor functions for the CDTORS, of
969 : : which they are LEN. The CDTORS are sorted by initialization
970 : : priority. If CTOR_P is true, these are constructors; otherwise,
971 : : they are destructors. */
972 : :
973 : : static void
974 : 72 : build_cdtor (bool ctor_p, const vec<tree> &cdtors)
975 : : {
976 : 72 : size_t i,j;
977 : 72 : size_t len = cdtors.length ();
978 : :
979 : 72 : i = 0;
980 : 168 : while (i < len)
981 : : {
982 : 96 : tree body;
983 : 96 : tree fn;
984 : 96 : priority_type priority;
985 : :
986 : 96 : priority = 0;
987 : 96 : body = NULL_TREE;
988 : 96 : j = i;
989 : 128 : do
990 : : {
991 : 128 : priority_type p;
992 : 128 : fn = cdtors[j];
993 : 128 : p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
994 : 128 : if (j == i)
995 : : priority = p;
996 : 32 : else if (p != priority)
997 : : break;
998 : 104 : j++;
999 : : }
1000 : 104 : while (j < len);
1001 : :
1002 : : /* When there is only one cdtor and target supports them, do nothing. */
1003 : 96 : if (j == i + 1
1004 : 88 : && targetm.have_ctors_dtors)
1005 : : {
1006 : 88 : i++;
1007 : 88 : continue;
1008 : : }
1009 : : /* Find the next batch of constructors/destructors with the same
1010 : : initialization priority. */
1011 : 24 : for (;i < j; i++)
1012 : : {
1013 : 16 : tree call;
1014 : 16 : fn = cdtors[i];
1015 : 16 : call = build_call_expr (fn, 0);
1016 : 16 : if (ctor_p)
1017 : 8 : DECL_STATIC_CONSTRUCTOR (fn) = 0;
1018 : : else
1019 : 8 : DECL_STATIC_DESTRUCTOR (fn) = 0;
1020 : : /* We do not want to optimize away pure/const calls here.
1021 : : When optimizing, these should be already removed, when not
1022 : : optimizing, we want user to be able to breakpoint in them. */
1023 : 16 : TREE_SIDE_EFFECTS (call) = 1;
1024 : 16 : append_to_statement_list (call, &body);
1025 : : }
1026 : 8 : gcc_assert (body != NULL_TREE);
1027 : : /* Generate a function to call all the function of like
1028 : : priority. */
1029 : 16 : cgraph_build_static_cdtor_1 (ctor_p ? 'I' : 'D', body, priority, true,
1030 : 8 : DECL_FUNCTION_SPECIFIC_OPTIMIZATION (cdtors[0]),
1031 : 8 : DECL_FUNCTION_SPECIFIC_TARGET (cdtors[0]));
1032 : : }
1033 : 72 : }
1034 : :
1035 : : /* Helper functions for build_cxa_dtor_registrations ().
1036 : : Build a decl for __cxa_atexit (). */
1037 : :
1038 : : static tree
1039 : 0 : build_cxa_atexit_decl ()
1040 : : {
1041 : : /* The parameter to "__cxa_atexit" is "void (*)(void *)". */
1042 : 0 : tree fn_type = build_function_type_list (void_type_node,
1043 : : ptr_type_node, NULL_TREE);
1044 : 0 : tree fn_ptr_type = build_pointer_type (fn_type);
1045 : : /* The declaration for `__cxa_atexit' is:
1046 : : int __cxa_atexit (void (*)(void *), void *, void *). */
1047 : 0 : const char *name = "__cxa_atexit";
1048 : 0 : tree cxa_name = get_identifier (name);
1049 : 0 : fn_type = build_function_type_list (integer_type_node, fn_ptr_type,
1050 : : ptr_type_node, ptr_type_node, NULL_TREE);
1051 : 0 : tree atexit_fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
1052 : : cxa_name, fn_type);
1053 : 0 : SET_DECL_ASSEMBLER_NAME (atexit_fndecl, cxa_name);
1054 : 0 : DECL_VISIBILITY (atexit_fndecl) = VISIBILITY_DEFAULT;
1055 : 0 : DECL_VISIBILITY_SPECIFIED (atexit_fndecl) = true;
1056 : 0 : set_call_expr_flags (atexit_fndecl, ECF_LEAF | ECF_NOTHROW);
1057 : 0 : TREE_PUBLIC (atexit_fndecl) = true;
1058 : 0 : DECL_EXTERNAL (atexit_fndecl) = true;
1059 : 0 : DECL_ARTIFICIAL (atexit_fndecl) = true;
1060 : 0 : return atexit_fndecl;
1061 : : }
1062 : :
1063 : : /* Build a decl for __dso_handle. */
1064 : :
1065 : : static tree
1066 : 0 : build_dso_handle_decl ()
1067 : : {
1068 : : /* Declare the __dso_handle variable. */
1069 : 0 : tree dso_handle_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
1070 : : get_identifier ("__dso_handle"),
1071 : : ptr_type_node);
1072 : 0 : TREE_PUBLIC (dso_handle_decl) = true;
1073 : 0 : DECL_EXTERNAL (dso_handle_decl) = true;
1074 : 0 : DECL_ARTIFICIAL (dso_handle_decl) = true;
1075 : : #ifdef HAVE_GAS_HIDDEN
1076 : 0 : if (dso_handle_decl != error_mark_node)
1077 : : {
1078 : 0 : DECL_VISIBILITY (dso_handle_decl) = VISIBILITY_HIDDEN;
1079 : 0 : DECL_VISIBILITY_SPECIFIED (dso_handle_decl) = true;
1080 : : }
1081 : : #endif
1082 : 0 : return dso_handle_decl;
1083 : : }
1084 : :
1085 : : /* This builds one or more constructor functions that register DTORs with
1086 : : __cxa_atexit (). Within a priority level, DTORs are registered in TU
1087 : : order - which means that they will run in reverse TU order from cxa_atexit.
1088 : : This is the same behavior as using a .fini / .mod_term_funcs section.
1089 : : As the functions are built, they are appended to the CTORs vector. */
1090 : :
1091 : : static void
1092 : 0 : build_cxa_dtor_registrations (const vec<tree> &dtors, vec<tree> *ctors)
1093 : : {
1094 : 0 : size_t i,j;
1095 : 0 : size_t len = dtors.length ();
1096 : :
1097 : 0 : location_t sav_loc = input_location;
1098 : 0 : input_location = UNKNOWN_LOCATION;
1099 : :
1100 : 0 : tree atexit_fndecl = build_cxa_atexit_decl ();
1101 : 0 : tree dso_handle_decl = build_dso_handle_decl ();
1102 : :
1103 : : /* We want &__dso_handle. */
1104 : 0 : tree dso_ptr = build1_loc (UNKNOWN_LOCATION, ADDR_EXPR,
1105 : : ptr_type_node, dso_handle_decl);
1106 : :
1107 : 0 : i = 0;
1108 : 0 : while (i < len)
1109 : : {
1110 : 0 : priority_type priority = 0;
1111 : 0 : tree body = NULL_TREE;
1112 : 0 : j = i;
1113 : 0 : do
1114 : : {
1115 : 0 : priority_type p;
1116 : 0 : tree fn = dtors[j];
1117 : 0 : p = DECL_FINI_PRIORITY (fn);
1118 : 0 : if (j == i)
1119 : : priority = p;
1120 : 0 : else if (p != priority)
1121 : : break;
1122 : 0 : j++;
1123 : : }
1124 : 0 : while (j < len);
1125 : :
1126 : : /* Find the next batch of destructors with the same initialization
1127 : : priority. */
1128 : 0 : for (;i < j; i++)
1129 : : {
1130 : 0 : tree fn = dtors[i];
1131 : 0 : DECL_STATIC_DESTRUCTOR (fn) = 0;
1132 : 0 : tree dtor_ptr = build1_loc (UNKNOWN_LOCATION, ADDR_EXPR,
1133 : : ptr_type_node, fn);
1134 : 0 : tree call_cxa_atexit
1135 : 0 : = build_call_expr_loc (UNKNOWN_LOCATION, atexit_fndecl, 3,
1136 : : dtor_ptr, null_pointer_node, dso_ptr);
1137 : 0 : TREE_SIDE_EFFECTS (call_cxa_atexit) = 1;
1138 : 0 : append_to_statement_list (call_cxa_atexit, &body);
1139 : : }
1140 : :
1141 : 0 : gcc_assert (body != NULL_TREE);
1142 : : /* Generate a function to register the DTORs at this priority. */
1143 : 0 : tree new_ctor
1144 : 0 : = cgraph_build_static_cdtor_1 ('I', body, priority, true,
1145 : 0 : DECL_FUNCTION_SPECIFIC_OPTIMIZATION (dtors[0]),
1146 : 0 : DECL_FUNCTION_SPECIFIC_TARGET (dtors[0]));
1147 : : /* Add this to the list of ctors. */
1148 : 0 : ctors->safe_push (new_ctor);
1149 : : }
1150 : 0 : input_location = sav_loc;
1151 : 0 : }
1152 : :
1153 : : /* Comparison function for qsort. P1 and P2 are actually of type
1154 : : "tree *" and point to static constructors. DECL_INIT_PRIORITY is
1155 : : used to determine the sort order. */
1156 : :
1157 : : static int
1158 : 96 : compare_ctor (const void *p1, const void *p2)
1159 : : {
1160 : 96 : tree f1;
1161 : 96 : tree f2;
1162 : 96 : int priority1;
1163 : 96 : int priority2;
1164 : :
1165 : 96 : f1 = *(const tree *)p1;
1166 : 96 : f2 = *(const tree *)p2;
1167 : 96 : priority1 = DECL_INIT_PRIORITY (f1);
1168 : 96 : priority2 = DECL_INIT_PRIORITY (f2);
1169 : :
1170 : 96 : if (priority1 < priority2)
1171 : : return -1;
1172 : 40 : else if (priority1 > priority2)
1173 : : return 1;
1174 : : else
1175 : : /* Ensure a stable sort. Constructors are executed in backwarding
1176 : : order to make LTO initialize braries first. */
1177 : 16 : return DECL_UID (f2) - DECL_UID (f1);
1178 : : }
1179 : :
1180 : : /* Comparison function for qsort. P1 and P2 are actually of type
1181 : : "tree *" and point to static destructors. DECL_FINI_PRIORITY is
1182 : : used to determine the sort order. */
1183 : :
1184 : : static int
1185 : 96 : compare_dtor (const void *p1, const void *p2)
1186 : : {
1187 : 96 : tree f1;
1188 : 96 : tree f2;
1189 : 96 : int priority1;
1190 : 96 : int priority2;
1191 : :
1192 : 96 : f1 = *(const tree *)p1;
1193 : 96 : f2 = *(const tree *)p2;
1194 : 96 : priority1 = DECL_FINI_PRIORITY (f1);
1195 : 96 : priority2 = DECL_FINI_PRIORITY (f2);
1196 : :
1197 : 96 : if (priority1 < priority2)
1198 : : return -1;
1199 : 40 : else if (priority1 > priority2)
1200 : : return 1;
1201 : : else
1202 : : /* Ensure a stable sort - into TU order. */
1203 : 16 : return DECL_UID (f1) - DECL_UID (f2);
1204 : : }
1205 : :
1206 : : /* Comparison function for qsort. P1 and P2 are of type "tree *" and point to
1207 : : a pair of static constructors or destructors. We first sort on the basis of
1208 : : priority and then into TU order (on the strict assumption that DECL_UIDs are
1209 : : ordered in the same way as the original functions). ???: this seems quite
1210 : : fragile. */
1211 : :
1212 : : static int
1213 : 0 : compare_cdtor_tu_order (const void *p1, const void *p2)
1214 : : {
1215 : 0 : tree f1;
1216 : 0 : tree f2;
1217 : 0 : int priority1;
1218 : 0 : int priority2;
1219 : :
1220 : 0 : f1 = *(const tree *)p1;
1221 : 0 : f2 = *(const tree *)p2;
1222 : : /* We process the DTORs first, and then remove their flag, so this order
1223 : : allows for functions that are declared as both CTOR and DTOR. */
1224 : 0 : if (DECL_STATIC_DESTRUCTOR (f1))
1225 : : {
1226 : 0 : gcc_checking_assert (DECL_STATIC_DESTRUCTOR (f2));
1227 : 0 : priority1 = DECL_FINI_PRIORITY (f1);
1228 : 0 : priority2 = DECL_FINI_PRIORITY (f2);
1229 : : }
1230 : : else
1231 : : {
1232 : 0 : priority1 = DECL_INIT_PRIORITY (f1);
1233 : 0 : priority2 = DECL_INIT_PRIORITY (f2);
1234 : : }
1235 : :
1236 : 0 : if (priority1 < priority2)
1237 : : return -1;
1238 : 0 : else if (priority1 > priority2)
1239 : : return 1;
1240 : : else
1241 : : /* For equal priority, sort into the order of definition in the TU. */
1242 : 0 : return DECL_UID (f1) - DECL_UID (f2);
1243 : : }
1244 : :
1245 : : /* Generate functions to call static constructors and destructors
1246 : : for targets that do not support .ctors/.dtors sections. These
1247 : : functions have magic names which are detected by collect2. */
1248 : :
1249 : : static void
1250 : 13227 : build_cdtor_fns (vec<tree> *ctors, vec<tree> *dtors)
1251 : : {
1252 : 13227 : if (!ctors->is_empty ())
1253 : : {
1254 : 59 : gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1255 : 59 : ctors->qsort (compare_ctor);
1256 : 59 : build_cdtor (/*ctor_p=*/true, *ctors);
1257 : : }
1258 : :
1259 : 13227 : if (!dtors->is_empty ())
1260 : : {
1261 : 13 : gcc_assert (!targetm.have_ctors_dtors || in_lto_p);
1262 : 13 : dtors->qsort (compare_dtor);
1263 : 13 : build_cdtor (/*ctor_p=*/false, *dtors);
1264 : : }
1265 : 13227 : }
1266 : :
1267 : : /* Generate new CTORs to register static destructors with __cxa_atexit and add
1268 : : them to the existing list of CTORs; we then process the revised CTORs list.
1269 : :
1270 : : We sort the DTORs into priority and then TU order, this means that they are
1271 : : registered in that order with __cxa_atexit () and therefore will be run in
1272 : : the reverse order.
1273 : :
1274 : : Likewise, CTORs are sorted into priority and then TU order, which means that
1275 : : they will run in that order.
1276 : :
1277 : : This matches the behavior of using init/fini or mod_init_func/mod_term_func
1278 : : sections. */
1279 : :
1280 : : static void
1281 : 0 : build_cxa_atexit_fns (vec<tree> *ctors, vec<tree> *dtors)
1282 : : {
1283 : 0 : if (!dtors->is_empty ())
1284 : : {
1285 : 0 : gcc_assert (targetm.dtors_from_cxa_atexit);
1286 : 0 : dtors->qsort (compare_cdtor_tu_order);
1287 : 0 : build_cxa_dtor_registrations (*dtors, ctors);
1288 : : }
1289 : :
1290 : 0 : if (!ctors->is_empty ())
1291 : : {
1292 : 0 : gcc_assert (targetm.dtors_from_cxa_atexit);
1293 : 0 : ctors->qsort (compare_cdtor_tu_order);
1294 : 0 : build_cdtor (/*ctor_p=*/true, *ctors);
1295 : : }
1296 : 0 : }
1297 : :
1298 : : /* Look for constructors and destructors and produce function calling them.
1299 : : This is needed for targets not supporting ctors or dtors, but we perform the
1300 : : transformation also at linktime to merge possibly numerous
1301 : : constructors/destructors into single function to improve code locality and
1302 : : reduce size. */
1303 : :
1304 : : static unsigned int
1305 : 13227 : ipa_cdtor_merge (void)
1306 : : {
1307 : : /* A vector of FUNCTION_DECLs declared as static constructors. */
1308 : 13227 : auto_vec<tree, 20> ctors;
1309 : : /* A vector of FUNCTION_DECLs declared as static destructors. */
1310 : 13227 : auto_vec<tree, 20> dtors;
1311 : 13227 : struct cgraph_node *node;
1312 : 92277 : FOR_EACH_DEFINED_FUNCTION (node)
1313 : 79050 : if (DECL_STATIC_CONSTRUCTOR (node->decl)
1314 : 79050 : || DECL_STATIC_DESTRUCTOR (node->decl))
1315 : 100 : record_cdtor_fn (node, &ctors, &dtors);
1316 : 13227 : if (targetm.dtors_from_cxa_atexit)
1317 : 0 : build_cxa_atexit_fns (&ctors, &dtors);
1318 : : else
1319 : 13227 : build_cdtor_fns (&ctors, &dtors);
1320 : 13227 : return 0;
1321 : 13227 : }
1322 : :
1323 : : namespace {
1324 : :
1325 : : const pass_data pass_data_ipa_cdtor_merge =
1326 : : {
1327 : : IPA_PASS, /* type */
1328 : : "cdtor", /* name */
1329 : : OPTGROUP_NONE, /* optinfo_flags */
1330 : : TV_CGRAPHOPT, /* tv_id */
1331 : : 0, /* properties_required */
1332 : : 0, /* properties_provided */
1333 : : 0, /* properties_destroyed */
1334 : : 0, /* todo_flags_start */
1335 : : 0, /* todo_flags_finish */
1336 : : };
1337 : :
1338 : : class pass_ipa_cdtor_merge : public ipa_opt_pass_d
1339 : : {
1340 : : public:
1341 : 289080 : pass_ipa_cdtor_merge (gcc::context *ctxt)
1342 : : : ipa_opt_pass_d (pass_data_ipa_cdtor_merge, ctxt,
1343 : : NULL, /* generate_summary */
1344 : : NULL, /* write_summary */
1345 : : NULL, /* read_summary */
1346 : : NULL, /* write_optimization_summary */
1347 : : NULL, /* read_optimization_summary */
1348 : : NULL, /* stmt_fixup */
1349 : : 0, /* function_transform_todo_flags_start */
1350 : : NULL, /* function_transform */
1351 : 289080 : NULL) /* variable_transform */
1352 : 289080 : {}
1353 : :
1354 : : /* opt_pass methods: */
1355 : : bool gate (function *) final override;
1356 : 13227 : unsigned int execute (function *) final override
1357 : : {
1358 : 13227 : return ipa_cdtor_merge ();
1359 : : }
1360 : :
1361 : : }; // class pass_ipa_cdtor_merge
1362 : :
1363 : : bool
1364 : 568632 : pass_ipa_cdtor_merge::gate (function *)
1365 : : {
1366 : : /* Perform the pass when we have no ctors/dtors support
1367 : : or at LTO time to merge multiple constructors into single
1368 : : function. */
1369 : 568632 : return !targetm.have_ctors_dtors || in_lto_p || targetm.dtors_from_cxa_atexit;
1370 : : }
1371 : :
1372 : : } // anon namespace
1373 : :
1374 : : ipa_opt_pass_d *
1375 : 289080 : make_pass_ipa_cdtor_merge (gcc::context *ctxt)
1376 : : {
1377 : 289080 : return new pass_ipa_cdtor_merge (ctxt);
1378 : : }
1379 : :
1380 : : /* Invalid pointer representing BOTTOM for single user dataflow. */
1381 : : #define BOTTOM ((cgraph_node *)(size_t) 2)
1382 : :
1383 : : /* Meet operation for single user dataflow.
1384 : : Here we want to associate variables with sigle function that may access it.
1385 : :
1386 : : FUNCTION is current single user of a variable, VAR is variable that uses it.
1387 : : Latttice is stored in SINGLE_USER_MAP.
1388 : :
1389 : : We represent:
1390 : : - TOP by no entry in SIGNLE_USER_MAP
1391 : : - BOTTOM by BOTTOM in AUX pointer (to save lookups)
1392 : : - known single user by cgraph pointer in SINGLE_USER_MAP. */
1393 : :
1394 : : cgraph_node *
1395 : 3437268 : meet (cgraph_node *function, varpool_node *var,
1396 : : hash_map<varpool_node *, cgraph_node *> &single_user_map)
1397 : : {
1398 : 3437268 : struct cgraph_node *user, **f;
1399 : :
1400 : 3437268 : if (var->aux == BOTTOM)
1401 : : return BOTTOM;
1402 : :
1403 : 2454775 : f = single_user_map.get (var);
1404 : 2454775 : if (!f)
1405 : : return function;
1406 : 1002824 : user = *f;
1407 : 1002824 : if (!function)
1408 : : return user;
1409 : 980984 : else if (function != user)
1410 : : return BOTTOM;
1411 : : else
1412 : : return function;
1413 : : }
1414 : :
1415 : : /* Propagation step of single-use dataflow.
1416 : :
1417 : : Check all uses of VNODE and see if they are used by single function FUNCTION.
1418 : : SINGLE_USER_MAP represents the dataflow lattice. */
1419 : :
1420 : : cgraph_node *
1421 : 1783279 : propagate_single_user (varpool_node *vnode, cgraph_node *function,
1422 : : hash_map<varpool_node *, cgraph_node *> &single_user_map)
1423 : : {
1424 : 1783279 : int i;
1425 : 1783279 : struct ipa_ref *ref;
1426 : :
1427 : 1783279 : gcc_assert (!vnode->externally_visible);
1428 : :
1429 : : /* If node is an alias, first meet with its target. */
1430 : 1783279 : if (vnode->alias)
1431 : 16240 : function = meet (function, vnode->get_alias_target (), single_user_map);
1432 : :
1433 : : /* Check all users and see if they correspond to a single function. */
1434 : 5813051 : for (i = 0; vnode->iterate_referring (i, ref) && function != BOTTOM; i++)
1435 : : {
1436 : 8059544 : struct cgraph_node *cnode = dyn_cast <cgraph_node *> (ref->referring);
1437 : 4029772 : if (cnode)
1438 : : {
1439 : 608744 : if (cnode->inlined_to)
1440 : 87154 : cnode = cnode->inlined_to;
1441 : 608744 : if (!function)
1442 : : function = cnode;
1443 : 308763 : else if (function != cnode)
1444 : 24833 : function = BOTTOM;
1445 : : }
1446 : : else
1447 : 6842056 : function = meet (function, dyn_cast <varpool_node *> (ref->referring),
1448 : : single_user_map);
1449 : : }
1450 : 1783279 : return function;
1451 : : }
1452 : :
1453 : : /* Pass setting used_by_single_function flag.
1454 : : This flag is set on variable when there is only one function that may
1455 : : possibly referr to it. */
1456 : :
1457 : : static unsigned int
1458 : 230804 : ipa_single_use (void)
1459 : : {
1460 : 230804 : varpool_node *first = (varpool_node *) (void *) 1;
1461 : 230804 : varpool_node *var;
1462 : 230804 : hash_map<varpool_node *, cgraph_node *> single_user_map;
1463 : :
1464 : 3091345 : FOR_EACH_DEFINED_VARIABLE (var)
1465 : 2860541 : if (!var->all_refs_explicit_p ())
1466 : 1560512 : var->aux = BOTTOM;
1467 : : else
1468 : : {
1469 : : /* Enqueue symbol for dataflow. */
1470 : 1300029 : var->aux = first;
1471 : 1300029 : first = var;
1472 : : }
1473 : :
1474 : : /* The actual dataflow. */
1475 : :
1476 : 2014083 : while (first != (void *) 1)
1477 : : {
1478 : 1783279 : cgraph_node *user, *orig_user, **f;
1479 : :
1480 : 1783279 : var = first;
1481 : 1783279 : first = (varpool_node *)first->aux;
1482 : :
1483 : 1783279 : f = single_user_map.get (var);
1484 : 1783279 : if (f)
1485 : 29107 : orig_user = *f;
1486 : : else
1487 : : orig_user = NULL;
1488 : 1783279 : user = propagate_single_user (var, orig_user, single_user_map);
1489 : :
1490 : 1783279 : gcc_checking_assert (var->aux != BOTTOM);
1491 : :
1492 : : /* If user differs, enqueue all references. */
1493 : 1783279 : if (user != orig_user)
1494 : : {
1495 : 1306006 : unsigned int i;
1496 : 1306006 : ipa_ref *ref;
1497 : :
1498 : 1306006 : single_user_map.put (var, user);
1499 : :
1500 : : /* Enqueue all aliases for re-processing. */
1501 : 2626042 : for (i = 0; var->iterate_direct_aliases (i, ref); i++)
1502 : 14030 : if (!ref->referring->aux)
1503 : : {
1504 : 4050 : ref->referring->aux = first;
1505 : 14030 : first = dyn_cast <varpool_node *> (ref->referring);
1506 : : }
1507 : : /* Enqueue all users for re-processing. */
1508 : 5214776 : for (i = 0; var->iterate_reference (i, ref); i++)
1509 : 1301382 : if (!ref->referred->aux
1510 : 732734 : && ref->referred->definition
1511 : 2513316 : && is_a <varpool_node *> (ref->referred))
1512 : : {
1513 : 479200 : ref->referred->aux = first;
1514 : 479200 : first = dyn_cast <varpool_node *> (ref->referred);
1515 : : }
1516 : :
1517 : : /* If user is BOTTOM, just punt on this var. */
1518 : 1306006 : if (user == BOTTOM)
1519 : 1011002 : var->aux = BOTTOM;
1520 : : else
1521 : 295004 : var->aux = NULL;
1522 : : }
1523 : : else
1524 : 477273 : var->aux = NULL;
1525 : : }
1526 : :
1527 : 3091345 : FOR_EACH_DEFINED_VARIABLE (var)
1528 : : {
1529 : 2860541 : if (var->aux != BOTTOM)
1530 : : {
1531 : : /* Not having the single user known means that the VAR is
1532 : : unreachable. Either someone forgot to remove unreachable
1533 : : variables or the reachability here is wrong. */
1534 : :
1535 : 289027 : gcc_checking_assert (single_user_map.get (var));
1536 : :
1537 : 289027 : if (dump_file)
1538 : : {
1539 : 10 : fprintf (dump_file, "Variable %s is used by single function\n",
1540 : : var->dump_name ());
1541 : : }
1542 : 289027 : var->used_by_single_function = true;
1543 : : }
1544 : 2860541 : var->aux = NULL;
1545 : : }
1546 : 230804 : return 0;
1547 : 230804 : }
1548 : :
1549 : : namespace {
1550 : :
1551 : : const pass_data pass_data_ipa_single_use =
1552 : : {
1553 : : IPA_PASS, /* type */
1554 : : "single-use", /* name */
1555 : : OPTGROUP_NONE, /* optinfo_flags */
1556 : : TV_CGRAPHOPT, /* tv_id */
1557 : : 0, /* properties_required */
1558 : : 0, /* properties_provided */
1559 : : 0, /* properties_destroyed */
1560 : : 0, /* todo_flags_start */
1561 : : 0, /* todo_flags_finish */
1562 : : };
1563 : :
1564 : : class pass_ipa_single_use : public ipa_opt_pass_d
1565 : : {
1566 : : public:
1567 : 289080 : pass_ipa_single_use (gcc::context *ctxt)
1568 : : : ipa_opt_pass_d (pass_data_ipa_single_use, ctxt,
1569 : : NULL, /* generate_summary */
1570 : : NULL, /* write_summary */
1571 : : NULL, /* read_summary */
1572 : : NULL, /* write_optimization_summary */
1573 : : NULL, /* read_optimization_summary */
1574 : : NULL, /* stmt_fixup */
1575 : : 0, /* function_transform_todo_flags_start */
1576 : : NULL, /* function_transform */
1577 : 289080 : NULL) /* variable_transform */
1578 : 289080 : {}
1579 : :
1580 : : /* opt_pass methods: */
1581 : 230804 : unsigned int execute (function *) final override { return ipa_single_use (); }
1582 : :
1583 : : }; // class pass_ipa_single_use
1584 : :
1585 : : } // anon namespace
1586 : :
1587 : : ipa_opt_pass_d *
1588 : 289080 : make_pass_ipa_single_use (gcc::context *ctxt)
1589 : : {
1590 : 289080 : return new pass_ipa_single_use (ctxt);
1591 : : }
1592 : :
|