]>
Commit | Line | Data |
---|---|---|
a66dc285 | 1 | /* LTO partitioning logic routines. |
23a5b65a | 2 | Copyright (C) 2009-2014 Free Software Foundation, Inc. |
a66dc285 JH |
3 | |
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify it under | |
7 | the terms of the GNU General Public License as published by the Free | |
8 | Software Foundation; either version 3, or (at your option) any later | |
9 | version. | |
10 | ||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GCC; see the file COPYING3. If not see | |
18 | <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "config.h" | |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
23 | #include "toplev.h" | |
24 | #include "tree.h" | |
d8a2d370 | 25 | #include "gcc-symtab.h" |
2fb9a547 AM |
26 | #include "basic-block.h" |
27 | #include "tree-ssa-alias.h" | |
28 | #include "internal-fn.h" | |
29 | #include "gimple-expr.h" | |
30 | #include "is-a.h" | |
8e9055ae | 31 | #include "gimple.h" |
a66dc285 JH |
32 | #include "tm.h" |
33 | #include "cgraph.h" | |
34 | #include "lto-streamer.h" | |
35 | #include "timevar.h" | |
36 | #include "params.h" | |
37 | #include "ipa-inline.h" | |
38 | #include "ipa-utils.h" | |
39 | #include "lto-partition.h" | |
40 | ||
c3c445e1 JH |
41 | /* Classifcation of symbols into classes WRT partitioning. */ |
42 | enum symbol_class | |
43 | { | |
44 | /* External declarations are ignored by partitioning algorithms and they are | |
45 | added into the boundary later via compute_ltrans_boundary. */ | |
46 | SYMBOL_EXTERNAL, | |
47 | /* Partitioned symbols are pur into one of partitions. */ | |
48 | SYMBOL_PARTITION, | |
49 | /* Duplicated symbols (such as comdat or constant pool references) are | |
50 | copied into every node needing them via add_symbol_to_partition. */ | |
51 | SYMBOL_DUPLICATE | |
52 | }; | |
53 | ||
9771b263 | 54 | vec<ltrans_partition> ltrans_partitions; |
a66dc285 | 55 | |
5e20cdc9 | 56 | static void add_symbol_to_partition (ltrans_partition part, symtab_node *node); |
c3c445e1 JH |
57 | |
58 | /* Classify symbol NODE. */ | |
59 | ||
60 | enum symbol_class | |
5e20cdc9 | 61 | get_symbol_class (symtab_node *node) |
c3c445e1 JH |
62 | { |
63 | /* Inline clones are always duplicated. | |
64 | This include external delcarations. */ | |
5d59b5e1 | 65 | cgraph_node *cnode = dyn_cast <cgraph_node> (node); |
815effe1 | 66 | |
67348ccc | 67 | if (DECL_ABSTRACT (node->decl)) |
815effe1 JH |
68 | return SYMBOL_EXTERNAL; |
69 | ||
5d59b5e1 | 70 | if (cnode && cnode->global.inlined_to) |
c3c445e1 JH |
71 | return SYMBOL_DUPLICATE; |
72 | ||
2d6e4603 | 73 | /* Weakref aliases are always duplicated. */ |
67348ccc | 74 | if (node->weakref) |
2d6e4603 JH |
75 | return SYMBOL_DUPLICATE; |
76 | ||
c3c445e1 | 77 | /* External declarations are external. */ |
67348ccc | 78 | if (DECL_EXTERNAL (node->decl)) |
c3c445e1 JH |
79 | return SYMBOL_EXTERNAL; |
80 | ||
5d59b5e1 | 81 | if (varpool_node *vnode = dyn_cast <varpool_node> (node)) |
c3c445e1 JH |
82 | { |
83 | /* Constant pool references use local symbol names that can not | |
84 | be promoted global. We should never put into a constant pool | |
85 | objects that can not be duplicated across partitions. */ | |
67348ccc | 86 | if (DECL_IN_CONSTANT_POOL (node->decl)) |
c3c445e1 | 87 | return SYMBOL_DUPLICATE; |
67348ccc | 88 | gcc_checking_assert (vnode->definition); |
c3c445e1 JH |
89 | } |
90 | /* Functions that are cloned may stay in callgraph even if they are unused. | |
91 | Handle them as external; compute_ltrans_boundary take care to make | |
92 | proper things to happen (i.e. to make them appear in the boundary but | |
93 | with body streamed, so clone can me materialized). */ | |
67348ccc | 94 | else if (!cgraph (node)->definition) |
c3c445e1 JH |
95 | return SYMBOL_EXTERNAL; |
96 | ||
c3c445e1 JH |
97 | /* Comdats are duplicated to every use unless they are keyed. |
98 | Those do not need duplication. */ | |
67348ccc DM |
99 | if (DECL_COMDAT (node->decl) |
100 | && !node->force_output | |
101 | && !symtab_used_from_object_file_p (node)) | |
c3c445e1 JH |
102 | return SYMBOL_DUPLICATE; |
103 | ||
104 | return SYMBOL_PARTITION; | |
105 | } | |
a66dc285 JH |
106 | |
107 | /* Create new partition with name NAME. */ | |
c3c445e1 | 108 | |
a66dc285 JH |
109 | static ltrans_partition |
110 | new_partition (const char *name) | |
111 | { | |
112 | ltrans_partition part = XCNEW (struct ltrans_partition_def); | |
e75f8f79 | 113 | part->encoder = lto_symtab_encoder_new (false); |
a66dc285 JH |
114 | part->name = name; |
115 | part->insns = 0; | |
9771b263 | 116 | ltrans_partitions.safe_push (part); |
a66dc285 JH |
117 | return part; |
118 | } | |
119 | ||
120 | /* Free memory used by ltrans datastructures. */ | |
c3c445e1 | 121 | |
a66dc285 JH |
122 | void |
123 | free_ltrans_partitions (void) | |
124 | { | |
125 | unsigned int idx; | |
126 | ltrans_partition part; | |
9771b263 | 127 | for (idx = 0; ltrans_partitions.iterate (idx, &part); idx++) |
a66dc285 | 128 | { |
c3c445e1 JH |
129 | if (part->initializers_visited) |
130 | pointer_set_destroy (part->initializers_visited); | |
7b99cca4 | 131 | /* Symtab encoder is freed after streaming. */ |
a66dc285 JH |
132 | free (part); |
133 | } | |
9771b263 | 134 | ltrans_partitions.release (); |
a66dc285 JH |
135 | } |
136 | ||
c3c445e1 JH |
137 | /* Return true if symbol is already in some partition. */ |
138 | ||
139 | static inline bool | |
5e20cdc9 | 140 | symbol_partitioned_p (symtab_node *node) |
a66dc285 | 141 | { |
67348ccc | 142 | return node->aux; |
1cdbb3f9 JH |
143 | } |
144 | ||
c3c445e1 | 145 | /* Add references into the partition. */ |
1cdbb3f9 | 146 | static void |
5e20cdc9 | 147 | add_references_to_partition (ltrans_partition part, symtab_node *node) |
1cdbb3f9 JH |
148 | { |
149 | int i; | |
150 | struct ipa_ref *ref; | |
151 | ||
c3c445e1 | 152 | /* Add all duplicated references to the partition. */ |
67348ccc | 153 | for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) |
c3c445e1 JH |
154 | if (get_symbol_class (ref->referred) == SYMBOL_DUPLICATE) |
155 | add_symbol_to_partition (part, ref->referred); | |
156 | /* References to a readonly variable may be constant foled into its value. | |
157 | Recursively look into the initializers of the constant variable and add | |
158 | references, too. */ | |
5d59b5e1 | 159 | else if (is_a <varpool_node> (ref->referred) |
67348ccc | 160 | && ctor_for_folding (ref->referred->decl) != error_mark_node |
c3c445e1 | 161 | && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred)) |
1cdbb3f9 | 162 | { |
c3c445e1 JH |
163 | if (!part->initializers_visited) |
164 | part->initializers_visited = pointer_set_create (); | |
165 | if (!pointer_set_insert (part->initializers_visited, ref->referred)) | |
166 | add_references_to_partition (part, ref->referred); | |
1cdbb3f9 | 167 | } |
a66dc285 JH |
168 | } |
169 | ||
c3c445e1 JH |
170 | /* Helper function for add_symbol_to_partition doing the actual dirty work |
171 | of adding NODE to PART. */ | |
a66dc285 JH |
172 | |
173 | static bool | |
5e20cdc9 | 174 | add_symbol_to_partition_1 (ltrans_partition part, symtab_node *node) |
a66dc285 | 175 | { |
c3c445e1 JH |
176 | enum symbol_class c = get_symbol_class (node); |
177 | int i; | |
178 | struct ipa_ref *ref; | |
5e20cdc9 | 179 | symtab_node *node1; |
a66dc285 | 180 | |
c3c445e1 | 181 | /* If NODE is already there, we have nothing to do. */ |
67348ccc | 182 | if (lto_symtab_encoder_in_partition_p (part->encoder, node)) |
c3c445e1 JH |
183 | return true; |
184 | ||
185 | /* non-duplicated aliases or tunks of a duplicated symbol needs to be output | |
186 | just once. | |
187 | ||
188 | Be lax about comdats; they may or may not be duplicated and we may | |
189 | end up in need to duplicate keyed comdat because it has unkeyed alias. */ | |
67348ccc | 190 | if (c == SYMBOL_PARTITION && !DECL_COMDAT (node->decl) |
c3c445e1 | 191 | && symbol_partitioned_p (node)) |
1cdbb3f9 JH |
192 | return false; |
193 | ||
c3c445e1 JH |
194 | /* Be sure that we never try to duplicate partitioned symbol |
195 | or add external symbol. */ | |
196 | gcc_assert (c != SYMBOL_EXTERNAL | |
197 | && (c == SYMBOL_DUPLICATE || !symbol_partitioned_p (node))); | |
198 | ||
67348ccc | 199 | lto_set_symtab_encoder_in_partition (part->encoder, node); |
a66dc285 | 200 | |
c3c445e1 | 201 | if (symbol_partitioned_p (node)) |
a66dc285 | 202 | { |
67348ccc | 203 | node->in_other_partition = 1; |
a66dc285 | 204 | if (cgraph_dump_file) |
c3c445e1 | 205 | fprintf (cgraph_dump_file, "Symbol node %s now used in multiple partitions\n", |
fec39fa6 | 206 | node->name ()); |
a66dc285 | 207 | } |
67348ccc | 208 | node->aux = (void *)((size_t)node->aux + 1); |
a66dc285 | 209 | |
5d59b5e1 | 210 | if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) |
c3c445e1 | 211 | { |
c3c445e1 JH |
212 | struct cgraph_edge *e; |
213 | part->insns += inline_summary (cnode)->self_size; | |
214 | ||
215 | /* Add all inline clones and callees that are duplicated. */ | |
216 | for (e = cnode->callees; e; e = e->next_callee) | |
217 | if (!e->inline_failed) | |
67348ccc DM |
218 | add_symbol_to_partition_1 (part, e->callee); |
219 | else if (get_symbol_class (e->callee) == SYMBOL_DUPLICATE) | |
220 | add_symbol_to_partition (part, e->callee); | |
c3c445e1 JH |
221 | |
222 | /* Add all thunks associated with the function. */ | |
223 | for (e = cnode->callers; e; e = e->next_caller) | |
224 | if (e->caller->thunk.thunk_p) | |
67348ccc | 225 | add_symbol_to_partition_1 (part, e->caller); |
c3c445e1 | 226 | } |
a66dc285 | 227 | |
c3c445e1 | 228 | add_references_to_partition (part, node); |
a66dc285 | 229 | |
c3c445e1 | 230 | /* Add all aliases associated with the symbol. */ |
67348ccc DM |
231 | for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) |
232 | if (ref->use == IPA_REF_ALIAS && !node->weakref) | |
c3c445e1 | 233 | add_symbol_to_partition_1 (part, ref->referring); |
a66dc285 | 234 | |
c3c445e1 | 235 | /* Ensure that SAME_COMDAT_GROUP lists all allways added in a group. */ |
67348ccc DM |
236 | if (node->same_comdat_group) |
237 | for (node1 = node->same_comdat_group; | |
238 | node1 != node; node1 = node1->same_comdat_group) | |
c3c445e1 JH |
239 | { |
240 | bool added = add_symbol_to_partition_1 (part, node1); | |
241 | gcc_assert (added); | |
242 | } | |
243 | return true; | |
a66dc285 JH |
244 | } |
245 | ||
c3c445e1 JH |
246 | /* If symbol NODE is really part of other symbol's definition (i.e. it is |
247 | internal label, thunk, alias or so), return the outer symbol. | |
248 | When add_symbol_to_partition_1 is called on the outer symbol it must | |
249 | eventually add NODE, too. */ | |
5e20cdc9 DM |
250 | static symtab_node * |
251 | contained_in_symbol (symtab_node *node) | |
c3c445e1 JH |
252 | { |
253 | /* Weakrefs are never contained in anything. */ | |
67348ccc | 254 | if (node->weakref) |
c3c445e1 | 255 | return node; |
5d59b5e1 | 256 | if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) |
c3c445e1 | 257 | { |
5d59b5e1 | 258 | cnode = cgraph_function_node (cnode, NULL); |
c3c445e1 JH |
259 | if (cnode->global.inlined_to) |
260 | cnode = cnode->global.inlined_to; | |
67348ccc | 261 | return cnode; |
c3c445e1 | 262 | } |
5d59b5e1 | 263 | else if (varpool_node *vnode = dyn_cast <varpool_node> (node)) |
67348ccc | 264 | return varpool_variable_node (vnode, NULL); |
c3c445e1 JH |
265 | return node; |
266 | } | |
267 | ||
268 | /* Add symbol NODE to partition. When definition of NODE is part | |
269 | of other symbol definition, add the other symbol, too. */ | |
a66dc285 JH |
270 | |
271 | static void | |
5e20cdc9 | 272 | add_symbol_to_partition (ltrans_partition part, symtab_node *node) |
a66dc285 | 273 | { |
5e20cdc9 | 274 | symtab_node *node1; |
a66dc285 | 275 | |
c3c445e1 JH |
276 | /* Verify that we do not try to duplicate something that can not be. */ |
277 | gcc_checking_assert (get_symbol_class (node) == SYMBOL_DUPLICATE | |
278 | || !symbol_partitioned_p (node)); | |
a66dc285 | 279 | |
c3c445e1 JH |
280 | while ((node1 = contained_in_symbol (node)) != node) |
281 | node = node1; | |
a66dc285 | 282 | |
c3c445e1 JH |
283 | /* If we have duplicated symbol contained in something we can not duplicate, |
284 | we are very badly screwed. The other way is possible, so we do not | |
285 | assert this in add_symbol_to_partition_1. | |
286 | ||
287 | Be lax about comdats; they may or may not be duplicated and we may | |
288 | end up in need to duplicate keyed comdat because it has unkeyed alias. */ | |
9cec31f4 | 289 | |
c3c445e1 | 290 | gcc_assert (get_symbol_class (node) == SYMBOL_DUPLICATE |
67348ccc | 291 | || DECL_COMDAT (node->decl) |
c3c445e1 | 292 | || !symbol_partitioned_p (node)); |
9cec31f4 | 293 | |
c3c445e1 | 294 | add_symbol_to_partition_1 (part, node); |
a66dc285 JH |
295 | } |
296 | ||
297 | /* Undo all additions until number of cgraph nodes in PARITION is N_CGRAPH_NODES | |
298 | and number of varpool nodes is N_VARPOOL_NODES. */ | |
299 | ||
300 | static void | |
7b99cca4 | 301 | undo_partition (ltrans_partition partition, unsigned int n_nodes) |
a66dc285 | 302 | { |
7b99cca4 | 303 | while (lto_symtab_encoder_size (partition->encoder) > (int)n_nodes) |
a66dc285 | 304 | { |
5e20cdc9 | 305 | symtab_node *node = lto_symtab_encoder_deref (partition->encoder, |
7b99cca4 | 306 | n_nodes); |
c3c445e1 JH |
307 | |
308 | /* After UNDO we no longer know what was visited. */ | |
309 | if (partition->initializers_visited) | |
310 | pointer_set_destroy (partition->initializers_visited); | |
311 | partition->initializers_visited = NULL; | |
312 | ||
5d59b5e1 LC |
313 | if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) |
314 | partition->insns -= inline_summary (cnode)->self_size; | |
7b99cca4 | 315 | lto_symtab_encoder_delete_node (partition->encoder, node); |
67348ccc | 316 | node->aux = (void *)((size_t)node->aux - 1); |
a66dc285 JH |
317 | } |
318 | } | |
319 | ||
a66dc285 JH |
320 | /* Group cgrah nodes by input files. This is used mainly for testing |
321 | right now. */ | |
322 | ||
323 | void | |
324 | lto_1_to_1_map (void) | |
325 | { | |
5e20cdc9 | 326 | symtab_node *node; |
a66dc285 JH |
327 | struct lto_file_decl_data *file_data; |
328 | struct pointer_map_t *pmap; | |
329 | ltrans_partition partition; | |
330 | void **slot; | |
331 | int npartitions = 0; | |
332 | ||
a66dc285 JH |
333 | pmap = pointer_map_create (); |
334 | ||
c3c445e1 | 335 | FOR_EACH_SYMBOL (node) |
a66dc285 | 336 | { |
c3c445e1 JH |
337 | if (get_symbol_class (node) != SYMBOL_PARTITION |
338 | || symbol_partitioned_p (node)) | |
a66dc285 JH |
339 | continue; |
340 | ||
67348ccc | 341 | file_data = node->lto_file_data; |
a66dc285 JH |
342 | |
343 | if (file_data) | |
344 | { | |
345 | slot = pointer_map_contains (pmap, file_data); | |
346 | if (slot) | |
347 | partition = (ltrans_partition) *slot; | |
348 | else | |
349 | { | |
350 | partition = new_partition (file_data->file_name); | |
351 | slot = pointer_map_insert (pmap, file_data); | |
352 | *slot = partition; | |
353 | npartitions++; | |
354 | } | |
355 | } | |
9771b263 DN |
356 | else if (!file_data && ltrans_partitions.length ()) |
357 | partition = ltrans_partitions[0]; | |
a66dc285 JH |
358 | else |
359 | { | |
360 | partition = new_partition (""); | |
361 | slot = pointer_map_insert (pmap, NULL); | |
362 | *slot = partition; | |
363 | npartitions++; | |
364 | } | |
365 | ||
67348ccc | 366 | add_symbol_to_partition (partition, node); |
a66dc285 | 367 | } |
a66dc285 JH |
368 | |
369 | /* If the cgraph is empty, create one cgraph node set so that there is still | |
370 | an output file for any variables that need to be exported in a DSO. */ | |
371 | if (!npartitions) | |
372 | new_partition ("empty"); | |
373 | ||
374 | pointer_map_destroy (pmap); | |
375 | ||
c3c445e1 JH |
376 | } |
377 | ||
378 | /* Maximal partitioning. Put every new symbol into new partition if possible. */ | |
a66dc285 | 379 | |
c3c445e1 JH |
380 | void |
381 | lto_max_map (void) | |
382 | { | |
5e20cdc9 | 383 | symtab_node *node; |
c3c445e1 JH |
384 | ltrans_partition partition; |
385 | int npartitions = 0; | |
386 | ||
387 | FOR_EACH_SYMBOL (node) | |
388 | { | |
389 | if (get_symbol_class (node) != SYMBOL_PARTITION | |
390 | || symbol_partitioned_p (node)) | |
391 | continue; | |
fec39fa6 | 392 | partition = new_partition (node->asm_name ()); |
67348ccc | 393 | add_symbol_to_partition (partition, node); |
c3c445e1 JH |
394 | npartitions++; |
395 | } | |
396 | if (!npartitions) | |
397 | new_partition ("empty"); | |
a66dc285 JH |
398 | } |
399 | ||
400 | /* Helper function for qsort; sort nodes by order. */ | |
401 | static int | |
402 | node_cmp (const void *pa, const void *pb) | |
403 | { | |
404 | const struct cgraph_node *a = *(const struct cgraph_node * const *) pa; | |
405 | const struct cgraph_node *b = *(const struct cgraph_node * const *) pb; | |
9cec31f4 ML |
406 | |
407 | /* Profile reorder flag enables function reordering based on first execution | |
408 | of a function. All functions with profile are placed in ascending | |
409 | order at the beginning. */ | |
410 | ||
411 | if (flag_profile_reorder_functions) | |
412 | { | |
413 | /* Functions with time profile are sorted in ascending order. */ | |
414 | if (a->tp_first_run && b->tp_first_run) | |
415 | return a->tp_first_run != b->tp_first_run | |
416 | ? a->tp_first_run - b->tp_first_run | |
417 | : a->order - b->order; | |
418 | ||
419 | /* Functions with time profile are sorted before the functions | |
420 | that do not have the profile. */ | |
421 | if (a->tp_first_run || b->tp_first_run) | |
422 | return b->tp_first_run - a->tp_first_run; | |
423 | } | |
424 | ||
67348ccc | 425 | return b->order - a->order; |
a66dc285 JH |
426 | } |
427 | ||
428 | /* Helper function for qsort; sort nodes by order. */ | |
429 | static int | |
430 | varpool_node_cmp (const void *pa, const void *pb) | |
431 | { | |
2c8326a5 OE |
432 | const varpool_node *a = *(const varpool_node * const *) pa; |
433 | const varpool_node *b = *(const varpool_node * const *) pb; | |
67348ccc | 434 | return b->order - a->order; |
a66dc285 JH |
435 | } |
436 | ||
437 | /* Group cgraph nodes into equally-sized partitions. | |
438 | ||
439 | The partitioning algorithm is simple: nodes are taken in predefined order. | |
440 | The order corresponds to the order we want functions to have in the final | |
441 | output. In the future this will be given by function reordering pass, but | |
442 | at the moment we use the topological order, which is a good approximation. | |
443 | ||
444 | The goal is to partition this linear order into intervals (partitions) so | |
445 | that all the partitions have approximately the same size and the number of | |
446 | callgraph or IPA reference edges crossing boundaries is minimal. | |
447 | ||
448 | This is a lot faster (O(n) in size of callgraph) than algorithms doing | |
449 | priority-based graph clustering that are generally O(n^2) and, since | |
450 | WHOPR is designed to make things go well across partitions, it leads | |
451 | to good results. | |
452 | ||
453 | We compute the expected size of a partition as: | |
454 | ||
455 | max (total_size / lto_partitions, min_partition_size) | |
456 | ||
457 | We use dynamic expected size of partition so small programs are partitioned | |
458 | into enough partitions to allow use of multiple CPUs, while large programs | |
459 | are not partitioned too much. Creating too many partitions significantly | |
460 | increases the streaming overhead. | |
461 | ||
462 | In the future, we would like to bound the maximal size of partitions so as | |
463 | to prevent the LTRANS stage from consuming too much memory. At the moment, | |
464 | however, the WPA stage is the most memory intensive for large benchmarks, | |
465 | since too many types and declarations are read into memory. | |
466 | ||
467 | The function implements a simple greedy algorithm. Nodes are being added | |
468 | to the current partition until after 3/4 of the expected partition size is | |
469 | reached. Past this threshold, we keep track of boundary size (number of | |
470 | edges going to other partitions) and continue adding functions until after | |
471 | the current partition has grown to twice the expected partition size. Then | |
472 | the process is undone to the point where the minimal ratio of boundary size | |
473 | and in-partition calls was reached. */ | |
474 | ||
475 | void | |
476 | lto_balanced_map (void) | |
477 | { | |
478 | int n_nodes = 0; | |
c525ba9a | 479 | int n_varpool_nodes = 0, varpool_pos = 0, best_varpool_pos = 0; |
a66dc285 | 480 | struct cgraph_node **order = XNEWVEC (struct cgraph_node *, cgraph_max_uid); |
2c8326a5 | 481 | varpool_node **varpool_order = NULL; |
6a49f3c9 | 482 | int i; |
a66dc285 JH |
483 | struct cgraph_node *node; |
484 | int total_size = 0, best_total_size = 0; | |
485 | int partition_size; | |
486 | ltrans_partition partition; | |
7b99cca4 | 487 | int last_visited_node = 0; |
2c8326a5 | 488 | varpool_node *vnode; |
a66dc285 | 489 | int cost = 0, internal = 0; |
7b99cca4 | 490 | int best_n_nodes = 0, best_i = 0, best_cost = |
a66dc285 JH |
491 | INT_MAX, best_internal = 0; |
492 | int npartitions; | |
493 | int current_order = -1; | |
494 | ||
65c70e6b | 495 | FOR_EACH_VARIABLE (vnode) |
67348ccc | 496 | gcc_assert (!vnode->aux); |
a66dc285 | 497 | |
6a49f3c9 | 498 | FOR_EACH_DEFINED_FUNCTION (node) |
67348ccc | 499 | if (get_symbol_class (node) == SYMBOL_PARTITION) |
6a49f3c9 JH |
500 | { |
501 | order[n_nodes++] = node; | |
502 | total_size += inline_summary (node)->size; | |
503 | } | |
a66dc285 | 504 | |
6a49f3c9 JH |
505 | /* Streaming works best when the source units do not cross partition |
506 | boundaries much. This is because importing function from a source | |
507 | unit tends to import a lot of global trees defined there. We should | |
508 | get better about minimizing the function bounday, but until that | |
509 | things works smoother if we order in source order. */ | |
510 | qsort (order, n_nodes, sizeof (struct cgraph_node *), node_cmp); | |
9cec31f4 ML |
511 | |
512 | if (cgraph_dump_file) | |
513 | for(i = 0; i < n_nodes; i++) | |
514 | fprintf (cgraph_dump_file, "Balanced map symbol order:%s:%u\n", order[i]->name (), order[i]->tp_first_run); | |
515 | ||
a66dc285 JH |
516 | if (!flag_toplevel_reorder) |
517 | { | |
65c70e6b | 518 | FOR_EACH_VARIABLE (vnode) |
67348ccc | 519 | if (get_symbol_class (vnode) == SYMBOL_PARTITION) |
a66dc285 | 520 | n_varpool_nodes++; |
2c8326a5 | 521 | varpool_order = XNEWVEC (varpool_node *, n_varpool_nodes); |
a66dc285 JH |
522 | |
523 | n_varpool_nodes = 0; | |
65c70e6b | 524 | FOR_EACH_VARIABLE (vnode) |
67348ccc | 525 | if (get_symbol_class (vnode) == SYMBOL_PARTITION) |
a66dc285 | 526 | varpool_order[n_varpool_nodes++] = vnode; |
2c8326a5 | 527 | qsort (varpool_order, n_varpool_nodes, sizeof (varpool_node *), |
a66dc285 JH |
528 | varpool_node_cmp); |
529 | } | |
530 | ||
531 | /* Compute partition size and create the first partition. */ | |
532 | partition_size = total_size / PARAM_VALUE (PARAM_LTO_PARTITIONS); | |
533 | if (partition_size < PARAM_VALUE (MIN_PARTITION_SIZE)) | |
534 | partition_size = PARAM_VALUE (MIN_PARTITION_SIZE); | |
535 | npartitions = 1; | |
536 | partition = new_partition (""); | |
537 | if (cgraph_dump_file) | |
538 | fprintf (cgraph_dump_file, "Total unit size: %i, partition size: %i\n", | |
539 | total_size, partition_size); | |
540 | ||
541 | for (i = 0; i < n_nodes; i++) | |
542 | { | |
67348ccc | 543 | if (symbol_partitioned_p (order[i])) |
a66dc285 JH |
544 | continue; |
545 | ||
67348ccc | 546 | current_order = order[i]->order; |
a66dc285 JH |
547 | |
548 | if (!flag_toplevel_reorder) | |
960bfb69 | 549 | while (varpool_pos < n_varpool_nodes |
67348ccc | 550 | && varpool_order[varpool_pos]->order < current_order) |
a66dc285 | 551 | { |
67348ccc DM |
552 | if (!symbol_partitioned_p (varpool_order[varpool_pos])) |
553 | add_symbol_to_partition (partition, varpool_order[varpool_pos]); | |
a66dc285 JH |
554 | varpool_pos++; |
555 | } | |
556 | ||
67348ccc | 557 | add_symbol_to_partition (partition, order[i]); |
a66dc285 JH |
558 | total_size -= inline_summary (order[i])->size; |
559 | ||
560 | ||
561 | /* Once we added a new node to the partition, we also want to add | |
562 | all referenced variables unless they was already added into some | |
563 | earlier partition. | |
c3c445e1 | 564 | add_symbol_to_partition adds possibly multiple nodes and |
a66dc285 JH |
565 | variables that are needed to satisfy needs of ORDER[i]. |
566 | We remember last visited cgraph and varpool node from last iteration | |
567 | of outer loop that allows us to process every new addition. | |
568 | ||
569 | At the same time we compute size of the boundary into COST. Every | |
570 | callgraph or IPA reference edge leaving the partition contributes into | |
571 | COST. Every edge inside partition was earlier computed as one leaving | |
572 | it and thus we need to subtract it from COST. */ | |
7b99cca4 | 573 | while (last_visited_node < lto_symtab_encoder_size (partition->encoder)) |
a66dc285 JH |
574 | { |
575 | struct ipa_ref_list *refs; | |
576 | int j; | |
577 | struct ipa_ref *ref; | |
5e20cdc9 | 578 | symtab_node *snode = lto_symtab_encoder_deref (partition->encoder, |
7b99cca4 | 579 | last_visited_node); |
a66dc285 | 580 | |
5d59b5e1 | 581 | if (cgraph_node *node = dyn_cast <cgraph_node> (snode)) |
a66dc285 JH |
582 | { |
583 | struct cgraph_edge *edge; | |
584 | ||
67348ccc | 585 | refs = &node->ref_list; |
a66dc285 | 586 | |
7b99cca4 | 587 | last_visited_node++; |
a66dc285 | 588 | |
67348ccc | 589 | gcc_assert (node->definition || node->weakref); |
a66dc285 JH |
590 | |
591 | /* Compute boundary cost of callgraph edges. */ | |
592 | for (edge = node->callees; edge; edge = edge->next_callee) | |
67348ccc | 593 | if (edge->callee->definition) |
a66dc285 JH |
594 | { |
595 | int edge_cost = edge->frequency; | |
7b99cca4 | 596 | int index; |
a66dc285 JH |
597 | |
598 | if (!edge_cost) | |
599 | edge_cost = 1; | |
600 | gcc_assert (edge_cost > 0); | |
7b99cca4 | 601 | index = lto_symtab_encoder_lookup (partition->encoder, |
67348ccc | 602 | edge->callee); |
7b99cca4 JH |
603 | if (index != LCC_NOT_FOUND |
604 | && index < last_visited_node - 1) | |
605 | cost -= edge_cost, internal += edge_cost; | |
a66dc285 JH |
606 | else |
607 | cost += edge_cost; | |
608 | } | |
609 | for (edge = node->callers; edge; edge = edge->next_caller) | |
610 | { | |
611 | int edge_cost = edge->frequency; | |
7b99cca4 | 612 | int index; |
a66dc285 | 613 | |
67348ccc | 614 | gcc_assert (edge->caller->definition); |
a66dc285 JH |
615 | if (!edge_cost) |
616 | edge_cost = 1; | |
617 | gcc_assert (edge_cost > 0); | |
7b99cca4 | 618 | index = lto_symtab_encoder_lookup (partition->encoder, |
67348ccc | 619 | edge->caller); |
7b99cca4 JH |
620 | if (index != LCC_NOT_FOUND |
621 | && index < last_visited_node - 1) | |
a66dc285 JH |
622 | cost -= edge_cost; |
623 | else | |
624 | cost += edge_cost; | |
625 | } | |
626 | } | |
627 | else | |
628 | { | |
67348ccc | 629 | refs = &snode->ref_list; |
7b99cca4 | 630 | last_visited_node++; |
a66dc285 JH |
631 | } |
632 | ||
633 | /* Compute boundary cost of IPA REF edges and at the same time look into | |
634 | variables referenced from current partition and try to add them. */ | |
635 | for (j = 0; ipa_ref_list_reference_iterate (refs, j, ref); j++) | |
5d59b5e1 | 636 | if (is_a <varpool_node> (ref->referred)) |
a66dc285 | 637 | { |
7b99cca4 | 638 | int index; |
a66dc285 JH |
639 | |
640 | vnode = ipa_ref_varpool_node (ref); | |
67348ccc | 641 | if (!vnode->definition) |
a66dc285 | 642 | continue; |
67348ccc DM |
643 | if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder |
644 | && get_symbol_class (vnode) == SYMBOL_PARTITION) | |
645 | add_symbol_to_partition (partition, vnode); | |
7b99cca4 | 646 | index = lto_symtab_encoder_lookup (partition->encoder, |
67348ccc | 647 | vnode); |
7b99cca4 JH |
648 | if (index != LCC_NOT_FOUND |
649 | && index < last_visited_node - 1) | |
a66dc285 JH |
650 | cost--, internal++; |
651 | else | |
652 | cost++; | |
653 | } | |
654 | else | |
655 | { | |
7b99cca4 | 656 | int index; |
a66dc285 JH |
657 | |
658 | node = ipa_ref_node (ref); | |
67348ccc | 659 | if (!node->definition) |
a66dc285 | 660 | continue; |
7b99cca4 | 661 | index = lto_symtab_encoder_lookup (partition->encoder, |
67348ccc | 662 | node); |
7b99cca4 JH |
663 | if (index != LCC_NOT_FOUND |
664 | && index < last_visited_node - 1) | |
a66dc285 JH |
665 | cost--, internal++; |
666 | else | |
667 | cost++; | |
668 | } | |
5932a4d4 | 669 | for (j = 0; ipa_ref_list_referring_iterate (refs, j, ref); j++) |
5d59b5e1 | 670 | if (is_a <varpool_node> (ref->referring)) |
a66dc285 | 671 | { |
7b99cca4 | 672 | int index; |
a66dc285 | 673 | |
5932a4d4 | 674 | vnode = ipa_ref_referring_varpool_node (ref); |
67348ccc DM |
675 | gcc_assert (vnode->definition); |
676 | if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder | |
677 | && get_symbol_class (vnode) == SYMBOL_PARTITION) | |
678 | add_symbol_to_partition (partition, vnode); | |
7b99cca4 | 679 | index = lto_symtab_encoder_lookup (partition->encoder, |
67348ccc | 680 | vnode); |
7b99cca4 JH |
681 | if (index != LCC_NOT_FOUND |
682 | && index < last_visited_node - 1) | |
a66dc285 JH |
683 | cost--; |
684 | else | |
685 | cost++; | |
686 | } | |
687 | else | |
688 | { | |
7b99cca4 | 689 | int index; |
a66dc285 | 690 | |
5932a4d4 | 691 | node = ipa_ref_referring_node (ref); |
67348ccc | 692 | gcc_assert (node->definition); |
7b99cca4 | 693 | index = lto_symtab_encoder_lookup (partition->encoder, |
67348ccc | 694 | node); |
7b99cca4 JH |
695 | if (index != LCC_NOT_FOUND |
696 | && index < last_visited_node - 1) | |
a66dc285 JH |
697 | cost--; |
698 | else | |
699 | cost++; | |
700 | } | |
701 | } | |
702 | ||
703 | /* If the partition is large enough, start looking for smallest boundary cost. */ | |
704 | if (partition->insns < partition_size * 3 / 4 | |
705 | || best_cost == INT_MAX | |
706 | || ((!cost | |
707 | || (best_internal * (HOST_WIDE_INT) cost | |
708 | > (internal * (HOST_WIDE_INT)best_cost))) | |
709 | && partition->insns < partition_size * 5 / 4)) | |
710 | { | |
711 | best_cost = cost; | |
712 | best_internal = internal; | |
713 | best_i = i; | |
7b99cca4 | 714 | best_n_nodes = lto_symtab_encoder_size (partition->encoder); |
a66dc285 | 715 | best_total_size = total_size; |
c525ba9a | 716 | best_varpool_pos = varpool_pos; |
a66dc285 JH |
717 | } |
718 | if (cgraph_dump_file) | |
9de04252 MJ |
719 | fprintf (cgraph_dump_file, "Step %i: added %s/%i, size %i, cost %i/%i " |
720 | "best %i/%i, step %i\n", i, | |
fec39fa6 | 721 | order[i]->name (), order[i]->order, |
9de04252 | 722 | partition->insns, cost, internal, |
a66dc285 JH |
723 | best_cost, best_internal, best_i); |
724 | /* Partition is too large, unwind into step when best cost was reached and | |
725 | start new partition. */ | |
726 | if (partition->insns > 2 * partition_size) | |
727 | { | |
728 | if (best_i != i) | |
729 | { | |
730 | if (cgraph_dump_file) | |
731 | fprintf (cgraph_dump_file, "Unwinding %i insertions to step %i\n", | |
732 | i - best_i, best_i); | |
7b99cca4 | 733 | undo_partition (partition, best_n_nodes); |
c525ba9a | 734 | varpool_pos = best_varpool_pos; |
a66dc285 JH |
735 | } |
736 | i = best_i; | |
737 | /* When we are finished, avoid creating empty partition. */ | |
67348ccc | 738 | while (i < n_nodes - 1 && symbol_partitioned_p (order[i + 1])) |
a66dc285 JH |
739 | i++; |
740 | if (i == n_nodes - 1) | |
741 | break; | |
742 | partition = new_partition (""); | |
7b99cca4 | 743 | last_visited_node = 0; |
a66dc285 JH |
744 | total_size = best_total_size; |
745 | cost = 0; | |
746 | ||
747 | if (cgraph_dump_file) | |
748 | fprintf (cgraph_dump_file, "New partition\n"); | |
749 | best_n_nodes = 0; | |
a66dc285 JH |
750 | best_cost = INT_MAX; |
751 | ||
752 | /* Since the size of partitions is just approximate, update the size after | |
753 | we finished current one. */ | |
754 | if (npartitions < PARAM_VALUE (PARAM_LTO_PARTITIONS)) | |
755 | partition_size = total_size | |
756 | / (PARAM_VALUE (PARAM_LTO_PARTITIONS) - npartitions); | |
757 | else | |
758 | partition_size = INT_MAX; | |
759 | ||
760 | if (partition_size < PARAM_VALUE (MIN_PARTITION_SIZE)) | |
761 | partition_size = PARAM_VALUE (MIN_PARTITION_SIZE); | |
762 | npartitions ++; | |
763 | } | |
764 | } | |
765 | ||
766 | /* Varables that are not reachable from the code go into last partition. */ | |
767 | if (flag_toplevel_reorder) | |
768 | { | |
65c70e6b | 769 | FOR_EACH_VARIABLE (vnode) |
67348ccc DM |
770 | if (get_symbol_class (vnode) == SYMBOL_PARTITION |
771 | && !symbol_partitioned_p (vnode)) | |
772 | add_symbol_to_partition (partition, vnode); | |
a66dc285 JH |
773 | } |
774 | else | |
775 | { | |
776 | while (varpool_pos < n_varpool_nodes) | |
777 | { | |
67348ccc DM |
778 | if (!symbol_partitioned_p (varpool_order[varpool_pos])) |
779 | add_symbol_to_partition (partition, varpool_order[varpool_pos]); | |
a66dc285 JH |
780 | varpool_pos++; |
781 | } | |
782 | free (varpool_order); | |
783 | } | |
784 | free (order); | |
785 | } | |
786 | ||
64cfa6c0 JH |
787 | /* Mangle NODE symbol name into a local name. |
788 | This is necessary to do | |
789 | 1) if two or more static vars of same assembler name | |
790 | are merged into single ltrans unit. | |
791 | 2) if prevoiusly static var was promoted hidden to avoid possible conflict | |
792 | with symbols defined out of the LTO world. | |
793 | */ | |
794 | ||
8ee05051 | 795 | static bool |
5e20cdc9 | 796 | privatize_symbol_name (symtab_node *node) |
64cfa6c0 | 797 | { |
67348ccc | 798 | tree decl = node->decl; |
64cfa6c0 | 799 | const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); |
64cfa6c0 JH |
800 | |
801 | /* Our renaming machinery do not handle more than one change of assembler name. | |
802 | We should not need more than one anyway. */ | |
67348ccc DM |
803 | if (node->lto_file_data |
804 | && lto_get_decl_name_mapping (node->lto_file_data, name) != name) | |
64cfa6c0 JH |
805 | { |
806 | if (cgraph_dump_file) | |
807 | fprintf (cgraph_dump_file, | |
808 | "Not privatizing symbol name: %s. It privatized already.\n", | |
809 | name); | |
8ee05051 | 810 | return false; |
64cfa6c0 JH |
811 | } |
812 | /* Avoid mangling of already mangled clones. | |
813 | ??? should have a flag whether a symbol has a 'private' name already, | |
814 | since we produce some symbols like that i.e. for global constructors | |
815 | that are not really clones. */ | |
67348ccc | 816 | if (node->unique_name) |
64cfa6c0 JH |
817 | { |
818 | if (cgraph_dump_file) | |
819 | fprintf (cgraph_dump_file, | |
820 | "Not privatizing symbol name: %s. Has unique name.\n", | |
821 | name); | |
8ee05051 | 822 | return false; |
64cfa6c0 | 823 | } |
64cfa6c0 | 824 | change_decl_assembler_name (decl, clone_function_name (decl, "lto_priv")); |
67348ccc DM |
825 | if (node->lto_file_data) |
826 | lto_record_renamed_decl (node->lto_file_data, name, | |
64cfa6c0 JH |
827 | IDENTIFIER_POINTER |
828 | (DECL_ASSEMBLER_NAME (decl))); | |
829 | if (cgraph_dump_file) | |
830 | fprintf (cgraph_dump_file, | |
831 | "Privatizing symbol name: %s -> %s\n", | |
832 | name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); | |
8ee05051 | 833 | return true; |
64cfa6c0 JH |
834 | } |
835 | ||
a66dc285 JH |
836 | /* Promote variable VNODE to be static. */ |
837 | ||
b4661bfe | 838 | static void |
5e20cdc9 | 839 | promote_symbol (symtab_node *node) |
a66dc285 | 840 | { |
b4661bfe | 841 | /* We already promoted ... */ |
67348ccc DM |
842 | if (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN |
843 | && DECL_VISIBILITY_SPECIFIED (node->decl) | |
844 | && TREE_PUBLIC (node->decl)) | |
b4661bfe | 845 | return; |
a66dc285 | 846 | |
67348ccc DM |
847 | gcc_checking_assert (!TREE_PUBLIC (node->decl) |
848 | && !DECL_EXTERNAL (node->decl)); | |
64cfa6c0 JH |
849 | /* Be sure that newly public symbol does not conflict with anything already |
850 | defined by the non-LTO part. */ | |
851 | privatize_symbol_name (node); | |
67348ccc DM |
852 | TREE_PUBLIC (node->decl) = 1; |
853 | DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN; | |
854 | DECL_VISIBILITY_SPECIFIED (node->decl) = true; | |
a66dc285 JH |
855 | if (cgraph_dump_file) |
856 | fprintf (cgraph_dump_file, | |
fec39fa6 | 857 | "Promoting as hidden: %s\n", node->name ()); |
a66dc285 JH |
858 | } |
859 | ||
64cfa6c0 JH |
860 | /* Return true if NODE needs named section even if it won't land in the partition |
861 | symbol table. | |
862 | FIXME: we should really not use named sections for inline clones and master clones. */ | |
863 | ||
864 | static bool | |
5e20cdc9 | 865 | may_need_named_section_p (lto_symtab_encoder_t encoder, symtab_node *node) |
64cfa6c0 JH |
866 | { |
867 | struct cgraph_node *cnode = dyn_cast <cgraph_node> (node); | |
868 | if (!cnode) | |
869 | return false; | |
870 | if (symtab_real_symbol_p (node)) | |
871 | return false; | |
64cfa6c0 JH |
872 | return (!encoder |
873 | || (lto_symtab_encoder_lookup (encoder, node) != LCC_NOT_FOUND | |
874 | && lto_symtab_encoder_encode_body_p (encoder, | |
875 | cnode))); | |
876 | } | |
877 | ||
878 | /* If NODE represents a static variable. See if there are other variables | |
879 | of the same name in partition ENCODER (or in whole compilation unit if | |
880 | ENCODER is NULL) and if so, mangle the statics. Always mangle all | |
881 | conflicting statics, so we reduce changes of silently miscompiling | |
9cec31f4 | 882 | asm statements referring to them by symbol name. */ |
64cfa6c0 JH |
883 | |
884 | static void | |
5e20cdc9 | 885 | rename_statics (lto_symtab_encoder_t encoder, symtab_node *node) |
64cfa6c0 | 886 | { |
67348ccc | 887 | tree decl = node->decl; |
5e20cdc9 | 888 | symtab_node *s; |
64cfa6c0 JH |
889 | tree name = DECL_ASSEMBLER_NAME (decl); |
890 | ||
891 | /* See if this is static symbol. */ | |
67348ccc | 892 | if ((node->externally_visible |
64cfa6c0 JH |
893 | /* FIXME: externally_visible is somewhat illogically not set for |
894 | external symbols (i.e. those not defined). Remove this test | |
895 | once this is fixed. */ | |
67348ccc | 896 | || DECL_EXTERNAL (node->decl) |
64cfa6c0 | 897 | || !symtab_real_symbol_p (node)) |
08346abd | 898 | && !may_need_named_section_p (encoder, node)) |
64cfa6c0 JH |
899 | return; |
900 | ||
901 | /* Now walk symbols sharing the same name and see if there are any conflicts. | |
902 | (all types of symbols counts here, since we can not have static of the | |
903 | same name as external or public symbol.) */ | |
904 | for (s = symtab_node_for_asm (name); | |
67348ccc | 905 | s; s = s->next_sharing_asm_name) |
64cfa6c0 | 906 | if ((symtab_real_symbol_p (s) || may_need_named_section_p (encoder, s)) |
67348ccc | 907 | && s->decl != node->decl |
64cfa6c0 JH |
908 | && (!encoder |
909 | || lto_symtab_encoder_lookup (encoder, s) != LCC_NOT_FOUND)) | |
910 | break; | |
911 | ||
912 | /* OK, no confict, so we have nothing to do. */ | |
913 | if (!s) | |
914 | return; | |
915 | ||
916 | if (cgraph_dump_file) | |
917 | fprintf (cgraph_dump_file, | |
fec39fa6 | 918 | "Renaming statics with asm name: %s\n", node->name ()); |
64cfa6c0 JH |
919 | |
920 | /* Assign every symbol in the set that shares the same ASM name an unique | |
921 | mangled name. */ | |
922 | for (s = symtab_node_for_asm (name); s;) | |
67348ccc | 923 | if (!s->externally_visible |
64cfa6c0 | 924 | && ((symtab_real_symbol_p (s) |
67348ccc DM |
925 | && !DECL_EXTERNAL (node->decl) |
926 | && !TREE_PUBLIC (node->decl)) | |
64cfa6c0 JH |
927 | || may_need_named_section_p (encoder, s)) |
928 | && (!encoder | |
929 | || lto_symtab_encoder_lookup (encoder, s) != LCC_NOT_FOUND)) | |
930 | { | |
8ee05051 | 931 | if (privatize_symbol_name (s)) |
1aa95df7 | 932 | /* Re-start from beginning since we do not know how many symbols changed a name. */ |
8ee05051 | 933 | s = symtab_node_for_asm (name); |
67348ccc | 934 | else s = s->next_sharing_asm_name; |
64cfa6c0 | 935 | } |
67348ccc | 936 | else s = s->next_sharing_asm_name; |
64cfa6c0 | 937 | } |
b4661bfe | 938 | |
a66dc285 JH |
939 | /* Find out all static decls that need to be promoted to global because |
940 | of cross file sharing. This function must be run in the WPA mode after | |
941 | all inlinees are added. */ | |
942 | ||
943 | void | |
944 | lto_promote_cross_file_statics (void) | |
945 | { | |
a66dc285 | 946 | unsigned i, n_sets; |
a66dc285 JH |
947 | |
948 | gcc_assert (flag_wpa); | |
949 | ||
b4661bfe | 950 | /* First compute boundaries. */ |
9771b263 | 951 | n_sets = ltrans_partitions.length (); |
a66dc285 JH |
952 | for (i = 0; i < n_sets; i++) |
953 | { | |
954 | ltrans_partition part | |
9771b263 | 955 | = ltrans_partitions[i]; |
b4661bfe JH |
956 | part->encoder = compute_ltrans_boundary (part->encoder); |
957 | } | |
a66dc285 | 958 | |
b4661bfe JH |
959 | /* Look at boundaries and promote symbols as needed. */ |
960 | for (i = 0; i < n_sets; i++) | |
961 | { | |
962 | lto_symtab_encoder_iterator lsei; | |
64cfa6c0 | 963 | lto_symtab_encoder_t encoder = ltrans_partitions[i]->encoder; |
a66dc285 | 964 | |
b4661bfe JH |
965 | for (lsei = lsei_start (encoder); !lsei_end_p (lsei); |
966 | lsei_next (&lsei)) | |
967 | { | |
5e20cdc9 | 968 | symtab_node *node = lsei_node (lsei); |
b4661bfe | 969 | |
64cfa6c0 JH |
970 | /* If symbol is static, rename it if its assembler name clash with |
971 | anything else in this unit. */ | |
972 | rename_statics (encoder, node); | |
973 | ||
b4661bfe | 974 | /* No need to promote if symbol already is externally visible ... */ |
67348ccc | 975 | if (node->externally_visible |
b4661bfe JH |
976 | /* ... or if it is part of current partition ... */ |
977 | || lto_symtab_encoder_in_partition_p (encoder, node) | |
978 | /* ... or if we do not partition it. This mean that it will | |
979 | appear in every partition refernecing it. */ | |
67348ccc | 980 | || get_symbol_class (node) != SYMBOL_PARTITION) |
b4661bfe | 981 | continue; |
a66dc285 | 982 | |
b4661bfe JH |
983 | promote_symbol (node); |
984 | } | |
a66dc285 | 985 | } |
a66dc285 | 986 | } |
64cfa6c0 JH |
987 | |
988 | /* Rename statics in the whole unit in the case that | |
989 | we do -flto-partition=none. */ | |
990 | ||
991 | void | |
992 | lto_promote_statics_nonwpa (void) | |
993 | { | |
5e20cdc9 | 994 | symtab_node *node; |
64cfa6c0 JH |
995 | FOR_EACH_SYMBOL (node) |
996 | rename_statics (NULL, node); | |
997 | } |