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