]>
Commit | Line | Data |
---|---|---|
d7f09764 | 1 | /* Top-level LTO routines. |
8d9254fc | 2 | Copyright (C) 2009-2020 Free Software Foundation, Inc. |
d7f09764 DN |
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" | |
d7f09764 | 24 | #include "tm.h" |
c7131fb2 AM |
25 | #include "function.h" |
26 | #include "bitmap.h" | |
60393bbc | 27 | #include "basic-block.h" |
c7131fb2 AM |
28 | #include "tree.h" |
29 | #include "gimple.h" | |
2adfab87 AM |
30 | #include "cfghooks.h" |
31 | #include "alloc-pool.h" | |
32 | #include "tree-pass.h" | |
2adfab87 AM |
33 | #include "tree-streamer.h" |
34 | #include "cgraph.h" | |
2adfab87 AM |
35 | #include "opts.h" |
36 | #include "toplev.h" | |
c7131fb2 | 37 | #include "stor-layout.h" |
dd912cb8 | 38 | #include "symbol-summary.h" |
8bc5448f | 39 | #include "tree-vrp.h" |
d7f09764 | 40 | #include "ipa-prop.h" |
7951d88a | 41 | #include "debug.h" |
d7f09764 | 42 | #include "lto.h" |
48d859bb | 43 | #include "lto-section-names.h" |
73ce4d1e | 44 | #include "splay-tree.h" |
a66dc285 | 45 | #include "lto-partition.h" |
315f8c0e DM |
46 | #include "context.h" |
47 | #include "pass_manager.h" | |
27d020cf | 48 | #include "ipa-fnsummary.h" |
1ee85ee1 | 49 | #include "ipa-utils.h" |
41dbbb37 | 50 | #include "gomp-constants.h" |
6b9ac179 | 51 | #include "lto-symtab.h" |
4a38b02b IV |
52 | #include "stringpool.h" |
53 | #include "fold-const.h" | |
eac3ab4a | 54 | #include "attribs.h" |
43fbc2e9 | 55 | #include "builtins.h" |
a79420f9 | 56 | #include "lto-common.h" |
d7f09764 | 57 | |
35f32ad4 | 58 | |
f300e7b8 JH |
59 | /* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver. */ |
60 | static int lto_parallelism; | |
61 | ||
e0f967db JH |
62 | /* Return true when NODE has a clone that is analyzed (i.e. we need |
63 | to load its body even if the node itself is not needed). */ | |
64 | ||
65 | static bool | |
66 | has_analyzed_clone_p (struct cgraph_node *node) | |
67 | { | |
68 | struct cgraph_node *orig = node; | |
69 | node = node->clones; | |
70 | if (node) | |
71 | while (node != orig) | |
72 | { | |
67348ccc | 73 | if (node->analyzed) |
e0f967db JH |
74 | return true; |
75 | if (node->clones) | |
76 | node = node->clones; | |
77 | else if (node->next_sibling_clone) | |
78 | node = node->next_sibling_clone; | |
79 | else | |
80 | { | |
81 | while (node != orig && !node->next_sibling_clone) | |
82 | node = node->clone_of; | |
83 | if (node != orig) | |
84 | node = node->next_sibling_clone; | |
85 | } | |
86 | } | |
87 | return false; | |
88 | } | |
89 | ||
7951d88a | 90 | /* Read the function body for the function associated with NODE. */ |
d7f09764 DN |
91 | |
92 | static void | |
93 | lto_materialize_function (struct cgraph_node *node) | |
94 | { | |
95 | tree decl; | |
d7f09764 | 96 | |
67348ccc | 97 | decl = node->decl; |
e0f967db JH |
98 | /* Read in functions with body (analyzed nodes) |
99 | and also functions that are needed to produce virtual clones. */ | |
d52f5295 | 100 | if ((node->has_gimple_body_p () && node->analyzed) |
a2e2a668 | 101 | || node->used_as_abstract_origin |
e70670cf | 102 | || has_analyzed_clone_p (node)) |
d7f09764 | 103 | { |
b5493fb2 | 104 | /* Clones don't need to be read. */ |
e0f967db JH |
105 | if (node->clone_of) |
106 | return; | |
a2e2a668 JH |
107 | if (DECL_FUNCTION_PERSONALITY (decl) && !first_personality_decl) |
108 | first_personality_decl = DECL_FUNCTION_PERSONALITY (decl); | |
a3d09469 RB |
109 | /* If the file contains a function with a language specific EH |
110 | personality set or with EH enabled initialize the backend EH | |
111 | machinery. */ | |
112 | if (DECL_FUNCTION_PERSONALITY (decl) | |
113 | || opt_for_fn (decl, flag_exceptions)) | |
114 | lto_init_eh (); | |
d7f09764 | 115 | } |
d7f09764 DN |
116 | |
117 | /* Let the middle end know about the function. */ | |
118 | rest_of_decl_compilation (decl, 1, 0); | |
d7f09764 DN |
119 | } |
120 | ||
a79420f9 | 121 | /* Materialize all the bodies for all the nodes in the callgraph. */ |
83fd5d11 RB |
122 | |
123 | static void | |
a79420f9 | 124 | materialize_cgraph (void) |
b823cdfe | 125 | { |
ee7a003f | 126 | struct cgraph_node *node; |
a79420f9 | 127 | timevar_id_t lto_timer; |
d7f09764 | 128 | |
a79420f9 ML |
129 | if (!quiet_flag) |
130 | fprintf (stderr, | |
131 | flag_wpa ? "Materializing decls:" : "Reading function bodies:"); | |
d7f09764 | 132 | |
d7f09764 | 133 | |
a79420f9 | 134 | FOR_EACH_FUNCTION (node) |
d7f09764 | 135 | { |
a79420f9 ML |
136 | if (node->lto_file_data) |
137 | { | |
138 | lto_materialize_function (node); | |
139 | lto_stats.num_input_cgraph_nodes++; | |
140 | } | |
d7f09764 DN |
141 | } |
142 | ||
d7f09764 | 143 | |
a79420f9 ML |
144 | /* Start the appropriate timer depending on the mode that we are |
145 | operating in. */ | |
146 | lto_timer = (flag_wpa) ? TV_WHOPR_WPA | |
147 | : (flag_ltrans) ? TV_WHOPR_LTRANS | |
148 | : TV_LTO; | |
149 | timevar_push (lto_timer); | |
d7f09764 | 150 | |
a79420f9 ML |
151 | current_function_decl = NULL; |
152 | set_cfun (NULL); | |
d7f09764 | 153 | |
a79420f9 ML |
154 | if (!quiet_flag) |
155 | fprintf (stderr, "\n"); | |
d7f09764 | 156 | |
a79420f9 | 157 | timevar_pop (lto_timer); |
d7f09764 DN |
158 | } |
159 | ||
f300e7b8 JH |
160 | /* Actually stream out ENCODER into TEMP_FILENAME. */ |
161 | ||
162 | static void | |
0c7f51e4 | 163 | stream_out (char *temp_filename, lto_symtab_encoder_t encoder, int part) |
f300e7b8 JH |
164 | { |
165 | lto_file *file = lto_obj_file_open (temp_filename, true); | |
166 | if (!file) | |
a9c697b8 | 167 | fatal_error (input_location, "%<lto_obj_file_open()%> failed"); |
f300e7b8 JH |
168 | lto_set_current_out_file (file); |
169 | ||
814f3331 JH |
170 | gcc_assert (!dump_file); |
171 | streamer_dump_file = dump_begin (TDI_lto_stream_out, NULL, part); | |
f300e7b8 JH |
172 | ipa_write_optimization_summaries (encoder); |
173 | ||
4a44a5f3 ML |
174 | free (CONST_CAST (char *, file->filename)); |
175 | ||
f300e7b8 JH |
176 | lto_set_current_out_file (NULL); |
177 | lto_obj_file_close (file); | |
178 | free (file); | |
814f3331 JH |
179 | if (streamer_dump_file) |
180 | { | |
181 | dump_end (TDI_lto_stream_out, streamer_dump_file); | |
182 | streamer_dump_file = NULL; | |
183 | } | |
f300e7b8 JH |
184 | } |
185 | ||
186 | /* Wait for forked process and signal errors. */ | |
187 | #ifdef HAVE_WORKING_FORK | |
188 | static void | |
189 | wait_for_child () | |
190 | { | |
191 | int status; | |
192 | do | |
193 | { | |
15df2655 JJ |
194 | #ifndef WCONTINUED |
195 | #define WCONTINUED 0 | |
196 | #endif | |
197 | int w = waitpid (0, &status, WUNTRACED | WCONTINUED); | |
f300e7b8 | 198 | if (w == -1) |
40fecdd6 | 199 | fatal_error (input_location, "waitpid failed"); |
f300e7b8 JH |
200 | |
201 | if (WIFEXITED (status) && WEXITSTATUS (status)) | |
40fecdd6 | 202 | fatal_error (input_location, "streaming subprocess failed"); |
f300e7b8 | 203 | else if (WIFSIGNALED (status)) |
40fecdd6 JM |
204 | fatal_error (input_location, |
205 | "streaming subprocess was killed by signal"); | |
f300e7b8 | 206 | } |
15df2655 | 207 | while (!WIFEXITED (status) && !WIFSIGNALED (status)); |
f300e7b8 JH |
208 | } |
209 | #endif | |
210 | ||
0c7f51e4 JH |
211 | static void |
212 | stream_out_partitions_1 (char *temp_filename, int blen, int min, int max) | |
213 | { | |
214 | /* Write all the nodes in SET. */ | |
215 | for (int p = min; p < max; p ++) | |
216 | { | |
217 | sprintf (temp_filename + blen, "%u.o", p); | |
218 | stream_out (temp_filename, ltrans_partitions[p]->encoder, p); | |
219 | ltrans_partitions[p]->encoder = NULL; | |
220 | } | |
221 | } | |
222 | ||
f300e7b8 JH |
223 | /* Stream out ENCODER into TEMP_FILENAME |
224 | Fork if that seems to help. */ | |
225 | ||
226 | static void | |
0c7f51e4 JH |
227 | stream_out_partitions (char *temp_filename, int blen, int min, int max, |
228 | bool ARG_UNUSED (last)) | |
f300e7b8 JH |
229 | { |
230 | #ifdef HAVE_WORKING_FORK | |
231 | static int nruns; | |
232 | ||
6dab804d | 233 | if (lto_parallelism <= 1) |
f300e7b8 | 234 | { |
0c7f51e4 | 235 | stream_out_partitions_1 (temp_filename, blen, min, max); |
f300e7b8 JH |
236 | return; |
237 | } | |
238 | ||
239 | /* Do not run more than LTO_PARALLELISM streamings | |
240 | FIXME: we ignore limits on jobserver. */ | |
241 | if (lto_parallelism > 0 && nruns >= lto_parallelism) | |
242 | { | |
243 | wait_for_child (); | |
244 | nruns --; | |
245 | } | |
246 | /* If this is not the last parallel partition, execute new | |
247 | streaming process. */ | |
248 | if (!last) | |
249 | { | |
250 | pid_t cpid = fork (); | |
251 | ||
252 | if (!cpid) | |
253 | { | |
254 | setproctitle ("lto1-wpa-streaming"); | |
0c7f51e4 | 255 | stream_out_partitions_1 (temp_filename, blen, min, max); |
f300e7b8 JH |
256 | exit (0); |
257 | } | |
258 | /* Fork failed; lets do the job ourseleves. */ | |
259 | else if (cpid == -1) | |
ee7a003f | 260 | stream_out_partitions_1 (temp_filename, blen, min, max); |
f300e7b8 JH |
261 | else |
262 | nruns++; | |
263 | } | |
264 | /* Last partition; stream it and wait for all children to die. */ | |
265 | else | |
266 | { | |
267 | int i; | |
0c7f51e4 | 268 | stream_out_partitions_1 (temp_filename, blen, min, max); |
f300e7b8 JH |
269 | for (i = 0; i < nruns; i++) |
270 | wait_for_child (); | |
271 | } | |
272 | asm_nodes_output = true; | |
273 | #else | |
0c7f51e4 | 274 | stream_out_partitions_1 (temp_filename, blen, min, max); |
f300e7b8 JH |
275 | #endif |
276 | } | |
277 | ||
b5611987 RG |
278 | /* Write all output files in WPA mode and the file with the list of |
279 | LTRANS units. */ | |
d7f09764 | 280 | |
b5611987 | 281 | static void |
d7f09764 DN |
282 | lto_wpa_write_files (void) |
283 | { | |
b5611987 | 284 | unsigned i, n_sets; |
9eec9488 | 285 | ltrans_partition part; |
b5611987 RG |
286 | FILE *ltrans_output_list_stream; |
287 | char *temp_filename; | |
b6e33d73 JH |
288 | auto_vec <char *>temp_filenames; |
289 | auto_vec <int>temp_priority; | |
b5611987 RG |
290 | size_t blen; |
291 | ||
292 | /* Open the LTRANS output list. */ | |
293 | if (!ltrans_output_list) | |
40fecdd6 | 294 | fatal_error (input_location, "no LTRANS output list filename provided"); |
d7f09764 DN |
295 | |
296 | timevar_push (TV_WHOPR_WPA); | |
297 | ||
9771b263 | 298 | FOR_EACH_VEC_ELT (ltrans_partitions, i, part) |
ee7a003f ML |
299 | lto_stats.num_output_symtab_nodes |
300 | += lto_symtab_encoder_size (part->encoder); | |
d7f09764 | 301 | |
d7f09764 DN |
302 | timevar_pop (TV_WHOPR_WPA); |
303 | ||
304 | timevar_push (TV_WHOPR_WPA_IO); | |
305 | ||
1fcf52a6 JH |
306 | cgraph_node *node; |
307 | /* Do body modifications needed for streaming before we fork out | |
308 | worker processes. */ | |
309 | FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) | |
f8cf94cd | 310 | if (!node->clone_of && gimple_has_body_p (node->decl)) |
1fcf52a6 JH |
311 | lto_prepare_function_for_streaming (node); |
312 | ||
e5207f1a | 313 | ggc_trim (); |
c9ef0409 JH |
314 | report_heap_memory_use (); |
315 | ||
b5611987 RG |
316 | /* Generate a prefix for the LTRANS unit files. */ |
317 | blen = strlen (ltrans_output_list); | |
318 | temp_filename = (char *) xmalloc (blen + sizeof ("2147483648.o")); | |
319 | strcpy (temp_filename, ltrans_output_list); | |
320 | if (blen > sizeof (".out") | |
321 | && strcmp (temp_filename + blen - sizeof (".out") + 1, | |
322 | ".out") == 0) | |
323 | temp_filename[blen - sizeof (".out") + 1] = '\0'; | |
324 | blen = strlen (temp_filename); | |
d7f09764 | 325 | |
9771b263 | 326 | n_sets = ltrans_partitions.length (); |
0c7f51e4 JH |
327 | unsigned sets_per_worker = n_sets; |
328 | if (lto_parallelism > 1) | |
329 | { | |
330 | if (lto_parallelism > (int)n_sets) | |
331 | lto_parallelism = n_sets; | |
332 | sets_per_worker = (n_sets + lto_parallelism - 1) / lto_parallelism; | |
333 | } | |
51973b1e | 334 | |
d7f09764 DN |
335 | for (i = 0; i < n_sets; i++) |
336 | { | |
9771b263 | 337 | ltrans_partition part = ltrans_partitions[i]; |
d7f09764 | 338 | |
b5611987 RG |
339 | /* Write all the nodes in SET. */ |
340 | sprintf (temp_filename + blen, "%u.o", i); | |
d7f09764 | 341 | |
b5611987 | 342 | if (!quiet_flag) |
ee7a003f ML |
343 | fprintf (stderr, " %s (%s %i insns)", temp_filename, part->name, |
344 | part->insns); | |
3dafb85c | 345 | if (symtab->dump_file) |
0a5fa5a1 | 346 | { |
ee7a003f ML |
347 | lto_symtab_encoder_iterator lsei; |
348 | ||
349 | fprintf (symtab->dump_file, | |
350 | "Writing partition %s to file %s, %i insns\n", | |
0a5fa5a1 | 351 | part->name, temp_filename, part->insns); |
3dafb85c | 352 | fprintf (symtab->dump_file, " Symbols in partition: "); |
ee7a003f ML |
353 | for (lsei = lsei_start_in_partition (part->encoder); |
354 | !lsei_end_p (lsei); | |
7b99cca4 JH |
355 | lsei_next_in_partition (&lsei)) |
356 | { | |
5e20cdc9 | 357 | symtab_node *node = lsei_node (lsei); |
3dafb85c | 358 | fprintf (symtab->dump_file, "%s ", node->asm_name ()); |
c3c445e1 | 359 | } |
3dafb85c | 360 | fprintf (symtab->dump_file, "\n Symbols in boundary: "); |
c3c445e1 JH |
361 | for (lsei = lsei_start (part->encoder); !lsei_end_p (lsei); |
362 | lsei_next (&lsei)) | |
363 | { | |
5e20cdc9 | 364 | symtab_node *node = lsei_node (lsei); |
c3c445e1 JH |
365 | if (!lto_symtab_encoder_in_partition_p (part->encoder, node)) |
366 | { | |
3dafb85c | 367 | fprintf (symtab->dump_file, "%s ", node->asm_name ()); |
7de90a6c | 368 | cgraph_node *cnode = dyn_cast <cgraph_node *> (node); |
5d59b5e1 | 369 | if (cnode |
ee7a003f ML |
370 | && lto_symtab_encoder_encode_body_p (part->encoder, |
371 | cnode)) | |
3dafb85c | 372 | fprintf (symtab->dump_file, "(body included)"); |
5d59b5e1 LC |
373 | else |
374 | { | |
7de90a6c | 375 | varpool_node *vnode = dyn_cast <varpool_node *> (node); |
5d59b5e1 | 376 | if (vnode |
ee7a003f ML |
377 | && lto_symtab_encoder_encode_initializer_p (part->encoder, |
378 | vnode)) | |
3dafb85c | 379 | fprintf (symtab->dump_file, "(initializer included)"); |
5d59b5e1 | 380 | } |
c3c445e1 | 381 | } |
7b99cca4 | 382 | } |
3dafb85c | 383 | fprintf (symtab->dump_file, "\n"); |
0a5fa5a1 | 384 | } |
7b99cca4 | 385 | gcc_checking_assert (lto_symtab_encoder_size (part->encoder) || !i); |
d7f09764 | 386 | |
b6e33d73 | 387 | temp_priority.safe_push (part->insns); |
f300e7b8 JH |
388 | temp_filenames.safe_push (xstrdup (temp_filename)); |
389 | } | |
9fd052e7 | 390 | memory_block_pool::trim (0); |
0c7f51e4 JH |
391 | |
392 | for (int set = 0; set < MAX (lto_parallelism, 1); set++) | |
393 | { | |
394 | stream_out_partitions (temp_filename, blen, set * sets_per_worker, | |
395 | MIN ((set + 1) * sets_per_worker, n_sets), | |
396 | set == MAX (lto_parallelism, 1) - 1); | |
397 | } | |
398 | ||
f300e7b8 JH |
399 | ltrans_output_list_stream = fopen (ltrans_output_list, "w"); |
400 | if (ltrans_output_list_stream == NULL) | |
40fecdd6 JM |
401 | fatal_error (input_location, |
402 | "opening LTRANS output list %s: %m", ltrans_output_list); | |
f300e7b8 JH |
403 | for (i = 0; i < n_sets; i++) |
404 | { | |
405 | unsigned int len = strlen (temp_filenames[i]); | |
b6e33d73 JH |
406 | if (fprintf (ltrans_output_list_stream, "%i\n", temp_priority[i]) < 0 |
407 | || fwrite (temp_filenames[i], 1, len, ltrans_output_list_stream) < len | |
48cf395b | 408 | || fwrite ("\n", 1, 1, ltrans_output_list_stream) < 1) |
40fecdd6 | 409 | fatal_error (input_location, "writing to LTRANS output list %s: %m", |
b5611987 | 410 | ltrans_output_list); |
f300e7b8 | 411 | free (temp_filenames[i]); |
d7f09764 DN |
412 | } |
413 | ||
b5611987 RG |
414 | lto_stats.num_output_files += n_sets; |
415 | ||
d7f09764 | 416 | /* Close the LTRANS output list. */ |
48cf395b | 417 | if (fclose (ltrans_output_list_stream)) |
40fecdd6 JM |
418 | fatal_error (input_location, |
419 | "closing LTRANS output list %s: %m", ltrans_output_list); | |
b5611987 | 420 | |
ee7a003f | 421 | free_ltrans_partitions (); |
da3202a8 | 422 | free (temp_filename); |
1cb1a99f | 423 | |
b5611987 | 424 | timevar_pop (TV_WHOPR_WPA_IO); |
d7f09764 DN |
425 | } |
426 | ||
d7f09764 DN |
427 | /* Perform whole program analysis (WPA) on the callgraph and write out the |
428 | optimization plan. */ | |
429 | ||
430 | static void | |
431 | do_whole_program_analysis (void) | |
432 | { | |
5e20cdc9 | 433 | symtab_node *node; |
c3c445e1 | 434 | |
f300e7b8 JH |
435 | lto_parallelism = 1; |
436 | ||
0c7f51e4 | 437 | /* TODO: jobserver communication is not supported, yet. */ |
f300e7b8 | 438 | if (!strcmp (flag_wpa, "jobserver")) |
028d4092 | 439 | lto_parallelism = param_max_lto_streaming_parallelism; |
f300e7b8 JH |
440 | else |
441 | { | |
442 | lto_parallelism = atoi (flag_wpa); | |
443 | if (lto_parallelism <= 0) | |
444 | lto_parallelism = 0; | |
028d4092 ML |
445 | if (lto_parallelism >= param_max_lto_streaming_parallelism) |
446 | lto_parallelism = param_max_lto_streaming_parallelism; | |
f300e7b8 JH |
447 | } |
448 | ||
a910399d LC |
449 | timevar_start (TV_PHASE_OPT_GEN); |
450 | ||
d7f09764 DN |
451 | /* Note that since we are in WPA mode, materialize_cgraph will not |
452 | actually read in all the function bodies. It only materializes | |
453 | the decls and cgraph nodes so that analysis can be performed. */ | |
454 | materialize_cgraph (); | |
455 | ||
456 | /* Reading in the cgraph uses different timers, start timing WPA now. */ | |
457 | timevar_push (TV_WHOPR_WPA); | |
458 | ||
49ba8180 | 459 | if (pre_ipa_mem_report) |
3518424d | 460 | dump_memory_report ("Memory consumption before IPA"); |
49ba8180 | 461 | |
3dafb85c | 462 | symtab->function_flags_ready = true; |
030cd86c | 463 | |
3dafb85c | 464 | if (symtab->dump_file) |
6c52831d | 465 | symtab->dump (symtab->dump_file); |
d7f09764 | 466 | bitmap_obstack_initialize (NULL); |
3dafb85c | 467 | symtab->state = IPA_SSA; |
d7f09764 | 468 | |
315f8c0e | 469 | execute_ipa_pass_list (g->get_passes ()->all_regular_ipa_passes); |
d7f09764 | 470 | |
65179585 RB |
471 | /* When WPA analysis raises errors, do not bother to output anything. */ |
472 | if (seen_error ()) | |
473 | return; | |
474 | ||
d7f09764 DN |
475 | /* We are about to launch the final LTRANS phase, stop the WPA timer. */ |
476 | timevar_pop (TV_WHOPR_WPA); | |
477 | ||
c38ee9a2 JH |
478 | /* We are no longer going to stream in anything. Free some memory. */ |
479 | lto_free_file_name_hash (); | |
480 | ||
481 | ||
c3c445e1 | 482 | timevar_push (TV_WHOPR_PARTITIONING); |
29a50dfb JH |
483 | |
484 | gcc_assert (!dump_file); | |
485 | dump_file = dump_begin (partition_dump_id, NULL); | |
486 | ||
487 | if (dump_file) | |
488 | symtab->dump (dump_file); | |
489 | ||
490 | symtab_node::checking_verify_symtab_nodes (); | |
491 | bitmap_obstack_release (NULL); | |
783dab6b | 492 | if (flag_lto_partition == LTO_PARTITION_1TO1) |
852e4bd2 | 493 | lto_1_to_1_map (); |
783dab6b | 494 | else if (flag_lto_partition == LTO_PARTITION_MAX) |
c3c445e1 | 495 | lto_max_map (); |
783dab6b | 496 | else if (flag_lto_partition == LTO_PARTITION_ONE) |
a2e76867 | 497 | lto_balanced_map (1, INT_MAX); |
783dab6b | 498 | else if (flag_lto_partition == LTO_PARTITION_BALANCED) |
028d4092 ML |
499 | lto_balanced_map (param_lto_partitions, |
500 | param_max_partition_size); | |
852e4bd2 | 501 | else |
783dab6b | 502 | gcc_unreachable (); |
3ee2243c | 503 | |
f658ad30 | 504 | /* Size summaries are needed for balanced partitioning. Free them now so |
bbe281da | 505 | the memory can be used for streamer caches. */ |
f658ad30 | 506 | ipa_free_size_summary (); |
bbe281da | 507 | |
c3c445e1 JH |
508 | /* AUX pointers are used by partitioning code to bookkeep number of |
509 | partitions symbol is in. This is no longer needed. */ | |
510 | FOR_EACH_SYMBOL (node) | |
67348ccc | 511 | node->aux = NULL; |
c3c445e1 | 512 | |
9771b263 | 513 | lto_stats.num_cgraph_partitions += ltrans_partitions.length (); |
e41106fc RB |
514 | |
515 | /* Find out statics that need to be promoted | |
516 | to globals with hidden visibility because they are accessed from multiple | |
517 | partitions. */ | |
518 | lto_promote_cross_file_statics (); | |
29a50dfb JH |
519 | if (dump_file) |
520 | dump_end (partition_dump_id, dump_file); | |
521 | dump_file = NULL; | |
c3c445e1 JH |
522 | timevar_pop (TV_WHOPR_PARTITIONING); |
523 | ||
a910399d | 524 | timevar_stop (TV_PHASE_OPT_GEN); |
a910399d | 525 | |
e41106fc RB |
526 | /* Collect a last time - in lto_wpa_write_files we may end up forking |
527 | with the idea that this doesn't increase memory usage. So we | |
528 | absoultely do not want to collect after that. */ | |
529 | ggc_collect (); | |
530 | ||
531 | timevar_start (TV_PHASE_STREAM_OUT); | |
e792884f JH |
532 | if (!quiet_flag) |
533 | { | |
534 | fprintf (stderr, "\nStreaming out"); | |
535 | fflush (stderr); | |
536 | } | |
b5611987 | 537 | lto_wpa_write_files (); |
e792884f JH |
538 | if (!quiet_flag) |
539 | fprintf (stderr, "\n"); | |
a910399d LC |
540 | timevar_stop (TV_PHASE_STREAM_OUT); |
541 | ||
49ba8180 | 542 | if (post_ipa_mem_report) |
3518424d | 543 | dump_memory_report ("Memory consumption after IPA"); |
49ba8180 | 544 | |
d7f09764 | 545 | /* Show the LTO report before launching LTRANS. */ |
057f8f20 | 546 | if (flag_lto_report || (flag_wpa && flag_lto_report_wpa)) |
b8f4e58f | 547 | print_lto_report_1 (); |
b3e44629 | 548 | if (mem_report_wpa) |
3518424d | 549 | dump_memory_report ("Final"); |
d7f09764 DN |
550 | } |
551 | ||
4a38b02b IV |
552 | /* Create artificial pointers for "omp declare target link" vars. */ |
553 | ||
554 | static void | |
555 | offload_handle_link_vars (void) | |
556 | { | |
557 | #ifdef ACCEL_COMPILER | |
558 | varpool_node *var; | |
559 | FOR_EACH_VARIABLE (var) | |
560 | if (lookup_attribute ("omp declare target link", | |
561 | DECL_ATTRIBUTES (var->decl))) | |
562 | { | |
563 | tree type = build_pointer_type (TREE_TYPE (var->decl)); | |
564 | tree link_ptr_var = make_node (VAR_DECL); | |
565 | TREE_TYPE (link_ptr_var) = type; | |
566 | TREE_USED (link_ptr_var) = 1; | |
567 | TREE_STATIC (link_ptr_var) = 1; | |
899ca90e | 568 | SET_DECL_MODE (link_ptr_var, TYPE_MODE (type)); |
4a38b02b IV |
569 | DECL_SIZE (link_ptr_var) = TYPE_SIZE (type); |
570 | DECL_SIZE_UNIT (link_ptr_var) = TYPE_SIZE_UNIT (type); | |
571 | DECL_ARTIFICIAL (link_ptr_var) = 1; | |
572 | tree var_name = DECL_ASSEMBLER_NAME (var->decl); | |
573 | char *new_name | |
574 | = ACONCAT ((IDENTIFIER_POINTER (var_name), "_linkptr", NULL)); | |
575 | DECL_NAME (link_ptr_var) = get_identifier (new_name); | |
576 | SET_DECL_ASSEMBLER_NAME (link_ptr_var, DECL_NAME (link_ptr_var)); | |
577 | SET_DECL_VALUE_EXPR (var->decl, build_simple_mem_ref (link_ptr_var)); | |
578 | DECL_HAS_VALUE_EXPR_P (var->decl) = 1; | |
579 | } | |
580 | #endif | |
581 | } | |
582 | ||
66d62d9f HK |
583 | unsigned int |
584 | lto_option_lang_mask (void) | |
585 | { | |
586 | return CL_LTO; | |
587 | } | |
588 | ||
d7f09764 DN |
589 | /* Main entry point for the GIMPLE front end. This front end has |
590 | three main personalities: | |
591 | ||
592 | - LTO (-flto). All the object files on the command line are | |
593 | loaded in memory and processed as a single translation unit. | |
594 | This is the traditional link-time optimization behavior. | |
595 | ||
596 | - WPA (-fwpa). Only the callgraph and summary information for | |
597 | files in the command file are loaded. A single callgraph | |
598 | (without function bodies) is instantiated for the whole set of | |
599 | files. IPA passes are only allowed to analyze the call graph | |
600 | and make transformation decisions. The callgraph is | |
601 | partitioned, each partition is written to a new object file | |
602 | together with the transformation decisions. | |
603 | ||
604 | - LTRANS (-fltrans). Similar to -flto but it prevents the IPA | |
605 | summary files from running again. Since WPA computed summary | |
606 | information and decided what transformations to apply, LTRANS | |
607 | simply applies them. */ | |
608 | ||
609 | void | |
b37421c6 | 610 | lto_main (void) |
d7f09764 | 611 | { |
a910399d LC |
612 | /* LTO is called as a front end, even though it is not a front end. |
613 | Because it is called as a front end, TV_PHASE_PARSING and | |
614 | TV_PARSE_GLOBAL are active, and we need to turn them off while | |
615 | doing LTO. Later we turn them back on so they are active up in | |
616 | toplev.c. */ | |
617 | timevar_pop (TV_PARSE_GLOBAL); | |
618 | timevar_stop (TV_PHASE_PARSING); | |
619 | ||
620 | timevar_start (TV_PHASE_SETUP); | |
621 | ||
47c79d56 | 622 | /* Initialize the LTO front end. */ |
a79420f9 | 623 | lto_fe_init (); |
d7f09764 | 624 | |
a910399d LC |
625 | timevar_stop (TV_PHASE_SETUP); |
626 | timevar_start (TV_PHASE_STREAM_IN); | |
627 | ||
d7f09764 DN |
628 | /* Read all the symbols and call graph from all the files in the |
629 | command line. */ | |
630 | read_cgraph_and_symbols (num_in_fnames, in_fnames); | |
631 | ||
a910399d LC |
632 | timevar_stop (TV_PHASE_STREAM_IN); |
633 | ||
1da2ed5f | 634 | if (!seen_error ()) |
d7f09764 | 635 | { |
4a38b02b IV |
636 | offload_handle_link_vars (); |
637 | ||
d7f09764 DN |
638 | /* If WPA is enabled analyze the whole call graph and create an |
639 | optimization plan. Otherwise, read in all the function | |
640 | bodies and continue with optimization. */ | |
641 | if (flag_wpa) | |
642 | do_whole_program_analysis (); | |
643 | else | |
644 | { | |
a910399d LC |
645 | timevar_start (TV_PHASE_OPT_GEN); |
646 | ||
d7f09764 | 647 | materialize_cgraph (); |
64cfa6c0 JH |
648 | if (!flag_ltrans) |
649 | lto_promote_statics_nonwpa (); | |
d7f09764 | 650 | |
321e76fb | 651 | /* Annotate the CU DIE and mark the early debug phase as finished. */ |
efd9eb29 | 652 | debuginfo_early_start (); |
68317985 | 653 | debug_hooks->early_finish ("<artificial>"); |
efd9eb29 | 654 | debuginfo_early_stop (); |
321e76fb | 655 | |
d7f09764 | 656 | /* Let the middle end know that we have read and merged all of |
ee7a003f | 657 | the input files. */ |
3dafb85c | 658 | symtab->compile (); |
a910399d LC |
659 | |
660 | timevar_stop (TV_PHASE_OPT_GEN); | |
d7f09764 DN |
661 | |
662 | /* FIXME lto, if the processes spawned by WPA fail, we miss | |
663 | the chance to print WPA's report, so WPA will call | |
664 | print_lto_report before launching LTRANS. If LTRANS was | |
665 | launched directly by the driver we would not need to do | |
666 | this. */ | |
057f8f20 | 667 | if (flag_lto_report || (flag_wpa && flag_lto_report_wpa)) |
b8f4e58f | 668 | print_lto_report_1 (); |
d7f09764 DN |
669 | } |
670 | } | |
a910399d LC |
671 | |
672 | /* Here we make LTO pretend to be a parser. */ | |
673 | timevar_start (TV_PHASE_PARSING); | |
674 | timevar_push (TV_PARSE_GLOBAL); | |
d7f09764 | 675 | } |