111
|
1 /* IPA visibility pass
|
145
|
2 Copyright (C) 2003-2020 Free Software Foundation, Inc.
|
111
|
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 /* This file implements two related passes:
|
|
21
|
|
22 - pass_data_ipa_function_and_variable_visibility run just after
|
|
23 symbol table, references and callgraph are built
|
|
24
|
|
25 - pass_data_ipa_function_and_variable_visibility run as first
|
|
26 proper IPA pass (that is after early optimization, or, (with LTO)
|
|
27 as a first pass done at link-time.
|
|
28
|
|
29 Purpose of both passes is to set correctly visibility properties
|
|
30 of all symbols. This includes:
|
|
31
|
|
32 - Symbol privatization:
|
|
33
|
|
34 Some symbols that are declared public by frontend may be
|
|
35 turned local (either by -fwhole-program flag, by linker plugin feedback
|
|
36 or by other reasons)
|
|
37
|
|
38 - Discovery of local functions:
|
|
39
|
|
40 A local function is one whose calls can occur only in the current
|
|
41 compilation unit and all its calls are explicit, so we can change
|
|
42 its calling convention. We simply mark all static functions whose
|
|
43 address is not taken as local.
|
|
44
|
145
|
45 externally_visible flag is set for symbols that cannot be privatized.
|
111
|
46 For privatized symbols we clear TREE_PUBLIC flag and dismantle comdat
|
|
47 group.
|
|
48
|
|
49 - Dismantling of comdat groups:
|
|
50
|
|
51 Comdat group represent a section that may be replaced by linker by
|
|
52 a different copy of the same section from other unit.
|
|
53 If we have resolution information (from linker plugin) and we know that
|
|
54 a given comdat gorup is prevailing, we can dismantle it and turn symbols
|
|
55 into normal symbols. If the resolution information says that the
|
|
56 section was previaled by copy from non-LTO code, we can also dismantle
|
|
57 it and turn all symbols into external.
|
|
58
|
|
59 - Local aliases:
|
|
60
|
|
61 Some symbols can be interposed by dynamic linker. Refering to these
|
|
62 symbols is expensive, since it needs to be overwritable by the dynamic
|
|
63 linker. In some cases we know that the interposition does not change
|
|
64 semantic and we can always refer to a local copy (as in the case of
|
|
65 inline function). In this case we produce a local alias and redirect
|
|
66 calls to it.
|
|
67
|
|
68 TODO: This should be done for references, too.
|
|
69
|
|
70 - Removal of static ocnstructors and destructors that have no side effects.
|
|
71
|
|
72 - Regularization of several oddities introduced by frontends that may
|
|
73 be impractical later in the optimization queue. */
|
|
74
|
|
75 #include "config.h"
|
|
76 #include "system.h"
|
|
77 #include "coretypes.h"
|
|
78 #include "tm.h"
|
|
79 #include "function.h"
|
|
80 #include "tree.h"
|
|
81 #include "gimple-expr.h"
|
|
82 #include "tree-pass.h"
|
|
83 #include "cgraph.h"
|
|
84 #include "calls.h"
|
|
85 #include "varasm.h"
|
|
86 #include "ipa-utils.h"
|
|
87 #include "stringpool.h"
|
|
88 #include "attribs.h"
|
|
89
|
145
|
90 /* Return true when NODE cannot be local. Worker for cgraph_local_node_p. */
|
111
|
91
|
|
92 static bool
|
|
93 non_local_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
|
|
94 {
|
|
95 return !(node->only_called_directly_or_aliased_p ()
|
|
96 /* i386 would need update to output thunk with local calling
|
|
97 conventions. */
|
|
98 && !node->thunk.thunk_p
|
|
99 && node->definition
|
|
100 && !DECL_EXTERNAL (node->decl)
|
|
101 && !lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl))
|
|
102 && !node->externally_visible
|
|
103 && !node->used_from_other_partition
|
|
104 && !node->in_other_partition
|
|
105 && node->get_availability () >= AVAIL_AVAILABLE);
|
|
106 }
|
|
107
|
|
108 /* Return true when function can be marked local. */
|
|
109
|
|
110 bool
|
|
111 cgraph_node::local_p (void)
|
|
112 {
|
|
113 cgraph_node *n = ultimate_alias_target ();
|
|
114
|
|
115 if (n->thunk.thunk_p)
|
|
116 return n->callees->callee->local_p ();
|
|
117 return !n->call_for_symbol_thunks_and_aliases (non_local_p,
|
|
118 NULL, true);
|
|
119
|
|
120 }
|
|
121
|
|
122 /* A helper for comdat_can_be_unshared_p. */
|
|
123
|
|
124 static bool
|
|
125 comdat_can_be_unshared_p_1 (symtab_node *node)
|
|
126 {
|
|
127 if (!node->externally_visible)
|
|
128 return true;
|
|
129 if (node->address_can_be_compared_p ())
|
|
130 {
|
|
131 struct ipa_ref *ref;
|
|
132
|
|
133 for (unsigned int i = 0; node->iterate_referring (i, ref); i++)
|
|
134 if (ref->address_matters_p ())
|
|
135 return false;
|
|
136 }
|
|
137
|
|
138 /* If the symbol is used in some weird way, better to not touch it. */
|
|
139 if (node->force_output)
|
|
140 return false;
|
|
141
|
|
142 /* Explicit instantiations needs to be output when possibly
|
|
143 used externally. */
|
|
144 if (node->forced_by_abi
|
|
145 && TREE_PUBLIC (node->decl)
|
|
146 && (node->resolution != LDPR_PREVAILING_DEF_IRONLY
|
|
147 && !flag_whole_program))
|
|
148 return false;
|
|
149
|
145
|
150 /* Non-readonly and volatile variables cannot be duplicated. */
|
111
|
151 if (is_a <varpool_node *> (node)
|
|
152 && (!TREE_READONLY (node->decl)
|
|
153 || TREE_THIS_VOLATILE (node->decl)))
|
|
154 return false;
|
|
155 return true;
|
|
156 }
|
|
157
|
|
158 /* COMDAT functions must be shared only if they have address taken,
|
|
159 otherwise we can produce our own private implementation with
|
|
160 -fwhole-program.
|
145
|
161 Return true when turning COMDAT function static cannot lead to wrong
|
111
|
162 code when the resulting object links with a library defining same COMDAT.
|
|
163
|
|
164 Virtual functions do have their addresses taken from the vtables,
|
|
165 but in C++ there is no way to compare their addresses for equality. */
|
|
166
|
|
167 static bool
|
|
168 comdat_can_be_unshared_p (symtab_node *node)
|
|
169 {
|
|
170 if (!comdat_can_be_unshared_p_1 (node))
|
|
171 return false;
|
|
172 if (node->same_comdat_group)
|
|
173 {
|
|
174 symtab_node *next;
|
|
175
|
|
176 /* If more than one function is in the same COMDAT group, it must
|
|
177 be shared even if just one function in the comdat group has
|
|
178 address taken. */
|
|
179 for (next = node->same_comdat_group;
|
|
180 next != node; next = next->same_comdat_group)
|
|
181 if (!comdat_can_be_unshared_p_1 (next))
|
|
182 return false;
|
|
183 }
|
|
184 return true;
|
|
185 }
|
|
186
|
|
187 /* Return true when function NODE should be considered externally visible. */
|
|
188
|
|
189 static bool
|
|
190 cgraph_externally_visible_p (struct cgraph_node *node,
|
|
191 bool whole_program)
|
|
192 {
|
|
193 while (node->transparent_alias && node->definition)
|
|
194 node = node->get_alias_target ();
|
|
195 if (!node->definition)
|
|
196 return false;
|
|
197 if (!TREE_PUBLIC (node->decl)
|
|
198 || DECL_EXTERNAL (node->decl))
|
|
199 return false;
|
|
200
|
|
201 /* Do not try to localize built-in functions yet. One of problems is that we
|
|
202 end up mangling their asm for WHOPR that makes it impossible to call them
|
|
203 using the implicit built-in declarations anymore. Similarly this enables
|
|
204 us to remove them as unreachable before actual calls may appear during
|
|
205 expansion or folding. */
|
131
|
206 if (fndecl_built_in_p (node->decl))
|
111
|
207 return true;
|
|
208
|
|
209 /* If linker counts on us, we must preserve the function. */
|
|
210 if (node->used_from_object_file_p ())
|
|
211 return true;
|
|
212 if (DECL_PRESERVE_P (node->decl))
|
|
213 return true;
|
|
214 if (lookup_attribute ("externally_visible",
|
|
215 DECL_ATTRIBUTES (node->decl)))
|
|
216 return true;
|
|
217 if (lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)))
|
|
218 return true;
|
|
219 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
|
220 && lookup_attribute ("dllexport",
|
|
221 DECL_ATTRIBUTES (node->decl)))
|
|
222 return true;
|
145
|
223
|
|
224 /* Limitation of gas requires us to output targets of symver aliases as
|
|
225 global symbols. This is binutils PR 25295. */
|
|
226 ipa_ref *ref;
|
|
227 FOR_EACH_ALIAS (node, ref)
|
|
228 if (ref->referring->symver)
|
|
229 return true;
|
|
230
|
111
|
231 if (node->resolution == LDPR_PREVAILING_DEF_IRONLY)
|
|
232 return false;
|
|
233 /* When doing LTO or whole program, we can bring COMDAT functoins static.
|
|
234 This improves code quality and we know we will duplicate them at most twice
|
|
235 (in the case that we are not using plugin and link with object file
|
|
236 implementing same COMDAT) */
|
|
237 if (((in_lto_p || whole_program) && !flag_incremental_link)
|
|
238 && DECL_COMDAT (node->decl)
|
|
239 && comdat_can_be_unshared_p (node))
|
|
240 return false;
|
|
241
|
|
242 /* When doing link time optimizations, hidden symbols become local. */
|
|
243 if ((in_lto_p && !flag_incremental_link)
|
|
244 && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
|
|
245 || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL)
|
|
246 /* Be sure that node is defined in IR file, not in other object
|
|
247 file. In that case we don't set used_from_other_object_file. */
|
|
248 && node->definition)
|
|
249 ;
|
|
250 else if (!whole_program)
|
|
251 return true;
|
|
252
|
|
253 if (MAIN_NAME_P (DECL_NAME (node->decl)))
|
|
254 return true;
|
|
255
|
|
256 return false;
|
|
257 }
|
|
258
|
|
259 /* Return true when variable should be considered externally visible. */
|
|
260
|
|
261 bool
|
|
262 varpool_node::externally_visible_p (void)
|
|
263 {
|
|
264 while (transparent_alias && definition)
|
|
265 return get_alias_target ()->externally_visible_p ();
|
|
266 if (DECL_EXTERNAL (decl))
|
|
267 return true;
|
|
268
|
|
269 if (!TREE_PUBLIC (decl))
|
|
270 return false;
|
|
271
|
|
272 /* If linker counts on us, we must preserve the function. */
|
|
273 if (used_from_object_file_p ())
|
|
274 return true;
|
|
275
|
|
276 /* Bringing TLS variables local may cause dynamic linker failures
|
|
277 on limits of static TLS vars. */
|
|
278 if (DECL_THREAD_LOCAL_P (decl)
|
|
279 && (DECL_TLS_MODEL (decl) != TLS_MODEL_EMULATED
|
|
280 && DECL_TLS_MODEL (decl) != TLS_MODEL_INITIAL_EXEC))
|
|
281 return true;
|
|
282
|
|
283 if (DECL_HARD_REGISTER (decl))
|
|
284 return true;
|
|
285 if (DECL_PRESERVE_P (decl))
|
|
286 return true;
|
|
287 if (lookup_attribute ("externally_visible",
|
|
288 DECL_ATTRIBUTES (decl)))
|
|
289 return true;
|
|
290 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
|
291 && lookup_attribute ("dllexport",
|
|
292 DECL_ATTRIBUTES (decl)))
|
|
293 return true;
|
|
294
|
145
|
295 /* Limitation of gas requires us to output targets of symver aliases as
|
|
296 global symbols. This is binutils PR 25295. */
|
|
297 ipa_ref *ref;
|
|
298 FOR_EACH_ALIAS (this, ref)
|
|
299 if (ref->referring->symver)
|
|
300 return true;
|
111
|
301
|
|
302 if (resolution == LDPR_PREVAILING_DEF_IRONLY)
|
|
303 return false;
|
|
304
|
|
305 /* As a special case, the COMDAT virtual tables can be unshared.
|
|
306 In LTO mode turn vtables into static variables. The variable is readonly,
|
|
307 so this does not enable more optimization, but referring static var
|
|
308 is faster for dynamic linking. Also this match logic hidding vtables
|
|
309 from LTO symbol tables. */
|
|
310 if (((in_lto_p || flag_whole_program) && !flag_incremental_link)
|
|
311 && DECL_COMDAT (decl)
|
|
312 && comdat_can_be_unshared_p (this))
|
|
313 return false;
|
|
314
|
|
315 /* When doing link time optimizations, hidden symbols become local. */
|
|
316 if (in_lto_p && !flag_incremental_link
|
|
317 && (DECL_VISIBILITY (decl) == VISIBILITY_HIDDEN
|
|
318 || DECL_VISIBILITY (decl) == VISIBILITY_INTERNAL)
|
|
319 /* Be sure that node is defined in IR file, not in other object
|
|
320 file. In that case we don't set used_from_other_object_file. */
|
|
321 && definition)
|
|
322 ;
|
|
323 else if (!flag_whole_program)
|
|
324 return true;
|
|
325
|
|
326 /* Do not attempt to privatize COMDATS by default.
|
|
327 This would break linking with C++ libraries sharing
|
|
328 inline definitions.
|
|
329
|
|
330 FIXME: We can do so for readonly vars with no address taken and
|
|
331 possibly also for vtables since no direct pointer comparsion is done.
|
|
332 It might be interesting to do so to reduce linking overhead. */
|
|
333 if (DECL_COMDAT (decl) || DECL_WEAK (decl))
|
|
334 return true;
|
|
335 return false;
|
|
336 }
|
|
337
|
|
338 /* Return true if reference to NODE can be replaced by a local alias.
|
|
339 Local aliases save dynamic linking overhead and enable more optimizations.
|
|
340 */
|
|
341
|
|
342 static bool
|
|
343 can_replace_by_local_alias (symtab_node *node)
|
|
344 {
|
|
345 /* If aliases aren't supported, we can't do replacement. */
|
|
346 if (!TARGET_SUPPORTS_ALIASES)
|
|
347 return false;
|
|
348
|
|
349 /* Weakrefs have a reason to be non-local. Be sure we do not replace
|
|
350 them. */
|
|
351 while (node->transparent_alias && node->definition && !node->weakref)
|
|
352 node = node->get_alias_target ();
|
|
353 if (node->weakref)
|
|
354 return false;
|
|
355
|
|
356 return (node->get_availability () > AVAIL_INTERPOSABLE
|
|
357 && !decl_binds_to_current_def_p (node->decl)
|
|
358 && !node->can_be_discarded_p ());
|
|
359 }
|
|
360
|
|
361 /* Return true if we can replace reference to NODE by local alias
|
|
362 within a virtual table. Generally we can replace function pointers
|
|
363 and virtual table pointers. */
|
|
364
|
|
365 static bool
|
|
366 can_replace_by_local_alias_in_vtable (symtab_node *node)
|
|
367 {
|
|
368 if (is_a <varpool_node *> (node)
|
|
369 && !DECL_VIRTUAL_P (node->decl))
|
|
370 return false;
|
|
371 return can_replace_by_local_alias (node);
|
|
372 }
|
|
373
|
|
374 /* walk_tree callback that rewrites initializer references. */
|
|
375
|
|
376 static tree
|
|
377 update_vtable_references (tree *tp, int *walk_subtrees,
|
|
378 void *data ATTRIBUTE_UNUSED)
|
|
379 {
|
|
380 if (VAR_OR_FUNCTION_DECL_P (*tp))
|
|
381 {
|
|
382 if (can_replace_by_local_alias_in_vtable (symtab_node::get (*tp)))
|
|
383 *tp = symtab_node::get (*tp)->noninterposable_alias ()->decl;
|
|
384 *walk_subtrees = 0;
|
|
385 }
|
|
386 else if (IS_TYPE_OR_DECL_P (*tp))
|
|
387 *walk_subtrees = 0;
|
|
388 return NULL;
|
|
389 }
|
|
390
|
|
391 /* In LTO we can remove COMDAT groups and weak symbols.
|
|
392 Either turn them into normal symbols or external symbol depending on
|
|
393 resolution info. */
|
|
394
|
|
395 static void
|
|
396 update_visibility_by_resolution_info (symtab_node * node)
|
|
397 {
|
|
398 bool define;
|
|
399
|
|
400 if (!node->externally_visible
|
|
401 || (!DECL_WEAK (node->decl) && !DECL_ONE_ONLY (node->decl))
|
|
402 || node->resolution == LDPR_UNKNOWN)
|
|
403 return;
|
|
404
|
|
405 define = (node->resolution == LDPR_PREVAILING_DEF_IRONLY
|
|
406 || node->resolution == LDPR_PREVAILING_DEF
|
|
407 || node->resolution == LDPR_UNDEF
|
|
408 || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
|
|
409
|
|
410 /* The linker decisions ought to agree in the whole group. */
|
|
411 if (node->same_comdat_group)
|
|
412 for (symtab_node *next = node->same_comdat_group;
|
|
413 next != node; next = next->same_comdat_group)
|
|
414 {
|
|
415 if (!next->externally_visible || next->transparent_alias)
|
|
416 continue;
|
|
417
|
|
418 bool same_def
|
|
419 = define == (next->resolution == LDPR_PREVAILING_DEF_IRONLY
|
|
420 || next->resolution == LDPR_PREVAILING_DEF
|
|
421 || next->resolution == LDPR_UNDEF
|
|
422 || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
|
|
423 gcc_assert (in_lto_p || same_def);
|
|
424 if (!same_def)
|
|
425 return;
|
|
426 }
|
|
427
|
|
428 if (node->same_comdat_group)
|
|
429 for (symtab_node *next = node->same_comdat_group;
|
|
430 next != node; next = next->same_comdat_group)
|
|
431 {
|
|
432 /* During incremental linking we need to keep symbol weak for future
|
|
433 linking. We can still drop definition if we know non-LTO world
|
|
434 prevails. */
|
|
435 if (!flag_incremental_link)
|
|
436 {
|
|
437 DECL_WEAK (next->decl) = false;
|
|
438 next->set_comdat_group (NULL);
|
|
439 }
|
|
440 if (!define)
|
|
441 {
|
|
442 if (next->externally_visible)
|
|
443 DECL_EXTERNAL (next->decl) = true;
|
|
444 next->set_comdat_group (NULL);
|
|
445 }
|
|
446 }
|
|
447
|
|
448 /* During incremental linking we need to keep symbol weak for future
|
|
449 linking. We can still drop definition if we know non-LTO world prevails. */
|
|
450 if (!flag_incremental_link)
|
|
451 {
|
|
452 DECL_WEAK (node->decl) = false;
|
|
453 node->set_comdat_group (NULL);
|
|
454 node->dissolve_same_comdat_group_list ();
|
|
455 }
|
|
456 if (!define)
|
|
457 {
|
|
458 DECL_EXTERNAL (node->decl) = true;
|
|
459 node->set_comdat_group (NULL);
|
|
460 node->dissolve_same_comdat_group_list ();
|
|
461 }
|
|
462 }
|
|
463
|
|
464 /* Try to get rid of weakref. */
|
|
465
|
|
466 static void
|
|
467 optimize_weakref (symtab_node *node)
|
|
468 {
|
|
469 bool strip_weakref = false;
|
|
470 bool static_alias = false;
|
|
471
|
|
472 gcc_assert (node->weakref);
|
|
473
|
145
|
474 /* Weakrefs with no target defined cannot be optimized. */
|
111
|
475 if (!node->analyzed)
|
|
476 return;
|
|
477 symtab_node *target = node->get_alias_target ();
|
|
478
|
|
479 /* Weakrefs to weakrefs can be optimized only if target can be. */
|
|
480 if (target->weakref)
|
|
481 optimize_weakref (target);
|
|
482 if (target->weakref)
|
|
483 return;
|
|
484
|
|
485 /* If we have definition of weakref's target and we know it binds locally,
|
|
486 we can turn weakref to static alias. */
|
|
487 if (TARGET_SUPPORTS_ALIASES
|
|
488 && target->definition && decl_binds_to_current_def_p (target->decl))
|
|
489 strip_weakref = static_alias = true;
|
|
490 /* Otherwise we can turn weakref into transparent alias. This transformation
|
|
491 may break asm statements which directly refers to symbol name and expect
|
|
492 GNU as to translate it via .weakref directive. So do not optimize when
|
|
493 DECL_PRESERVED is set and .weakref is supported. */
|
|
494 else if ((!DECL_PRESERVE_P (target->decl)
|
|
495 || IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl)))
|
|
496 && !DECL_WEAK (target->decl)
|
|
497 && !DECL_EXTERNAL (target->decl)
|
|
498 && ((target->definition && !target->can_be_discarded_p ())
|
|
499 || target->resolution != LDPR_UNDEF))
|
|
500 strip_weakref = true;
|
|
501 if (!strip_weakref)
|
|
502 return;
|
|
503 node->weakref = false;
|
|
504 IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl)) = 0;
|
|
505 TREE_CHAIN (DECL_ASSEMBLER_NAME (node->decl)) = NULL_TREE;
|
|
506 DECL_ATTRIBUTES (node->decl) = remove_attribute ("weakref",
|
|
507 DECL_ATTRIBUTES
|
|
508 (node->decl));
|
|
509
|
|
510 if (dump_file)
|
|
511 fprintf (dump_file, "Optimizing weakref %s %s\n",
|
145
|
512 node->dump_name (),
|
111
|
513 static_alias ? "as static alias" : "as transparent alias");
|
|
514
|
|
515 if (static_alias)
|
|
516 {
|
|
517 /* make_decl_local will shortcircuit if it doesn't see TREE_PUBLIC.
|
|
518 be sure it really clears the WEAK flag. */
|
|
519 TREE_PUBLIC (node->decl) = true;
|
|
520 node->make_decl_local ();
|
|
521 node->forced_by_abi = false;
|
|
522 node->resolution = LDPR_PREVAILING_DEF_IRONLY;
|
|
523 node->externally_visible = false;
|
|
524 gcc_assert (!DECL_WEAK (node->decl));
|
|
525 node->transparent_alias = false;
|
|
526 }
|
|
527 else
|
|
528 {
|
|
529 symtab->change_decl_assembler_name
|
|
530 (node->decl, DECL_ASSEMBLER_NAME (node->get_alias_target ()->decl));
|
|
531 node->transparent_alias = true;
|
|
532 node->copy_visibility_from (target);
|
|
533 }
|
|
534 gcc_assert (node->alias);
|
|
535 }
|
|
536
|
|
537 /* NODE is an externally visible definition, which we've discovered is
|
|
538 not needed externally. Make it local to this compilation. */
|
|
539
|
|
540 static void
|
|
541 localize_node (bool whole_program, symtab_node *node)
|
|
542 {
|
|
543 gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl));
|
|
544
|
|
545 /* It is possible that one comdat group contains both hidden and non-hidden
|
|
546 symbols. In this case we can privatize all hidden symbol but we need
|
|
547 to keep non-hidden exported. */
|
|
548 if (node->same_comdat_group
|
145
|
549 && (node->resolution == LDPR_PREVAILING_DEF_IRONLY
|
|
550 || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP))
|
111
|
551 {
|
|
552 symtab_node *next;
|
|
553 for (next = node->same_comdat_group;
|
|
554 next != node; next = next->same_comdat_group)
|
|
555 if (next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
|
|
556 || next->resolution == LDPR_PREVAILING_DEF)
|
|
557 break;
|
|
558 if (node != next)
|
|
559 {
|
|
560 if (!node->transparent_alias)
|
|
561 {
|
|
562 node->resolution = LDPR_PREVAILING_DEF_IRONLY;
|
|
563 node->make_decl_local ();
|
|
564 if (!flag_incremental_link)
|
|
565 node->unique_name |= true;
|
|
566 return;
|
|
567 }
|
|
568 }
|
|
569 }
|
|
570 /* For similar reason do not privatize whole comdat when seeing comdat
|
|
571 local. Wait for non-comdat symbol to be privatized first. */
|
|
572 if (node->comdat_local_p ())
|
|
573 return;
|
|
574
|
|
575 if (node->same_comdat_group && TREE_PUBLIC (node->decl))
|
|
576 {
|
|
577 for (symtab_node *next = node->same_comdat_group;
|
|
578 next != node; next = next->same_comdat_group)
|
|
579 {
|
|
580 next->set_comdat_group (NULL);
|
|
581 if (!next->alias)
|
|
582 next->set_section (NULL);
|
|
583 if (!next->transparent_alias)
|
|
584 next->make_decl_local ();
|
|
585 next->unique_name
|
|
586 |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
|
|
587 || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
|
|
588 && TREE_PUBLIC (next->decl)
|
|
589 && !flag_incremental_link);
|
|
590 }
|
|
591
|
|
592 /* Now everything's localized, the grouping has no meaning, and
|
|
593 will cause crashes if we keep it around. */
|
|
594 node->dissolve_same_comdat_group_list ();
|
|
595 }
|
|
596
|
|
597 node->unique_name
|
|
598 |= ((node->resolution == LDPR_PREVAILING_DEF_IRONLY
|
|
599 || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
|
|
600 && TREE_PUBLIC (node->decl)
|
|
601 && !flag_incremental_link);
|
|
602
|
|
603 if (TREE_PUBLIC (node->decl))
|
|
604 node->set_comdat_group (NULL);
|
|
605 if (DECL_COMDAT (node->decl) && !node->alias)
|
|
606 node->set_section (NULL);
|
|
607 if (!node->transparent_alias)
|
|
608 {
|
|
609 node->resolution = LDPR_PREVAILING_DEF_IRONLY;
|
|
610 node->make_decl_local ();
|
|
611 }
|
|
612 }
|
|
613
|
|
614 /* Decide on visibility of all symbols. */
|
|
615
|
|
616 static unsigned int
|
|
617 function_and_variable_visibility (bool whole_program)
|
|
618 {
|
|
619 struct cgraph_node *node;
|
|
620 varpool_node *vnode;
|
|
621
|
|
622 /* All aliases should be processed at this point. */
|
|
623 gcc_checking_assert (!alias_pairs || !alias_pairs->length ());
|
|
624
|
|
625 #ifdef ASM_OUTPUT_DEF
|
|
626 FOR_EACH_DEFINED_FUNCTION (node)
|
|
627 {
|
|
628 if (node->get_availability () != AVAIL_INTERPOSABLE
|
|
629 || DECL_EXTERNAL (node->decl)
|
131
|
630 || node->has_aliases_p ()
|
|
631 || lookup_attribute ("noipa", DECL_ATTRIBUTES (node->decl)))
|
111
|
632 continue;
|
|
633
|
|
634 cgraph_node *alias = 0;
|
145
|
635 cgraph_edge *next_edge;
|
|
636 for (cgraph_edge *e = node->callees; e; e = next_edge)
|
111
|
637 {
|
145
|
638 next_edge = e->next_callee;
|
111
|
639 /* Recursive function calls usually can't be interposed. */
|
|
640
|
|
641 if (!e->recursive_p ())
|
|
642 continue;
|
|
643
|
|
644 if (!alias)
|
|
645 {
|
|
646 alias = dyn_cast<cgraph_node *> (node->noninterposable_alias ());
|
|
647 gcc_assert (alias && alias != node);
|
|
648 }
|
|
649
|
|
650 e->redirect_callee (alias);
|
|
651 if (gimple_has_body_p (e->caller->decl))
|
|
652 {
|
|
653 push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
|
145
|
654 cgraph_edge::redirect_call_stmt_to_callee (e);
|
111
|
655 pop_cfun ();
|
|
656 }
|
|
657 }
|
|
658 }
|
|
659 #endif
|
|
660
|
|
661 FOR_EACH_FUNCTION (node)
|
|
662 {
|
|
663 int flags = flags_from_decl_or_type (node->decl);
|
|
664
|
|
665 /* Optimize away PURE and CONST constructors and destructors. */
|
|
666 if (node->analyzed
|
|
667 && (DECL_STATIC_CONSTRUCTOR (node->decl)
|
|
668 || DECL_STATIC_DESTRUCTOR (node->decl))
|
|
669 && (flags & (ECF_CONST | ECF_PURE))
|
|
670 && !(flags & ECF_LOOPING_CONST_OR_PURE)
|
|
671 && opt_for_fn (node->decl, optimize))
|
|
672 {
|
|
673 DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
|
|
674 DECL_STATIC_DESTRUCTOR (node->decl) = 0;
|
|
675 }
|
|
676
|
|
677 /* Frontends and alias code marks nodes as needed before parsing
|
|
678 is finished. We may end up marking as node external nodes
|
|
679 where this flag is meaningless strip it. */
|
|
680 if (DECL_EXTERNAL (node->decl) || !node->definition)
|
|
681 {
|
|
682 node->force_output = 0;
|
|
683 node->forced_by_abi = 0;
|
|
684 }
|
|
685
|
|
686 /* C++ FE on lack of COMDAT support create local COMDAT functions
|
145
|
687 (that ought to be shared but cannot due to object format
|
111
|
688 limitations). It is necessary to keep the flag to make rest of C++ FE
|
|
689 happy. Clear the flag here to avoid confusion in middle-end. */
|
|
690 if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
|
|
691 DECL_COMDAT (node->decl) = 0;
|
|
692
|
|
693 /* For external decls stop tracking same_comdat_group. It doesn't matter
|
|
694 what comdat group they are in when they won't be emitted in this TU.
|
|
695
|
|
696 An exception is LTO where we may end up with both external
|
|
697 and non-external declarations in the same comdat group in
|
|
698 the case declarations was not merged. */
|
|
699 if (node->same_comdat_group && DECL_EXTERNAL (node->decl) && !in_lto_p)
|
|
700 {
|
|
701 if (flag_checking)
|
|
702 {
|
|
703 for (symtab_node *n = node->same_comdat_group;
|
|
704 n != node;
|
|
705 n = n->same_comdat_group)
|
|
706 /* If at least one of same comdat group functions is external,
|
|
707 all of them have to be, otherwise it is a front-end bug. */
|
|
708 gcc_assert (DECL_EXTERNAL (n->decl));
|
|
709 }
|
|
710 node->dissolve_same_comdat_group_list ();
|
|
711 }
|
|
712 gcc_assert ((!DECL_WEAK (node->decl)
|
|
713 && !DECL_COMDAT (node->decl))
|
|
714 || TREE_PUBLIC (node->decl)
|
|
715 || node->weakref
|
|
716 || DECL_EXTERNAL (node->decl));
|
|
717 if (cgraph_externally_visible_p (node, whole_program))
|
|
718 {
|
145
|
719 gcc_assert (!node->inlined_to);
|
111
|
720 node->externally_visible = true;
|
|
721 }
|
|
722 else
|
|
723 {
|
|
724 node->externally_visible = false;
|
|
725 node->forced_by_abi = false;
|
|
726 }
|
|
727 if (!node->externally_visible
|
|
728 && node->definition && !node->weakref
|
|
729 && !DECL_EXTERNAL (node->decl))
|
|
730 localize_node (whole_program, node);
|
|
731
|
|
732 if (node->thunk.thunk_p
|
|
733 && TREE_PUBLIC (node->decl))
|
|
734 {
|
|
735 struct cgraph_node *decl_node = node;
|
|
736
|
|
737 decl_node = decl_node->callees->callee->function_symbol ();
|
|
738
|
|
739 /* Thunks have the same visibility as function they are attached to.
|
|
740 Make sure the C++ front end set this up properly. */
|
|
741 if (DECL_ONE_ONLY (decl_node->decl))
|
|
742 {
|
|
743 gcc_checking_assert (DECL_COMDAT (node->decl)
|
|
744 == DECL_COMDAT (decl_node->decl));
|
|
745 gcc_checking_assert (node->in_same_comdat_group_p (decl_node));
|
|
746 gcc_checking_assert (node->same_comdat_group);
|
|
747 }
|
|
748 node->forced_by_abi = decl_node->forced_by_abi;
|
|
749 if (DECL_EXTERNAL (decl_node->decl))
|
|
750 DECL_EXTERNAL (node->decl) = 1;
|
|
751 }
|
|
752
|
|
753 update_visibility_by_resolution_info (node);
|
|
754 if (node->weakref)
|
|
755 optimize_weakref (node);
|
|
756 }
|
|
757 FOR_EACH_DEFINED_FUNCTION (node)
|
|
758 {
|
145
|
759 if (!node->local)
|
|
760 node->local |= node->local_p ();
|
111
|
761
|
145
|
762 /* If we know that function cannot be overwritten by a
|
|
763 different semantics and moreover its section cannot be
|
111
|
764 discarded, replace all direct calls by calls to an
|
|
765 noninterposable alias. This make dynamic linking cheaper and
|
|
766 enable more optimization.
|
|
767
|
|
768 TODO: We can also update virtual tables. */
|
|
769 if (node->callers
|
|
770 && can_replace_by_local_alias (node))
|
|
771 {
|
|
772 cgraph_node *alias = dyn_cast<cgraph_node *>
|
|
773 (node->noninterposable_alias ());
|
|
774
|
|
775 if (alias && alias != node)
|
|
776 {
|
|
777 while (node->callers)
|
|
778 {
|
|
779 struct cgraph_edge *e = node->callers;
|
|
780
|
|
781 e->redirect_callee (alias);
|
|
782 if (gimple_has_body_p (e->caller->decl))
|
|
783 {
|
|
784 push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
|
145
|
785 cgraph_edge::redirect_call_stmt_to_callee (e);
|
111
|
786 pop_cfun ();
|
|
787 }
|
|
788 }
|
|
789 }
|
|
790 }
|
|
791 }
|
|
792 FOR_EACH_VARIABLE (vnode)
|
|
793 {
|
|
794 /* weak flag makes no sense on local variables. */
|
|
795 gcc_assert (!DECL_WEAK (vnode->decl)
|
|
796 || vnode->weakref
|
|
797 || TREE_PUBLIC (vnode->decl)
|
|
798 || DECL_EXTERNAL (vnode->decl));
|
145
|
799 /* In several cases declarations cannot be common:
|
111
|
800
|
|
801 - when declaration has initializer
|
|
802 - when it is in weak
|
|
803 - when it has specific section
|
|
804 - when it resides in non-generic address space.
|
|
805 - if declaration is local, it will get into .local common section
|
|
806 so common flag is not needed. Frontends still produce these in
|
|
807 certain cases, such as for:
|
|
808
|
|
809 static int a __attribute__ ((common))
|
|
810
|
|
811 Canonicalize things here and clear the redundant flag. */
|
|
812 if (DECL_COMMON (vnode->decl)
|
|
813 && (!(TREE_PUBLIC (vnode->decl)
|
|
814 || DECL_EXTERNAL (vnode->decl))
|
|
815 || (DECL_INITIAL (vnode->decl)
|
|
816 && DECL_INITIAL (vnode->decl) != error_mark_node)
|
|
817 || DECL_WEAK (vnode->decl)
|
|
818 || DECL_SECTION_NAME (vnode->decl) != NULL
|
|
819 || ! (ADDR_SPACE_GENERIC_P
|
|
820 (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
|
|
821 DECL_COMMON (vnode->decl) = 0;
|
|
822 if (vnode->weakref)
|
|
823 optimize_weakref (vnode);
|
|
824 }
|
|
825 FOR_EACH_DEFINED_VARIABLE (vnode)
|
|
826 {
|
|
827 if (!vnode->definition)
|
|
828 continue;
|
|
829 if (vnode->externally_visible_p ())
|
|
830 vnode->externally_visible = true;
|
|
831 else
|
|
832 {
|
|
833 vnode->externally_visible = false;
|
|
834 vnode->forced_by_abi = false;
|
|
835 }
|
|
836 if (lookup_attribute ("no_reorder",
|
|
837 DECL_ATTRIBUTES (vnode->decl)))
|
|
838 vnode->no_reorder = 1;
|
|
839
|
|
840 if (!vnode->externally_visible
|
|
841 && !vnode->transparent_alias
|
|
842 && !DECL_EXTERNAL (vnode->decl))
|
|
843 localize_node (whole_program, vnode);
|
|
844
|
|
845 update_visibility_by_resolution_info (vnode);
|
|
846
|
|
847 /* Update virtual tables to point to local aliases where possible. */
|
|
848 if (DECL_VIRTUAL_P (vnode->decl)
|
|
849 && !DECL_EXTERNAL (vnode->decl))
|
|
850 {
|
|
851 int i;
|
|
852 struct ipa_ref *ref;
|
|
853 bool found = false;
|
|
854
|
|
855 /* See if there is something to update. */
|
|
856 for (i = 0; vnode->iterate_reference (i, ref); i++)
|
|
857 if (ref->use == IPA_REF_ADDR
|
|
858 && can_replace_by_local_alias_in_vtable (ref->referred))
|
|
859 {
|
|
860 found = true;
|
|
861 break;
|
|
862 }
|
|
863 if (found)
|
|
864 {
|
|
865 hash_set<tree> visited_nodes;
|
|
866
|
|
867 vnode->get_constructor ();
|
|
868 walk_tree (&DECL_INITIAL (vnode->decl),
|
|
869 update_vtable_references, NULL, &visited_nodes);
|
|
870 vnode->remove_all_references ();
|
|
871 record_references_in_initializer (vnode->decl, false);
|
|
872 }
|
|
873 }
|
|
874 }
|
|
875
|
|
876 if (dump_file)
|
|
877 {
|
|
878 fprintf (dump_file, "\nMarking local functions:");
|
|
879 FOR_EACH_DEFINED_FUNCTION (node)
|
145
|
880 if (node->local)
|
|
881 fprintf (dump_file, " %s", node->dump_name ());
|
111
|
882 fprintf (dump_file, "\n\n");
|
|
883 fprintf (dump_file, "\nMarking externally visible functions:");
|
|
884 FOR_EACH_DEFINED_FUNCTION (node)
|
|
885 if (node->externally_visible)
|
145
|
886 fprintf (dump_file, " %s", node->dump_name ());
|
111
|
887 fprintf (dump_file, "\n\n");
|
|
888 fprintf (dump_file, "\nMarking externally visible variables:");
|
|
889 FOR_EACH_DEFINED_VARIABLE (vnode)
|
|
890 if (vnode->externally_visible)
|
145
|
891 fprintf (dump_file, " %s", vnode->dump_name ());
|
111
|
892 fprintf (dump_file, "\n\n");
|
|
893 }
|
|
894 symtab->function_flags_ready = true;
|
|
895 return 0;
|
|
896 }
|
|
897
|
|
898 /* Local function pass handling visibilities. This happens before LTO streaming
|
|
899 so in particular -fwhole-program should be ignored at this level. */
|
|
900
|
|
901 namespace {
|
|
902
|
|
903 const pass_data pass_data_ipa_function_and_variable_visibility =
|
|
904 {
|
|
905 SIMPLE_IPA_PASS, /* type */
|
|
906 "visibility", /* name */
|
|
907 OPTGROUP_NONE, /* optinfo_flags */
|
|
908 TV_CGRAPHOPT, /* tv_id */
|
|
909 0, /* properties_required */
|
|
910 0, /* properties_provided */
|
|
911 0, /* properties_destroyed */
|
|
912 0, /* todo_flags_start */
|
|
913 ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
|
|
914 };
|
|
915
|
|
916 /* Bring functions local at LTO time with -fwhole-program. */
|
|
917
|
|
918 static unsigned int
|
|
919 whole_program_function_and_variable_visibility (void)
|
|
920 {
|
|
921 function_and_variable_visibility (flag_whole_program);
|
|
922 if (optimize || in_lto_p)
|
145
|
923 ipa_discover_variable_flags ();
|
111
|
924 return 0;
|
|
925 }
|
|
926
|
|
927 } // anon namespace
|
|
928
|
|
929 namespace {
|
|
930
|
|
931 const pass_data pass_data_ipa_whole_program_visibility =
|
|
932 {
|
|
933 IPA_PASS, /* type */
|
|
934 "whole-program", /* name */
|
|
935 OPTGROUP_NONE, /* optinfo_flags */
|
|
936 TV_CGRAPHOPT, /* tv_id */
|
|
937 0, /* properties_required */
|
|
938 0, /* properties_provided */
|
|
939 0, /* properties_destroyed */
|
|
940 0, /* todo_flags_start */
|
|
941 ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
|
|
942 };
|
|
943
|
|
944 class pass_ipa_whole_program_visibility : public ipa_opt_pass_d
|
|
945 {
|
|
946 public:
|
|
947 pass_ipa_whole_program_visibility (gcc::context *ctxt)
|
|
948 : ipa_opt_pass_d (pass_data_ipa_whole_program_visibility, ctxt,
|
|
949 NULL, /* generate_summary */
|
|
950 NULL, /* write_summary */
|
|
951 NULL, /* read_summary */
|
|
952 NULL, /* write_optimization_summary */
|
|
953 NULL, /* read_optimization_summary */
|
|
954 NULL, /* stmt_fixup */
|
|
955 0, /* function_transform_todo_flags_start */
|
|
956 NULL, /* function_transform */
|
|
957 NULL) /* variable_transform */
|
|
958 {}
|
|
959
|
|
960 /* opt_pass methods: */
|
|
961
|
|
962 virtual bool gate (function *)
|
|
963 {
|
|
964 /* Do not re-run on ltrans stage. */
|
|
965 return !flag_ltrans;
|
|
966 }
|
|
967 virtual unsigned int execute (function *)
|
|
968 {
|
|
969 return whole_program_function_and_variable_visibility ();
|
|
970 }
|
|
971
|
|
972 }; // class pass_ipa_whole_program_visibility
|
|
973
|
|
974 } // anon namespace
|
|
975
|
|
976 ipa_opt_pass_d *
|
|
977 make_pass_ipa_whole_program_visibility (gcc::context *ctxt)
|
|
978 {
|
|
979 return new pass_ipa_whole_program_visibility (ctxt);
|
|
980 }
|
|
981
|
|
982 class pass_ipa_function_and_variable_visibility : public simple_ipa_opt_pass
|
|
983 {
|
|
984 public:
|
|
985 pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
|
|
986 : simple_ipa_opt_pass (pass_data_ipa_function_and_variable_visibility,
|
|
987 ctxt)
|
|
988 {}
|
|
989
|
|
990 /* opt_pass methods: */
|
|
991 virtual unsigned int execute (function *)
|
|
992 {
|
|
993 return function_and_variable_visibility (flag_whole_program && !flag_lto);
|
|
994 }
|
|
995
|
|
996 }; // class pass_ipa_function_and_variable_visibility
|
|
997
|
|
998 simple_ipa_opt_pass *
|
|
999 make_pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
|
|
1000 {
|
|
1001 return new pass_ipa_function_and_variable_visibility (ctxt);
|
|
1002 }
|