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