xref: /netbsd/external/gpl3/gcc.old/dist/gcc/lto/lto.c (revision ec02198a)
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