]>
Commit | Line | Data |
---|---|---|
7bfefa9d | 1 | /* Top-level LTO routines. |
b630a10e | 2 | Copyright 2009, 2010, 2011 Free Software Foundation, Inc. |
7bfefa9d | 3 | Contributed by CodeSourcery, Inc. |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it under | |
8 | the terms of the GNU General Public License as published by the Free | |
9 | Software Foundation; either version 3, or (at your option) any later | |
10 | version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GCC; see the file COPYING3. If not see | |
19 | <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | #include "config.h" | |
22 | #include "system.h" | |
23 | #include "coretypes.h" | |
24 | #include "opts.h" | |
25 | #include "toplev.h" | |
26 | #include "tree.h" | |
d534cab0 | 27 | #include "tree-flow.h" |
852f689e | 28 | #include "diagnostic-core.h" |
7bfefa9d | 29 | #include "tm.h" |
7bfefa9d | 30 | #include "cgraph.h" |
31 | #include "ggc.h" | |
32 | #include "tree-ssa-operands.h" | |
33 | #include "tree-pass.h" | |
34 | #include "langhooks.h" | |
35 | #include "vec.h" | |
36 | #include "bitmap.h" | |
37 | #include "pointer-set.h" | |
38 | #include "ipa-prop.h" | |
39 | #include "common.h" | |
3c9e9cba | 40 | #include "debug.h" |
7bfefa9d | 41 | #include "timevar.h" |
42 | #include "gimple.h" | |
43 | #include "lto.h" | |
44 | #include "lto-tree.h" | |
45 | #include "lto-streamer.h" | |
2541503d | 46 | #include "tree-streamer.h" |
f18bad33 | 47 | #include "splay-tree.h" |
48e3ea52 | 48 | #include "params.h" |
c7b2cc59 | 49 | #include "ipa-inline.h" |
7771d558 | 50 | #include "ipa-utils.h" |
7bfefa9d | 51 | |
3c9e9cba | 52 | static GTY(()) tree first_personality_decl; |
53 | ||
654ca0f7 | 54 | /* Returns a hash code for P. */ |
55 | ||
56 | static hashval_t | |
57 | hash_name (const void *p) | |
58 | { | |
59 | const struct lto_section_slot *ds = (const struct lto_section_slot *) p; | |
60 | return (hashval_t) htab_hash_string (ds->name); | |
61 | } | |
62 | ||
63 | ||
64 | /* Returns nonzero if P1 and P2 are equal. */ | |
65 | ||
66 | static int | |
67 | eq_name (const void *p1, const void *p2) | |
68 | { | |
69 | const struct lto_section_slot *s1 = | |
70 | (const struct lto_section_slot *) p1; | |
71 | const struct lto_section_slot *s2 = | |
72 | (const struct lto_section_slot *) p2; | |
73 | ||
74 | return strcmp (s1->name, s2->name) == 0; | |
75 | } | |
76 | ||
77 | /* Free lto_section_slot */ | |
78 | ||
79 | static void | |
80 | free_with_string (void *arg) | |
81 | { | |
82 | struct lto_section_slot *s = (struct lto_section_slot *)arg; | |
83 | ||
84 | free (CONST_CAST (char *, s->name)); | |
85 | free (arg); | |
86 | } | |
87 | ||
88 | /* Create section hash table */ | |
89 | ||
90 | htab_t | |
91 | lto_obj_create_section_hash_table (void) | |
92 | { | |
93 | return htab_create (37, hash_name, eq_name, free_with_string); | |
94 | } | |
3c9e9cba | 95 | |
7bfefa9d | 96 | /* Read the constructors and inits. */ |
97 | ||
98 | static void | |
99 | lto_materialize_constructors_and_inits (struct lto_file_decl_data * file_data) | |
100 | { | |
101 | size_t len; | |
102 | const char *data = lto_get_section_data (file_data, | |
103 | LTO_section_static_initializer, | |
104 | NULL, &len); | |
105 | lto_input_constructors_and_inits (file_data, data); | |
106 | lto_free_section_data (file_data, LTO_section_static_initializer, NULL, | |
107 | data, len); | |
108 | } | |
109 | ||
97b862d3 | 110 | /* Return true when NODE has a clone that is analyzed (i.e. we need |
111 | to load its body even if the node itself is not needed). */ | |
112 | ||
113 | static bool | |
114 | has_analyzed_clone_p (struct cgraph_node *node) | |
115 | { | |
116 | struct cgraph_node *orig = node; | |
117 | node = node->clones; | |
118 | if (node) | |
119 | while (node != orig) | |
120 | { | |
121 | if (node->analyzed) | |
122 | return true; | |
123 | if (node->clones) | |
124 | node = node->clones; | |
125 | else if (node->next_sibling_clone) | |
126 | node = node->next_sibling_clone; | |
127 | else | |
128 | { | |
129 | while (node != orig && !node->next_sibling_clone) | |
130 | node = node->clone_of; | |
131 | if (node != orig) | |
132 | node = node->next_sibling_clone; | |
133 | } | |
134 | } | |
135 | return false; | |
136 | } | |
137 | ||
3c9e9cba | 138 | /* Read the function body for the function associated with NODE. */ |
7bfefa9d | 139 | |
140 | static void | |
141 | lto_materialize_function (struct cgraph_node *node) | |
142 | { | |
143 | tree decl; | |
144 | struct lto_file_decl_data *file_data; | |
145 | const char *data, *name; | |
146 | size_t len; | |
7bfefa9d | 147 | |
7bfefa9d | 148 | decl = node->decl; |
97b862d3 | 149 | /* Read in functions with body (analyzed nodes) |
150 | and also functions that are needed to produce virtual clones. */ | |
91bf9d9a | 151 | if (cgraph_function_with_gimple_body_p (node) || has_analyzed_clone_p (node)) |
7bfefa9d | 152 | { |
91bf9d9a | 153 | /* Clones and thunks don't need to be read. */ |
97b862d3 | 154 | if (node->clone_of) |
155 | return; | |
7bfefa9d | 156 | |
157 | /* Load the function body only if not operating in WPA mode. In | |
158 | WPA mode, the body of the function is not needed. */ | |
159 | if (!flag_wpa) | |
160 | { | |
5cd33168 | 161 | file_data = node->local.lto_file_data; |
162 | name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); | |
163 | ||
164 | /* We may have renamed the declaration, e.g., a static function. */ | |
165 | name = lto_get_decl_name_mapping (file_data, name); | |
166 | ||
167 | data = lto_get_section_data (file_data, LTO_section_function_body, | |
168 | name, &len); | |
169 | if (!data) | |
170 | fatal_error ("%s: section %s is missing", | |
171 | file_data->file_name, | |
172 | name); | |
173 | ||
174 | gcc_assert (DECL_STRUCT_FUNCTION (decl) == NULL); | |
175 | ||
3c9e9cba | 176 | allocate_struct_function (decl, false); |
177 | announce_function (decl); | |
7bfefa9d | 178 | lto_input_function_body (file_data, decl, data); |
3c9e9cba | 179 | if (DECL_FUNCTION_PERSONALITY (decl) && !first_personality_decl) |
180 | first_personality_decl = DECL_FUNCTION_PERSONALITY (decl); | |
7bfefa9d | 181 | lto_stats.num_function_bodies++; |
5cd33168 | 182 | lto_free_section_data (file_data, LTO_section_function_body, name, |
183 | data, len); | |
184 | ggc_collect (); | |
7bfefa9d | 185 | } |
7bfefa9d | 186 | } |
7bfefa9d | 187 | |
188 | /* Let the middle end know about the function. */ | |
189 | rest_of_decl_compilation (decl, 1, 0); | |
7bfefa9d | 190 | } |
191 | ||
192 | ||
851d9296 | 193 | /* Decode the content of memory pointed to by DATA in the in decl |
194 | state object STATE. DATA_IN points to a data_in structure for | |
195 | decoding. Return the address after the decoded object in the | |
196 | input. */ | |
7bfefa9d | 197 | |
198 | static const uint32_t * | |
199 | lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data, | |
200 | struct lto_in_decl_state *state) | |
201 | { | |
202 | uint32_t ix; | |
203 | tree decl; | |
204 | uint32_t i, j; | |
205 | ||
206 | ix = *data++; | |
7f385784 | 207 | decl = streamer_tree_cache_get (data_in->reader_cache, ix); |
7bfefa9d | 208 | if (TREE_CODE (decl) != FUNCTION_DECL) |
209 | { | |
210 | gcc_assert (decl == void_type_node); | |
211 | decl = NULL_TREE; | |
212 | } | |
213 | state->fn_decl = decl; | |
214 | ||
215 | for (i = 0; i < LTO_N_DECL_STREAMS; i++) | |
216 | { | |
217 | uint32_t size = *data++; | |
ba72912a | 218 | tree *decls = ggc_alloc_vec_tree (size); |
7bfefa9d | 219 | |
220 | for (j = 0; j < size; j++) | |
7f385784 | 221 | decls[j] = streamer_tree_cache_get (data_in->reader_cache, data[j]); |
d534cab0 | 222 | |
223 | state->streams[i].size = size; | |
224 | state->streams[i].trees = decls; | |
225 | data += size; | |
226 | } | |
227 | ||
228 | return data; | |
229 | } | |
230 | ||
231 | /* A hashtable of trees that potentially refer to variables or functions | |
232 | that must be replaced with their prevailing variant. */ | |
233 | static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node))) htab_t | |
234 | tree_with_vars; | |
235 | ||
236 | /* Remember that T is a tree that (potentially) refers to a variable | |
237 | or function decl that may be replaced with its prevailing variant. */ | |
238 | static void | |
239 | remember_with_vars (tree t) | |
240 | { | |
241 | *(tree *) htab_find_slot (tree_with_vars, t, INSERT) = t; | |
242 | } | |
243 | ||
244 | #define LTO_FIXUP_TREE(tt) \ | |
245 | do \ | |
246 | { \ | |
247 | if (tt) \ | |
248 | { \ | |
249 | if (TYPE_P (tt)) \ | |
250 | (tt) = gimple_register_type (tt); \ | |
251 | if (VAR_OR_FUNCTION_DECL_P (tt) && TREE_PUBLIC (tt)) \ | |
252 | remember_with_vars (t); \ | |
253 | } \ | |
254 | } while (0) | |
255 | ||
256 | static void lto_fixup_types (tree); | |
257 | ||
1e184c62 | 258 | /* Fix up fields of a tree_typed T. */ |
d534cab0 | 259 | |
260 | static void | |
1e184c62 | 261 | lto_ft_typed (tree t) |
d534cab0 | 262 | { |
d534cab0 | 263 | LTO_FIXUP_TREE (TREE_TYPE (t)); |
1e184c62 | 264 | } |
265 | ||
266 | /* Fix up fields of a tree_common T. */ | |
d534cab0 | 267 | |
1e184c62 | 268 | static void |
269 | lto_ft_common (tree t) | |
270 | { | |
271 | lto_ft_typed (t); | |
d534cab0 | 272 | LTO_FIXUP_TREE (TREE_CHAIN (t)); |
273 | } | |
274 | ||
275 | /* Fix up fields of a decl_minimal T. */ | |
276 | ||
277 | static void | |
278 | lto_ft_decl_minimal (tree t) | |
279 | { | |
280 | lto_ft_common (t); | |
281 | LTO_FIXUP_TREE (DECL_NAME (t)); | |
282 | LTO_FIXUP_TREE (DECL_CONTEXT (t)); | |
283 | } | |
284 | ||
285 | /* Fix up fields of a decl_common T. */ | |
286 | ||
287 | static void | |
288 | lto_ft_decl_common (tree t) | |
289 | { | |
290 | lto_ft_decl_minimal (t); | |
291 | LTO_FIXUP_TREE (DECL_SIZE (t)); | |
292 | LTO_FIXUP_TREE (DECL_SIZE_UNIT (t)); | |
293 | LTO_FIXUP_TREE (DECL_INITIAL (t)); | |
294 | LTO_FIXUP_TREE (DECL_ATTRIBUTES (t)); | |
295 | LTO_FIXUP_TREE (DECL_ABSTRACT_ORIGIN (t)); | |
296 | } | |
297 | ||
298 | /* Fix up fields of a decl_with_vis T. */ | |
299 | ||
300 | static void | |
301 | lto_ft_decl_with_vis (tree t) | |
302 | { | |
303 | lto_ft_decl_common (t); | |
304 | ||
305 | /* Accessor macro has side-effects, use field-name here. */ | |
306 | LTO_FIXUP_TREE (t->decl_with_vis.assembler_name); | |
307 | LTO_FIXUP_TREE (DECL_SECTION_NAME (t)); | |
308 | } | |
309 | ||
310 | /* Fix up fields of a decl_non_common T. */ | |
311 | ||
312 | static void | |
313 | lto_ft_decl_non_common (tree t) | |
314 | { | |
315 | lto_ft_decl_with_vis (t); | |
316 | LTO_FIXUP_TREE (DECL_ARGUMENT_FLD (t)); | |
317 | LTO_FIXUP_TREE (DECL_RESULT_FLD (t)); | |
318 | LTO_FIXUP_TREE (DECL_VINDEX (t)); | |
319 | } | |
320 | ||
321 | /* Fix up fields of a decl_non_common T. */ | |
322 | ||
323 | static void | |
324 | lto_ft_function (tree t) | |
325 | { | |
326 | lto_ft_decl_non_common (t); | |
327 | LTO_FIXUP_TREE (DECL_FUNCTION_PERSONALITY (t)); | |
328 | } | |
329 | ||
330 | /* Fix up fields of a field_decl T. */ | |
331 | ||
332 | static void | |
333 | lto_ft_field_decl (tree t) | |
334 | { | |
335 | lto_ft_decl_common (t); | |
336 | LTO_FIXUP_TREE (DECL_FIELD_OFFSET (t)); | |
337 | LTO_FIXUP_TREE (DECL_BIT_FIELD_TYPE (t)); | |
338 | LTO_FIXUP_TREE (DECL_QUALIFIER (t)); | |
339 | LTO_FIXUP_TREE (DECL_FIELD_BIT_OFFSET (t)); | |
340 | LTO_FIXUP_TREE (DECL_FCONTEXT (t)); | |
341 | } | |
342 | ||
343 | /* Fix up fields of a type T. */ | |
344 | ||
345 | static void | |
346 | lto_ft_type (tree t) | |
347 | { | |
d534cab0 | 348 | lto_ft_common (t); |
349 | LTO_FIXUP_TREE (TYPE_CACHED_VALUES (t)); | |
350 | LTO_FIXUP_TREE (TYPE_SIZE (t)); | |
351 | LTO_FIXUP_TREE (TYPE_SIZE_UNIT (t)); | |
352 | LTO_FIXUP_TREE (TYPE_ATTRIBUTES (t)); | |
353 | LTO_FIXUP_TREE (TYPE_NAME (t)); | |
354 | ||
355 | /* Accessors are for derived node types only. */ | |
356 | if (!POINTER_TYPE_P (t)) | |
8f2eb9e1 | 357 | LTO_FIXUP_TREE (TYPE_MINVAL (t)); |
358 | LTO_FIXUP_TREE (TYPE_MAXVAL (t)); | |
d534cab0 | 359 | |
360 | /* Accessor is for derived node types only. */ | |
8f2eb9e1 | 361 | LTO_FIXUP_TREE (t->type_non_common.binfo); |
d534cab0 | 362 | |
363 | LTO_FIXUP_TREE (TYPE_CONTEXT (t)); | |
d534cab0 | 364 | } |
365 | ||
366 | /* Fix up fields of a BINFO T. */ | |
367 | ||
368 | static void | |
369 | lto_ft_binfo (tree t) | |
370 | { | |
371 | unsigned HOST_WIDE_INT i, n; | |
372 | tree base, saved_base; | |
373 | ||
374 | lto_ft_common (t); | |
375 | LTO_FIXUP_TREE (BINFO_VTABLE (t)); | |
376 | LTO_FIXUP_TREE (BINFO_OFFSET (t)); | |
377 | LTO_FIXUP_TREE (BINFO_VIRTUALS (t)); | |
378 | LTO_FIXUP_TREE (BINFO_VPTR_FIELD (t)); | |
379 | n = VEC_length (tree, BINFO_BASE_ACCESSES (t)); | |
380 | for (i = 0; i < n; i++) | |
381 | { | |
382 | saved_base = base = BINFO_BASE_ACCESS (t, i); | |
383 | LTO_FIXUP_TREE (base); | |
384 | if (base != saved_base) | |
385 | VEC_replace (tree, BINFO_BASE_ACCESSES (t), i, base); | |
386 | } | |
387 | LTO_FIXUP_TREE (BINFO_INHERITANCE_CHAIN (t)); | |
388 | LTO_FIXUP_TREE (BINFO_SUBVTT_INDEX (t)); | |
389 | LTO_FIXUP_TREE (BINFO_VPTR_INDEX (t)); | |
390 | n = BINFO_N_BASE_BINFOS (t); | |
391 | for (i = 0; i < n; i++) | |
392 | { | |
393 | saved_base = base = BINFO_BASE_BINFO (t, i); | |
394 | LTO_FIXUP_TREE (base); | |
395 | if (base != saved_base) | |
396 | VEC_replace (tree, BINFO_BASE_BINFOS (t), i, base); | |
397 | } | |
398 | } | |
399 | ||
400 | /* Fix up fields of a CONSTRUCTOR T. */ | |
401 | ||
402 | static void | |
403 | lto_ft_constructor (tree t) | |
404 | { | |
405 | unsigned HOST_WIDE_INT idx; | |
406 | constructor_elt *ce; | |
407 | ||
1e184c62 | 408 | lto_ft_typed (t); |
d534cab0 | 409 | |
410 | for (idx = 0; | |
411 | VEC_iterate(constructor_elt, CONSTRUCTOR_ELTS (t), idx, ce); | |
412 | idx++) | |
413 | { | |
414 | LTO_FIXUP_TREE (ce->index); | |
415 | LTO_FIXUP_TREE (ce->value); | |
416 | } | |
417 | } | |
418 | ||
419 | /* Fix up fields of an expression tree T. */ | |
420 | ||
421 | static void | |
422 | lto_ft_expr (tree t) | |
423 | { | |
424 | int i; | |
1e184c62 | 425 | lto_ft_typed (t); |
d534cab0 | 426 | for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i) |
427 | LTO_FIXUP_TREE (TREE_OPERAND (t, i)); | |
428 | } | |
429 | ||
430 | /* Given a tree T fixup fields of T by replacing types with their merged | |
431 | variant and other entities by an equal entity from an earlier compilation | |
432 | unit, or an entity being canonical in a different way. This includes | |
433 | for instance integer or string constants. */ | |
434 | ||
435 | static void | |
436 | lto_fixup_types (tree t) | |
437 | { | |
438 | switch (TREE_CODE (t)) | |
439 | { | |
440 | case IDENTIFIER_NODE: | |
441 | break; | |
442 | ||
443 | case TREE_LIST: | |
444 | LTO_FIXUP_TREE (TREE_VALUE (t)); | |
445 | LTO_FIXUP_TREE (TREE_PURPOSE (t)); | |
446 | LTO_FIXUP_TREE (TREE_CHAIN (t)); | |
447 | break; | |
448 | ||
449 | case FIELD_DECL: | |
450 | lto_ft_field_decl (t); | |
451 | break; | |
452 | ||
453 | case LABEL_DECL: | |
454 | case CONST_DECL: | |
455 | case PARM_DECL: | |
456 | case RESULT_DECL: | |
457 | case IMPORTED_DECL: | |
458 | lto_ft_decl_common (t); | |
459 | break; | |
460 | ||
461 | case VAR_DECL: | |
462 | lto_ft_decl_with_vis (t); | |
463 | break; | |
464 | ||
465 | case TYPE_DECL: | |
466 | lto_ft_decl_non_common (t); | |
467 | break; | |
468 | ||
469 | case FUNCTION_DECL: | |
470 | lto_ft_function (t); | |
471 | break; | |
472 | ||
473 | case TREE_BINFO: | |
474 | lto_ft_binfo (t); | |
475 | break; | |
476 | ||
477 | case PLACEHOLDER_EXPR: | |
478 | lto_ft_common (t); | |
479 | break; | |
480 | ||
481 | case BLOCK: | |
482 | case TRANSLATION_UNIT_DECL: | |
483 | case OPTIMIZATION_NODE: | |
484 | case TARGET_OPTION_NODE: | |
485 | break; | |
486 | ||
487 | default: | |
488 | if (TYPE_P (t)) | |
489 | lto_ft_type (t); | |
490 | else if (TREE_CODE (t) == CONSTRUCTOR) | |
491 | lto_ft_constructor (t); | |
492 | else if (CONSTANT_CLASS_P (t)) | |
493 | LTO_FIXUP_TREE (TREE_TYPE (t)); | |
494 | else if (EXPR_P (t)) | |
495 | { | |
496 | lto_ft_expr (t); | |
497 | } | |
498 | else | |
499 | { | |
500 | remember_with_vars (t); | |
501 | } | |
502 | } | |
503 | } | |
504 | ||
f05c9dfb | 505 | |
506 | /* Return the resolution for the decl with index INDEX from DATA_IN. */ | |
507 | ||
508 | static enum ld_plugin_symbol_resolution | |
509 | get_resolution (struct data_in *data_in, unsigned index) | |
510 | { | |
511 | if (data_in->globals_resolution) | |
512 | { | |
513 | ld_plugin_symbol_resolution_t ret; | |
514 | /* We can have references to not emitted functions in | |
515 | DECL_FUNCTION_PERSONALITY at least. So we can and have | |
516 | to indeed return LDPR_UNKNOWN in some cases. */ | |
517 | if (VEC_length (ld_plugin_symbol_resolution_t, | |
518 | data_in->globals_resolution) <= index) | |
519 | return LDPR_UNKNOWN; | |
520 | ret = VEC_index (ld_plugin_symbol_resolution_t, | |
521 | data_in->globals_resolution, | |
522 | index); | |
523 | return ret; | |
524 | } | |
525 | else | |
526 | /* Delay resolution finding until decl merging. */ | |
527 | return LDPR_UNKNOWN; | |
528 | } | |
529 | ||
530 | ||
531 | /* Register DECL with the global symbol table and change its | |
532 | name if necessary to avoid name clashes for static globals across | |
533 | different files. */ | |
534 | ||
535 | static void | |
536 | lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl) | |
537 | { | |
538 | tree context; | |
539 | ||
540 | /* Variable has file scope, not local. Need to ensure static variables | |
541 | between different files don't clash unexpectedly. */ | |
542 | if (!TREE_PUBLIC (decl) | |
543 | && !((context = decl_function_context (decl)) | |
544 | && auto_var_in_fn_p (decl, context))) | |
545 | { | |
546 | /* ??? We normally pre-mangle names before we serialize them | |
547 | out. Here, in lto1, we do not know the language, and | |
548 | thus cannot do the mangling again. Instead, we just | |
549 | append a suffix to the mangled name. The resulting name, | |
550 | however, is not a properly-formed mangled name, and will | |
551 | confuse any attempt to unmangle it. */ | |
552 | const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); | |
553 | char *label; | |
554 | ||
555 | ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl)); | |
556 | SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label)); | |
557 | rest_of_decl_compilation (decl, 1, 0); | |
558 | VEC_safe_push (tree, gc, lto_global_var_decls, decl); | |
559 | } | |
560 | ||
561 | /* If this variable has already been declared, queue the | |
562 | declaration for merging. */ | |
563 | if (TREE_PUBLIC (decl)) | |
564 | { | |
565 | unsigned ix; | |
7f385784 | 566 | if (!streamer_tree_cache_lookup (data_in->reader_cache, decl, &ix)) |
f05c9dfb | 567 | gcc_unreachable (); |
568 | lto_symtab_register_decl (decl, get_resolution (data_in, ix), | |
569 | data_in->file_data); | |
570 | } | |
571 | } | |
572 | ||
573 | ||
574 | /* Register DECL with the global symbol table and change its | |
575 | name if necessary to avoid name clashes for static globals across | |
576 | different files. DATA_IN contains descriptors and tables for the | |
577 | file being read. */ | |
578 | ||
579 | static void | |
580 | lto_register_function_decl_in_symtab (struct data_in *data_in, tree decl) | |
581 | { | |
582 | /* Need to ensure static entities between different files | |
583 | don't clash unexpectedly. */ | |
584 | if (!TREE_PUBLIC (decl)) | |
585 | { | |
586 | /* We must not use the DECL_ASSEMBLER_NAME macro here, as it | |
587 | may set the assembler name where it was previously empty. */ | |
588 | tree old_assembler_name = decl->decl_with_vis.assembler_name; | |
589 | ||
590 | /* FIXME lto: We normally pre-mangle names before we serialize | |
591 | them out. Here, in lto1, we do not know the language, and | |
592 | thus cannot do the mangling again. Instead, we just append a | |
593 | suffix to the mangled name. The resulting name, however, is | |
594 | not a properly-formed mangled name, and will confuse any | |
595 | attempt to unmangle it. */ | |
596 | const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); | |
597 | char *label; | |
598 | ||
599 | ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl)); | |
600 | SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label)); | |
601 | ||
602 | /* We may arrive here with the old assembler name not set | |
603 | if the function body is not needed, e.g., it has been | |
604 | inlined away and does not appear in the cgraph. */ | |
605 | if (old_assembler_name) | |
606 | { | |
607 | tree new_assembler_name = DECL_ASSEMBLER_NAME (decl); | |
608 | ||
609 | /* Make the original assembler name available for later use. | |
610 | We may have used it to indicate the section within its | |
611 | object file where the function body may be found. | |
612 | FIXME lto: Find a better way to maintain the function decl | |
613 | to body section mapping so we don't need this hack. */ | |
614 | lto_record_renamed_decl (data_in->file_data, | |
615 | IDENTIFIER_POINTER (old_assembler_name), | |
616 | IDENTIFIER_POINTER (new_assembler_name)); | |
617 | ||
618 | /* Also register the reverse mapping so that we can find the | |
619 | new name given to an existing assembler name (used when | |
620 | restoring alias pairs in input_constructors_or_inits. */ | |
621 | lto_record_renamed_decl (data_in->file_data, | |
622 | IDENTIFIER_POINTER (new_assembler_name), | |
623 | IDENTIFIER_POINTER (old_assembler_name)); | |
624 | } | |
625 | } | |
626 | ||
627 | /* If this variable has already been declared, queue the | |
628 | declaration for merging. */ | |
629 | if (TREE_PUBLIC (decl) && !DECL_ABSTRACT (decl)) | |
630 | { | |
631 | unsigned ix; | |
7f385784 | 632 | if (!streamer_tree_cache_lookup (data_in->reader_cache, decl, &ix)) |
f05c9dfb | 633 | gcc_unreachable (); |
634 | lto_symtab_register_decl (decl, get_resolution (data_in, ix), | |
635 | data_in->file_data); | |
636 | } | |
637 | } | |
638 | ||
639 | ||
d534cab0 | 640 | /* Given a streamer cache structure DATA_IN (holding a sequence of trees |
641 | for one compilation unit) go over all trees starting at index FROM until the | |
642 | end of the sequence and replace fields of those trees, and the trees | |
643 | themself with their canonical variants as per gimple_register_type. */ | |
644 | ||
645 | static void | |
646 | uniquify_nodes (struct data_in *data_in, unsigned from) | |
647 | { | |
7f385784 | 648 | struct streamer_tree_cache_d *cache = data_in->reader_cache; |
d534cab0 | 649 | unsigned len = VEC_length (tree, cache->nodes); |
650 | unsigned i; | |
bddb3763 | 651 | |
f05c9dfb | 652 | /* Go backwards because children streamed for the first time come |
bddb3763 | 653 | as part of their parents, and hence are created after them. */ |
4d83607a | 654 | |
bbcef2a7 | 655 | /* First register all the types in the cache. This makes sure to |
656 | have the original structure in the type cycles when registering | |
657 | them and computing hashes. */ | |
bddb3763 | 658 | for (i = len; i-- > from;) |
659 | { | |
660 | tree t = VEC_index (tree, cache->nodes, i); | |
bbcef2a7 | 661 | if (t && TYPE_P (t)) |
f05c9dfb | 662 | gimple_register_type (t); |
bddb3763 | 663 | } |
664 | ||
4d83607a | 665 | /* Second fixup all trees in the new cache entries. */ |
d534cab0 | 666 | for (i = len; i-- > from;) |
667 | { | |
668 | tree t = VEC_index (tree, cache->nodes, i); | |
669 | tree oldt = t; | |
670 | if (!t) | |
671 | continue; | |
672 | ||
673 | /* First fixup the fields of T. */ | |
674 | lto_fixup_types (t); | |
675 | ||
4d83607a | 676 | if (!TYPE_P (t)) |
677 | continue; | |
678 | ||
d534cab0 | 679 | /* Now try to find a canonical variant of T itself. */ |
4d83607a | 680 | t = gimple_register_type (t); |
681 | ||
682 | if (t == oldt) | |
d534cab0 | 683 | { |
4d83607a | 684 | /* The following re-creates proper variant lists while fixing up |
685 | the variant leaders. We do not stream TYPE_NEXT_VARIANT so the | |
686 | variant list state before fixup is broken. */ | |
687 | tree tem, mv; | |
688 | ||
689 | /* Remove us from our main variant list if we are not the | |
690 | variant leader. */ | |
691 | if (TYPE_MAIN_VARIANT (t) != t) | |
d534cab0 | 692 | { |
4d83607a | 693 | tem = TYPE_MAIN_VARIANT (t); |
694 | while (tem && TYPE_NEXT_VARIANT (tem) != t) | |
695 | tem = TYPE_NEXT_VARIANT (tem); | |
696 | if (tem) | |
697 | TYPE_NEXT_VARIANT (tem) = TYPE_NEXT_VARIANT (t); | |
698 | TYPE_NEXT_VARIANT (t) = NULL_TREE; | |
d534cab0 | 699 | } |
4d83607a | 700 | |
701 | /* Query our new main variant. */ | |
702 | mv = gimple_register_type (TYPE_MAIN_VARIANT (t)); | |
703 | ||
704 | /* If we were the variant leader and we get replaced ourselves drop | |
705 | all variants from our list. */ | |
706 | if (TYPE_MAIN_VARIANT (t) == t | |
707 | && mv != t) | |
d534cab0 | 708 | { |
4d83607a | 709 | tem = t; |
710 | while (tem) | |
711 | { | |
712 | tree tem2 = TYPE_NEXT_VARIANT (tem); | |
713 | TYPE_NEXT_VARIANT (tem) = NULL_TREE; | |
714 | tem = tem2; | |
715 | } | |
d534cab0 | 716 | } |
7bfefa9d | 717 | |
4d83607a | 718 | /* If we are not our own variant leader link us into our new leaders |
719 | variant list. */ | |
720 | if (mv != t) | |
721 | { | |
722 | TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (mv); | |
723 | TYPE_NEXT_VARIANT (mv) = t; | |
b6c200c3 | 724 | if (RECORD_OR_UNION_TYPE_P (t)) |
725 | TYPE_BINFO (t) = TYPE_BINFO (mv); | |
4d83607a | 726 | } |
727 | ||
728 | /* Finally adjust our main variant and fix it up. */ | |
729 | TYPE_MAIN_VARIANT (t) = mv; | |
730 | ||
731 | /* The following reconstructs the pointer chains | |
732 | of the new pointed-to type if we are a main variant. We do | |
733 | not stream those so they are broken before fixup. */ | |
734 | if (TREE_CODE (t) == POINTER_TYPE | |
735 | && TYPE_MAIN_VARIANT (t) == t) | |
736 | { | |
737 | TYPE_NEXT_PTR_TO (t) = TYPE_POINTER_TO (TREE_TYPE (t)); | |
738 | TYPE_POINTER_TO (TREE_TYPE (t)) = t; | |
739 | } | |
740 | else if (TREE_CODE (t) == REFERENCE_TYPE | |
741 | && TYPE_MAIN_VARIANT (t) == t) | |
742 | { | |
743 | TYPE_NEXT_REF_TO (t) = TYPE_REFERENCE_TO (TREE_TYPE (t)); | |
744 | TYPE_REFERENCE_TO (TREE_TYPE (t)) = t; | |
745 | } | |
746 | } | |
747 | ||
8f2b914f | 748 | else |
4d83607a | 749 | { |
8f2b914f | 750 | if (RECORD_OR_UNION_TYPE_P (t)) |
751 | { | |
752 | tree f1, f2; | |
753 | if (TYPE_FIELDS (t) != TYPE_FIELDS (oldt)) | |
754 | for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (oldt); | |
755 | f1 && f2; f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) | |
756 | { | |
757 | unsigned ix; | |
758 | gcc_assert (f1 != f2 && DECL_NAME (f1) == DECL_NAME (f2)); | |
7f385784 | 759 | if (!streamer_tree_cache_lookup (cache, f2, &ix)) |
8f2b914f | 760 | gcc_unreachable (); |
761 | /* If we're going to replace an element which we'd | |
762 | still visit in the next iterations, we wouldn't | |
763 | handle it, so do it here. We do have to handle it | |
764 | even though the field_decl itself will be removed, | |
765 | as it could refer to e.g. integer_cst which we | |
766 | wouldn't reach via any other way, hence they | |
767 | (and their type) would stay uncollected. */ | |
768 | /* ??? We should rather make sure to replace all | |
769 | references to f2 with f1. That means handling | |
770 | COMPONENT_REFs and CONSTRUCTOR elements in | |
771 | lto_fixup_types and special-case the field-decl | |
772 | operand handling. */ | |
773 | if (ix < i) | |
774 | lto_fixup_types (f2); | |
7f385784 | 775 | streamer_tree_cache_insert_at (cache, f1, ix); |
8f2b914f | 776 | } |
777 | } | |
4d83607a | 778 | |
d534cab0 | 779 | /* If we found a tree that is equal to oldt replace it in the |
780 | cache, so that further users (in the various LTO sections) | |
781 | make use of it. */ | |
7f385784 | 782 | streamer_tree_cache_insert_at (cache, t, i); |
7bfefa9d | 783 | } |
7bfefa9d | 784 | } |
4d83607a | 785 | |
bbcef2a7 | 786 | /* Finally compute the canonical type of all TREE_TYPEs and register |
787 | VAR_DECL and FUNCTION_DECL nodes in the symbol table. | |
788 | From this point there are no longer any types with | |
789 | TYPE_STRUCTURAL_EQUALITY_P and its type-based alias problems. | |
790 | This step requires the TYPE_POINTER_TO lists being present, so | |
791 | make sure it is done last. */ | |
4d83607a | 792 | for (i = len; i-- > from;) |
793 | { | |
794 | tree t = VEC_index (tree, cache->nodes, i); | |
bbcef2a7 | 795 | if (t == NULL_TREE) |
4d83607a | 796 | continue; |
797 | ||
bbcef2a7 | 798 | if (TREE_CODE (t) == VAR_DECL) |
799 | lto_register_var_decl_in_symtab (data_in, t); | |
800 | else if (TREE_CODE (t) == FUNCTION_DECL && !DECL_BUILT_IN (t)) | |
801 | lto_register_function_decl_in_symtab (data_in, t); | |
802 | else if (TYPE_P (t) && !TYPE_CANONICAL (t)) | |
4d83607a | 803 | TYPE_CANONICAL (t) = gimple_register_canonical_type (t); |
804 | } | |
7bfefa9d | 805 | } |
806 | ||
f05c9dfb | 807 | |
7bfefa9d | 808 | /* Read all the symbols from buffer DATA, using descriptors in DECL_DATA. |
809 | RESOLUTIONS is the set of symbols picked by the linker (read from the | |
810 | resolution file when the linker plugin is being used). */ | |
811 | ||
812 | static void | |
813 | lto_read_decls (struct lto_file_decl_data *decl_data, const void *data, | |
814 | VEC(ld_plugin_symbol_resolution_t,heap) *resolutions) | |
815 | { | |
816 | const struct lto_decl_header *header = (const struct lto_decl_header *) data; | |
817 | const int32_t decl_offset = sizeof (struct lto_decl_header); | |
818 | const int32_t main_offset = decl_offset + header->decl_state_size; | |
819 | const int32_t string_offset = main_offset + header->main_size; | |
820 | struct lto_input_block ib_main; | |
821 | struct data_in *data_in; | |
822 | unsigned int i; | |
823 | const uint32_t *data_ptr, *data_end; | |
824 | uint32_t num_decl_states; | |
825 | ||
826 | LTO_INIT_INPUT_BLOCK (ib_main, (const char *) data + main_offset, 0, | |
827 | header->main_size); | |
828 | ||
829 | data_in = lto_data_in_create (decl_data, (const char *) data + string_offset, | |
830 | header->string_size, resolutions); | |
831 | ||
832 | /* Read the global declarations and types. */ | |
833 | while (ib_main.p < ib_main.len) | |
834 | { | |
d534cab0 | 835 | tree t; |
836 | unsigned from = VEC_length (tree, data_in->reader_cache->nodes); | |
515cf651 | 837 | t = stream_read_tree (&ib_main, data_in); |
7bfefa9d | 838 | gcc_assert (t && ib_main.p <= ib_main.len); |
d534cab0 | 839 | uniquify_nodes (data_in, from); |
7bfefa9d | 840 | } |
841 | ||
842 | /* Read in lto_in_decl_state objects. */ | |
843 | data_ptr = (const uint32_t *) ((const char*) data + decl_offset); | |
844 | data_end = | |
845 | (const uint32_t *) ((const char*) data_ptr + header->decl_state_size); | |
846 | num_decl_states = *data_ptr++; | |
847 | ||
848 | gcc_assert (num_decl_states > 0); | |
849 | decl_data->global_decl_state = lto_new_in_decl_state (); | |
850 | data_ptr = lto_read_in_decl_state (data_in, data_ptr, | |
851 | decl_data->global_decl_state); | |
852 | ||
853 | /* Read in per-function decl states and enter them in hash table. */ | |
854 | decl_data->function_decl_states = | |
57305941 | 855 | htab_create_ggc (37, lto_hash_in_decl_state, lto_eq_in_decl_state, NULL); |
7bfefa9d | 856 | |
857 | for (i = 1; i < num_decl_states; i++) | |
858 | { | |
859 | struct lto_in_decl_state *state = lto_new_in_decl_state (); | |
860 | void **slot; | |
861 | ||
862 | data_ptr = lto_read_in_decl_state (data_in, data_ptr, state); | |
863 | slot = htab_find_slot (decl_data->function_decl_states, state, INSERT); | |
864 | gcc_assert (*slot == NULL); | |
865 | *slot = state; | |
866 | } | |
867 | ||
868 | if (data_ptr != data_end) | |
869 | internal_error ("bytecode stream: garbage at the end of symbols section"); | |
870 | ||
871 | /* Set the current decl state to be the global state. */ | |
872 | decl_data->current_decl_state = decl_data->global_decl_state; | |
873 | ||
7bfefa9d | 874 | lto_data_in_delete (data_in); |
875 | } | |
876 | ||
81897669 | 877 | /* strtoll is not portable. */ |
878 | int64_t | |
879 | lto_parse_hex (const char *p) { | |
880 | uint64_t ret = 0; | |
881 | for (; *p != '\0'; ++p) | |
882 | { | |
883 | char c = *p; | |
884 | unsigned char part; | |
885 | ret <<= 4; | |
886 | if (c >= '0' && c <= '9') | |
887 | part = c - '0'; | |
888 | else if (c >= 'a' && c <= 'f') | |
889 | part = c - 'a' + 10; | |
890 | else if (c >= 'A' && c <= 'F') | |
891 | part = c - 'A' + 10; | |
892 | else | |
893 | internal_error ("could not parse hex number"); | |
894 | ret |= part; | |
895 | } | |
896 | return ret; | |
897 | } | |
898 | ||
7bfefa9d | 899 | /* Read resolution for file named FILE_NAME. The resolution is read from |
f18bad33 | 900 | RESOLUTION. */ |
7bfefa9d | 901 | |
f18bad33 | 902 | static void |
903 | lto_resolution_read (splay_tree file_ids, FILE *resolution, lto_file *file) | |
7bfefa9d | 904 | { |
905 | /* We require that objects in the resolution file are in the same | |
906 | order as the lto1 command line. */ | |
907 | unsigned int name_len; | |
908 | char *obj_name; | |
909 | unsigned int num_symbols; | |
910 | unsigned int i; | |
f18bad33 | 911 | struct lto_file_decl_data *file_data; |
7bfefa9d | 912 | unsigned max_index = 0; |
f18bad33 | 913 | splay_tree_node nd = NULL; |
7bfefa9d | 914 | |
915 | if (!resolution) | |
f18bad33 | 916 | return; |
7bfefa9d | 917 | |
b7fedf62 | 918 | name_len = strlen (file->filename); |
7bfefa9d | 919 | obj_name = XNEWVEC (char, name_len + 1); |
920 | fscanf (resolution, " "); /* Read white space. */ | |
921 | ||
922 | fread (obj_name, sizeof (char), name_len, resolution); | |
923 | obj_name[name_len] = '\0'; | |
82715bcd | 924 | if (filename_cmp (obj_name, file->filename) != 0) |
7bfefa9d | 925 | internal_error ("unexpected file name %s in linker resolution file. " |
b7fedf62 | 926 | "Expected %s", obj_name, file->filename); |
927 | if (file->offset != 0) | |
928 | { | |
929 | int t; | |
81897669 | 930 | char offset_p[17]; |
931 | int64_t offset; | |
932 | t = fscanf (resolution, "@0x%16s", offset_p); | |
b7fedf62 | 933 | if (t != 1) |
934 | internal_error ("could not parse file offset"); | |
81897669 | 935 | offset = lto_parse_hex (offset_p); |
b7fedf62 | 936 | if (offset != file->offset) |
937 | internal_error ("unexpected offset"); | |
938 | } | |
7bfefa9d | 939 | |
940 | free (obj_name); | |
941 | ||
942 | fscanf (resolution, "%u", &num_symbols); | |
943 | ||
944 | for (i = 0; i < num_symbols; i++) | |
945 | { | |
d405c5a4 | 946 | int t; |
f18bad33 | 947 | unsigned index, id; |
7bfefa9d | 948 | char r_str[27]; |
6c8c5385 | 949 | enum ld_plugin_symbol_resolution r = (enum ld_plugin_symbol_resolution) 0; |
7bfefa9d | 950 | unsigned int j; |
951 | unsigned int lto_resolution_str_len = | |
952 | sizeof (lto_resolution_str) / sizeof (char *); | |
953 | ||
f18bad33 | 954 | t = fscanf (resolution, "%u %x %26s %*[^\n]\n", &index, &id, r_str); |
955 | if (t != 3) | |
bf776685 | 956 | internal_error ("invalid line in the resolution file"); |
7bfefa9d | 957 | if (index > max_index) |
958 | max_index = index; | |
959 | ||
960 | for (j = 0; j < lto_resolution_str_len; j++) | |
961 | { | |
962 | if (strcmp (lto_resolution_str[j], r_str) == 0) | |
963 | { | |
964 | r = (enum ld_plugin_symbol_resolution) j; | |
965 | break; | |
966 | } | |
967 | } | |
d405c5a4 | 968 | if (j == lto_resolution_str_len) |
bf776685 | 969 | internal_error ("invalid resolution in the resolution file"); |
7bfefa9d | 970 | |
f18bad33 | 971 | if (!(nd && nd->key == id)) |
972 | { | |
973 | nd = splay_tree_lookup (file_ids, id); | |
974 | if (nd == NULL) | |
bf776685 | 975 | internal_error ("resolution sub id %x not in object file", id); |
f18bad33 | 976 | } |
977 | ||
978 | file_data = (struct lto_file_decl_data *)nd->value; | |
979 | if (cgraph_dump_file) | |
980 | fprintf (cgraph_dump_file, "Adding resolution %u %u to id %x\n", | |
981 | index, r, file_data->id); | |
982 | VEC_safe_grow_cleared (ld_plugin_symbol_resolution_t, heap, | |
983 | file_data->resolutions, | |
50b2dbd9 | 984 | max_index + 1); |
f18bad33 | 985 | VEC_replace (ld_plugin_symbol_resolution_t, |
986 | file_data->resolutions, index, r); | |
7bfefa9d | 987 | } |
f18bad33 | 988 | } |
7bfefa9d | 989 | |
f18bad33 | 990 | /* Is the name for a id'ed LTO section? */ |
991 | ||
992 | static int | |
993 | lto_section_with_id (const char *name, unsigned *id) | |
994 | { | |
eaa13879 | 995 | const char *s; |
f18bad33 | 996 | |
997 | if (strncmp (name, LTO_SECTION_NAME_PREFIX, strlen (LTO_SECTION_NAME_PREFIX))) | |
998 | return 0; | |
999 | s = strrchr (name, '.'); | |
1000 | return s && sscanf (s, ".%x", id) == 1; | |
1001 | } | |
1002 | ||
1003 | /* Create file_data of each sub file id */ | |
1004 | ||
1005 | static int | |
1006 | create_subid_section_table (void **slot, void *data) | |
1007 | { | |
1008 | struct lto_section_slot s_slot, *new_slot; | |
1009 | struct lto_section_slot *ls = *(struct lto_section_slot **)slot; | |
1010 | splay_tree file_ids = (splay_tree)data; | |
1011 | unsigned id; | |
1012 | splay_tree_node nd; | |
1013 | void **hash_slot; | |
1014 | char *new_name; | |
1015 | struct lto_file_decl_data *file_data; | |
1016 | ||
1017 | if (!lto_section_with_id (ls->name, &id)) | |
1018 | return 1; | |
1019 | ||
1020 | /* Find hash table of sub module id */ | |
1021 | nd = splay_tree_lookup (file_ids, id); | |
1022 | if (nd != NULL) | |
1023 | { | |
1024 | file_data = (struct lto_file_decl_data *)nd->value; | |
1025 | } | |
1026 | else | |
1027 | { | |
1028 | file_data = ggc_alloc_lto_file_decl_data (); | |
1029 | memset(file_data, 0, sizeof (struct lto_file_decl_data)); | |
1030 | file_data->id = id; | |
1031 | file_data->section_hash_table = lto_obj_create_section_hash_table ();; | |
1032 | splay_tree_insert (file_ids, id, (splay_tree_value)file_data); | |
1033 | } | |
1034 | ||
1035 | /* Copy section into sub module hash table */ | |
1036 | new_name = XDUPVEC (char, ls->name, strlen (ls->name) + 1); | |
1037 | s_slot.name = new_name; | |
1038 | hash_slot = htab_find_slot (file_data->section_hash_table, &s_slot, INSERT); | |
1039 | gcc_assert (*hash_slot == NULL); | |
1040 | ||
1041 | new_slot = XDUP (struct lto_section_slot, ls); | |
1042 | new_slot->name = new_name; | |
1043 | *hash_slot = new_slot; | |
1044 | return 1; | |
1045 | } | |
1046 | ||
1047 | /* Read declarations and other initializations for a FILE_DATA. */ | |
1048 | ||
1049 | static void | |
1050 | lto_file_finalize (struct lto_file_decl_data *file_data, lto_file *file) | |
1051 | { | |
1052 | const char *data; | |
1053 | size_t len; | |
1054 | ||
1055 | file_data->renaming_hash_table = lto_create_renaming_table (); | |
1056 | file_data->file_name = file->filename; | |
1057 | data = lto_get_section_data (file_data, LTO_section_decls, NULL, &len); | |
fd30d60a | 1058 | if (data == NULL) |
1059 | { | |
bf776685 | 1060 | internal_error ("cannot read LTO decls from %s", file_data->file_name); |
fd30d60a | 1061 | return; |
1062 | } | |
f18bad33 | 1063 | lto_read_decls (file_data, data, file_data->resolutions); |
1064 | lto_free_section_data (file_data, LTO_section_decls, NULL, data, len); | |
1065 | } | |
1066 | ||
1067 | struct lwstate | |
1068 | { | |
1069 | lto_file *file; | |
1070 | struct lto_file_decl_data **file_data; | |
1071 | int *count; | |
1072 | }; | |
1073 | ||
1074 | /* Traverse ids and create a list of file_datas out of it. */ | |
1075 | ||
1076 | static int lto_create_files_from_ids (splay_tree_node node, void *data) | |
1077 | { | |
1078 | struct lwstate *lw = (struct lwstate *)data; | |
1079 | struct lto_file_decl_data *file_data = (struct lto_file_decl_data *)node->value; | |
1080 | ||
1081 | lto_file_finalize (file_data, lw->file); | |
1082 | if (cgraph_dump_file) | |
1083 | fprintf (cgraph_dump_file, "Creating file %s with sub id %x\n", | |
1084 | file_data->file_name, file_data->id); | |
1085 | file_data->next = *lw->file_data; | |
1086 | *lw->file_data = file_data; | |
1087 | (*lw->count)++; | |
1088 | return 0; | |
7bfefa9d | 1089 | } |
1090 | ||
1091 | /* Generate a TREE representation for all types and external decls | |
1092 | entities in FILE. | |
1093 | ||
1094 | Read all of the globals out of the file. Then read the cgraph | |
1095 | and process the .o index into the cgraph nodes so that it can open | |
1096 | the .o file to load the functions and ipa information. */ | |
1097 | ||
1098 | static struct lto_file_decl_data * | |
f18bad33 | 1099 | lto_file_read (lto_file *file, FILE *resolution_file, int *count) |
7bfefa9d | 1100 | { |
f18bad33 | 1101 | struct lto_file_decl_data *file_data = NULL; |
1102 | splay_tree file_ids; | |
1103 | htab_t section_hash_table; | |
1104 | struct lwstate state; | |
7bfefa9d | 1105 | |
f18bad33 | 1106 | section_hash_table = lto_obj_build_section_table (file); |
7bfefa9d | 1107 | |
f18bad33 | 1108 | /* Find all sub modules in the object and put their sections into new hash |
1109 | tables in a splay tree. */ | |
1110 | file_ids = splay_tree_new (splay_tree_compare_ints, NULL, NULL); | |
1111 | htab_traverse (section_hash_table, create_subid_section_table, file_ids); | |
1112 | ||
1113 | /* Add resolutions to file ids */ | |
1114 | lto_resolution_read (file_ids, resolution_file, file); | |
1115 | ||
1116 | /* Finalize each lto file for each submodule in the merged object | |
1117 | and create list for returning. */ | |
1118 | state.file = file; | |
1119 | state.file_data = &file_data; | |
1120 | state.count = count; | |
1121 | splay_tree_foreach (file_ids, lto_create_files_from_ids, &state); | |
1122 | ||
1123 | splay_tree_delete (file_ids); | |
1124 | htab_delete (section_hash_table); | |
7bfefa9d | 1125 | |
1126 | return file_data; | |
1127 | } | |
1128 | ||
1129 | #if HAVE_MMAP_FILE && HAVE_SYSCONF && defined _SC_PAGE_SIZE | |
1130 | #define LTO_MMAP_IO 1 | |
1131 | #endif | |
1132 | ||
1133 | #if LTO_MMAP_IO | |
1134 | /* Page size of machine is used for mmap and munmap calls. */ | |
1135 | static size_t page_mask; | |
1136 | #endif | |
1137 | ||
1138 | /* Get the section data of length LEN from FILENAME starting at | |
1139 | OFFSET. The data segment must be freed by the caller when the | |
1140 | caller is finished. Returns NULL if all was not well. */ | |
1141 | ||
1142 | static char * | |
1143 | lto_read_section_data (struct lto_file_decl_data *file_data, | |
1144 | intptr_t offset, size_t len) | |
1145 | { | |
1146 | char *result; | |
f5a023c5 | 1147 | static int fd = -1; |
1148 | static char *fd_name; | |
7bfefa9d | 1149 | #if LTO_MMAP_IO |
1150 | intptr_t computed_len; | |
1151 | intptr_t computed_offset; | |
1152 | intptr_t diff; | |
1153 | #endif | |
1154 | ||
f5a023c5 | 1155 | /* Keep a single-entry file-descriptor cache. The last file we |
1156 | touched will get closed at exit. | |
1157 | ??? Eventually we want to add a more sophisticated larger cache | |
1158 | or rather fix function body streaming to not stream them in | |
1159 | practically random order. */ | |
1160 | if (fd != -1 | |
82715bcd | 1161 | && filename_cmp (fd_name, file_data->file_name) != 0) |
f5a023c5 | 1162 | { |
1163 | free (fd_name); | |
1164 | close (fd); | |
1165 | fd = -1; | |
1166 | } | |
1167 | if (fd == -1) | |
1168 | { | |
27721832 | 1169 | fd = open (file_data->file_name, O_RDONLY|O_BINARY); |
f5a023c5 | 1170 | if (fd == -1) |
1171 | return NULL; | |
fad71d4f | 1172 | fd_name = xstrdup (file_data->file_name); |
f5a023c5 | 1173 | } |
7bfefa9d | 1174 | |
1175 | #if LTO_MMAP_IO | |
1176 | if (!page_mask) | |
1177 | { | |
1178 | size_t page_size = sysconf (_SC_PAGE_SIZE); | |
1179 | page_mask = ~(page_size - 1); | |
1180 | } | |
1181 | ||
1182 | computed_offset = offset & page_mask; | |
1183 | diff = offset - computed_offset; | |
1184 | computed_len = len + diff; | |
1185 | ||
1186 | result = (char *) mmap (NULL, computed_len, PROT_READ, MAP_PRIVATE, | |
f5a023c5 | 1187 | fd, computed_offset); |
7bfefa9d | 1188 | if (result == MAP_FAILED) |
f5a023c5 | 1189 | return NULL; |
7bfefa9d | 1190 | |
1191 | return result + diff; | |
1192 | #else | |
1193 | result = (char *) xmalloc (len); | |
f5a023c5 | 1194 | if (lseek (fd, offset, SEEK_SET) != offset |
1195 | || read (fd, result, len) != (ssize_t) len) | |
7bfefa9d | 1196 | { |
1197 | free (result); | |
fad71d4f | 1198 | result = NULL; |
7bfefa9d | 1199 | } |
fad71d4f | 1200 | #ifdef __MINGW32__ |
1201 | /* Native windows doesn't supports delayed unlink on opened file. So | |
1202 | we close file here again. This produces higher I/O load, but at least | |
1203 | it prevents to have dangling file handles preventing unlink. */ | |
1204 | free (fd_name); | |
1205 | fd_name = NULL; | |
1206 | close (fd); | |
1207 | fd = -1; | |
1208 | #endif | |
7bfefa9d | 1209 | return result; |
1210 | #endif | |
1211 | } | |
1212 | ||
1213 | ||
1214 | /* Get the section data from FILE_DATA of SECTION_TYPE with NAME. | |
1215 | NAME will be NULL unless the section type is for a function | |
1216 | body. */ | |
1217 | ||
1218 | static const char * | |
1219 | get_section_data (struct lto_file_decl_data *file_data, | |
1220 | enum lto_section_type section_type, | |
1221 | const char *name, | |
1222 | size_t *len) | |
1223 | { | |
1224 | htab_t section_hash_table = file_data->section_hash_table; | |
1225 | struct lto_section_slot *f_slot; | |
1226 | struct lto_section_slot s_slot; | |
f18bad33 | 1227 | const char *section_name = lto_get_section_name (section_type, name, file_data); |
7bfefa9d | 1228 | char *data = NULL; |
1229 | ||
1230 | *len = 0; | |
1231 | s_slot.name = section_name; | |
1232 | f_slot = (struct lto_section_slot *) htab_find (section_hash_table, &s_slot); | |
1233 | if (f_slot) | |
1234 | { | |
1235 | data = lto_read_section_data (file_data, f_slot->start, f_slot->len); | |
1236 | *len = f_slot->len; | |
1237 | } | |
1238 | ||
1239 | free (CONST_CAST (char *, section_name)); | |
1240 | return data; | |
1241 | } | |
1242 | ||
1243 | ||
1244 | /* Free the section data from FILE_DATA of SECTION_TYPE with NAME that | |
1245 | starts at OFFSET and has LEN bytes. */ | |
1246 | ||
1247 | static void | |
f5a023c5 | 1248 | free_section_data (struct lto_file_decl_data *file_data ATTRIBUTE_UNUSED, |
7bfefa9d | 1249 | enum lto_section_type section_type ATTRIBUTE_UNUSED, |
1250 | const char *name ATTRIBUTE_UNUSED, | |
1251 | const char *offset, size_t len ATTRIBUTE_UNUSED) | |
1252 | { | |
1253 | #if LTO_MMAP_IO | |
1254 | intptr_t computed_len; | |
1255 | intptr_t computed_offset; | |
1256 | intptr_t diff; | |
1257 | #endif | |
1258 | ||
7bfefa9d | 1259 | #if LTO_MMAP_IO |
1260 | computed_offset = ((intptr_t) offset) & page_mask; | |
1261 | diff = (intptr_t) offset - computed_offset; | |
1262 | computed_len = len + diff; | |
1263 | ||
1264 | munmap ((caddr_t) computed_offset, computed_len); | |
1265 | #else | |
1266 | free (CONST_CAST(char *, offset)); | |
1267 | #endif | |
1268 | } | |
1269 | ||
68b8d829 | 1270 | /* Structure describing ltrans partitions. */ |
1271 | ||
19ad01f7 | 1272 | struct ltrans_partition_def |
68b8d829 | 1273 | { |
1274 | cgraph_node_set cgraph_set; | |
1275 | varpool_node_set varpool_set; | |
19ad01f7 | 1276 | const char * name; |
68b8d829 | 1277 | int insns; |
1278 | }; | |
1279 | ||
1280 | typedef struct ltrans_partition_def *ltrans_partition; | |
1281 | DEF_VEC_P(ltrans_partition); | |
19ad01f7 | 1282 | DEF_VEC_ALLOC_P(ltrans_partition,heap); |
68b8d829 | 1283 | |
19ad01f7 | 1284 | static VEC(ltrans_partition, heap) *ltrans_partitions; |
7bfefa9d | 1285 | |
7550e1d1 | 1286 | static void add_cgraph_node_to_partition (ltrans_partition part, struct cgraph_node *node); |
1287 | static void add_varpool_node_to_partition (ltrans_partition part, struct varpool_node *vnode); | |
1288 | ||
68b8d829 | 1289 | /* Create new partition with name NAME. */ |
1290 | static ltrans_partition | |
1291 | new_partition (const char *name) | |
1292 | { | |
19ad01f7 | 1293 | ltrans_partition part = XCNEW (struct ltrans_partition_def); |
68b8d829 | 1294 | part->cgraph_set = cgraph_node_set_new (); |
1295 | part->varpool_set = varpool_node_set_new (); | |
1296 | part->name = name; | |
1297 | part->insns = 0; | |
19ad01f7 | 1298 | VEC_safe_push (ltrans_partition, heap, ltrans_partitions, part); |
68b8d829 | 1299 | return part; |
1300 | } | |
1301 | ||
19ad01f7 | 1302 | /* Free memory used by ltrans datastructures. */ |
1303 | static void | |
423ba805 | 1304 | free_ltrans_partitions (void) |
19ad01f7 | 1305 | { |
1306 | unsigned int idx; | |
1307 | ltrans_partition part; | |
1308 | for (idx = 0; VEC_iterate (ltrans_partition, ltrans_partitions, idx, part); idx++) | |
1309 | { | |
423ba805 | 1310 | free_cgraph_node_set (part->cgraph_set); |
19ad01f7 | 1311 | free (part); |
1312 | } | |
423ba805 | 1313 | VEC_free (ltrans_partition, heap, ltrans_partitions); |
19ad01f7 | 1314 | } |
1315 | ||
7550e1d1 | 1316 | /* See all references that go to comdat objects and bring them into partition too. */ |
1317 | static void | |
1318 | add_references_to_partition (ltrans_partition part, struct ipa_ref_list *refs) | |
1319 | { | |
1320 | int i; | |
1321 | struct ipa_ref *ref; | |
1322 | for (i = 0; ipa_ref_list_reference_iterate (refs, i, ref); i++) | |
1323 | { | |
1324 | if (ref->refered_type == IPA_REF_CGRAPH | |
c70f46b0 | 1325 | && DECL_COMDAT (cgraph_function_node (ipa_ref_node (ref), NULL)->decl) |
7550e1d1 | 1326 | && !cgraph_node_in_set_p (ipa_ref_node (ref), part->cgraph_set)) |
1327 | add_cgraph_node_to_partition (part, ipa_ref_node (ref)); | |
1328 | else | |
1329 | if (ref->refered_type == IPA_REF_VARPOOL | |
1330 | && DECL_COMDAT (ipa_ref_varpool_node (ref)->decl) | |
1331 | && !varpool_node_in_set_p (ipa_ref_varpool_node (ref), part->varpool_set)) | |
1332 | add_varpool_node_to_partition (part, ipa_ref_varpool_node (ref)); | |
1333 | } | |
1334 | } | |
1335 | ||
c70f46b0 | 1336 | /* Worker for add_cgraph_node_to_partition. */ |
1337 | ||
1338 | static bool | |
1339 | add_cgraph_node_to_partition_1 (struct cgraph_node *node, void *data) | |
1340 | { | |
1341 | ltrans_partition part = (ltrans_partition) data; | |
1342 | ||
1343 | /* non-COMDAT aliases of COMDAT functions needs to be output just once. */ | |
1344 | if (!DECL_COMDAT (node->decl) | |
1345 | && !node->global.inlined_to | |
1346 | && node->aux) | |
1347 | { | |
1348 | gcc_assert (node->thunk.thunk_p || node->alias); | |
1349 | return false; | |
1350 | } | |
1351 | ||
1352 | if (node->aux) | |
1353 | { | |
1354 | node->in_other_partition = 1; | |
1355 | if (cgraph_dump_file) | |
1356 | fprintf (cgraph_dump_file, "Node %s/%i now used in multiple partitions\n", | |
1357 | cgraph_node_name (node), node->uid); | |
1358 | } | |
1359 | node->aux = (void *)((size_t)node->aux + 1); | |
1360 | cgraph_node_set_add (part->cgraph_set, node); | |
1361 | return false; | |
1362 | } | |
1363 | ||
7550e1d1 | 1364 | /* Add NODE to partition as well as the inline callees and referred comdats into partition PART. */ |
68b8d829 | 1365 | |
1366 | static void | |
1367 | add_cgraph_node_to_partition (ltrans_partition part, struct cgraph_node *node) | |
1368 | { | |
1369 | struct cgraph_edge *e; | |
91bf9d9a | 1370 | cgraph_node_set_iterator csi; |
c70f46b0 | 1371 | struct cgraph_node *n; |
1372 | ||
1373 | /* We always decide on functions, not associated thunks and aliases. */ | |
1374 | node = cgraph_function_node (node, NULL); | |
91bf9d9a | 1375 | |
1376 | /* If NODE is already there, we have nothing to do. */ | |
1377 | csi = cgraph_node_set_find (part->cgraph_set, node); | |
1378 | if (!csi_end_p (csi)) | |
1379 | return; | |
7550e1d1 | 1380 | |
c70f46b0 | 1381 | cgraph_for_node_thunks_and_aliases (node, add_cgraph_node_to_partition_1, part, true); |
1382 | ||
c7b2cc59 | 1383 | part->insns += inline_summary (node)->self_size; |
7550e1d1 | 1384 | |
7550e1d1 | 1385 | |
68b8d829 | 1386 | cgraph_node_set_add (part->cgraph_set, node); |
7550e1d1 | 1387 | |
68b8d829 | 1388 | for (e = node->callees; e; e = e->next_callee) |
c70f46b0 | 1389 | if ((!e->inline_failed |
1390 | || DECL_COMDAT (cgraph_function_node (e->callee, NULL)->decl)) | |
7550e1d1 | 1391 | && !cgraph_node_in_set_p (e->callee, part->cgraph_set)) |
68b8d829 | 1392 | add_cgraph_node_to_partition (part, e->callee); |
7550e1d1 | 1393 | |
1394 | add_references_to_partition (part, &node->ref_list); | |
1395 | ||
c70f46b0 | 1396 | if (node->same_comdat_group) |
1397 | for (n = node->same_comdat_group; n != node; n = n->same_comdat_group) | |
1398 | add_cgraph_node_to_partition (part, n); | |
7550e1d1 | 1399 | } |
1400 | ||
1401 | /* Add VNODE to partition as well as comdat references partition PART. */ | |
1402 | ||
1403 | static void | |
1404 | add_varpool_node_to_partition (ltrans_partition part, struct varpool_node *vnode) | |
1405 | { | |
91bf9d9a | 1406 | varpool_node_set_iterator vsi; |
1407 | ||
1408 | /* If NODE is already there, we have nothing to do. */ | |
1409 | vsi = varpool_node_set_find (part->varpool_set, vnode); | |
1410 | if (!vsi_end_p (vsi)) | |
1411 | return; | |
1412 | ||
7550e1d1 | 1413 | varpool_node_set_add (part->varpool_set, vnode); |
1414 | ||
1415 | if (vnode->aux) | |
4037a4c1 | 1416 | { |
1417 | vnode->in_other_partition = 1; | |
1418 | if (cgraph_dump_file) | |
1419 | fprintf (cgraph_dump_file, "Varpool node %s now used in multiple partitions\n", | |
1420 | varpool_node_name (vnode)); | |
1421 | } | |
48e3ea52 | 1422 | vnode->aux = (void *)((size_t)vnode->aux + 1); |
7550e1d1 | 1423 | |
1424 | add_references_to_partition (part, &vnode->ref_list); | |
1425 | ||
1426 | if (vnode->same_comdat_group | |
1427 | && !varpool_node_in_set_p (vnode->same_comdat_group, part->varpool_set)) | |
1428 | add_varpool_node_to_partition (part, vnode->same_comdat_group); | |
68b8d829 | 1429 | } |
7bfefa9d | 1430 | |
48e3ea52 | 1431 | /* Undo all additions until number of cgraph nodes in PARITION is N_CGRAPH_NODES |
1432 | and number of varpool nodes is N_VARPOOL_NODES. */ | |
1433 | ||
1434 | static void | |
1435 | undo_partition (ltrans_partition partition, unsigned int n_cgraph_nodes, | |
1436 | unsigned int n_varpool_nodes) | |
1437 | { | |
1438 | while (VEC_length (cgraph_node_ptr, partition->cgraph_set->nodes) > | |
1439 | n_cgraph_nodes) | |
1440 | { | |
1441 | struct cgraph_node *node = VEC_index (cgraph_node_ptr, | |
1442 | partition->cgraph_set->nodes, | |
1443 | n_cgraph_nodes); | |
c7b2cc59 | 1444 | partition->insns -= inline_summary (node)->self_size; |
48e3ea52 | 1445 | cgraph_node_set_remove (partition->cgraph_set, node); |
1446 | node->aux = (void *)((size_t)node->aux - 1); | |
1447 | } | |
1448 | while (VEC_length (varpool_node_ptr, partition->varpool_set->nodes) > | |
1449 | n_varpool_nodes) | |
1450 | { | |
1451 | struct varpool_node *node = VEC_index (varpool_node_ptr, | |
1452 | partition->varpool_set->nodes, | |
1453 | n_varpool_nodes); | |
1454 | varpool_node_set_remove (partition->varpool_set, node); | |
1455 | node->aux = (void *)((size_t)node->aux - 1); | |
1456 | } | |
1457 | } | |
1458 | ||
1459 | /* Return true if NODE should be partitioned. | |
1460 | This means that partitioning algorithm should put NODE into one of partitions. | |
1461 | This apply to most functions with bodies. Functions that are not partitions | |
1462 | are put into every unit needing them. This is the case of i.e. COMDATs. */ | |
1463 | ||
1464 | static bool | |
1465 | partition_cgraph_node_p (struct cgraph_node *node) | |
1466 | { | |
1467 | /* We will get proper partition based on function they are inlined to. */ | |
1468 | if (node->global.inlined_to) | |
1469 | return false; | |
1470 | /* Nodes without a body do not need partitioning. */ | |
1471 | if (!node->analyzed) | |
1472 | return false; | |
1473 | /* Extern inlines and comdat are always only in partitions they are needed. */ | |
1474 | if (DECL_EXTERNAL (node->decl) | |
7ad28d2a | 1475 | || (DECL_COMDAT (node->decl) |
1476 | && !cgraph_used_from_object_file_p (node))) | |
48e3ea52 | 1477 | return false; |
232c9ac7 | 1478 | if (lookup_attribute ("weakref", DECL_ATTRIBUTES (node->decl))) |
1479 | return false; | |
48e3ea52 | 1480 | return true; |
1481 | } | |
1482 | ||
1483 | /* Return true if VNODE should be partitioned. | |
1484 | This means that partitioning algorithm should put VNODE into one of partitions. */ | |
1485 | ||
1486 | static bool | |
1487 | partition_varpool_node_p (struct varpool_node *vnode) | |
1488 | { | |
1489 | if (vnode->alias || !vnode->needed) | |
1490 | return false; | |
1491 | /* Constant pool and comdat are always only in partitions they are needed. */ | |
1492 | if (DECL_IN_CONSTANT_POOL (vnode->decl) | |
7ad28d2a | 1493 | || (DECL_COMDAT (vnode->decl) |
4037a4c1 | 1494 | && !vnode->force_output |
7ad28d2a | 1495 | && !varpool_used_from_object_file_p (vnode))) |
48e3ea52 | 1496 | return false; |
232c9ac7 | 1497 | if (lookup_attribute ("weakref", DECL_ATTRIBUTES (vnode->decl))) |
1498 | return false; | |
48e3ea52 | 1499 | return true; |
1500 | } | |
1501 | ||
7bfefa9d | 1502 | /* Group cgrah nodes by input files. This is used mainly for testing |
1503 | right now. */ | |
1504 | ||
1505 | static void | |
1506 | lto_1_to_1_map (void) | |
1507 | { | |
1508 | struct cgraph_node *node; | |
0cddb138 | 1509 | struct varpool_node *vnode; |
7bfefa9d | 1510 | struct lto_file_decl_data *file_data; |
1511 | struct pointer_map_t *pmap; | |
68b8d829 | 1512 | ltrans_partition partition; |
7bfefa9d | 1513 | void **slot; |
68b8d829 | 1514 | int npartitions = 0; |
7bfefa9d | 1515 | |
1516 | timevar_push (TV_WHOPR_WPA); | |
1517 | ||
7bfefa9d | 1518 | pmap = pointer_map_create (); |
1519 | ||
1520 | for (node = cgraph_nodes; node; node = node->next) | |
1521 | { | |
e71f2f1c | 1522 | if (!partition_cgraph_node_p (node) |
1523 | || node->aux) | |
7550e1d1 | 1524 | continue; |
25429dc2 | 1525 | |
7bfefa9d | 1526 | file_data = node->local.lto_file_data; |
7bfefa9d | 1527 | |
c5cc4842 | 1528 | if (file_data) |
1529 | { | |
1530 | slot = pointer_map_contains (pmap, file_data); | |
1531 | if (slot) | |
1532 | partition = (ltrans_partition) *slot; | |
1533 | else | |
1534 | { | |
1535 | partition = new_partition (file_data->file_name); | |
1536 | slot = pointer_map_insert (pmap, file_data); | |
1537 | *slot = partition; | |
1538 | npartitions++; | |
1539 | } | |
1540 | } | |
1541 | else if (!file_data | |
1542 | && VEC_length (ltrans_partition, ltrans_partitions)) | |
1543 | partition = VEC_index (ltrans_partition, ltrans_partitions, 0); | |
7bfefa9d | 1544 | else |
1545 | { | |
c5cc4842 | 1546 | partition = new_partition (""); |
1547 | slot = pointer_map_insert (pmap, NULL); | |
68b8d829 | 1548 | *slot = partition; |
1549 | npartitions++; | |
7bfefa9d | 1550 | } |
1551 | ||
e71f2f1c | 1552 | add_cgraph_node_to_partition (partition, node); |
7bfefa9d | 1553 | } |
1554 | ||
0cddb138 | 1555 | for (vnode = varpool_nodes; vnode; vnode = vnode->next) |
1556 | { | |
e71f2f1c | 1557 | if (!partition_varpool_node_p (vnode) |
1558 | || vnode->aux) | |
7550e1d1 | 1559 | continue; |
fab8a209 | 1560 | file_data = vnode->lto_file_data; |
68b8d829 | 1561 | slot = pointer_map_contains (pmap, file_data); |
0cddb138 | 1562 | if (slot) |
68b8d829 | 1563 | partition = (ltrans_partition) *slot; |
0cddb138 | 1564 | else |
1565 | { | |
68b8d829 | 1566 | partition = new_partition (file_data->file_name); |
0cddb138 | 1567 | slot = pointer_map_insert (pmap, file_data); |
68b8d829 | 1568 | *slot = partition; |
1569 | npartitions++; | |
0cddb138 | 1570 | } |
1571 | ||
e71f2f1c | 1572 | add_varpool_node_to_partition (partition, vnode); |
0cddb138 | 1573 | } |
7550e1d1 | 1574 | for (node = cgraph_nodes; node; node = node->next) |
1575 | node->aux = NULL; | |
1576 | for (vnode = varpool_nodes; vnode; vnode = vnode->next) | |
1577 | vnode->aux = NULL; | |
0cddb138 | 1578 | |
1579 | /* If the cgraph is empty, create one cgraph node set so that there is still | |
1580 | an output file for any variables that need to be exported in a DSO. */ | |
68b8d829 | 1581 | if (!npartitions) |
1582 | new_partition ("empty"); | |
0cddb138 | 1583 | |
7bfefa9d | 1584 | pointer_map_destroy (pmap); |
1585 | ||
7bfefa9d | 1586 | timevar_pop (TV_WHOPR_WPA); |
1587 | ||
68b8d829 | 1588 | lto_stats.num_cgraph_partitions += VEC_length (ltrans_partition, |
1589 | ltrans_partitions); | |
7bfefa9d | 1590 | } |
1591 | ||
48e3ea52 | 1592 | |
b630a10e | 1593 | /* Group cgraph nodes into equally-sized partitions. |
48e3ea52 | 1594 | |
b630a10e | 1595 | The partitioning algorithm is simple: nodes are taken in predefined order. |
1596 | The order corresponds to the order we want functions to have in the final | |
1597 | output. In the future this will be given by function reordering pass, but | |
1598 | at the moment we use the topological order, which is a good approximation. | |
48e3ea52 | 1599 | |
b630a10e | 1600 | The goal is to partition this linear order into intervals (partitions) so |
1601 | that all the partitions have approximately the same size and the number of | |
1602 | callgraph or IPA reference edges crossing boundaries is minimal. | |
48e3ea52 | 1603 | |
1604 | This is a lot faster (O(n) in size of callgraph) than algorithms doing | |
b630a10e | 1605 | priority-based graph clustering that are generally O(n^2) and, since |
1606 | WHOPR is designed to make things go well across partitions, it leads | |
1607 | to good results. | |
1608 | ||
1609 | We compute the expected size of a partition as: | |
1610 | ||
1611 | max (total_size / lto_partitions, min_partition_size) | |
1612 | ||
1613 | We use dynamic expected size of partition so small programs are partitioned | |
1614 | into enough partitions to allow use of multiple CPUs, while large programs | |
1615 | are not partitioned too much. Creating too many partitions significantly | |
1616 | increases the streaming overhead. | |
1617 | ||
1618 | In the future, we would like to bound the maximal size of partitions so as | |
1619 | to prevent the LTRANS stage from consuming too much memory. At the moment, | |
1620 | however, the WPA stage is the most memory intensive for large benchmarks, | |
1621 | since too many types and declarations are read into memory. | |
1622 | ||
1623 | The function implements a simple greedy algorithm. Nodes are being added | |
1624 | to the current partition until after 3/4 of the expected partition size is | |
1625 | reached. Past this threshold, we keep track of boundary size (number of | |
1626 | edges going to other partitions) and continue adding functions until after | |
1627 | the current partition has grown to twice the expected partition size. Then | |
1628 | the process is undone to the point where the minimal ratio of boundary size | |
1629 | and in-partition calls was reached. */ | |
48e3ea52 | 1630 | |
1631 | static void | |
1632 | lto_balanced_map (void) | |
1633 | { | |
1634 | int n_nodes = 0; | |
1635 | struct cgraph_node **postorder = | |
1636 | XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); | |
1637 | struct cgraph_node **order = XNEWVEC (struct cgraph_node *, cgraph_max_uid); | |
1638 | int i, postorder_len; | |
1639 | struct cgraph_node *node; | |
1e52cb3c | 1640 | int total_size = 0, best_total_size = 0; |
48e3ea52 | 1641 | int partition_size; |
1642 | ltrans_partition partition; | |
1643 | unsigned int last_visited_cgraph_node = 0, last_visited_varpool_node = 0; | |
1644 | struct varpool_node *vnode; | |
1645 | int cost = 0, internal = 0; | |
1646 | int best_n_nodes = 0, best_n_varpool_nodes = 0, best_i = 0, best_cost = | |
1647 | INT_MAX, best_internal = 0; | |
1648 | int npartitions; | |
1649 | ||
4037a4c1 | 1650 | for (vnode = varpool_nodes; vnode; vnode = vnode->next) |
1651 | gcc_assert (!vnode->aux); | |
48e3ea52 | 1652 | /* Until we have better ordering facility, use toplogical order. |
1653 | Include only nodes we will partition and compute estimate of program | |
1654 | size. Note that since nodes that are not partitioned might be put into | |
1655 | multiple partitions, this is just an estimate of real size. This is why | |
1656 | we keep partition_size updated after every partition is finalized. */ | |
7771d558 | 1657 | postorder_len = ipa_reverse_postorder (postorder); |
48e3ea52 | 1658 | for (i = 0; i < postorder_len; i++) |
1659 | { | |
1660 | node = postorder[i]; | |
1661 | if (partition_cgraph_node_p (node)) | |
1662 | { | |
1663 | order[n_nodes++] = node; | |
cbd7f5a0 | 1664 | total_size += inline_summary (node)->size; |
48e3ea52 | 1665 | } |
1666 | } | |
1667 | free (postorder); | |
1668 | ||
1669 | /* Compute partition size and create the first partition. */ | |
1670 | partition_size = total_size / PARAM_VALUE (PARAM_LTO_PARTITIONS); | |
1671 | if (partition_size < PARAM_VALUE (MIN_PARTITION_SIZE)) | |
1672 | partition_size = PARAM_VALUE (MIN_PARTITION_SIZE); | |
1673 | npartitions = 1; | |
1674 | partition = new_partition (""); | |
1675 | if (cgraph_dump_file) | |
1676 | fprintf (cgraph_dump_file, "Total unit size: %i, partition size: %i\n", | |
1677 | total_size, partition_size); | |
1678 | ||
1679 | for (i = 0; i < n_nodes; i++) | |
1680 | { | |
e71f2f1c | 1681 | if (order[i]->aux) |
1682 | continue; | |
1683 | add_cgraph_node_to_partition (partition, order[i]); | |
cbd7f5a0 | 1684 | total_size -= inline_summary (order[i])->size; |
48e3ea52 | 1685 | |
1686 | /* Once we added a new node to the partition, we also want to add | |
1687 | all referenced variables unless they was already added into some | |
1688 | earlier partition. | |
1689 | add_cgraph_node_to_partition adds possibly multiple nodes and | |
1690 | variables that are needed to satisfy needs of ORDER[i]. | |
1691 | We remember last visited cgraph and varpool node from last iteration | |
1692 | of outer loop that allows us to process every new addition. | |
1693 | ||
1694 | At the same time we compute size of the boundary into COST. Every | |
1695 | callgraph or IPA reference edge leaving the partition contributes into | |
1696 | COST. Every edge inside partition was earlier computed as one leaving | |
1697 | it and thus we need to subtract it from COST. */ | |
1698 | while (last_visited_cgraph_node < | |
1699 | VEC_length (cgraph_node_ptr, partition->cgraph_set->nodes) | |
1700 | || last_visited_varpool_node < VEC_length (varpool_node_ptr, | |
1701 | partition->varpool_set-> | |
1702 | nodes)) | |
1703 | { | |
1704 | struct ipa_ref_list *refs; | |
1705 | int j; | |
1706 | struct ipa_ref *ref; | |
1707 | bool cgraph_p = false; | |
1708 | ||
1709 | if (last_visited_cgraph_node < | |
1710 | VEC_length (cgraph_node_ptr, partition->cgraph_set->nodes)) | |
1711 | { | |
1712 | struct cgraph_edge *edge; | |
1713 | ||
1714 | cgraph_p = true; | |
1715 | node = VEC_index (cgraph_node_ptr, partition->cgraph_set->nodes, | |
1716 | last_visited_cgraph_node); | |
1717 | refs = &node->ref_list; | |
1718 | ||
48e3ea52 | 1719 | last_visited_cgraph_node++; |
1720 | ||
1721 | gcc_assert (node->analyzed); | |
1722 | ||
1723 | /* Compute boundary cost of callgrpah edges. */ | |
1724 | for (edge = node->callees; edge; edge = edge->next_callee) | |
1725 | if (edge->callee->analyzed) | |
1726 | { | |
1727 | int edge_cost = edge->frequency; | |
1728 | cgraph_node_set_iterator csi; | |
1729 | ||
1730 | if (!edge_cost) | |
1731 | edge_cost = 1; | |
1732 | gcc_assert (edge_cost > 0); | |
1733 | csi = cgraph_node_set_find (partition->cgraph_set, edge->callee); | |
1734 | if (!csi_end_p (csi) | |
1735 | && csi.index < last_visited_cgraph_node - 1) | |
1736 | cost -= edge_cost, internal+= edge_cost; | |
1737 | else | |
1738 | cost += edge_cost; | |
1739 | } | |
1740 | for (edge = node->callers; edge; edge = edge->next_caller) | |
1741 | { | |
1742 | int edge_cost = edge->frequency; | |
1743 | cgraph_node_set_iterator csi; | |
1744 | ||
1745 | gcc_assert (edge->caller->analyzed); | |
1746 | if (!edge_cost) | |
1747 | edge_cost = 1; | |
1748 | gcc_assert (edge_cost > 0); | |
1749 | csi = cgraph_node_set_find (partition->cgraph_set, edge->caller); | |
1750 | if (!csi_end_p (csi) | |
1751 | && csi.index < last_visited_cgraph_node) | |
1752 | cost -= edge_cost; | |
1753 | else | |
1754 | cost += edge_cost; | |
1755 | } | |
1756 | } | |
1757 | else | |
1758 | { | |
1759 | refs = | |
1760 | &VEC_index (varpool_node_ptr, partition->varpool_set->nodes, | |
1761 | last_visited_varpool_node)->ref_list; | |
1762 | last_visited_varpool_node++; | |
1763 | } | |
1764 | ||
1765 | /* Compute boundary cost of IPA REF edges and at the same time look into | |
1766 | variables referenced from current partition and try to add them. */ | |
1767 | for (j = 0; ipa_ref_list_reference_iterate (refs, j, ref); j++) | |
1768 | if (ref->refered_type == IPA_REF_VARPOOL) | |
1769 | { | |
1770 | varpool_node_set_iterator vsi; | |
1771 | ||
1772 | vnode = ipa_ref_varpool_node (ref); | |
1773 | if (!vnode->finalized) | |
1774 | continue; | |
1775 | if (!vnode->aux && partition_varpool_node_p (vnode)) | |
1776 | add_varpool_node_to_partition (partition, vnode); | |
1777 | vsi = varpool_node_set_find (partition->varpool_set, vnode); | |
1778 | if (!vsi_end_p (vsi) | |
1779 | && vsi.index < last_visited_varpool_node - !cgraph_p) | |
1780 | cost--, internal++; | |
1781 | else | |
1782 | cost++; | |
1783 | } | |
1784 | else | |
1785 | { | |
1786 | cgraph_node_set_iterator csi; | |
1787 | ||
1788 | node = ipa_ref_node (ref); | |
1789 | if (!node->analyzed) | |
1790 | continue; | |
1791 | csi = cgraph_node_set_find (partition->cgraph_set, node); | |
1792 | if (!csi_end_p (csi) | |
1793 | && csi.index < last_visited_cgraph_node - cgraph_p) | |
1794 | cost--, internal++; | |
1795 | else | |
1796 | cost++; | |
1797 | } | |
1798 | for (j = 0; ipa_ref_list_refering_iterate (refs, j, ref); j++) | |
1799 | if (ref->refering_type == IPA_REF_VARPOOL) | |
1800 | { | |
1801 | varpool_node_set_iterator vsi; | |
1802 | ||
1803 | vnode = ipa_ref_refering_varpool_node (ref); | |
1804 | gcc_assert (vnode->finalized); | |
1805 | if (!vnode->aux && partition_varpool_node_p (vnode)) | |
1806 | add_varpool_node_to_partition (partition, vnode); | |
1807 | vsi = varpool_node_set_find (partition->varpool_set, vnode); | |
1808 | if (!vsi_end_p (vsi) | |
1809 | && vsi.index < last_visited_varpool_node) | |
1810 | cost--; | |
1811 | else | |
1812 | cost++; | |
1813 | } | |
1814 | else | |
1815 | { | |
1816 | cgraph_node_set_iterator csi; | |
1817 | ||
1818 | node = ipa_ref_refering_node (ref); | |
1819 | gcc_assert (node->analyzed); | |
1820 | csi = cgraph_node_set_find (partition->cgraph_set, node); | |
1821 | if (!csi_end_p (csi) | |
1822 | && csi.index < last_visited_cgraph_node) | |
1823 | cost--; | |
1824 | else | |
1825 | cost++; | |
1826 | } | |
1827 | } | |
1828 | ||
1829 | /* If the partition is large enough, start looking for smallest boundary cost. */ | |
1830 | if (partition->insns < partition_size * 3 / 4 | |
1831 | || best_cost == INT_MAX | |
1832 | || ((!cost | |
1833 | || (best_internal * (HOST_WIDE_INT) cost | |
1834 | > (internal * (HOST_WIDE_INT)best_cost))) | |
1835 | && partition->insns < partition_size * 5 / 4)) | |
1836 | { | |
1837 | best_cost = cost; | |
1838 | best_internal = internal; | |
1839 | best_i = i; | |
1840 | best_n_nodes = VEC_length (cgraph_node_ptr, | |
1841 | partition->cgraph_set->nodes); | |
1842 | best_n_varpool_nodes = VEC_length (varpool_node_ptr, | |
1843 | partition->varpool_set->nodes); | |
1e52cb3c | 1844 | best_total_size = total_size; |
48e3ea52 | 1845 | } |
1846 | if (cgraph_dump_file) | |
4037a4c1 | 1847 | fprintf (cgraph_dump_file, "Step %i: added %s/%i, size %i, cost %i/%i best %i/%i, step %i\n", i, |
1848 | cgraph_node_name (order[i]), order[i]->uid, partition->insns, cost, internal, | |
48e3ea52 | 1849 | best_cost, best_internal, best_i); |
1850 | /* Partition is too large, unwind into step when best cost was reached and | |
1851 | start new partition. */ | |
1852 | if (partition->insns > 2 * partition_size) | |
1853 | { | |
1854 | if (best_i != i) | |
1855 | { | |
1856 | if (cgraph_dump_file) | |
1857 | fprintf (cgraph_dump_file, "Unwinding %i insertions to step %i\n", | |
1858 | i - best_i, best_i); | |
1859 | undo_partition (partition, best_n_nodes, best_n_varpool_nodes); | |
1860 | } | |
1861 | i = best_i; | |
11da9120 | 1862 | /* When we are finished, avoid creating empty partition. */ |
e71f2f1c | 1863 | while (i < n_nodes - 1 && order[i + 1]->aux) |
1864 | i++; | |
11da9120 | 1865 | if (i == n_nodes - 1) |
1866 | break; | |
48e3ea52 | 1867 | partition = new_partition (""); |
1868 | last_visited_cgraph_node = 0; | |
1869 | last_visited_varpool_node = 0; | |
1e52cb3c | 1870 | total_size = best_total_size; |
48e3ea52 | 1871 | cost = 0; |
1872 | ||
1873 | if (cgraph_dump_file) | |
1874 | fprintf (cgraph_dump_file, "New partition\n"); | |
1875 | best_n_nodes = 0; | |
1876 | best_n_varpool_nodes = 0; | |
1877 | best_cost = INT_MAX; | |
1878 | ||
1879 | /* Since the size of partitions is just approximate, update the size after | |
1880 | we finished current one. */ | |
1881 | if (npartitions < PARAM_VALUE (PARAM_LTO_PARTITIONS)) | |
1882 | partition_size = total_size | |
1883 | / (PARAM_VALUE (PARAM_LTO_PARTITIONS) - npartitions); | |
1884 | else | |
1885 | partition_size = INT_MAX; | |
1886 | ||
1887 | if (partition_size < PARAM_VALUE (MIN_PARTITION_SIZE)) | |
1888 | partition_size = PARAM_VALUE (MIN_PARTITION_SIZE); | |
1889 | npartitions ++; | |
1890 | } | |
1891 | } | |
1892 | ||
1893 | /* Varables that are not reachable from the code go into last partition. */ | |
1894 | for (vnode = varpool_nodes; vnode; vnode = vnode->next) | |
1895 | if (partition_varpool_node_p (vnode) && !vnode->aux) | |
1896 | add_varpool_node_to_partition (partition, vnode); | |
1897 | free (order); | |
1898 | } | |
1899 | ||
e5507c85 | 1900 | /* Promote variable VNODE to be static. */ |
1901 | ||
1902 | static bool | |
1903 | promote_var (struct varpool_node *vnode) | |
1904 | { | |
1905 | if (TREE_PUBLIC (vnode->decl) || DECL_EXTERNAL (vnode->decl)) | |
1906 | return false; | |
1907 | gcc_assert (flag_wpa); | |
1908 | TREE_PUBLIC (vnode->decl) = 1; | |
1909 | DECL_VISIBILITY (vnode->decl) = VISIBILITY_HIDDEN; | |
be147e7f | 1910 | DECL_VISIBILITY_SPECIFIED (vnode->decl) = true; |
ecb08119 | 1911 | if (cgraph_dump_file) |
1912 | fprintf (cgraph_dump_file, | |
1913 | "Promoting var as hidden: %s\n", varpool_node_name (vnode)); | |
e5507c85 | 1914 | return true; |
1915 | } | |
1916 | ||
1917 | /* Promote function NODE to be static. */ | |
1918 | ||
1919 | static bool | |
1920 | promote_fn (struct cgraph_node *node) | |
1921 | { | |
1922 | gcc_assert (flag_wpa); | |
1923 | if (TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)) | |
1924 | return false; | |
1925 | TREE_PUBLIC (node->decl) = 1; | |
1926 | DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN; | |
be147e7f | 1927 | DECL_VISIBILITY_SPECIFIED (node->decl) = true; |
ecb08119 | 1928 | if (cgraph_dump_file) |
1929 | fprintf (cgraph_dump_file, | |
1930 | "Promoting function as hidden: %s/%i\n", | |
1931 | cgraph_node_name (node), node->uid); | |
e5507c85 | 1932 | return true; |
1933 | } | |
1934 | ||
7bfefa9d | 1935 | /* Find out all static decls that need to be promoted to global because |
1936 | of cross file sharing. This function must be run in the WPA mode after | |
1937 | all inlinees are added. */ | |
1938 | ||
1939 | static void | |
1940 | lto_promote_cross_file_statics (void) | |
1941 | { | |
0cddb138 | 1942 | struct varpool_node *vnode; |
7bfefa9d | 1943 | unsigned i, n_sets; |
1944 | cgraph_node_set set; | |
8d810329 | 1945 | varpool_node_set vset; |
7bfefa9d | 1946 | cgraph_node_set_iterator csi; |
8d810329 | 1947 | varpool_node_set_iterator vsi; |
e5507c85 | 1948 | VEC(varpool_node_ptr, heap) *promoted_initializers = NULL; |
1949 | struct pointer_set_t *inserted = pointer_set_create (); | |
7bfefa9d | 1950 | |
0cddb138 | 1951 | gcc_assert (flag_wpa); |
7bfefa9d | 1952 | |
68b8d829 | 1953 | n_sets = VEC_length (ltrans_partition, ltrans_partitions); |
7bfefa9d | 1954 | for (i = 0; i < n_sets; i++) |
1955 | { | |
b630a10e | 1956 | ltrans_partition part |
1957 | = VEC_index (ltrans_partition, ltrans_partitions, i); | |
68b8d829 | 1958 | set = part->cgraph_set; |
1959 | vset = part->varpool_set; | |
7bfefa9d | 1960 | |
c70f46b0 | 1961 | /* If node called or referred to from other partition, it needs to be |
1962 | globalized. */ | |
7bfefa9d | 1963 | for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) |
0cddb138 | 1964 | { |
1965 | struct cgraph_node *node = csi_node (csi); | |
0cddb138 | 1966 | if (node->local.externally_visible) |
1967 | continue; | |
a510bd8d | 1968 | if (node->global.inlined_to) |
25429dc2 | 1969 | continue; |
7550e1d1 | 1970 | if ((!DECL_EXTERNAL (node->decl) && !DECL_COMDAT (node->decl)) |
25429dc2 | 1971 | && (referenced_from_other_partition_p (&node->ref_list, set, vset) |
1972 | || reachable_from_other_partition_p (node, set))) | |
e5507c85 | 1973 | promote_fn (node); |
0cddb138 | 1974 | } |
8d810329 | 1975 | for (vsi = vsi_start (vset); !vsi_end_p (vsi); vsi_next (&vsi)) |
1976 | { | |
1977 | vnode = vsi_node (vsi); | |
1978 | /* Constant pool references use internal labels and thus can not | |
1979 | be made global. It is sensible to keep those ltrans local to | |
1980 | allow better optimization. */ | |
7550e1d1 | 1981 | if (!DECL_IN_CONSTANT_POOL (vnode->decl) && !DECL_COMDAT (vnode->decl) |
1982 | && !vnode->externally_visible && vnode->analyzed | |
1983 | && referenced_from_other_partition_p (&vnode->ref_list, | |
1984 | set, vset)) | |
e5507c85 | 1985 | promote_var (vnode); |
1986 | } | |
1987 | ||
b630a10e | 1988 | /* We export the initializer of a read-only var into each partition |
1989 | referencing the var. Folding might take declarations from the | |
1990 | initializer and use them, so everything referenced from the | |
1991 | initializer can be accessed from this partition after folding. | |
e5507c85 | 1992 | |
1993 | This means that we need to promote all variables and functions | |
b630a10e | 1994 | referenced from all initializers of read-only vars referenced |
1995 | from this partition that are not in this partition. This needs | |
1996 | to be done recursively. */ | |
e5507c85 | 1997 | for (vnode = varpool_nodes; vnode; vnode = vnode->next) |
7ae8b539 | 1998 | if (const_value_known_p (vnode->decl) |
e5507c85 | 1999 | && DECL_INITIAL (vnode->decl) |
2000 | && !varpool_node_in_set_p (vnode, vset) | |
2001 | && referenced_from_this_partition_p (&vnode->ref_list, set, vset) | |
2002 | && !pointer_set_insert (inserted, vnode)) | |
2003 | VEC_safe_push (varpool_node_ptr, heap, promoted_initializers, vnode); | |
b630a10e | 2004 | |
e5507c85 | 2005 | while (!VEC_empty (varpool_node_ptr, promoted_initializers)) |
2006 | { | |
2007 | int i; | |
2008 | struct ipa_ref *ref; | |
2009 | ||
2010 | vnode = VEC_pop (varpool_node_ptr, promoted_initializers); | |
b630a10e | 2011 | for (i = 0; |
2012 | ipa_ref_list_reference_iterate (&vnode->ref_list, i, ref); | |
2013 | i++) | |
8d810329 | 2014 | { |
e5507c85 | 2015 | if (ref->refered_type == IPA_REF_CGRAPH) |
2016 | { | |
2017 | struct cgraph_node *n = ipa_ref_node (ref); | |
2018 | gcc_assert (!n->global.inlined_to); | |
2019 | if (!n->local.externally_visible | |
2020 | && !cgraph_node_in_set_p (n, set)) | |
2021 | promote_fn (n); | |
2022 | } | |
2023 | else | |
2024 | { | |
2025 | struct varpool_node *v = ipa_ref_varpool_node (ref); | |
2026 | if (varpool_node_in_set_p (v, vset)) | |
2027 | continue; | |
b630a10e | 2028 | |
2029 | /* Constant pool references use internal labels and thus | |
2030 | cannot be made global. It is sensible to keep those | |
2031 | ltrans local to allow better optimization. */ | |
e5507c85 | 2032 | if (DECL_IN_CONSTANT_POOL (v->decl)) |
2033 | { | |
2034 | if (!pointer_set_insert (inserted, vnode)) | |
2035 | VEC_safe_push (varpool_node_ptr, heap, | |
2036 | promoted_initializers, v); | |
2037 | } | |
b630a10e | 2038 | else if (!v->externally_visible && v->analyzed) |
e5507c85 | 2039 | { |
2040 | if (promote_var (v) | |
9ced88d0 | 2041 | && DECL_INITIAL (v->decl) |
2042 | && const_value_known_p (v->decl) | |
e5507c85 | 2043 | && !pointer_set_insert (inserted, vnode)) |
2044 | VEC_safe_push (varpool_node_ptr, heap, | |
2045 | promoted_initializers, v); | |
2046 | } | |
2047 | } | |
8d810329 | 2048 | } |
2049 | } | |
7bfefa9d | 2050 | } |
e5507c85 | 2051 | pointer_set_destroy (inserted); |
7bfefa9d | 2052 | } |
2053 | ||
7bfefa9d | 2054 | static lto_file *current_lto_file; |
2055 | ||
68b8d829 | 2056 | /* Helper for qsort; compare partitions and return one with smaller size. |
2057 | We sort from greatest to smallest so parallel build doesn't stale on the | |
2058 | longest compilation being executed too late. */ | |
2059 | ||
2060 | static int | |
2061 | cmp_partitions (const void *a, const void *b) | |
2062 | { | |
2063 | const struct ltrans_partition_def *pa | |
2064 | = *(struct ltrans_partition_def *const *)a; | |
2065 | const struct ltrans_partition_def *pb | |
2066 | = *(struct ltrans_partition_def *const *)b; | |
2067 | return pb->insns - pa->insns; | |
2068 | } | |
7bfefa9d | 2069 | |
2024fa7d | 2070 | /* Write all output files in WPA mode and the file with the list of |
2071 | LTRANS units. */ | |
7bfefa9d | 2072 | |
2024fa7d | 2073 | static void |
7bfefa9d | 2074 | lto_wpa_write_files (void) |
2075 | { | |
2024fa7d | 2076 | unsigned i, n_sets; |
7bfefa9d | 2077 | lto_file *file; |
2078 | cgraph_node_set set; | |
0cddb138 | 2079 | varpool_node_set vset; |
68b8d829 | 2080 | ltrans_partition part; |
2024fa7d | 2081 | FILE *ltrans_output_list_stream; |
2082 | char *temp_filename; | |
2083 | size_t blen; | |
2084 | ||
2085 | /* Open the LTRANS output list. */ | |
2086 | if (!ltrans_output_list) | |
2087 | fatal_error ("no LTRANS output list filename provided"); | |
2088 | ltrans_output_list_stream = fopen (ltrans_output_list, "w"); | |
2089 | if (ltrans_output_list_stream == NULL) | |
2090 | fatal_error ("opening LTRANS output list %s: %m", ltrans_output_list); | |
7bfefa9d | 2091 | |
2092 | timevar_push (TV_WHOPR_WPA); | |
2093 | ||
48148244 | 2094 | FOR_EACH_VEC_ELT (ltrans_partition, ltrans_partitions, i, part) |
68b8d829 | 2095 | lto_stats.num_output_cgraph_nodes += VEC_length (cgraph_node_ptr, |
2096 | part->cgraph_set->nodes); | |
7bfefa9d | 2097 | |
c5cc4842 | 2098 | /* Find out statics that need to be promoted |
2099 | to globals with hidden visibility because they are accessed from multiple | |
2100 | partitions. */ | |
7bfefa9d | 2101 | lto_promote_cross_file_statics (); |
2102 | ||
2103 | timevar_pop (TV_WHOPR_WPA); | |
2104 | ||
2105 | timevar_push (TV_WHOPR_WPA_IO); | |
2106 | ||
2024fa7d | 2107 | /* Generate a prefix for the LTRANS unit files. */ |
2108 | blen = strlen (ltrans_output_list); | |
2109 | temp_filename = (char *) xmalloc (blen + sizeof ("2147483648.o")); | |
2110 | strcpy (temp_filename, ltrans_output_list); | |
2111 | if (blen > sizeof (".out") | |
2112 | && strcmp (temp_filename + blen - sizeof (".out") + 1, | |
2113 | ".out") == 0) | |
2114 | temp_filename[blen - sizeof (".out") + 1] = '\0'; | |
2115 | blen = strlen (temp_filename); | |
7bfefa9d | 2116 | |
68b8d829 | 2117 | n_sets = VEC_length (ltrans_partition, ltrans_partitions); |
75510792 | 2118 | VEC_qsort (ltrans_partition, ltrans_partitions, cmp_partitions); |
7bfefa9d | 2119 | for (i = 0; i < n_sets; i++) |
2120 | { | |
2024fa7d | 2121 | size_t len; |
68b8d829 | 2122 | ltrans_partition part = VEC_index (ltrans_partition, ltrans_partitions, i); |
7bfefa9d | 2123 | |
68b8d829 | 2124 | set = part->cgraph_set; |
2125 | vset = part->varpool_set; | |
7bfefa9d | 2126 | |
2024fa7d | 2127 | /* Write all the nodes in SET. */ |
2128 | sprintf (temp_filename + blen, "%u.o", i); | |
2129 | file = lto_obj_file_open (temp_filename, true); | |
2130 | if (!file) | |
2131 | fatal_error ("lto_obj_file_open() failed"); | |
7bfefa9d | 2132 | |
2024fa7d | 2133 | if (!quiet_flag) |
68b8d829 | 2134 | fprintf (stderr, " %s (%s %i insns)", temp_filename, part->name, part->insns); |
ecb08119 | 2135 | if (cgraph_dump_file) |
2136 | { | |
d534cab0 | 2137 | fprintf (cgraph_dump_file, "Writing partition %s to file %s, %i insns\n", |
ecb08119 | 2138 | part->name, temp_filename, part->insns); |
2139 | fprintf (cgraph_dump_file, "cgraph nodes:"); | |
2140 | dump_cgraph_node_set (cgraph_dump_file, set); | |
2141 | fprintf (cgraph_dump_file, "varpool nodes:"); | |
2142 | dump_varpool_node_set (cgraph_dump_file, vset); | |
2143 | } | |
d45127a1 | 2144 | gcc_checking_assert (cgraph_node_set_nonempty_p (set) |
2145 | || varpool_node_set_nonempty_p (vset) || !i); | |
7bfefa9d | 2146 | |
2024fa7d | 2147 | lto_set_current_out_file (file); |
264cbb51 | 2148 | |
2024fa7d | 2149 | ipa_write_optimization_summaries (set, vset); |
7bfefa9d | 2150 | |
2024fa7d | 2151 | lto_set_current_out_file (NULL); |
2152 | lto_obj_file_close (file); | |
7bfefa9d | 2153 | |
2024fa7d | 2154 | len = strlen (temp_filename); |
2155 | if (fwrite (temp_filename, 1, len, ltrans_output_list_stream) < len | |
264cbb51 | 2156 | || fwrite ("\n", 1, 1, ltrans_output_list_stream) < 1) |
2024fa7d | 2157 | fatal_error ("writing to LTRANS output list %s: %m", |
2158 | ltrans_output_list); | |
7bfefa9d | 2159 | } |
2160 | ||
2024fa7d | 2161 | lto_stats.num_output_files += n_sets; |
2162 | ||
7bfefa9d | 2163 | /* Close the LTRANS output list. */ |
264cbb51 | 2164 | if (fclose (ltrans_output_list_stream)) |
2024fa7d | 2165 | fatal_error ("closing LTRANS output list %s: %m", ltrans_output_list); |
2166 | ||
19ad01f7 | 2167 | free_ltrans_partitions(); |
2168 | ||
2024fa7d | 2169 | timevar_pop (TV_WHOPR_WPA_IO); |
7bfefa9d | 2170 | } |
2171 | ||
2172 | ||
d534cab0 | 2173 | /* If TT is a variable or function decl replace it with its |
2174 | prevailing variant. */ | |
2175 | #define LTO_SET_PREVAIL(tt) \ | |
2176 | do {\ | |
2177 | if ((tt) && VAR_OR_FUNCTION_DECL_P (tt)) \ | |
2178 | tt = lto_symtab_prevailing_decl (tt); \ | |
2179 | } while (0) | |
7bfefa9d | 2180 | |
d534cab0 | 2181 | /* Ensure that TT isn't a replacable var of function decl. */ |
2182 | #define LTO_NO_PREVAIL(tt) \ | |
2183 | gcc_assert (!(tt) || !VAR_OR_FUNCTION_DECL_P (tt)) | |
7bfefa9d | 2184 | |
d534cab0 | 2185 | /* Given a tree T replace all fields referring to variables or functions |
2186 | with their prevailing variant. */ | |
7bfefa9d | 2187 | static void |
d534cab0 | 2188 | lto_fixup_prevailing_decls (tree t) |
7bfefa9d | 2189 | { |
d534cab0 | 2190 | enum tree_code code = TREE_CODE (t); |
2191 | LTO_NO_PREVAIL (TREE_TYPE (t)); | |
1e184c62 | 2192 | if (CODE_CONTAINS_STRUCT (code, TS_COMMON)) |
2193 | LTO_NO_PREVAIL (TREE_CHAIN (t)); | |
d534cab0 | 2194 | if (DECL_P (t)) |
7bfefa9d | 2195 | { |
d534cab0 | 2196 | LTO_NO_PREVAIL (DECL_NAME (t)); |
2197 | LTO_SET_PREVAIL (DECL_CONTEXT (t)); | |
2198 | if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) | |
7bfefa9d | 2199 | { |
d534cab0 | 2200 | LTO_SET_PREVAIL (DECL_SIZE (t)); |
2201 | LTO_SET_PREVAIL (DECL_SIZE_UNIT (t)); | |
2202 | LTO_SET_PREVAIL (DECL_INITIAL (t)); | |
2203 | LTO_NO_PREVAIL (DECL_ATTRIBUTES (t)); | |
2204 | LTO_SET_PREVAIL (DECL_ABSTRACT_ORIGIN (t)); | |
7bfefa9d | 2205 | } |
d534cab0 | 2206 | if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) |
7bfefa9d | 2207 | { |
d534cab0 | 2208 | LTO_NO_PREVAIL (t->decl_with_vis.assembler_name); |
2209 | LTO_NO_PREVAIL (DECL_SECTION_NAME (t)); | |
7bfefa9d | 2210 | } |
d534cab0 | 2211 | if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON)) |
7bfefa9d | 2212 | { |
d534cab0 | 2213 | LTO_NO_PREVAIL (DECL_ARGUMENT_FLD (t)); |
2214 | LTO_NO_PREVAIL (DECL_RESULT_FLD (t)); | |
2215 | LTO_NO_PREVAIL (DECL_VINDEX (t)); | |
2216 | } | |
2217 | if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL)) | |
2218 | LTO_SET_PREVAIL (DECL_FUNCTION_PERSONALITY (t)); | |
2219 | if (CODE_CONTAINS_STRUCT (code, TS_FIELD_DECL)) | |
2220 | { | |
2221 | LTO_NO_PREVAIL (DECL_FIELD_OFFSET (t)); | |
2222 | LTO_NO_PREVAIL (DECL_BIT_FIELD_TYPE (t)); | |
2223 | LTO_NO_PREVAIL (DECL_QUALIFIER (t)); | |
2224 | LTO_NO_PREVAIL (DECL_FIELD_BIT_OFFSET (t)); | |
2225 | LTO_NO_PREVAIL (DECL_FCONTEXT (t)); | |
7bfefa9d | 2226 | } |
2227 | } | |
d534cab0 | 2228 | else if (TYPE_P (t)) |
7bfefa9d | 2229 | { |
d534cab0 | 2230 | LTO_NO_PREVAIL (TYPE_CACHED_VALUES (t)); |
2231 | LTO_SET_PREVAIL (TYPE_SIZE (t)); | |
2232 | LTO_SET_PREVAIL (TYPE_SIZE_UNIT (t)); | |
2233 | LTO_NO_PREVAIL (TYPE_ATTRIBUTES (t)); | |
2234 | LTO_NO_PREVAIL (TYPE_NAME (t)); | |
7bfefa9d | 2235 | |
8f2eb9e1 | 2236 | LTO_SET_PREVAIL (TYPE_MINVAL (t)); |
2237 | LTO_SET_PREVAIL (TYPE_MAXVAL (t)); | |
2238 | LTO_SET_PREVAIL (t->type_non_common.binfo); | |
7bfefa9d | 2239 | |
d534cab0 | 2240 | LTO_SET_PREVAIL (TYPE_CONTEXT (t)); |
7bfefa9d | 2241 | |
d534cab0 | 2242 | LTO_NO_PREVAIL (TYPE_CANONICAL (t)); |
2243 | LTO_NO_PREVAIL (TYPE_MAIN_VARIANT (t)); | |
2244 | LTO_NO_PREVAIL (TYPE_NEXT_VARIANT (t)); | |
7bfefa9d | 2245 | } |
d534cab0 | 2246 | else if (EXPR_P (t)) |
7bfefa9d | 2247 | { |
d534cab0 | 2248 | int i; |
2249 | LTO_NO_PREVAIL (t->exp.block); | |
2250 | for (i = TREE_OPERAND_LENGTH (t) - 1; i >= 0; --i) | |
2251 | LTO_SET_PREVAIL (TREE_OPERAND (t, i)); | |
7bfefa9d | 2252 | } |
d534cab0 | 2253 | else |
7bfefa9d | 2254 | { |
d534cab0 | 2255 | switch (code) |
7bfefa9d | 2256 | { |
d534cab0 | 2257 | case TREE_LIST: |
2258 | LTO_SET_PREVAIL (TREE_VALUE (t)); | |
2259 | LTO_SET_PREVAIL (TREE_PURPOSE (t)); | |
2260 | break; | |
2261 | default: | |
2262 | gcc_unreachable (); | |
7bfefa9d | 2263 | } |
2264 | } | |
7bfefa9d | 2265 | } |
d534cab0 | 2266 | #undef LTO_SET_PREVAIL |
2267 | #undef LTO_NO_PREVAIL | |
7bfefa9d | 2268 | |
2269 | /* Helper function of lto_fixup_decls. Walks the var and fn streams in STATE, | |
d534cab0 | 2270 | replaces var and function decls with the corresponding prevailing def. */ |
7bfefa9d | 2271 | |
2272 | static void | |
d534cab0 | 2273 | lto_fixup_state (struct lto_in_decl_state *state) |
7bfefa9d | 2274 | { |
2275 | unsigned i, si; | |
2276 | struct lto_tree_ref_table *table; | |
2277 | ||
2278 | /* Although we only want to replace FUNCTION_DECLs and VAR_DECLs, | |
2279 | we still need to walk from all DECLs to find the reachable | |
2280 | FUNCTION_DECLs and VAR_DECLs. */ | |
2281 | for (si = 0; si < LTO_N_DECL_STREAMS; si++) | |
2282 | { | |
2283 | table = &state->streams[si]; | |
2284 | for (i = 0; i < table->size; i++) | |
d534cab0 | 2285 | { |
2286 | tree *tp = table->trees + i; | |
2287 | if (VAR_OR_FUNCTION_DECL_P (*tp)) | |
2288 | *tp = lto_symtab_prevailing_decl (*tp); | |
2289 | } | |
7bfefa9d | 2290 | } |
2291 | } | |
2292 | ||
d534cab0 | 2293 | /* A callback of htab_traverse. Just extracts a state from SLOT |
2294 | and calls lto_fixup_state. */ | |
7bfefa9d | 2295 | |
2296 | static int | |
d534cab0 | 2297 | lto_fixup_state_aux (void **slot, void *aux ATTRIBUTE_UNUSED) |
7bfefa9d | 2298 | { |
2299 | struct lto_in_decl_state *state = (struct lto_in_decl_state *) *slot; | |
d534cab0 | 2300 | lto_fixup_state (state); |
7bfefa9d | 2301 | return 1; |
2302 | } | |
2303 | ||
7bfefa9d | 2304 | /* Fix the decls from all FILES. Replaces each decl with the corresponding |
2305 | prevailing one. */ | |
2306 | ||
2307 | static void | |
2308 | lto_fixup_decls (struct lto_file_decl_data **files) | |
2309 | { | |
2310 | unsigned int i; | |
d534cab0 | 2311 | htab_iterator hi; |
2312 | tree t; | |
2313 | ||
2314 | FOR_EACH_HTAB_ELEMENT (tree_with_vars, t, tree, hi) | |
2315 | lto_fixup_prevailing_decls (t); | |
7bfefa9d | 2316 | |
7bfefa9d | 2317 | for (i = 0; files[i]; i++) |
2318 | { | |
2319 | struct lto_file_decl_data *file = files[i]; | |
2320 | struct lto_in_decl_state *state = file->global_decl_state; | |
d534cab0 | 2321 | lto_fixup_state (state); |
7bfefa9d | 2322 | |
d534cab0 | 2323 | htab_traverse (file->function_decl_states, lto_fixup_state_aux, NULL); |
7bfefa9d | 2324 | } |
7bfefa9d | 2325 | } |
2326 | ||
7bfefa9d | 2327 | /* Read the options saved from each file in the command line. Called |
2328 | from lang_hooks.post_options which is called by process_options | |
2329 | right before all the options are used to initialize the compiler. | |
2330 | This assumes that decode_options has already run, so the | |
2331 | num_in_fnames and in_fnames are properly set. | |
2332 | ||
2333 | Note that this assumes that all the files had been compiled with | |
2334 | the same options, which is not a good assumption. In general, | |
2335 | options ought to be read from all the files in the set and merged. | |
2336 | However, it is still unclear what the merge rules should be. */ | |
2337 | ||
2338 | void | |
2339 | lto_read_all_file_options (void) | |
2340 | { | |
2341 | size_t i; | |
2342 | ||
2343 | /* Clear any file options currently saved. */ | |
2344 | lto_clear_file_options (); | |
2345 | ||
2346 | /* Set the hooks to read ELF sections. */ | |
2347 | lto_set_in_hooks (NULL, get_section_data, free_section_data); | |
68b8d829 | 2348 | if (!quiet_flag) |
2349 | fprintf (stderr, "Reading command line options:"); | |
7bfefa9d | 2350 | |
2351 | for (i = 0; i < num_in_fnames; i++) | |
2352 | { | |
2353 | struct lto_file_decl_data *file_data; | |
3ba0ce47 | 2354 | lto_file *file = lto_obj_file_open (in_fnames[i], false); |
7bfefa9d | 2355 | if (!file) |
2356 | break; | |
68b8d829 | 2357 | if (!quiet_flag) |
2358 | { | |
2359 | fprintf (stderr, " %s", in_fnames[i]); | |
2360 | fflush (stderr); | |
2361 | } | |
7bfefa9d | 2362 | |
2363 | file_data = XCNEW (struct lto_file_decl_data); | |
2364 | file_data->file_name = file->filename; | |
3ba0ce47 | 2365 | file_data->section_hash_table = lto_obj_build_section_table (file); |
7bfefa9d | 2366 | |
2367 | lto_read_file_options (file_data); | |
2368 | ||
3ba0ce47 | 2369 | lto_obj_file_close (file); |
7bfefa9d | 2370 | htab_delete (file_data->section_hash_table); |
7bfefa9d | 2371 | free (file_data); |
2372 | } | |
2373 | ||
2edfba82 | 2374 | if (!quiet_flag) |
2375 | fprintf (stderr, "\n"); | |
2376 | ||
7bfefa9d | 2377 | /* Apply globally the options read from all the files. */ |
2378 | lto_reissue_options (); | |
2379 | } | |
2380 | ||
57305941 | 2381 | static GTY((length ("lto_stats.num_input_files + 1"))) struct lto_file_decl_data **all_file_decl_data; |
7bfefa9d | 2382 | |
f18bad33 | 2383 | /* Turn file datas for sub files into a single array, so that they look |
2384 | like separate files for further passes. */ | |
2385 | ||
2386 | static void | |
2387 | lto_flatten_files (struct lto_file_decl_data **orig, int count, int last_file_ix) | |
2388 | { | |
2389 | struct lto_file_decl_data *n, *next; | |
2390 | int i, k; | |
2391 | ||
2392 | lto_stats.num_input_files = count; | |
2393 | all_file_decl_data | |
2394 | = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (count + 1); | |
2395 | /* Set the hooks so that all of the ipa passes can read in their data. */ | |
2396 | lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data); | |
2397 | for (i = 0, k = 0; i < last_file_ix; i++) | |
2398 | { | |
2399 | for (n = orig[i]; n != NULL; n = next) | |
2400 | { | |
2401 | all_file_decl_data[k++] = n; | |
2402 | next = n->next; | |
2403 | n->next = NULL; | |
2404 | } | |
2405 | } | |
2406 | all_file_decl_data[k] = NULL; | |
2407 | gcc_assert (k == count); | |
2408 | } | |
2409 | ||
3210ebe5 | 2410 | /* Input file data before flattening (i.e. splitting them to subfiles to support |
2411 | incremental linking. */ | |
2412 | static int real_file_count; | |
2413 | static GTY((length ("real_file_count + 1"))) struct lto_file_decl_data **real_file_decl_data; | |
2414 | ||
7bfefa9d | 2415 | /* Read all the symbols from the input files FNAMES. NFILES is the |
2416 | number of files requested in the command line. Instantiate a | |
2417 | global call graph by aggregating all the sub-graphs found in each | |
2418 | file. */ | |
2419 | ||
2420 | static void | |
2421 | read_cgraph_and_symbols (unsigned nfiles, const char **fnames) | |
2422 | { | |
2423 | unsigned int i, last_file_ix; | |
7bfefa9d | 2424 | FILE *resolution; |
fd193bcd | 2425 | struct cgraph_node *node; |
f18bad33 | 2426 | int count = 0; |
2427 | struct lto_file_decl_data **decl_data; | |
7bfefa9d | 2428 | |
01ec0a6c | 2429 | init_cgraph (); |
7bfefa9d | 2430 | |
e2050933 | 2431 | timevar_push (TV_IPA_LTO_DECL_IN); |
7bfefa9d | 2432 | |
3210ebe5 | 2433 | real_file_decl_data |
2434 | = decl_data = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (nfiles + 1); | |
2435 | real_file_count = nfiles; | |
7bfefa9d | 2436 | |
2437 | /* Read the resolution file. */ | |
2438 | resolution = NULL; | |
2439 | if (resolution_file_name) | |
2440 | { | |
2441 | int t; | |
2442 | unsigned num_objects; | |
2443 | ||
2444 | resolution = fopen (resolution_file_name, "r"); | |
c515f146 | 2445 | if (resolution == NULL) |
8fb69344 | 2446 | fatal_error ("could not open symbol resolution file: %m"); |
c515f146 | 2447 | |
7bfefa9d | 2448 | t = fscanf (resolution, "%u", &num_objects); |
2449 | gcc_assert (t == 1); | |
2450 | ||
2451 | /* True, since the plugin splits the archives. */ | |
2452 | gcc_assert (num_objects == nfiles); | |
2453 | } | |
2454 | ||
d534cab0 | 2455 | tree_with_vars = htab_create_ggc (101, htab_hash_pointer, htab_eq_pointer, |
2456 | NULL); | |
2457 | ||
ddc90d88 | 2458 | if (!quiet_flag) |
2459 | fprintf (stderr, "Reading object files:"); | |
2460 | ||
7bfefa9d | 2461 | /* Read all of the object files specified on the command line. */ |
2462 | for (i = 0, last_file_ix = 0; i < nfiles; ++i) | |
2463 | { | |
2464 | struct lto_file_decl_data *file_data = NULL; | |
ddc90d88 | 2465 | if (!quiet_flag) |
2466 | { | |
2467 | fprintf (stderr, " %s", fnames[i]); | |
2468 | fflush (stderr); | |
2469 | } | |
7bfefa9d | 2470 | |
3ba0ce47 | 2471 | current_lto_file = lto_obj_file_open (fnames[i], false); |
7bfefa9d | 2472 | if (!current_lto_file) |
2473 | break; | |
2474 | ||
f18bad33 | 2475 | file_data = lto_file_read (current_lto_file, resolution, &count); |
7bfefa9d | 2476 | if (!file_data) |
fad71d4f | 2477 | { |
2478 | lto_obj_file_close (current_lto_file); | |
2479 | current_lto_file = NULL; | |
2480 | break; | |
2481 | } | |
7bfefa9d | 2482 | |
f18bad33 | 2483 | decl_data[last_file_ix++] = file_data; |
7bfefa9d | 2484 | |
3ba0ce47 | 2485 | lto_obj_file_close (current_lto_file); |
7bfefa9d | 2486 | current_lto_file = NULL; |
7a52b640 | 2487 | ggc_collect (); |
7bfefa9d | 2488 | } |
2489 | ||
f18bad33 | 2490 | lto_flatten_files (decl_data, count, last_file_ix); |
2491 | lto_stats.num_input_files = count; | |
3210ebe5 | 2492 | ggc_free(decl_data); |
2493 | real_file_decl_data = NULL; | |
f18bad33 | 2494 | |
7bfefa9d | 2495 | if (resolution_file_name) |
2496 | fclose (resolution); | |
2497 | ||
7bfefa9d | 2498 | /* Set the hooks so that all of the ipa passes can read in their data. */ |
2499 | lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data); | |
2500 | ||
e2050933 | 2501 | timevar_pop (TV_IPA_LTO_DECL_IN); |
7bfefa9d | 2502 | |
ddc90d88 | 2503 | if (!quiet_flag) |
2504 | fprintf (stderr, "\nReading the callgraph\n"); | |
2505 | ||
57305941 | 2506 | timevar_push (TV_IPA_LTO_CGRAPH_IO); |
7bfefa9d | 2507 | /* Read the callgraph. */ |
2508 | input_cgraph (); | |
57305941 | 2509 | timevar_pop (TV_IPA_LTO_CGRAPH_IO); |
7bfefa9d | 2510 | |
ddc90d88 | 2511 | if (!quiet_flag) |
2512 | fprintf (stderr, "Merging declarations\n"); | |
2513 | ||
57305941 | 2514 | timevar_push (TV_IPA_LTO_DECL_MERGE); |
21ce3cc7 | 2515 | /* Merge global decls. */ |
2516 | lto_symtab_merge_decls (); | |
2517 | ||
4f3aea0d | 2518 | /* If there were errors during symbol merging bail out, we have no |
2519 | good way to recover here. */ | |
2520 | if (seen_error ()) | |
baa6eec4 | 2521 | fatal_error ("errors during merging of translation units"); |
4f3aea0d | 2522 | |
21ce3cc7 | 2523 | /* Fixup all decls and types and free the type hash tables. */ |
2524 | lto_fixup_decls (all_file_decl_data); | |
d534cab0 | 2525 | htab_delete (tree_with_vars); |
2526 | tree_with_vars = NULL; | |
21ce3cc7 | 2527 | free_gimple_type_tables (); |
57305941 | 2528 | ggc_collect (); |
2529 | ||
2530 | timevar_pop (TV_IPA_LTO_DECL_MERGE); | |
2531 | /* Each pass will set the appropriate timer. */ | |
21ce3cc7 | 2532 | |
ddc90d88 | 2533 | if (!quiet_flag) |
2534 | fprintf (stderr, "Reading summaries\n"); | |
2535 | ||
fd193bcd | 2536 | /* Read the IPA summary data. */ |
ddc90d88 | 2537 | if (flag_ltrans) |
2538 | ipa_read_optimization_summaries (); | |
2539 | else | |
2540 | ipa_read_summaries (); | |
7bfefa9d | 2541 | |
21ce3cc7 | 2542 | /* Finally merge the cgraph according to the decl merging decisions. */ |
57305941 | 2543 | timevar_push (TV_IPA_LTO_CGRAPH_MERGE); |
01ec0a6c | 2544 | if (cgraph_dump_file) |
2545 | { | |
2546 | fprintf (cgraph_dump_file, "Before merging:\n"); | |
2547 | dump_cgraph (cgraph_dump_file); | |
2548 | dump_varpool (cgraph_dump_file); | |
2549 | } | |
21ce3cc7 | 2550 | lto_symtab_merge_cgraph_nodes (); |
57305941 | 2551 | ggc_collect (); |
7bfefa9d | 2552 | |
59dd4830 | 2553 | if (flag_ltrans) |
2554 | for (node = cgraph_nodes; node; node = node->next) | |
6d1cc52c | 2555 | { |
6d1cc52c | 2556 | /* FIXME: ipa_transforms_to_apply holds list of passes that have optimization |
2557 | summaries computed and needs to apply changes. At the moment WHOPR only | |
2558 | supports inlining, so we can push it here by hand. In future we need to stream | |
2559 | this field into ltrans compilation. */ | |
2560 | if (node->analyzed) | |
2561 | VEC_safe_push (ipa_opt_pass, heap, | |
2562 | node->ipa_transforms_to_apply, | |
2563 | (ipa_opt_pass)&pass_ipa_inline); | |
2564 | } | |
25429dc2 | 2565 | lto_symtab_free (); |
2566 | ||
57305941 | 2567 | timevar_pop (TV_IPA_LTO_CGRAPH_MERGE); |
7bfefa9d | 2568 | |
57305941 | 2569 | timevar_push (TV_IPA_LTO_DECL_INIT_IO); |
7bfefa9d | 2570 | |
7bfefa9d | 2571 | /* FIXME lto. This loop needs to be changed to use the pass manager to |
2572 | call the ipa passes directly. */ | |
852f689e | 2573 | if (!seen_error ()) |
7bfefa9d | 2574 | for (i = 0; i < last_file_ix; i++) |
2575 | { | |
2576 | struct lto_file_decl_data *file_data = all_file_decl_data [i]; | |
2577 | lto_materialize_constructors_and_inits (file_data); | |
2578 | } | |
2579 | ||
2580 | /* Indicate that the cgraph is built and ready. */ | |
2581 | cgraph_function_flags_ready = true; | |
2582 | ||
57305941 | 2583 | timevar_pop (TV_IPA_LTO_DECL_INIT_IO); |
2584 | ggc_free (all_file_decl_data); | |
2585 | all_file_decl_data = NULL; | |
7bfefa9d | 2586 | } |
2587 | ||
2588 | ||
2589 | /* Materialize all the bodies for all the nodes in the callgraph. */ | |
2590 | ||
2591 | static void | |
2592 | materialize_cgraph (void) | |
2593 | { | |
2594 | tree decl; | |
2595 | struct cgraph_node *node; | |
2596 | unsigned i; | |
2597 | timevar_id_t lto_timer; | |
2598 | ||
ddc90d88 | 2599 | if (!quiet_flag) |
2600 | fprintf (stderr, | |
2601 | flag_wpa ? "Materializing decls:" : "Reading function bodies:"); | |
2602 | ||
2603 | ||
7bfefa9d | 2604 | /* Now that we have input the cgraph, we need to clear all of the aux |
2605 | nodes and read the functions if we are not running in WPA mode. */ | |
e2050933 | 2606 | timevar_push (TV_IPA_LTO_GIMPLE_IN); |
7bfefa9d | 2607 | |
2608 | for (node = cgraph_nodes; node; node = node->next) | |
2609 | { | |
97b862d3 | 2610 | if (node->local.lto_file_data) |
7bfefa9d | 2611 | { |
2612 | lto_materialize_function (node); | |
2613 | lto_stats.num_input_cgraph_nodes++; | |
2614 | } | |
2615 | } | |
2616 | ||
e2050933 | 2617 | timevar_pop (TV_IPA_LTO_GIMPLE_IN); |
7bfefa9d | 2618 | |
2619 | /* Start the appropriate timer depending on the mode that we are | |
2620 | operating in. */ | |
2621 | lto_timer = (flag_wpa) ? TV_WHOPR_WPA | |
2622 | : (flag_ltrans) ? TV_WHOPR_LTRANS | |
2623 | : TV_LTO; | |
2624 | timevar_push (lto_timer); | |
2625 | ||
2626 | current_function_decl = NULL; | |
2627 | set_cfun (NULL); | |
2628 | ||
2629 | /* Inform the middle end about the global variables we have seen. */ | |
48148244 | 2630 | FOR_EACH_VEC_ELT (tree, lto_global_var_decls, i, decl) |
7bfefa9d | 2631 | rest_of_decl_compilation (decl, 1, 0); |
2632 | ||
ddc90d88 | 2633 | if (!quiet_flag) |
2634 | fprintf (stderr, "\n"); | |
7bfefa9d | 2635 | |
2636 | timevar_pop (lto_timer); | |
2637 | } | |
2638 | ||
2639 | ||
2640 | /* Perform whole program analysis (WPA) on the callgraph and write out the | |
2641 | optimization plan. */ | |
2642 | ||
2643 | static void | |
2644 | do_whole_program_analysis (void) | |
2645 | { | |
7bfefa9d | 2646 | /* Note that since we are in WPA mode, materialize_cgraph will not |
2647 | actually read in all the function bodies. It only materializes | |
2648 | the decls and cgraph nodes so that analysis can be performed. */ | |
2649 | materialize_cgraph (); | |
2650 | ||
2651 | /* Reading in the cgraph uses different timers, start timing WPA now. */ | |
2652 | timevar_push (TV_WHOPR_WPA); | |
2653 | ||
57305941 | 2654 | if (pre_ipa_mem_report) |
2655 | { | |
2656 | fprintf (stderr, "Memory consumption before IPA\n"); | |
2657 | dump_memory_report (false); | |
2658 | } | |
2659 | ||
4037a4c1 | 2660 | cgraph_function_flags_ready = true; |
2661 | ||
ecb08119 | 2662 | if (cgraph_dump_file) |
2663 | { | |
2664 | dump_cgraph (cgraph_dump_file); | |
2665 | dump_varpool (cgraph_dump_file); | |
2666 | } | |
7bfefa9d | 2667 | bitmap_obstack_initialize (NULL); |
e7eaba7b | 2668 | cgraph_state = CGRAPH_STATE_IPA_SSA; |
7bfefa9d | 2669 | |
e7eaba7b | 2670 | execute_ipa_pass_list (all_regular_ipa_passes); |
7bfefa9d | 2671 | |
ecb08119 | 2672 | if (cgraph_dump_file) |
2673 | { | |
2674 | fprintf (cgraph_dump_file, "Optimized "); | |
2675 | dump_cgraph (cgraph_dump_file); | |
2676 | dump_varpool (cgraph_dump_file); | |
2677 | } | |
7bfefa9d | 2678 | verify_cgraph (); |
2679 | bitmap_obstack_release (NULL); | |
2680 | ||
2681 | /* We are about to launch the final LTRANS phase, stop the WPA timer. */ | |
2682 | timevar_pop (TV_WHOPR_WPA); | |
2683 | ||
48e3ea52 | 2684 | if (flag_lto_partition_1to1) |
2685 | lto_1_to_1_map (); | |
2686 | else | |
2687 | lto_balanced_map (); | |
e7eaba7b | 2688 | |
ddc90d88 | 2689 | if (!quiet_flag) |
2690 | { | |
2691 | fprintf (stderr, "\nStreaming out"); | |
2692 | fflush (stderr); | |
2693 | } | |
2024fa7d | 2694 | lto_wpa_write_files (); |
57305941 | 2695 | ggc_collect (); |
ddc90d88 | 2696 | if (!quiet_flag) |
2697 | fprintf (stderr, "\n"); | |
7bfefa9d | 2698 | |
57305941 | 2699 | if (post_ipa_mem_report) |
2700 | { | |
2701 | fprintf (stderr, "Memory consumption after IPA\n"); | |
2702 | dump_memory_report (false); | |
2703 | } | |
2704 | ||
7bfefa9d | 2705 | /* Show the LTO report before launching LTRANS. */ |
2706 | if (flag_lto_report) | |
2707 | print_lto_report (); | |
7bfefa9d | 2708 | } |
2709 | ||
2710 | ||
3c9e9cba | 2711 | static GTY(()) tree lto_eh_personality_decl; |
2712 | ||
2713 | /* Return the LTO personality function decl. */ | |
2714 | ||
2715 | tree | |
2716 | lto_eh_personality (void) | |
2717 | { | |
2718 | if (!lto_eh_personality_decl) | |
2719 | { | |
2720 | /* Use the first personality DECL for our personality if we don't | |
2721 | support multiple ones. This ensures that we don't artificially | |
2722 | create the need for them in a single-language program. */ | |
2723 | if (first_personality_decl && !dwarf2out_do_cfi_asm ()) | |
2724 | lto_eh_personality_decl = first_personality_decl; | |
2725 | else | |
2726 | lto_eh_personality_decl = lhd_gcc_personality (); | |
2727 | } | |
2728 | ||
2729 | return lto_eh_personality_decl; | |
2730 | } | |
2731 | ||
a3de1f55 | 2732 | /* Set the process name based on the LTO mode. */ |
2733 | ||
2734 | static void | |
2735 | lto_process_name (void) | |
2736 | { | |
2737 | if (flag_lto) | |
2738 | setproctitle ("lto1-lto"); | |
2739 | if (flag_wpa) | |
2740 | setproctitle ("lto1-wpa"); | |
2741 | if (flag_ltrans) | |
2742 | setproctitle ("lto1-ltrans"); | |
2743 | } | |
3c9e9cba | 2744 | |
a0605d65 | 2745 | |
2746 | /* Initialize the LTO front end. */ | |
2747 | ||
2748 | static void | |
2749 | lto_init (void) | |
2750 | { | |
2751 | lto_process_name (); | |
2752 | lto_streamer_hooks_init (); | |
2753 | lto_reader_init (); | |
2754 | memset (<o_stats, 0, sizeof (lto_stats)); | |
2755 | bitmap_obstack_initialize (NULL); | |
2756 | gimple_register_cfg_hooks (); | |
2757 | } | |
2758 | ||
2759 | ||
7bfefa9d | 2760 | /* Main entry point for the GIMPLE front end. This front end has |
2761 | three main personalities: | |
2762 | ||
2763 | - LTO (-flto). All the object files on the command line are | |
2764 | loaded in memory and processed as a single translation unit. | |
2765 | This is the traditional link-time optimization behavior. | |
2766 | ||
2767 | - WPA (-fwpa). Only the callgraph and summary information for | |
2768 | files in the command file are loaded. A single callgraph | |
2769 | (without function bodies) is instantiated for the whole set of | |
2770 | files. IPA passes are only allowed to analyze the call graph | |
2771 | and make transformation decisions. The callgraph is | |
2772 | partitioned, each partition is written to a new object file | |
2773 | together with the transformation decisions. | |
2774 | ||
2775 | - LTRANS (-fltrans). Similar to -flto but it prevents the IPA | |
2776 | summary files from running again. Since WPA computed summary | |
2777 | information and decided what transformations to apply, LTRANS | |
2778 | simply applies them. */ | |
2779 | ||
2780 | void | |
b8ba44e7 | 2781 | lto_main (void) |
7bfefa9d | 2782 | { |
a0605d65 | 2783 | /* Initialize the LTO front end. */ |
2784 | lto_init (); | |
7bfefa9d | 2785 | |
2786 | /* Read all the symbols and call graph from all the files in the | |
2787 | command line. */ | |
2788 | read_cgraph_and_symbols (num_in_fnames, in_fnames); | |
2789 | ||
852f689e | 2790 | if (!seen_error ()) |
7bfefa9d | 2791 | { |
2792 | /* If WPA is enabled analyze the whole call graph and create an | |
2793 | optimization plan. Otherwise, read in all the function | |
2794 | bodies and continue with optimization. */ | |
2795 | if (flag_wpa) | |
2796 | do_whole_program_analysis (); | |
2797 | else | |
2798 | { | |
2799 | materialize_cgraph (); | |
2800 | ||
2801 | /* Let the middle end know that we have read and merged all of | |
2802 | the input files. */ | |
2803 | cgraph_optimize (); | |
2804 | ||
2805 | /* FIXME lto, if the processes spawned by WPA fail, we miss | |
2806 | the chance to print WPA's report, so WPA will call | |
2807 | print_lto_report before launching LTRANS. If LTRANS was | |
2808 | launched directly by the driver we would not need to do | |
2809 | this. */ | |
2810 | if (flag_lto_report) | |
2811 | print_lto_report (); | |
2812 | } | |
2813 | } | |
2814 | } | |
2815 | ||
2816 | #include "gt-lto-lto.h" |