163d1a8abSmrg /* Top-level LTO routines.
2*ec02198aSmrg Copyright (C) 2009-2020 Free Software Foundation, Inc.
363d1a8abSmrg Contributed by CodeSourcery, Inc.
463d1a8abSmrg
563d1a8abSmrg This file is part of GCC.
663d1a8abSmrg
763d1a8abSmrg GCC is free software; you can redistribute it and/or modify it under
863d1a8abSmrg the terms of the GNU General Public License as published by the Free
963d1a8abSmrg Software Foundation; either version 3, or (at your option) any later
1063d1a8abSmrg version.
1163d1a8abSmrg
1263d1a8abSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1363d1a8abSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
1463d1a8abSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1563d1a8abSmrg for more details.
1663d1a8abSmrg
1763d1a8abSmrg You should have received a copy of the GNU General Public License
1863d1a8abSmrg along with GCC; see the file COPYING3. If not see
1963d1a8abSmrg <http://www.gnu.org/licenses/>. */
2063d1a8abSmrg
2163d1a8abSmrg #include "config.h"
2263d1a8abSmrg #include "system.h"
2363d1a8abSmrg #include "coretypes.h"
2463d1a8abSmrg #include "tm.h"
2563d1a8abSmrg #include "function.h"
2663d1a8abSmrg #include "bitmap.h"
2763d1a8abSmrg #include "basic-block.h"
2863d1a8abSmrg #include "tree.h"
2963d1a8abSmrg #include "gimple.h"
3063d1a8abSmrg #include "cfghooks.h"
3163d1a8abSmrg #include "alloc-pool.h"
3263d1a8abSmrg #include "tree-pass.h"
3363d1a8abSmrg #include "tree-streamer.h"
3463d1a8abSmrg #include "cgraph.h"
3563d1a8abSmrg #include "opts.h"
3663d1a8abSmrg #include "toplev.h"
3763d1a8abSmrg #include "stor-layout.h"
3863d1a8abSmrg #include "symbol-summary.h"
3963d1a8abSmrg #include "tree-vrp.h"
4063d1a8abSmrg #include "ipa-prop.h"
4163d1a8abSmrg #include "debug.h"
4263d1a8abSmrg #include "lto.h"
4363d1a8abSmrg #include "lto-section-names.h"
4463d1a8abSmrg #include "splay-tree.h"
4563d1a8abSmrg #include "lto-partition.h"
4663d1a8abSmrg #include "context.h"
4763d1a8abSmrg #include "pass_manager.h"
48c7a68eb7Smrg #include "ipa-fnsummary.h"
4963d1a8abSmrg #include "ipa-utils.h"
5063d1a8abSmrg #include "gomp-constants.h"
5163d1a8abSmrg #include "lto-symtab.h"
5263d1a8abSmrg #include "stringpool.h"
5363d1a8abSmrg #include "fold-const.h"
54c7a68eb7Smrg #include "attribs.h"
5563d1a8abSmrg #include "builtins.h"
56*ec02198aSmrg #include "lto-common.h"
5763d1a8abSmrg
5863d1a8abSmrg
5963d1a8abSmrg /* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver. */
6063d1a8abSmrg static int lto_parallelism;
6163d1a8abSmrg
6263d1a8abSmrg /* Return true when NODE has a clone that is analyzed (i.e. we need
6363d1a8abSmrg to load its body even if the node itself is not needed). */
6463d1a8abSmrg
6563d1a8abSmrg static bool
has_analyzed_clone_p(struct cgraph_node * node)6663d1a8abSmrg has_analyzed_clone_p (struct cgraph_node *node)
6763d1a8abSmrg {
6863d1a8abSmrg struct cgraph_node *orig = node;
6963d1a8abSmrg node = node->clones;
7063d1a8abSmrg if (node)
7163d1a8abSmrg while (node != orig)
7263d1a8abSmrg {
7363d1a8abSmrg if (node->analyzed)
7463d1a8abSmrg return true;
7563d1a8abSmrg if (node->clones)
7663d1a8abSmrg node = node->clones;
7763d1a8abSmrg else if (node->next_sibling_clone)
7863d1a8abSmrg node = node->next_sibling_clone;
7963d1a8abSmrg else
8063d1a8abSmrg {
8163d1a8abSmrg while (node != orig && !node->next_sibling_clone)
8263d1a8abSmrg node = node->clone_of;
8363d1a8abSmrg if (node != orig)
8463d1a8abSmrg node = node->next_sibling_clone;
8563d1a8abSmrg }
8663d1a8abSmrg }
8763d1a8abSmrg return false;
8863d1a8abSmrg }
8963d1a8abSmrg
9063d1a8abSmrg /* Read the function body for the function associated with NODE. */
9163d1a8abSmrg
9263d1a8abSmrg static void
lto_materialize_function(struct cgraph_node * node)9363d1a8abSmrg lto_materialize_function (struct cgraph_node *node)
9463d1a8abSmrg {
9563d1a8abSmrg tree decl;
9663d1a8abSmrg
9763d1a8abSmrg decl = node->decl;
9863d1a8abSmrg /* Read in functions with body (analyzed nodes)
9963d1a8abSmrg and also functions that are needed to produce virtual clones. */
10063d1a8abSmrg if ((node->has_gimple_body_p () && node->analyzed)
10163d1a8abSmrg || node->used_as_abstract_origin
10263d1a8abSmrg || has_analyzed_clone_p (node))
10363d1a8abSmrg {
10463d1a8abSmrg /* Clones don't need to be read. */
10563d1a8abSmrg if (node->clone_of)
10663d1a8abSmrg return;
10763d1a8abSmrg if (DECL_FUNCTION_PERSONALITY (decl) && !first_personality_decl)
10863d1a8abSmrg first_personality_decl = DECL_FUNCTION_PERSONALITY (decl);
109*ec02198aSmrg /* If the file contains a function with a language specific EH
110*ec02198aSmrg personality set or with EH enabled initialize the backend EH
111*ec02198aSmrg machinery. */
112*ec02198aSmrg if (DECL_FUNCTION_PERSONALITY (decl)
113*ec02198aSmrg || opt_for_fn (decl, flag_exceptions))
114*ec02198aSmrg lto_init_eh ();
11563d1a8abSmrg }
11663d1a8abSmrg
11763d1a8abSmrg /* Let the middle end know about the function. */
11863d1a8abSmrg rest_of_decl_compilation (decl, 1, 0);
11963d1a8abSmrg }
12063d1a8abSmrg
121*ec02198aSmrg /* Materialize all the bodies for all the nodes in the callgraph. */
12263d1a8abSmrg
12363d1a8abSmrg static void
materialize_cgraph(void)124*ec02198aSmrg materialize_cgraph (void)
12563d1a8abSmrg {
126*ec02198aSmrg struct cgraph_node *node;
127*ec02198aSmrg timevar_id_t lto_timer;
12863d1a8abSmrg
129*ec02198aSmrg if (!quiet_flag)
130*ec02198aSmrg fprintf (stderr,
131*ec02198aSmrg flag_wpa ? "Materializing decls:" : "Reading function bodies:");
13263d1a8abSmrg
13363d1a8abSmrg
134*ec02198aSmrg FOR_EACH_FUNCTION (node)
13563d1a8abSmrg {
136*ec02198aSmrg if (node->lto_file_data)
13763d1a8abSmrg {
138*ec02198aSmrg lto_materialize_function (node);
139*ec02198aSmrg lto_stats.num_input_cgraph_nodes++;
14063d1a8abSmrg }
14163d1a8abSmrg }
14263d1a8abSmrg
14363d1a8abSmrg
144*ec02198aSmrg /* Start the appropriate timer depending on the mode that we are
145*ec02198aSmrg operating in. */
146*ec02198aSmrg lto_timer = (flag_wpa) ? TV_WHOPR_WPA
147*ec02198aSmrg : (flag_ltrans) ? TV_WHOPR_LTRANS
148*ec02198aSmrg : TV_LTO;
149*ec02198aSmrg timevar_push (lto_timer);
15063d1a8abSmrg
151*ec02198aSmrg current_function_decl = NULL;
152*ec02198aSmrg set_cfun (NULL);
15363d1a8abSmrg
154*ec02198aSmrg if (!quiet_flag)
155*ec02198aSmrg fprintf (stderr, "\n");
15663d1a8abSmrg
157*ec02198aSmrg timevar_pop (lto_timer);
15863d1a8abSmrg }
15963d1a8abSmrg
16063d1a8abSmrg /* Actually stream out ENCODER into TEMP_FILENAME. */
16163d1a8abSmrg
16263d1a8abSmrg static void
stream_out(char * temp_filename,lto_symtab_encoder_t encoder,int part)1630fc04c29Smrg stream_out (char *temp_filename, lto_symtab_encoder_t encoder, int part)
16463d1a8abSmrg {
16563d1a8abSmrg lto_file *file = lto_obj_file_open (temp_filename, true);
16663d1a8abSmrg if (!file)
167*ec02198aSmrg fatal_error (input_location, "%<lto_obj_file_open()%> failed");
16863d1a8abSmrg lto_set_current_out_file (file);
16963d1a8abSmrg
1700fc04c29Smrg gcc_assert (!dump_file);
1710fc04c29Smrg streamer_dump_file = dump_begin (TDI_lto_stream_out, NULL, part);
17263d1a8abSmrg ipa_write_optimization_summaries (encoder);
17363d1a8abSmrg
17463d1a8abSmrg free (CONST_CAST (char *, file->filename));
17563d1a8abSmrg
17663d1a8abSmrg lto_set_current_out_file (NULL);
17763d1a8abSmrg lto_obj_file_close (file);
17863d1a8abSmrg free (file);
1790fc04c29Smrg if (streamer_dump_file)
1800fc04c29Smrg {
1810fc04c29Smrg dump_end (TDI_lto_stream_out, streamer_dump_file);
1820fc04c29Smrg streamer_dump_file = NULL;
1830fc04c29Smrg }
18463d1a8abSmrg }
18563d1a8abSmrg
18663d1a8abSmrg /* Wait for forked process and signal errors. */
18763d1a8abSmrg #ifdef HAVE_WORKING_FORK
18863d1a8abSmrg static void
wait_for_child()18963d1a8abSmrg wait_for_child ()
19063d1a8abSmrg {
19163d1a8abSmrg int status;
19263d1a8abSmrg do
19363d1a8abSmrg {
19463d1a8abSmrg #ifndef WCONTINUED
19563d1a8abSmrg #define WCONTINUED 0
19663d1a8abSmrg #endif
19763d1a8abSmrg int w = waitpid (0, &status, WUNTRACED | WCONTINUED);
19863d1a8abSmrg if (w == -1)
19963d1a8abSmrg fatal_error (input_location, "waitpid failed");
20063d1a8abSmrg
20163d1a8abSmrg if (WIFEXITED (status) && WEXITSTATUS (status))
20263d1a8abSmrg fatal_error (input_location, "streaming subprocess failed");
20363d1a8abSmrg else if (WIFSIGNALED (status))
20463d1a8abSmrg fatal_error (input_location,
20563d1a8abSmrg "streaming subprocess was killed by signal");
20663d1a8abSmrg }
20763d1a8abSmrg while (!WIFEXITED (status) && !WIFSIGNALED (status));
20863d1a8abSmrg }
20963d1a8abSmrg #endif
21063d1a8abSmrg
2110fc04c29Smrg static void
stream_out_partitions_1(char * temp_filename,int blen,int min,int max)2120fc04c29Smrg stream_out_partitions_1 (char *temp_filename, int blen, int min, int max)
2130fc04c29Smrg {
2140fc04c29Smrg /* Write all the nodes in SET. */
2150fc04c29Smrg for (int p = min; p < max; p ++)
2160fc04c29Smrg {
2170fc04c29Smrg sprintf (temp_filename + blen, "%u.o", p);
2180fc04c29Smrg stream_out (temp_filename, ltrans_partitions[p]->encoder, p);
2190fc04c29Smrg ltrans_partitions[p]->encoder = NULL;
2200fc04c29Smrg }
2210fc04c29Smrg }
2220fc04c29Smrg
22363d1a8abSmrg /* Stream out ENCODER into TEMP_FILENAME
22463d1a8abSmrg Fork if that seems to help. */
22563d1a8abSmrg
22663d1a8abSmrg static void
stream_out_partitions(char * temp_filename,int blen,int min,int max,bool ARG_UNUSED (last))2270fc04c29Smrg stream_out_partitions (char *temp_filename, int blen, int min, int max,
22863d1a8abSmrg bool ARG_UNUSED (last))
22963d1a8abSmrg {
23063d1a8abSmrg #ifdef HAVE_WORKING_FORK
23163d1a8abSmrg static int nruns;
23263d1a8abSmrg
23363d1a8abSmrg if (lto_parallelism <= 1)
23463d1a8abSmrg {
2350fc04c29Smrg stream_out_partitions_1 (temp_filename, blen, min, max);
23663d1a8abSmrg return;
23763d1a8abSmrg }
23863d1a8abSmrg
23963d1a8abSmrg /* Do not run more than LTO_PARALLELISM streamings
24063d1a8abSmrg FIXME: we ignore limits on jobserver. */
24163d1a8abSmrg if (lto_parallelism > 0 && nruns >= lto_parallelism)
24263d1a8abSmrg {
24363d1a8abSmrg wait_for_child ();
24463d1a8abSmrg nruns --;
24563d1a8abSmrg }
24663d1a8abSmrg /* If this is not the last parallel partition, execute new
24763d1a8abSmrg streaming process. */
24863d1a8abSmrg if (!last)
24963d1a8abSmrg {
25063d1a8abSmrg pid_t cpid = fork ();
25163d1a8abSmrg
25263d1a8abSmrg if (!cpid)
25363d1a8abSmrg {
25463d1a8abSmrg setproctitle ("lto1-wpa-streaming");
2550fc04c29Smrg stream_out_partitions_1 (temp_filename, blen, min, max);
25663d1a8abSmrg exit (0);
25763d1a8abSmrg }
25863d1a8abSmrg /* Fork failed; lets do the job ourseleves. */
25963d1a8abSmrg else if (cpid == -1)
2600fc04c29Smrg stream_out_partitions_1 (temp_filename, blen, min, max);
26163d1a8abSmrg else
26263d1a8abSmrg nruns++;
26363d1a8abSmrg }
26463d1a8abSmrg /* Last partition; stream it and wait for all children to die. */
26563d1a8abSmrg else
26663d1a8abSmrg {
26763d1a8abSmrg int i;
2680fc04c29Smrg stream_out_partitions_1 (temp_filename, blen, min, max);
26963d1a8abSmrg for (i = 0; i < nruns; i++)
27063d1a8abSmrg wait_for_child ();
27163d1a8abSmrg }
27263d1a8abSmrg asm_nodes_output = true;
27363d1a8abSmrg #else
2740fc04c29Smrg stream_out_partitions_1 (temp_filename, blen, min, max);
27563d1a8abSmrg #endif
27663d1a8abSmrg }
27763d1a8abSmrg
27863d1a8abSmrg /* Write all output files in WPA mode and the file with the list of
27963d1a8abSmrg LTRANS units. */
28063d1a8abSmrg
28163d1a8abSmrg static void
lto_wpa_write_files(void)28263d1a8abSmrg lto_wpa_write_files (void)
28363d1a8abSmrg {
28463d1a8abSmrg unsigned i, n_sets;
28563d1a8abSmrg ltrans_partition part;
28663d1a8abSmrg FILE *ltrans_output_list_stream;
28763d1a8abSmrg char *temp_filename;
288c7a68eb7Smrg auto_vec <char *>temp_filenames;
289c7a68eb7Smrg auto_vec <int>temp_priority;
29063d1a8abSmrg size_t blen;
29163d1a8abSmrg
29263d1a8abSmrg /* Open the LTRANS output list. */
29363d1a8abSmrg if (!ltrans_output_list)
29463d1a8abSmrg fatal_error (input_location, "no LTRANS output list filename provided");
29563d1a8abSmrg
29663d1a8abSmrg timevar_push (TV_WHOPR_WPA);
29763d1a8abSmrg
29863d1a8abSmrg FOR_EACH_VEC_ELT (ltrans_partitions, i, part)
299*ec02198aSmrg lto_stats.num_output_symtab_nodes
300*ec02198aSmrg += lto_symtab_encoder_size (part->encoder);
30163d1a8abSmrg
30263d1a8abSmrg timevar_pop (TV_WHOPR_WPA);
30363d1a8abSmrg
30463d1a8abSmrg timevar_push (TV_WHOPR_WPA_IO);
30563d1a8abSmrg
3060fc04c29Smrg cgraph_node *node;
3070fc04c29Smrg /* Do body modifications needed for streaming before we fork out
3080fc04c29Smrg worker processes. */
3090fc04c29Smrg FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node)
3100fc04c29Smrg if (!node->clone_of && gimple_has_body_p (node->decl))
3110fc04c29Smrg lto_prepare_function_for_streaming (node);
3120fc04c29Smrg
313*ec02198aSmrg ggc_trim ();
314*ec02198aSmrg report_heap_memory_use ();
315*ec02198aSmrg
31663d1a8abSmrg /* Generate a prefix for the LTRANS unit files. */
31763d1a8abSmrg blen = strlen (ltrans_output_list);
31863d1a8abSmrg temp_filename = (char *) xmalloc (blen + sizeof ("2147483648.o"));
31963d1a8abSmrg strcpy (temp_filename, ltrans_output_list);
32063d1a8abSmrg if (blen > sizeof (".out")
32163d1a8abSmrg && strcmp (temp_filename + blen - sizeof (".out") + 1,
32263d1a8abSmrg ".out") == 0)
32363d1a8abSmrg temp_filename[blen - sizeof (".out") + 1] = '\0';
32463d1a8abSmrg blen = strlen (temp_filename);
32563d1a8abSmrg
32663d1a8abSmrg n_sets = ltrans_partitions.length ();
3270fc04c29Smrg unsigned sets_per_worker = n_sets;
3280fc04c29Smrg if (lto_parallelism > 1)
3290fc04c29Smrg {
3300fc04c29Smrg if (lto_parallelism > (int)n_sets)
3310fc04c29Smrg lto_parallelism = n_sets;
3320fc04c29Smrg sets_per_worker = (n_sets + lto_parallelism - 1) / lto_parallelism;
3330fc04c29Smrg }
33463d1a8abSmrg
33563d1a8abSmrg for (i = 0; i < n_sets; i++)
33663d1a8abSmrg {
33763d1a8abSmrg ltrans_partition part = ltrans_partitions[i];
33863d1a8abSmrg
33963d1a8abSmrg /* Write all the nodes in SET. */
34063d1a8abSmrg sprintf (temp_filename + blen, "%u.o", i);
34163d1a8abSmrg
34263d1a8abSmrg if (!quiet_flag)
343*ec02198aSmrg fprintf (stderr, " %s (%s %i insns)", temp_filename, part->name,
344*ec02198aSmrg part->insns);
34563d1a8abSmrg if (symtab->dump_file)
34663d1a8abSmrg {
34763d1a8abSmrg lto_symtab_encoder_iterator lsei;
34863d1a8abSmrg
349*ec02198aSmrg fprintf (symtab->dump_file,
350*ec02198aSmrg "Writing partition %s to file %s, %i insns\n",
35163d1a8abSmrg part->name, temp_filename, part->insns);
35263d1a8abSmrg fprintf (symtab->dump_file, " Symbols in partition: ");
353*ec02198aSmrg for (lsei = lsei_start_in_partition (part->encoder);
354*ec02198aSmrg !lsei_end_p (lsei);
35563d1a8abSmrg lsei_next_in_partition (&lsei))
35663d1a8abSmrg {
35763d1a8abSmrg symtab_node *node = lsei_node (lsei);
358*ec02198aSmrg fprintf (symtab->dump_file, "%s ", node->dump_asm_name ());
35963d1a8abSmrg }
36063d1a8abSmrg fprintf (symtab->dump_file, "\n Symbols in boundary: ");
36163d1a8abSmrg for (lsei = lsei_start (part->encoder); !lsei_end_p (lsei);
36263d1a8abSmrg lsei_next (&lsei))
36363d1a8abSmrg {
36463d1a8abSmrg symtab_node *node = lsei_node (lsei);
36563d1a8abSmrg if (!lto_symtab_encoder_in_partition_p (part->encoder, node))
36663d1a8abSmrg {
367*ec02198aSmrg fprintf (symtab->dump_file, "%s ", node->dump_asm_name ());
36863d1a8abSmrg cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
36963d1a8abSmrg if (cnode
370*ec02198aSmrg && lto_symtab_encoder_encode_body_p (part->encoder,
371*ec02198aSmrg cnode))
37263d1a8abSmrg fprintf (symtab->dump_file, "(body included)");
37363d1a8abSmrg else
37463d1a8abSmrg {
37563d1a8abSmrg varpool_node *vnode = dyn_cast <varpool_node *> (node);
37663d1a8abSmrg if (vnode
377*ec02198aSmrg && lto_symtab_encoder_encode_initializer_p (part->encoder,
378*ec02198aSmrg vnode))
37963d1a8abSmrg fprintf (symtab->dump_file, "(initializer included)");
38063d1a8abSmrg }
38163d1a8abSmrg }
38263d1a8abSmrg }
38363d1a8abSmrg fprintf (symtab->dump_file, "\n");
38463d1a8abSmrg }
38563d1a8abSmrg gcc_checking_assert (lto_symtab_encoder_size (part->encoder) || !i);
38663d1a8abSmrg
387c7a68eb7Smrg temp_priority.safe_push (part->insns);
38863d1a8abSmrg temp_filenames.safe_push (xstrdup (temp_filename));
38963d1a8abSmrg }
390*ec02198aSmrg memory_block_pool::trim (0);
3910fc04c29Smrg
3920fc04c29Smrg for (int set = 0; set < MAX (lto_parallelism, 1); set++)
3930fc04c29Smrg {
3940fc04c29Smrg stream_out_partitions (temp_filename, blen, set * sets_per_worker,
3950fc04c29Smrg MIN ((set + 1) * sets_per_worker, n_sets),
3960fc04c29Smrg set == MAX (lto_parallelism, 1) - 1);
3970fc04c29Smrg }
3980fc04c29Smrg
39963d1a8abSmrg ltrans_output_list_stream = fopen (ltrans_output_list, "w");
40063d1a8abSmrg if (ltrans_output_list_stream == NULL)
40163d1a8abSmrg fatal_error (input_location,
40263d1a8abSmrg "opening LTRANS output list %s: %m", ltrans_output_list);
40363d1a8abSmrg for (i = 0; i < n_sets; i++)
40463d1a8abSmrg {
40563d1a8abSmrg unsigned int len = strlen (temp_filenames[i]);
406c7a68eb7Smrg if (fprintf (ltrans_output_list_stream, "%i\n", temp_priority[i]) < 0
407c7a68eb7Smrg || fwrite (temp_filenames[i], 1, len, ltrans_output_list_stream) < len
40863d1a8abSmrg || fwrite ("\n", 1, 1, ltrans_output_list_stream) < 1)
40963d1a8abSmrg fatal_error (input_location, "writing to LTRANS output list %s: %m",
41063d1a8abSmrg ltrans_output_list);
41163d1a8abSmrg free (temp_filenames[i]);
41263d1a8abSmrg }
41363d1a8abSmrg
41463d1a8abSmrg lto_stats.num_output_files += n_sets;
41563d1a8abSmrg
41663d1a8abSmrg /* Close the LTRANS output list. */
41763d1a8abSmrg if (fclose (ltrans_output_list_stream))
41863d1a8abSmrg fatal_error (input_location,
41963d1a8abSmrg "closing LTRANS output list %s: %m", ltrans_output_list);
42063d1a8abSmrg
42163d1a8abSmrg free_ltrans_partitions ();
42263d1a8abSmrg free (temp_filename);
42363d1a8abSmrg
42463d1a8abSmrg timevar_pop (TV_WHOPR_WPA_IO);
42563d1a8abSmrg }
42663d1a8abSmrg
42763d1a8abSmrg /* Perform whole program analysis (WPA) on the callgraph and write out the
42863d1a8abSmrg optimization plan. */
42963d1a8abSmrg
43063d1a8abSmrg static void
do_whole_program_analysis(void)43163d1a8abSmrg do_whole_program_analysis (void)
43263d1a8abSmrg {
43363d1a8abSmrg symtab_node *node;
43463d1a8abSmrg
43563d1a8abSmrg lto_parallelism = 1;
43663d1a8abSmrg
4370fc04c29Smrg /* TODO: jobserver communication is not supported, yet. */
43863d1a8abSmrg if (!strcmp (flag_wpa, "jobserver"))
439*ec02198aSmrg lto_parallelism = param_max_lto_streaming_parallelism;
44063d1a8abSmrg else
44163d1a8abSmrg {
44263d1a8abSmrg lto_parallelism = atoi (flag_wpa);
44363d1a8abSmrg if (lto_parallelism <= 0)
44463d1a8abSmrg lto_parallelism = 0;
445*ec02198aSmrg if (lto_parallelism >= param_max_lto_streaming_parallelism)
446*ec02198aSmrg lto_parallelism = param_max_lto_streaming_parallelism;
44763d1a8abSmrg }
44863d1a8abSmrg
44963d1a8abSmrg timevar_start (TV_PHASE_OPT_GEN);
45063d1a8abSmrg
45163d1a8abSmrg /* Note that since we are in WPA mode, materialize_cgraph will not
45263d1a8abSmrg actually read in all the function bodies. It only materializes
45363d1a8abSmrg the decls and cgraph nodes so that analysis can be performed. */
45463d1a8abSmrg materialize_cgraph ();
45563d1a8abSmrg
45663d1a8abSmrg /* Reading in the cgraph uses different timers, start timing WPA now. */
45763d1a8abSmrg timevar_push (TV_WHOPR_WPA);
45863d1a8abSmrg
45963d1a8abSmrg if (pre_ipa_mem_report)
460*ec02198aSmrg dump_memory_report ("Memory consumption before IPA");
46163d1a8abSmrg
46263d1a8abSmrg symtab->function_flags_ready = true;
46363d1a8abSmrg
46463d1a8abSmrg if (symtab->dump_file)
465c7a68eb7Smrg symtab->dump (symtab->dump_file);
46663d1a8abSmrg bitmap_obstack_initialize (NULL);
46763d1a8abSmrg symtab->state = IPA_SSA;
46863d1a8abSmrg
46963d1a8abSmrg execute_ipa_pass_list (g->get_passes ()->all_regular_ipa_passes);
47063d1a8abSmrg
47163d1a8abSmrg /* When WPA analysis raises errors, do not bother to output anything. */
47263d1a8abSmrg if (seen_error ())
47363d1a8abSmrg return;
47463d1a8abSmrg
47563d1a8abSmrg /* We are about to launch the final LTRANS phase, stop the WPA timer. */
47663d1a8abSmrg timevar_pop (TV_WHOPR_WPA);
47763d1a8abSmrg
478*ec02198aSmrg /* We are no longer going to stream in anything. Free some memory. */
479*ec02198aSmrg lto_free_file_name_hash ();
480*ec02198aSmrg
481*ec02198aSmrg
48263d1a8abSmrg timevar_push (TV_WHOPR_PARTITIONING);
4830fc04c29Smrg
4840fc04c29Smrg gcc_assert (!dump_file);
4850fc04c29Smrg dump_file = dump_begin (partition_dump_id, NULL);
4860fc04c29Smrg
4870fc04c29Smrg if (dump_file)
4880fc04c29Smrg symtab->dump (dump_file);
4890fc04c29Smrg
4900fc04c29Smrg symtab_node::checking_verify_symtab_nodes ();
4910fc04c29Smrg bitmap_obstack_release (NULL);
49263d1a8abSmrg if (flag_lto_partition == LTO_PARTITION_1TO1)
49363d1a8abSmrg lto_1_to_1_map ();
49463d1a8abSmrg else if (flag_lto_partition == LTO_PARTITION_MAX)
49563d1a8abSmrg lto_max_map ();
49663d1a8abSmrg else if (flag_lto_partition == LTO_PARTITION_ONE)
49763d1a8abSmrg lto_balanced_map (1, INT_MAX);
49863d1a8abSmrg else if (flag_lto_partition == LTO_PARTITION_BALANCED)
499*ec02198aSmrg lto_balanced_map (param_lto_partitions,
500*ec02198aSmrg param_max_partition_size);
50163d1a8abSmrg else
50263d1a8abSmrg gcc_unreachable ();
50363d1a8abSmrg
504*ec02198aSmrg /* Size summaries are needed for balanced partitioning. Free them now so
50563d1a8abSmrg the memory can be used for streamer caches. */
506*ec02198aSmrg ipa_free_size_summary ();
50763d1a8abSmrg
50863d1a8abSmrg /* AUX pointers are used by partitioning code to bookkeep number of
50963d1a8abSmrg partitions symbol is in. This is no longer needed. */
51063d1a8abSmrg FOR_EACH_SYMBOL (node)
51163d1a8abSmrg node->aux = NULL;
51263d1a8abSmrg
51363d1a8abSmrg lto_stats.num_cgraph_partitions += ltrans_partitions.length ();
51463d1a8abSmrg
51563d1a8abSmrg /* Find out statics that need to be promoted
51663d1a8abSmrg to globals with hidden visibility because they are accessed from multiple
51763d1a8abSmrg partitions. */
51863d1a8abSmrg lto_promote_cross_file_statics ();
5190fc04c29Smrg if (dump_file)
5200fc04c29Smrg dump_end (partition_dump_id, dump_file);
5210fc04c29Smrg dump_file = NULL;
52263d1a8abSmrg timevar_pop (TV_WHOPR_PARTITIONING);
52363d1a8abSmrg
52463d1a8abSmrg timevar_stop (TV_PHASE_OPT_GEN);
52563d1a8abSmrg
52663d1a8abSmrg /* Collect a last time - in lto_wpa_write_files we may end up forking
52763d1a8abSmrg with the idea that this doesn't increase memory usage. So we
52863d1a8abSmrg absoultely do not want to collect after that. */
52963d1a8abSmrg ggc_collect ();
53063d1a8abSmrg
53163d1a8abSmrg timevar_start (TV_PHASE_STREAM_OUT);
53263d1a8abSmrg if (!quiet_flag)
53363d1a8abSmrg {
53463d1a8abSmrg fprintf (stderr, "\nStreaming out");
53563d1a8abSmrg fflush (stderr);
53663d1a8abSmrg }
53763d1a8abSmrg lto_wpa_write_files ();
53863d1a8abSmrg if (!quiet_flag)
53963d1a8abSmrg fprintf (stderr, "\n");
54063d1a8abSmrg timevar_stop (TV_PHASE_STREAM_OUT);
54163d1a8abSmrg
54263d1a8abSmrg if (post_ipa_mem_report)
543*ec02198aSmrg dump_memory_report ("Memory consumption after IPA");
54463d1a8abSmrg
54563d1a8abSmrg /* Show the LTO report before launching LTRANS. */
54663d1a8abSmrg if (flag_lto_report || (flag_wpa && flag_lto_report_wpa))
54763d1a8abSmrg print_lto_report_1 ();
54863d1a8abSmrg if (mem_report_wpa)
549*ec02198aSmrg dump_memory_report ("Final");
55063d1a8abSmrg }
55163d1a8abSmrg
55263d1a8abSmrg /* Create artificial pointers for "omp declare target link" vars. */
55363d1a8abSmrg
55463d1a8abSmrg static void
offload_handle_link_vars(void)55563d1a8abSmrg offload_handle_link_vars (void)
55663d1a8abSmrg {
55763d1a8abSmrg #ifdef ACCEL_COMPILER
55863d1a8abSmrg varpool_node *var;
55963d1a8abSmrg FOR_EACH_VARIABLE (var)
56063d1a8abSmrg if (lookup_attribute ("omp declare target link",
56163d1a8abSmrg DECL_ATTRIBUTES (var->decl)))
56263d1a8abSmrg {
56363d1a8abSmrg tree type = build_pointer_type (TREE_TYPE (var->decl));
564*ec02198aSmrg tree link_ptr_var = build_decl (UNKNOWN_LOCATION, VAR_DECL,
565*ec02198aSmrg clone_function_name (var->decl,
566*ec02198aSmrg "linkptr"), type);
56763d1a8abSmrg TREE_USED (link_ptr_var) = 1;
56863d1a8abSmrg TREE_STATIC (link_ptr_var) = 1;
569*ec02198aSmrg TREE_PUBLIC (link_ptr_var) = TREE_PUBLIC (var->decl);
57063d1a8abSmrg DECL_ARTIFICIAL (link_ptr_var) = 1;
57163d1a8abSmrg SET_DECL_ASSEMBLER_NAME (link_ptr_var, DECL_NAME (link_ptr_var));
57263d1a8abSmrg SET_DECL_VALUE_EXPR (var->decl, build_simple_mem_ref (link_ptr_var));
57363d1a8abSmrg DECL_HAS_VALUE_EXPR_P (var->decl) = 1;
57463d1a8abSmrg }
57563d1a8abSmrg #endif
57663d1a8abSmrg }
57763d1a8abSmrg
578*ec02198aSmrg unsigned int
lto_option_lang_mask(void)579*ec02198aSmrg lto_option_lang_mask (void)
580*ec02198aSmrg {
581*ec02198aSmrg return CL_LTO;
582*ec02198aSmrg }
58363d1a8abSmrg
58463d1a8abSmrg /* Main entry point for the GIMPLE front end. This front end has
58563d1a8abSmrg three main personalities:
58663d1a8abSmrg
58763d1a8abSmrg - LTO (-flto). All the object files on the command line are
58863d1a8abSmrg loaded in memory and processed as a single translation unit.
58963d1a8abSmrg This is the traditional link-time optimization behavior.
59063d1a8abSmrg
59163d1a8abSmrg - WPA (-fwpa). Only the callgraph and summary information for
59263d1a8abSmrg files in the command file are loaded. A single callgraph
59363d1a8abSmrg (without function bodies) is instantiated for the whole set of
59463d1a8abSmrg files. IPA passes are only allowed to analyze the call graph
59563d1a8abSmrg and make transformation decisions. The callgraph is
59663d1a8abSmrg partitioned, each partition is written to a new object file
59763d1a8abSmrg together with the transformation decisions.
59863d1a8abSmrg
59963d1a8abSmrg - LTRANS (-fltrans). Similar to -flto but it prevents the IPA
60063d1a8abSmrg summary files from running again. Since WPA computed summary
60163d1a8abSmrg information and decided what transformations to apply, LTRANS
60263d1a8abSmrg simply applies them. */
60363d1a8abSmrg
60463d1a8abSmrg void
lto_main(void)60563d1a8abSmrg lto_main (void)
60663d1a8abSmrg {
60763d1a8abSmrg /* LTO is called as a front end, even though it is not a front end.
60863d1a8abSmrg Because it is called as a front end, TV_PHASE_PARSING and
60963d1a8abSmrg TV_PARSE_GLOBAL are active, and we need to turn them off while
61063d1a8abSmrg doing LTO. Later we turn them back on so they are active up in
61163d1a8abSmrg toplev.c. */
61263d1a8abSmrg timevar_pop (TV_PARSE_GLOBAL);
61363d1a8abSmrg timevar_stop (TV_PHASE_PARSING);
61463d1a8abSmrg
61563d1a8abSmrg timevar_start (TV_PHASE_SETUP);
61663d1a8abSmrg
61763d1a8abSmrg /* Initialize the LTO front end. */
618*ec02198aSmrg lto_fe_init ();
61963d1a8abSmrg
62063d1a8abSmrg timevar_stop (TV_PHASE_SETUP);
62163d1a8abSmrg timevar_start (TV_PHASE_STREAM_IN);
62263d1a8abSmrg
62363d1a8abSmrg /* Read all the symbols and call graph from all the files in the
62463d1a8abSmrg command line. */
62563d1a8abSmrg read_cgraph_and_symbols (num_in_fnames, in_fnames);
62663d1a8abSmrg
62763d1a8abSmrg timevar_stop (TV_PHASE_STREAM_IN);
62863d1a8abSmrg
62963d1a8abSmrg if (!seen_error ())
63063d1a8abSmrg {
63163d1a8abSmrg offload_handle_link_vars ();
63263d1a8abSmrg
63363d1a8abSmrg /* If WPA is enabled analyze the whole call graph and create an
63463d1a8abSmrg optimization plan. Otherwise, read in all the function
63563d1a8abSmrg bodies and continue with optimization. */
63663d1a8abSmrg if (flag_wpa)
63763d1a8abSmrg do_whole_program_analysis ();
63863d1a8abSmrg else
63963d1a8abSmrg {
64063d1a8abSmrg timevar_start (TV_PHASE_OPT_GEN);
64163d1a8abSmrg
64263d1a8abSmrg materialize_cgraph ();
64363d1a8abSmrg if (!flag_ltrans)
64463d1a8abSmrg lto_promote_statics_nonwpa ();
64563d1a8abSmrg
64663d1a8abSmrg /* Annotate the CU DIE and mark the early debug phase as finished. */
6470fc04c29Smrg debuginfo_early_start ();
64863d1a8abSmrg debug_hooks->early_finish ("<artificial>");
6490fc04c29Smrg debuginfo_early_stop ();
65063d1a8abSmrg
65163d1a8abSmrg /* Let the middle end know that we have read and merged all of
65263d1a8abSmrg the input files. */
65363d1a8abSmrg symtab->compile ();
65463d1a8abSmrg
65563d1a8abSmrg timevar_stop (TV_PHASE_OPT_GEN);
65663d1a8abSmrg
65763d1a8abSmrg /* FIXME lto, if the processes spawned by WPA fail, we miss
65863d1a8abSmrg the chance to print WPA's report, so WPA will call
65963d1a8abSmrg print_lto_report before launching LTRANS. If LTRANS was
66063d1a8abSmrg launched directly by the driver we would not need to do
66163d1a8abSmrg this. */
66263d1a8abSmrg if (flag_lto_report || (flag_wpa && flag_lto_report_wpa))
66363d1a8abSmrg print_lto_report_1 ();
66463d1a8abSmrg }
66563d1a8abSmrg }
66663d1a8abSmrg
66763d1a8abSmrg /* Here we make LTO pretend to be a parser. */
66863d1a8abSmrg timevar_start (TV_PHASE_PARSING);
66963d1a8abSmrg timevar_push (TV_PARSE_GLOBAL);
67063d1a8abSmrg }
671