111
|
1 /* IPA visibility pass
|
|
2 Copyright (C) 2003-2017 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 /* 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
|
|
45 externally_visible flag is set for symbols that can not be privatized.
|
|
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
|
|
90 /* Return true when NODE can not be local. Worker for cgraph_local_node_p. */
|
|
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
|
|
150 /* Non-readonly and volatile variables can not be duplicated. */
|
|
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.
|
|
161 Return true when turning COMDAT function static can not lead to wrong
|
|
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. */
|
|
206 if (DECL_BUILT_IN (node->decl))
|
|
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;
|
|
223 if (node->resolution == LDPR_PREVAILING_DEF_IRONLY)
|
|
224 return false;
|
|
225 /* When doing LTO or whole program, we can bring COMDAT functoins static.
|
|
226 This improves code quality and we know we will duplicate them at most twice
|
|
227 (in the case that we are not using plugin and link with object file
|
|
228 implementing same COMDAT) */
|
|
229 if (((in_lto_p || whole_program) && !flag_incremental_link)
|
|
230 && DECL_COMDAT (node->decl)
|
|
231 && comdat_can_be_unshared_p (node))
|
|
232 return false;
|
|
233
|
|
234 /* When doing link time optimizations, hidden symbols become local. */
|
|
235 if ((in_lto_p && !flag_incremental_link)
|
|
236 && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
|
|
237 || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL)
|
|
238 /* Be sure that node is defined in IR file, not in other object
|
|
239 file. In that case we don't set used_from_other_object_file. */
|
|
240 && node->definition)
|
|
241 ;
|
|
242 else if (!whole_program)
|
|
243 return true;
|
|
244
|
|
245 if (MAIN_NAME_P (DECL_NAME (node->decl)))
|
|
246 return true;
|
|
247
|
|
248 if (node->instrumentation_clone
|
|
249 && MAIN_NAME_P (DECL_NAME (node->orig_decl)))
|
|
250 return true;
|
|
251
|
|
252 return false;
|
|
253 }
|
|
254
|
|
255 /* Return true when variable should be considered externally visible. */
|
|
256
|
|
257 bool
|
|
258 varpool_node::externally_visible_p (void)
|
|
259 {
|
|
260 while (transparent_alias && definition)
|
|
261 return get_alias_target ()->externally_visible_p ();
|
|
262 if (DECL_EXTERNAL (decl))
|
|
263 return true;
|
|
264
|
|
265 if (!TREE_PUBLIC (decl))
|
|
266 return false;
|
|
267
|
|
268 /* If linker counts on us, we must preserve the function. */
|
|
269 if (used_from_object_file_p ())
|
|
270 return true;
|
|
271
|
|
272 /* Bringing TLS variables local may cause dynamic linker failures
|
|
273 on limits of static TLS vars. */
|
|
274 if (DECL_THREAD_LOCAL_P (decl)
|
|
275 && (DECL_TLS_MODEL (decl) != TLS_MODEL_EMULATED
|
|
276 && DECL_TLS_MODEL (decl) != TLS_MODEL_INITIAL_EXEC))
|
|
277 return true;
|
|
278
|
|
279 if (DECL_HARD_REGISTER (decl))
|
|
280 return true;
|
|
281 if (DECL_PRESERVE_P (decl))
|
|
282 return true;
|
|
283 if (lookup_attribute ("externally_visible",
|
|
284 DECL_ATTRIBUTES (decl)))
|
|
285 return true;
|
|
286 if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
|
287 && lookup_attribute ("dllexport",
|
|
288 DECL_ATTRIBUTES (decl)))
|
|
289 return true;
|
|
290
|
|
291 /* See if we have linker information about symbol not being used or
|
|
292 if we need to make guess based on the declaration.
|
|
293
|
|
294 Even if the linker clams the symbol is unused, never bring internal
|
|
295 symbols that are declared by user as used or externally visible.
|
|
296 This is needed for i.e. references from asm statements. */
|
|
297 if (used_from_object_file_p ())
|
|
298 return true;
|
|
299 if (resolution == LDPR_PREVAILING_DEF_IRONLY)
|
|
300 return false;
|
|
301
|
|
302 /* As a special case, the COMDAT virtual tables can be unshared.
|
|
303 In LTO mode turn vtables into static variables. The variable is readonly,
|
|
304 so this does not enable more optimization, but referring static var
|
|
305 is faster for dynamic linking. Also this match logic hidding vtables
|
|
306 from LTO symbol tables. */
|
|
307 if (((in_lto_p || flag_whole_program) && !flag_incremental_link)
|
|
308 && DECL_COMDAT (decl)
|
|
309 && comdat_can_be_unshared_p (this))
|
|
310 return false;
|
|
311
|
|
312 /* When doing link time optimizations, hidden symbols become local. */
|
|
313 if (in_lto_p && !flag_incremental_link
|
|
314 && (DECL_VISIBILITY (decl) == VISIBILITY_HIDDEN
|
|
315 || DECL_VISIBILITY (decl) == VISIBILITY_INTERNAL)
|
|
316 /* Be sure that node is defined in IR file, not in other object
|
|
317 file. In that case we don't set used_from_other_object_file. */
|
|
318 && definition)
|
|
319 ;
|
|
320 else if (!flag_whole_program)
|
|
321 return true;
|
|
322
|
|
323 /* Do not attempt to privatize COMDATS by default.
|
|
324 This would break linking with C++ libraries sharing
|
|
325 inline definitions.
|
|
326
|
|
327 FIXME: We can do so for readonly vars with no address taken and
|
|
328 possibly also for vtables since no direct pointer comparsion is done.
|
|
329 It might be interesting to do so to reduce linking overhead. */
|
|
330 if (DECL_COMDAT (decl) || DECL_WEAK (decl))
|
|
331 return true;
|
|
332 return false;
|
|
333 }
|
|
334
|
|
335 /* Return true if reference to NODE can be replaced by a local alias.
|
|
336 Local aliases save dynamic linking overhead and enable more optimizations.
|
|
337 */
|
|
338
|
|
339 static bool
|
|
340 can_replace_by_local_alias (symtab_node *node)
|
|
341 {
|
|
342 /* If aliases aren't supported, we can't do replacement. */
|
|
343 if (!TARGET_SUPPORTS_ALIASES)
|
|
344 return false;
|
|
345
|
|
346 /* Weakrefs have a reason to be non-local. Be sure we do not replace
|
|
347 them. */
|
|
348 while (node->transparent_alias && node->definition && !node->weakref)
|
|
349 node = node->get_alias_target ();
|
|
350 if (node->weakref)
|
|
351 return false;
|
|
352
|
|
353 return (node->get_availability () > AVAIL_INTERPOSABLE
|
|
354 && !decl_binds_to_current_def_p (node->decl)
|
|
355 && !node->can_be_discarded_p ());
|
|
356 }
|
|
357
|
|
358 /* Return true if we can replace reference to NODE by local alias
|
|
359 within a virtual table. Generally we can replace function pointers
|
|
360 and virtual table pointers. */
|
|
361
|
|
362 static bool
|
|
363 can_replace_by_local_alias_in_vtable (symtab_node *node)
|
|
364 {
|
|
365 if (is_a <varpool_node *> (node)
|
|
366 && !DECL_VIRTUAL_P (node->decl))
|
|
367 return false;
|
|
368 return can_replace_by_local_alias (node);
|
|
369 }
|
|
370
|
|
371 /* walk_tree callback that rewrites initializer references. */
|
|
372
|
|
373 static tree
|
|
374 update_vtable_references (tree *tp, int *walk_subtrees,
|
|
375 void *data ATTRIBUTE_UNUSED)
|
|
376 {
|
|
377 if (VAR_OR_FUNCTION_DECL_P (*tp))
|
|
378 {
|
|
379 if (can_replace_by_local_alias_in_vtable (symtab_node::get (*tp)))
|
|
380 *tp = symtab_node::get (*tp)->noninterposable_alias ()->decl;
|
|
381 *walk_subtrees = 0;
|
|
382 }
|
|
383 else if (IS_TYPE_OR_DECL_P (*tp))
|
|
384 *walk_subtrees = 0;
|
|
385 return NULL;
|
|
386 }
|
|
387
|
|
388 /* In LTO we can remove COMDAT groups and weak symbols.
|
|
389 Either turn them into normal symbols or external symbol depending on
|
|
390 resolution info. */
|
|
391
|
|
392 static void
|
|
393 update_visibility_by_resolution_info (symtab_node * node)
|
|
394 {
|
|
395 bool define;
|
|
396
|
|
397 if (!node->externally_visible
|
|
398 || (!DECL_WEAK (node->decl) && !DECL_ONE_ONLY (node->decl))
|
|
399 || node->resolution == LDPR_UNKNOWN)
|
|
400 return;
|
|
401
|
|
402 define = (node->resolution == LDPR_PREVAILING_DEF_IRONLY
|
|
403 || node->resolution == LDPR_PREVAILING_DEF
|
|
404 || node->resolution == LDPR_UNDEF
|
|
405 || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
|
|
406
|
|
407 /* The linker decisions ought to agree in the whole group. */
|
|
408 if (node->same_comdat_group)
|
|
409 for (symtab_node *next = node->same_comdat_group;
|
|
410 next != node; next = next->same_comdat_group)
|
|
411 {
|
|
412 if (!next->externally_visible || next->transparent_alias)
|
|
413 continue;
|
|
414
|
|
415 bool same_def
|
|
416 = define == (next->resolution == LDPR_PREVAILING_DEF_IRONLY
|
|
417 || next->resolution == LDPR_PREVAILING_DEF
|
|
418 || next->resolution == LDPR_UNDEF
|
|
419 || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP);
|
|
420 gcc_assert (in_lto_p || same_def);
|
|
421 if (!same_def)
|
|
422 return;
|
|
423 }
|
|
424
|
|
425 if (node->same_comdat_group)
|
|
426 for (symtab_node *next = node->same_comdat_group;
|
|
427 next != node; next = next->same_comdat_group)
|
|
428 {
|
|
429 /* During incremental linking we need to keep symbol weak for future
|
|
430 linking. We can still drop definition if we know non-LTO world
|
|
431 prevails. */
|
|
432 if (!flag_incremental_link)
|
|
433 {
|
|
434 DECL_WEAK (next->decl) = false;
|
|
435 next->set_comdat_group (NULL);
|
|
436 }
|
|
437 if (!define)
|
|
438 {
|
|
439 if (next->externally_visible)
|
|
440 DECL_EXTERNAL (next->decl) = true;
|
|
441 next->set_comdat_group (NULL);
|
|
442 }
|
|
443 }
|
|
444
|
|
445 /* During incremental linking we need to keep symbol weak for future
|
|
446 linking. We can still drop definition if we know non-LTO world prevails. */
|
|
447 if (!flag_incremental_link)
|
|
448 {
|
|
449 DECL_WEAK (node->decl) = false;
|
|
450 node->set_comdat_group (NULL);
|
|
451 node->dissolve_same_comdat_group_list ();
|
|
452 }
|
|
453 if (!define)
|
|
454 {
|
|
455 DECL_EXTERNAL (node->decl) = true;
|
|
456 node->set_comdat_group (NULL);
|
|
457 node->dissolve_same_comdat_group_list ();
|
|
458 }
|
|
459 }
|
|
460
|
|
461 /* Try to get rid of weakref. */
|
|
462
|
|
463 static void
|
|
464 optimize_weakref (symtab_node *node)
|
|
465 {
|
|
466 bool strip_weakref = false;
|
|
467 bool static_alias = false;
|
|
468
|
|
469 gcc_assert (node->weakref);
|
|
470
|
|
471 /* Weakrefs with no target defined can not be optimized. */
|
|
472 if (!node->analyzed)
|
|
473 return;
|
|
474 symtab_node *target = node->get_alias_target ();
|
|
475
|
|
476 /* Weakrefs to weakrefs can be optimized only if target can be. */
|
|
477 if (target->weakref)
|
|
478 optimize_weakref (target);
|
|
479 if (target->weakref)
|
|
480 return;
|
|
481
|
|
482 /* If we have definition of weakref's target and we know it binds locally,
|
|
483 we can turn weakref to static alias. */
|
|
484 if (TARGET_SUPPORTS_ALIASES
|
|
485 && target->definition && decl_binds_to_current_def_p (target->decl))
|
|
486 strip_weakref = static_alias = true;
|
|
487 /* Otherwise we can turn weakref into transparent alias. This transformation
|
|
488 may break asm statements which directly refers to symbol name and expect
|
|
489 GNU as to translate it via .weakref directive. So do not optimize when
|
|
490 DECL_PRESERVED is set and .weakref is supported. */
|
|
491 else if ((!DECL_PRESERVE_P (target->decl)
|
|
492 || IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl)))
|
|
493 && !DECL_WEAK (target->decl)
|
|
494 && !DECL_EXTERNAL (target->decl)
|
|
495 && ((target->definition && !target->can_be_discarded_p ())
|
|
496 || target->resolution != LDPR_UNDEF))
|
|
497 strip_weakref = true;
|
|
498 if (!strip_weakref)
|
|
499 return;
|
|
500 node->weakref = false;
|
|
501 IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (node->decl)) = 0;
|
|
502 TREE_CHAIN (DECL_ASSEMBLER_NAME (node->decl)) = NULL_TREE;
|
|
503 DECL_ATTRIBUTES (node->decl) = remove_attribute ("weakref",
|
|
504 DECL_ATTRIBUTES
|
|
505 (node->decl));
|
|
506
|
|
507 if (dump_file)
|
|
508 fprintf (dump_file, "Optimizing weakref %s %s\n",
|
|
509 node->name(),
|
|
510 static_alias ? "as static alias" : "as transparent alias");
|
|
511
|
|
512 if (static_alias)
|
|
513 {
|
|
514 /* make_decl_local will shortcircuit if it doesn't see TREE_PUBLIC.
|
|
515 be sure it really clears the WEAK flag. */
|
|
516 TREE_PUBLIC (node->decl) = true;
|
|
517 node->make_decl_local ();
|
|
518 node->forced_by_abi = false;
|
|
519 node->resolution = LDPR_PREVAILING_DEF_IRONLY;
|
|
520 node->externally_visible = false;
|
|
521 gcc_assert (!DECL_WEAK (node->decl));
|
|
522 node->transparent_alias = false;
|
|
523 }
|
|
524 else
|
|
525 {
|
|
526 symtab->change_decl_assembler_name
|
|
527 (node->decl, DECL_ASSEMBLER_NAME (node->get_alias_target ()->decl));
|
|
528 node->transparent_alias = true;
|
|
529 node->copy_visibility_from (target);
|
|
530 }
|
|
531 gcc_assert (node->alias);
|
|
532 }
|
|
533
|
|
534 /* NODE is an externally visible definition, which we've discovered is
|
|
535 not needed externally. Make it local to this compilation. */
|
|
536
|
|
537 static void
|
|
538 localize_node (bool whole_program, symtab_node *node)
|
|
539 {
|
|
540 gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl));
|
|
541
|
|
542 /* It is possible that one comdat group contains both hidden and non-hidden
|
|
543 symbols. In this case we can privatize all hidden symbol but we need
|
|
544 to keep non-hidden exported. */
|
|
545 if (node->same_comdat_group
|
|
546 && node->resolution == LDPR_PREVAILING_DEF_IRONLY)
|
|
547 {
|
|
548 symtab_node *next;
|
|
549 for (next = node->same_comdat_group;
|
|
550 next != node; next = next->same_comdat_group)
|
|
551 if (next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
|
|
552 || next->resolution == LDPR_PREVAILING_DEF)
|
|
553 break;
|
|
554 if (node != next)
|
|
555 {
|
|
556 if (!node->transparent_alias)
|
|
557 {
|
|
558 node->resolution = LDPR_PREVAILING_DEF_IRONLY;
|
|
559 node->make_decl_local ();
|
|
560 if (!flag_incremental_link)
|
|
561 node->unique_name |= true;
|
|
562 return;
|
|
563 }
|
|
564 }
|
|
565 }
|
|
566 /* For similar reason do not privatize whole comdat when seeing comdat
|
|
567 local. Wait for non-comdat symbol to be privatized first. */
|
|
568 if (node->comdat_local_p ())
|
|
569 return;
|
|
570
|
|
571 if (node->same_comdat_group && TREE_PUBLIC (node->decl))
|
|
572 {
|
|
573 for (symtab_node *next = node->same_comdat_group;
|
|
574 next != node; next = next->same_comdat_group)
|
|
575 {
|
|
576 next->set_comdat_group (NULL);
|
|
577 if (!next->alias)
|
|
578 next->set_section (NULL);
|
|
579 if (!next->transparent_alias)
|
|
580 next->make_decl_local ();
|
|
581 next->unique_name
|
|
582 |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
|
|
583 || next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
|
|
584 && TREE_PUBLIC (next->decl)
|
|
585 && !flag_incremental_link);
|
|
586 }
|
|
587
|
|
588 /* Now everything's localized, the grouping has no meaning, and
|
|
589 will cause crashes if we keep it around. */
|
|
590 node->dissolve_same_comdat_group_list ();
|
|
591 }
|
|
592
|
|
593 node->unique_name
|
|
594 |= ((node->resolution == LDPR_PREVAILING_DEF_IRONLY
|
|
595 || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
|
|
596 && TREE_PUBLIC (node->decl)
|
|
597 && !flag_incremental_link);
|
|
598
|
|
599 if (TREE_PUBLIC (node->decl))
|
|
600 node->set_comdat_group (NULL);
|
|
601 if (DECL_COMDAT (node->decl) && !node->alias)
|
|
602 node->set_section (NULL);
|
|
603 if (!node->transparent_alias)
|
|
604 {
|
|
605 node->resolution = LDPR_PREVAILING_DEF_IRONLY;
|
|
606 node->make_decl_local ();
|
|
607 }
|
|
608 }
|
|
609
|
|
610 /* Decide on visibility of all symbols. */
|
|
611
|
|
612 static unsigned int
|
|
613 function_and_variable_visibility (bool whole_program)
|
|
614 {
|
|
615 struct cgraph_node *node;
|
|
616 varpool_node *vnode;
|
|
617
|
|
618 /* All aliases should be processed at this point. */
|
|
619 gcc_checking_assert (!alias_pairs || !alias_pairs->length ());
|
|
620
|
|
621 #ifdef ASM_OUTPUT_DEF
|
|
622 FOR_EACH_DEFINED_FUNCTION (node)
|
|
623 {
|
|
624 if (node->get_availability () != AVAIL_INTERPOSABLE
|
|
625 || DECL_EXTERNAL (node->decl)
|
|
626 || node->has_aliases_p ())
|
|
627 continue;
|
|
628
|
|
629 cgraph_node *alias = 0;
|
|
630 for (cgraph_edge *e = node->callees; e; e = e->next_callee)
|
|
631 {
|
|
632 /* Recursive function calls usually can't be interposed. */
|
|
633
|
|
634 if (!e->recursive_p ())
|
|
635 continue;
|
|
636
|
|
637 if (!alias)
|
|
638 {
|
|
639 alias = dyn_cast<cgraph_node *> (node->noninterposable_alias ());
|
|
640 gcc_assert (alias && alias != node);
|
|
641 }
|
|
642
|
|
643 e->redirect_callee (alias);
|
|
644 if (gimple_has_body_p (e->caller->decl))
|
|
645 {
|
|
646 push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
|
|
647 e->redirect_call_stmt_to_callee ();
|
|
648 pop_cfun ();
|
|
649 }
|
|
650 }
|
|
651 }
|
|
652 #endif
|
|
653
|
|
654 FOR_EACH_FUNCTION (node)
|
|
655 {
|
|
656 int flags = flags_from_decl_or_type (node->decl);
|
|
657
|
|
658 /* Optimize away PURE and CONST constructors and destructors. */
|
|
659 if (node->analyzed
|
|
660 && (DECL_STATIC_CONSTRUCTOR (node->decl)
|
|
661 || DECL_STATIC_DESTRUCTOR (node->decl))
|
|
662 && (flags & (ECF_CONST | ECF_PURE))
|
|
663 && !(flags & ECF_LOOPING_CONST_OR_PURE)
|
|
664 && opt_for_fn (node->decl, optimize))
|
|
665 {
|
|
666 DECL_STATIC_CONSTRUCTOR (node->decl) = 0;
|
|
667 DECL_STATIC_DESTRUCTOR (node->decl) = 0;
|
|
668 }
|
|
669
|
|
670 /* Frontends and alias code marks nodes as needed before parsing
|
|
671 is finished. We may end up marking as node external nodes
|
|
672 where this flag is meaningless strip it. */
|
|
673 if (DECL_EXTERNAL (node->decl) || !node->definition)
|
|
674 {
|
|
675 node->force_output = 0;
|
|
676 node->forced_by_abi = 0;
|
|
677 }
|
|
678
|
|
679 /* C++ FE on lack of COMDAT support create local COMDAT functions
|
|
680 (that ought to be shared but can not due to object format
|
|
681 limitations). It is necessary to keep the flag to make rest of C++ FE
|
|
682 happy. Clear the flag here to avoid confusion in middle-end. */
|
|
683 if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl))
|
|
684 DECL_COMDAT (node->decl) = 0;
|
|
685
|
|
686 /* For external decls stop tracking same_comdat_group. It doesn't matter
|
|
687 what comdat group they are in when they won't be emitted in this TU.
|
|
688
|
|
689 An exception is LTO where we may end up with both external
|
|
690 and non-external declarations in the same comdat group in
|
|
691 the case declarations was not merged. */
|
|
692 if (node->same_comdat_group && DECL_EXTERNAL (node->decl) && !in_lto_p)
|
|
693 {
|
|
694 if (flag_checking)
|
|
695 {
|
|
696 for (symtab_node *n = node->same_comdat_group;
|
|
697 n != node;
|
|
698 n = n->same_comdat_group)
|
|
699 /* If at least one of same comdat group functions is external,
|
|
700 all of them have to be, otherwise it is a front-end bug. */
|
|
701 gcc_assert (DECL_EXTERNAL (n->decl));
|
|
702 }
|
|
703 node->dissolve_same_comdat_group_list ();
|
|
704 }
|
|
705 gcc_assert ((!DECL_WEAK (node->decl)
|
|
706 && !DECL_COMDAT (node->decl))
|
|
707 || TREE_PUBLIC (node->decl)
|
|
708 || node->weakref
|
|
709 || DECL_EXTERNAL (node->decl));
|
|
710 if (cgraph_externally_visible_p (node, whole_program))
|
|
711 {
|
|
712 gcc_assert (!node->global.inlined_to);
|
|
713 node->externally_visible = true;
|
|
714 }
|
|
715 else
|
|
716 {
|
|
717 node->externally_visible = false;
|
|
718 node->forced_by_abi = false;
|
|
719 }
|
|
720 if (!node->externally_visible
|
|
721 && node->definition && !node->weakref
|
|
722 && !DECL_EXTERNAL (node->decl))
|
|
723 localize_node (whole_program, node);
|
|
724
|
|
725 if (node->thunk.thunk_p
|
|
726 && !node->thunk.add_pointer_bounds_args
|
|
727 && TREE_PUBLIC (node->decl))
|
|
728 {
|
|
729 struct cgraph_node *decl_node = node;
|
|
730
|
|
731 decl_node = decl_node->callees->callee->function_symbol ();
|
|
732
|
|
733 /* Thunks have the same visibility as function they are attached to.
|
|
734 Make sure the C++ front end set this up properly. */
|
|
735 if (DECL_ONE_ONLY (decl_node->decl))
|
|
736 {
|
|
737 gcc_checking_assert (DECL_COMDAT (node->decl)
|
|
738 == DECL_COMDAT (decl_node->decl));
|
|
739 gcc_checking_assert (node->in_same_comdat_group_p (decl_node));
|
|
740 gcc_checking_assert (node->same_comdat_group);
|
|
741 }
|
|
742 node->forced_by_abi = decl_node->forced_by_abi;
|
|
743 if (DECL_EXTERNAL (decl_node->decl))
|
|
744 DECL_EXTERNAL (node->decl) = 1;
|
|
745 }
|
|
746
|
|
747 update_visibility_by_resolution_info (node);
|
|
748 if (node->weakref)
|
|
749 optimize_weakref (node);
|
|
750 }
|
|
751 FOR_EACH_DEFINED_FUNCTION (node)
|
|
752 {
|
|
753 if (!node->local.local)
|
|
754 node->local.local |= node->local_p ();
|
|
755
|
|
756 /* If we know that function can not be overwritten by a
|
|
757 different semantics and moreover its section can not be
|
|
758 discarded, replace all direct calls by calls to an
|
|
759 noninterposable alias. This make dynamic linking cheaper and
|
|
760 enable more optimization.
|
|
761
|
|
762 TODO: We can also update virtual tables. */
|
|
763 if (node->callers
|
|
764 && can_replace_by_local_alias (node))
|
|
765 {
|
|
766 cgraph_node *alias = dyn_cast<cgraph_node *>
|
|
767 (node->noninterposable_alias ());
|
|
768
|
|
769 if (alias && alias != node)
|
|
770 {
|
|
771 while (node->callers)
|
|
772 {
|
|
773 struct cgraph_edge *e = node->callers;
|
|
774
|
|
775 e->redirect_callee (alias);
|
|
776 if (gimple_has_body_p (e->caller->decl))
|
|
777 {
|
|
778 push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
|
|
779 e->redirect_call_stmt_to_callee ();
|
|
780 pop_cfun ();
|
|
781 }
|
|
782 }
|
|
783 }
|
|
784 }
|
|
785 }
|
|
786 FOR_EACH_VARIABLE (vnode)
|
|
787 {
|
|
788 /* weak flag makes no sense on local variables. */
|
|
789 gcc_assert (!DECL_WEAK (vnode->decl)
|
|
790 || vnode->weakref
|
|
791 || TREE_PUBLIC (vnode->decl)
|
|
792 || DECL_EXTERNAL (vnode->decl));
|
|
793 /* In several cases declarations can not be common:
|
|
794
|
|
795 - when declaration has initializer
|
|
796 - when it is in weak
|
|
797 - when it has specific section
|
|
798 - when it resides in non-generic address space.
|
|
799 - if declaration is local, it will get into .local common section
|
|
800 so common flag is not needed. Frontends still produce these in
|
|
801 certain cases, such as for:
|
|
802
|
|
803 static int a __attribute__ ((common))
|
|
804
|
|
805 Canonicalize things here and clear the redundant flag. */
|
|
806 if (DECL_COMMON (vnode->decl)
|
|
807 && (!(TREE_PUBLIC (vnode->decl)
|
|
808 || DECL_EXTERNAL (vnode->decl))
|
|
809 || (DECL_INITIAL (vnode->decl)
|
|
810 && DECL_INITIAL (vnode->decl) != error_mark_node)
|
|
811 || DECL_WEAK (vnode->decl)
|
|
812 || DECL_SECTION_NAME (vnode->decl) != NULL
|
|
813 || ! (ADDR_SPACE_GENERIC_P
|
|
814 (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
|
|
815 DECL_COMMON (vnode->decl) = 0;
|
|
816 if (vnode->weakref)
|
|
817 optimize_weakref (vnode);
|
|
818 }
|
|
819 FOR_EACH_DEFINED_VARIABLE (vnode)
|
|
820 {
|
|
821 if (!vnode->definition)
|
|
822 continue;
|
|
823 if (vnode->externally_visible_p ())
|
|
824 vnode->externally_visible = true;
|
|
825 else
|
|
826 {
|
|
827 vnode->externally_visible = false;
|
|
828 vnode->forced_by_abi = false;
|
|
829 }
|
|
830 if (lookup_attribute ("no_reorder",
|
|
831 DECL_ATTRIBUTES (vnode->decl)))
|
|
832 vnode->no_reorder = 1;
|
|
833
|
|
834 if (!vnode->externally_visible
|
|
835 && !vnode->transparent_alias
|
|
836 && !DECL_EXTERNAL (vnode->decl))
|
|
837 localize_node (whole_program, vnode);
|
|
838
|
|
839 update_visibility_by_resolution_info (vnode);
|
|
840
|
|
841 /* Update virtual tables to point to local aliases where possible. */
|
|
842 if (DECL_VIRTUAL_P (vnode->decl)
|
|
843 && !DECL_EXTERNAL (vnode->decl))
|
|
844 {
|
|
845 int i;
|
|
846 struct ipa_ref *ref;
|
|
847 bool found = false;
|
|
848
|
|
849 /* See if there is something to update. */
|
|
850 for (i = 0; vnode->iterate_reference (i, ref); i++)
|
|
851 if (ref->use == IPA_REF_ADDR
|
|
852 && can_replace_by_local_alias_in_vtable (ref->referred))
|
|
853 {
|
|
854 found = true;
|
|
855 break;
|
|
856 }
|
|
857 if (found)
|
|
858 {
|
|
859 hash_set<tree> visited_nodes;
|
|
860
|
|
861 vnode->get_constructor ();
|
|
862 walk_tree (&DECL_INITIAL (vnode->decl),
|
|
863 update_vtable_references, NULL, &visited_nodes);
|
|
864 vnode->remove_all_references ();
|
|
865 record_references_in_initializer (vnode->decl, false);
|
|
866 }
|
|
867 }
|
|
868 }
|
|
869
|
|
870 if (dump_file)
|
|
871 {
|
|
872 fprintf (dump_file, "\nMarking local functions:");
|
|
873 FOR_EACH_DEFINED_FUNCTION (node)
|
|
874 if (node->local.local)
|
|
875 fprintf (dump_file, " %s", node->name ());
|
|
876 fprintf (dump_file, "\n\n");
|
|
877 fprintf (dump_file, "\nMarking externally visible functions:");
|
|
878 FOR_EACH_DEFINED_FUNCTION (node)
|
|
879 if (node->externally_visible)
|
|
880 fprintf (dump_file, " %s", node->name ());
|
|
881 fprintf (dump_file, "\n\n");
|
|
882 fprintf (dump_file, "\nMarking externally visible variables:");
|
|
883 FOR_EACH_DEFINED_VARIABLE (vnode)
|
|
884 if (vnode->externally_visible)
|
|
885 fprintf (dump_file, " %s", vnode->name ());
|
|
886 fprintf (dump_file, "\n\n");
|
|
887 }
|
|
888 symtab->function_flags_ready = true;
|
|
889 return 0;
|
|
890 }
|
|
891
|
|
892 /* Local function pass handling visibilities. This happens before LTO streaming
|
|
893 so in particular -fwhole-program should be ignored at this level. */
|
|
894
|
|
895 namespace {
|
|
896
|
|
897 const pass_data pass_data_ipa_function_and_variable_visibility =
|
|
898 {
|
|
899 SIMPLE_IPA_PASS, /* type */
|
|
900 "visibility", /* name */
|
|
901 OPTGROUP_NONE, /* optinfo_flags */
|
|
902 TV_CGRAPHOPT, /* tv_id */
|
|
903 0, /* properties_required */
|
|
904 0, /* properties_provided */
|
|
905 0, /* properties_destroyed */
|
|
906 0, /* todo_flags_start */
|
|
907 ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
|
|
908 };
|
|
909
|
|
910 /* Bring functions local at LTO time with -fwhole-program. */
|
|
911
|
|
912 static unsigned int
|
|
913 whole_program_function_and_variable_visibility (void)
|
|
914 {
|
|
915 function_and_variable_visibility (flag_whole_program);
|
|
916 if (optimize || in_lto_p)
|
|
917 ipa_discover_readonly_nonaddressable_vars ();
|
|
918 return 0;
|
|
919 }
|
|
920
|
|
921 } // anon namespace
|
|
922
|
|
923 namespace {
|
|
924
|
|
925 const pass_data pass_data_ipa_whole_program_visibility =
|
|
926 {
|
|
927 IPA_PASS, /* type */
|
|
928 "whole-program", /* name */
|
|
929 OPTGROUP_NONE, /* optinfo_flags */
|
|
930 TV_CGRAPHOPT, /* tv_id */
|
|
931 0, /* properties_required */
|
|
932 0, /* properties_provided */
|
|
933 0, /* properties_destroyed */
|
|
934 0, /* todo_flags_start */
|
|
935 ( TODO_remove_functions | TODO_dump_symtab ), /* todo_flags_finish */
|
|
936 };
|
|
937
|
|
938 class pass_ipa_whole_program_visibility : public ipa_opt_pass_d
|
|
939 {
|
|
940 public:
|
|
941 pass_ipa_whole_program_visibility (gcc::context *ctxt)
|
|
942 : ipa_opt_pass_d (pass_data_ipa_whole_program_visibility, ctxt,
|
|
943 NULL, /* generate_summary */
|
|
944 NULL, /* write_summary */
|
|
945 NULL, /* read_summary */
|
|
946 NULL, /* write_optimization_summary */
|
|
947 NULL, /* read_optimization_summary */
|
|
948 NULL, /* stmt_fixup */
|
|
949 0, /* function_transform_todo_flags_start */
|
|
950 NULL, /* function_transform */
|
|
951 NULL) /* variable_transform */
|
|
952 {}
|
|
953
|
|
954 /* opt_pass methods: */
|
|
955
|
|
956 virtual bool gate (function *)
|
|
957 {
|
|
958 /* Do not re-run on ltrans stage. */
|
|
959 return !flag_ltrans;
|
|
960 }
|
|
961 virtual unsigned int execute (function *)
|
|
962 {
|
|
963 return whole_program_function_and_variable_visibility ();
|
|
964 }
|
|
965
|
|
966 }; // class pass_ipa_whole_program_visibility
|
|
967
|
|
968 } // anon namespace
|
|
969
|
|
970 ipa_opt_pass_d *
|
|
971 make_pass_ipa_whole_program_visibility (gcc::context *ctxt)
|
|
972 {
|
|
973 return new pass_ipa_whole_program_visibility (ctxt);
|
|
974 }
|
|
975
|
|
976 class pass_ipa_function_and_variable_visibility : public simple_ipa_opt_pass
|
|
977 {
|
|
978 public:
|
|
979 pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
|
|
980 : simple_ipa_opt_pass (pass_data_ipa_function_and_variable_visibility,
|
|
981 ctxt)
|
|
982 {}
|
|
983
|
|
984 /* opt_pass methods: */
|
|
985 virtual unsigned int execute (function *)
|
|
986 {
|
|
987 return function_and_variable_visibility (flag_whole_program && !flag_lto);
|
|
988 }
|
|
989
|
|
990 }; // class pass_ipa_function_and_variable_visibility
|
|
991
|
|
992 simple_ipa_opt_pass *
|
|
993 make_pass_ipa_function_and_variable_visibility (gcc::context *ctxt)
|
|
994 {
|
|
995 return new pass_ipa_function_and_variable_visibility (ctxt);
|
|
996 }
|