diff gcc/lto/lto.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/gcc/lto/lto.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/lto/lto.c	Thu Oct 25 07:37:49 2018 +0900
@@ -1,5 +1,5 @@
 /* Top-level LTO routines.
-   Copyright (C) 2009-2017 Free Software Foundation, Inc.
+   Copyright (C) 2009-2018 Free Software Foundation, Inc.
    Contributed by CodeSourcery, Inc.
 
 This file is part of GCC.
@@ -54,6 +54,7 @@
 #include "stringpool.h"
 #include "fold-const.h"
 #include "attribs.h"
+#include "builtins.h"
 
 
 /* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver.  */
@@ -316,7 +317,7 @@
 
   if (VECTOR_TYPE_P (type))
     {
-      hstate.add_int (TYPE_VECTOR_SUBPARTS (type));
+      hstate.add_poly_int (TYPE_VECTOR_SUBPARTS (type));
       hstate.add_int (TYPE_UNSIGNED (type));
     }
 
@@ -830,12 +831,19 @@
 register_resolution (struct lto_file_decl_data *file_data, tree decl,
 		     enum ld_plugin_symbol_resolution resolution)
 {
+  bool existed;
   if (resolution == LDPR_UNKNOWN)
     return;
   if (!file_data->resolution_map)
     file_data->resolution_map
       = new hash_map<tree, ld_plugin_symbol_resolution>;
-  file_data->resolution_map->put (decl, resolution);
+  ld_plugin_symbol_resolution_t &res
+     = file_data->resolution_map->get_or_insert (decl, &existed);
+  if (!existed
+      || resolution == LDPR_PREVAILING_DEF_IRONLY
+      || resolution == LDPR_PREVAILING_DEF
+      || resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
+    res = resolution;
 }
 
 /* Register DECL with the global symbol table and change its
@@ -878,6 +886,18 @@
 			 decl, get_resolution (data_in, ix));
 }
 
+/* Check if T is a decl and needs register its resolution info.  */
+
+static void
+lto_maybe_register_decl (struct data_in *data_in, tree t, unsigned ix)
+{
+  if (TREE_CODE (t) == VAR_DECL)
+    lto_register_var_decl_in_symtab (data_in, t, ix);
+  else if (TREE_CODE (t) == FUNCTION_DECL
+	   && !fndecl_built_in_p (t))
+    lto_register_function_decl_in_symtab (data_in, t, ix);
+}
+
 
 /* For the type T re-materialize it in the type variant list and
    the pointer/reference-to chains.  */
@@ -1065,6 +1085,12 @@
 			TREE_FIXED_CST_PTR (t1), TREE_FIXED_CST_PTR (t2)))
       return false;
 
+  if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
+    {
+      compare_values (VECTOR_CST_LOG2_NPATTERNS);
+      compare_values (VECTOR_CST_NELTS_PER_PATTERN);
+    }
+
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
     {
       compare_values (DECL_MODE);
@@ -1087,6 +1113,7 @@
 	{
 	  compare_values (DECL_PACKED);
 	  compare_values (DECL_NONADDRESSABLE_P);
+	  compare_values (DECL_PADDING_P);
 	  compare_values (DECL_OFFSET_ALIGN);
 	}
       else if (code == VAR_DECL)
@@ -1165,6 +1192,7 @@
 	compare_values (TYPE_NONALIASED_COMPONENT);
       if (AGGREGATE_TYPE_P (t1))
 	compare_values (TYPE_TYPELESS_STORAGE);
+      compare_values (TYPE_EMPTY_P);
       compare_values (TYPE_PACKED);
       compare_values (TYPE_RESTRICT);
       compare_values (TYPE_USER_ALIGN);
@@ -1194,8 +1222,8 @@
       return false;
 
   if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION))
-    if (memcmp (TREE_OPTIMIZATION (t1), TREE_OPTIMIZATION (t2),
-		sizeof (struct cl_optimization)) != 0)
+    if (!cl_optimization_option_eq (TREE_OPTIMIZATION (t1),
+				    TREE_OPTIMIZATION (t2)))
       return false;
 
   if (CODE_CONTAINS_STRUCT (code, TS_BINFO))
@@ -1279,11 +1307,12 @@
 
   if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
     {
-      unsigned i;
       /* Note that the number of elements for EXPR has already been emitted
 	 in EXPR's header (see streamer_write_tree_header).  */
-      for (i = 0; i < VECTOR_CST_NELTS (t1); ++i)
-	compare_tree_edges (VECTOR_CST_ELT (t1, i), VECTOR_CST_ELT (t2, i));
+      unsigned int count = vector_cst_encoded_nelts (t1);
+      for (unsigned int i = 0; i < count; ++i)
+	compare_tree_edges (VECTOR_CST_ENCODED_ELT (t1, i),
+			    VECTOR_CST_ENCODED_ELT (t2, i));
     }
 
   if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX))
@@ -1608,7 +1637,25 @@
 	  /* Fixup the streamer cache with the prevailing nodes according
 	     to the tree node mapping computed by compare_tree_sccs.  */
 	  if (len == 1)
-	    streamer_tree_cache_replace_tree (cache, pscc->entries[0], from);
+	    {
+	      /* If we got a debug reference queued, see if the prevailing
+	         tree has a debug reference and if not, register the one
+		 for the tree we are about to throw away.  */
+	      if (dref_queue.length () == 1)
+		{
+		  dref_entry e = dref_queue.pop ();
+		  gcc_assert (e.decl
+			      == streamer_tree_cache_get_tree (cache, from));
+		  const char *sym;
+		  unsigned HOST_WIDE_INT off;
+		  if (!debug_hooks->die_ref_for_decl (pscc->entries[0], &sym,
+						      &off))
+		    debug_hooks->register_external_die (pscc->entries[0],
+							e.sym, e.off);
+		}
+	      lto_maybe_register_decl (data_in, pscc->entries[0], from);
+	      streamer_tree_cache_replace_tree (cache, pscc->entries[0], from);
+	    }
 	  else
 	    {
 	      tree *map2 = XALLOCAVEC (tree, 2 * len);
@@ -1620,8 +1667,12 @@
 	      qsort (map2, len, 2 * sizeof (tree), cmp_tree);
 	      qsort (map, len, 2 * sizeof (tree), cmp_tree);
 	      for (unsigned i = 0; i < len; ++i)
-		streamer_tree_cache_replace_tree (cache, map[2*i],
-						  (uintptr_t)map2[2*i]);
+		{
+		  lto_maybe_register_decl (data_in, map[2*i],
+					   (uintptr_t)map2[2*i]);
+		  streamer_tree_cache_replace_tree (cache, map[2*i],
+						    (uintptr_t)map2[2*i]);
+		}
 	    }
 
 	  /* Free the tree nodes from the read SCC.  */
@@ -1633,7 +1684,9 @@
 	      free_node (scc->entries[i]);
 	    }
 
-	  /* Drop DIE references.  */
+	  /* Drop DIE references.
+	     ???  Do as in the size-one SCC case which involves sorting
+	     the queue.  */
 	  dref_queue.truncate (0);
 
 	  break;
@@ -1659,6 +1712,36 @@
 }
 
 
+/* Compare types based on source file location.  */
+
+static int
+cmp_type_location (const void *p1_, const void *p2_)
+{
+  tree *p1 = (tree*)(const_cast<void *>(p1_));
+  tree *p2 = (tree*)(const_cast<void *>(p2_));
+  if (*p1 == *p2)
+    return 0;
+
+  tree tname1 = TYPE_NAME (*p1);
+  tree tname2 = TYPE_NAME (*p2);
+  expanded_location xloc1 = expand_location (DECL_SOURCE_LOCATION (tname1));
+  expanded_location xloc2 = expand_location (DECL_SOURCE_LOCATION (tname2));
+
+  const char *f1 = lbasename (xloc1.file);
+  const char *f2 = lbasename (xloc2.file);
+  int r = strcmp (f1, f2);
+  if (r == 0)
+    {
+      int l1 = xloc1.line;
+      int l2 = xloc2.line;
+      if (l1 != l2)
+	return l1 - l2;
+      return xloc1.column - xloc2.column;
+    }
+  else
+    return r;
+}
+
 /* Read all the symbols from buffer DATA, using descriptors in DECL_DATA.
    RESOLUTIONS is the set of symbols picked by the linker (read from the
    resolution file when the linker plugin is being used).  */
@@ -1675,6 +1758,7 @@
   unsigned int i;
   const uint32_t *data_ptr, *data_end;
   uint32_t num_decl_states;
+  auto_vec<tree> odr_types;
 
   lto_input_block ib_main ((const char *) data + main_offset,
 			   header->main_size, decl_data->mode_table);
@@ -1736,14 +1820,15 @@
 		  seen_type = true;
 		  num_prevailing_types++;
 		  lto_fixup_prevailing_type (t);
-		}
-	      /* Compute the canonical type of all types.
-		 ???  Should be able to assert that !TYPE_CANONICAL.  */
-	      if (TYPE_P (t) && !TYPE_CANONICAL (t))
-		{
-		  gimple_register_canonical_type (t);
+
+		  /* Compute the canonical type of all types.
+		     Because SCC components are streamed in random (hash) order
+		     we may have encountered the type before while registering
+		     type canonical of a derived type in the same SCC.  */
+		  if (!TYPE_CANONICAL (t))
+		    gimple_register_canonical_type (t);
 		  if (odr_type_p (t))
-		    register_odr_type (t);
+		    odr_types.safe_push (t);
 		}
 	      /* Link shared INTEGER_CSTs into TYPE_CACHED_VALUEs of its
 		 type which is also member of this SCC.  */
@@ -1752,13 +1837,7 @@
 		cache_integer_cst (t);
 	      if (!flag_ltrans)
 		{
-		  /* Register variables and functions with the
-		     symbol table.  */
-		  if (TREE_CODE (t) == VAR_DECL)
-		    lto_register_var_decl_in_symtab (data_in, t, from + i);
-		  else if (TREE_CODE (t) == FUNCTION_DECL
-			   && !DECL_BUILT_IN (t))
-		    lto_register_function_decl_in_symtab (data_in, t, from + i);
+		  lto_maybe_register_decl (data_in, t, from + i);
 		  /* Scan the tree for references to global functions or
 		     variables and record those for later fixup.  */
 		  if (mentions_vars_p (t))
@@ -1811,6 +1890,15 @@
       *slot = state;
     }
 
+  /* Sort types for the file before registering in ODR machinery.  */
+  if (lto_location_cache::current_cache)
+    lto_location_cache::current_cache->apply_location_cache ();
+  odr_types.qsort (cmp_type_location);
+
+  /* Register ODR types.  */
+  for (unsigned i = 0; i < odr_types.length (); i++)
+    register_odr_type (odr_types[i]);
+
   if (data_ptr != data_end)
     internal_error ("bytecode stream: garbage at the end of symbols section");
 
@@ -1987,7 +2075,7 @@
       file_data = ggc_alloc<lto_file_decl_data> ();
       memset(file_data, 0, sizeof (struct lto_file_decl_data));
       file_data->id = id;
-      file_data->section_hash_table = lto_obj_create_section_hash_table ();;
+      file_data->section_hash_table = lto_obj_create_section_hash_table ();
       lto_splay_tree_insert (file_ids, id, file_data);
 
       /* Maintain list in linker order */
@@ -2252,48 +2340,18 @@
 
 static lto_file *current_lto_file;
 
-/* Helper for qsort; compare partitions and return one with smaller size.
-   We sort from greatest to smallest so parallel build doesn't stale on the
-   longest compilation being executed too late.  */
-
-static int
-cmp_partitions_size (const void *a, const void *b)
-{
-  const struct ltrans_partition_def *pa
-     = *(struct ltrans_partition_def *const *)a;
-  const struct ltrans_partition_def *pb
-     = *(struct ltrans_partition_def *const *)b;
-  return pb->insns - pa->insns;
-}
-
-/* Helper for qsort; compare partitions and return one with smaller order.  */
-
-static int
-cmp_partitions_order (const void *a, const void *b)
-{
-  const struct ltrans_partition_def *pa
-     = *(struct ltrans_partition_def *const *)a;
-  const struct ltrans_partition_def *pb
-     = *(struct ltrans_partition_def *const *)b;
-  int ordera = -1, orderb = -1;
-
-  if (lto_symtab_encoder_size (pa->encoder))
-    ordera = lto_symtab_encoder_deref (pa->encoder, 0)->order;
-  if (lto_symtab_encoder_size (pb->encoder))
-    orderb = lto_symtab_encoder_deref (pb->encoder, 0)->order;
-  return orderb - ordera;
-}
-
 /* Actually stream out ENCODER into TEMP_FILENAME.  */
 
 static void
-do_stream_out (char *temp_filename, lto_symtab_encoder_t encoder)
+do_stream_out (char *temp_filename, lto_symtab_encoder_t encoder, int part)
 {
   lto_file *file = lto_obj_file_open (temp_filename, true);
   if (!file)
     fatal_error (input_location, "lto_obj_file_open() failed");
   lto_set_current_out_file (file);
 
+  gcc_assert (!dump_file);
+  streamer_dump_file = dump_begin (TDI_lto_stream_out, NULL, part);
   ipa_write_optimization_summaries (encoder);
 
   free (CONST_CAST (char *, file->filename));
@@ -2301,6 +2359,11 @@
   lto_set_current_out_file (NULL);
   lto_obj_file_close (file);
   free (file);
+  if (streamer_dump_file)
+    {
+      dump_end (TDI_lto_stream_out, streamer_dump_file);
+      streamer_dump_file = NULL;
+    }
 }
 
 /* Wait for forked process and signal errors.  */
@@ -2333,14 +2396,14 @@
 
 static void
 stream_out (char *temp_filename, lto_symtab_encoder_t encoder,
-	    bool ARG_UNUSED (last))
+	    bool ARG_UNUSED (last), int part)
 {
 #ifdef HAVE_WORKING_FORK
   static int nruns;
 
   if (lto_parallelism <= 1)
     {
-      do_stream_out (temp_filename, encoder);
+      do_stream_out (temp_filename, encoder, part);
       return;
     }
 
@@ -2360,12 +2423,12 @@
       if (!cpid)
 	{
 	  setproctitle ("lto1-wpa-streaming");
-	  do_stream_out (temp_filename, encoder);
+	  do_stream_out (temp_filename, encoder, part);
 	  exit (0);
 	}
       /* Fork failed; lets do the job ourseleves.  */
       else if (cpid == -1)
-        do_stream_out (temp_filename, encoder);
+        do_stream_out (temp_filename, encoder, part);
       else
 	nruns++;
     }
@@ -2373,13 +2436,13 @@
   else
     {
       int i;
-      do_stream_out (temp_filename, encoder);
+      do_stream_out (temp_filename, encoder, part);
       for (i = 0; i < nruns; i++)
 	wait_for_child ();
     }
   asm_nodes_output = true;
 #else
-  do_stream_out (temp_filename, encoder);
+  do_stream_out (temp_filename, encoder, part);
 #endif
 }
 
@@ -2393,7 +2456,8 @@
   ltrans_partition part;
   FILE *ltrans_output_list_stream;
   char *temp_filename;
-  vec <char *>temp_filenames = vNULL;
+  auto_vec <char *>temp_filenames;
+  auto_vec <int>temp_priority;
   size_t blen;
 
   /* Open the LTRANS output list.  */
@@ -2421,15 +2485,6 @@
 
   n_sets = ltrans_partitions.length ();
 
-  /* Sort partitions by size so small ones are compiled last.
-     FIXME: Even when not reordering we may want to output one list for parallel make
-     and other for final link command.  */
-
-  if (!flag_profile_reorder_functions || !flag_profile_use)
-    ltrans_partitions.qsort (flag_toplevel_reorder
-			   ? cmp_partitions_size
-			   : cmp_partitions_order);
-
   for (i = 0; i < n_sets; i++)
     {
       ltrans_partition part = ltrans_partitions[i];
@@ -2477,10 +2532,11 @@
 	}
       gcc_checking_assert (lto_symtab_encoder_size (part->encoder) || !i);
 
-      stream_out (temp_filename, part->encoder, i == n_sets - 1);
+      stream_out (temp_filename, part->encoder, i == n_sets - 1, i);
 
       part->encoder = NULL;
 
+      temp_priority.safe_push (part->insns);
       temp_filenames.safe_push (xstrdup (temp_filename));
     }
   ltrans_output_list_stream = fopen (ltrans_output_list, "w");
@@ -2490,13 +2546,13 @@
   for (i = 0; i < n_sets; i++)
     {
       unsigned int len = strlen (temp_filenames[i]);
-      if (fwrite (temp_filenames[i], 1, len, ltrans_output_list_stream) < len
+      if (fprintf (ltrans_output_list_stream, "%i\n", temp_priority[i]) < 0
+	  || fwrite (temp_filenames[i], 1, len, ltrans_output_list_stream) < len
 	  || fwrite ("\n", 1, 1, ltrans_output_list_stream) < 1)
 	fatal_error (input_location, "writing to LTRANS output list %s: %m",
 		     ltrans_output_list);
      free (temp_filenames[i]);
     }
-  temp_filenames.release();
 
   lto_stats.num_output_files += n_sets;
 
@@ -2864,13 +2920,26 @@
 
   /* Store resolutions into the symbol table.  */
 
-  ld_plugin_symbol_resolution_t *res;
   FOR_EACH_SYMBOL (snode)
-    if (snode->real_symbol_p ()
-	&& snode->lto_file_data
-	&& snode->lto_file_data->resolution_map
-	&& (res = snode->lto_file_data->resolution_map->get (snode->decl)))
-      snode->resolution = *res;
+    if (snode->externally_visible && snode->real_symbol_p ()
+	&& snode->lto_file_data && snode->lto_file_data->resolution_map
+	&& !(TREE_CODE (snode->decl) == FUNCTION_DECL
+	     && fndecl_built_in_p (snode->decl))
+	&& !(VAR_P (snode->decl) && DECL_HARD_REGISTER (snode->decl)))
+      {
+	ld_plugin_symbol_resolution_t *res;
+
+	res = snode->lto_file_data->resolution_map->get (snode->decl);
+	if (!res || *res == LDPR_UNKNOWN)
+	  {
+	    if (snode->output_to_lto_symbol_table_p ())
+	      fatal_error (input_location, "missing resolution data for %s",
+		           IDENTIFIER_POINTER
+			     (DECL_ASSEMBLER_NAME (snode->decl)));
+	  }
+	else
+          snode->resolution = *res;
+      }
   for (i = 0; all_file_decl_data[i]; i++)
     if (all_file_decl_data[i]->resolution_map)
       {
@@ -2928,29 +2997,43 @@
       all_file_decl_data[i]->current_decl_state = NULL; 
     }
 
-  /* Finally merge the cgraph according to the decl merging decisions.  */
-  timevar_push (TV_IPA_LTO_CGRAPH_MERGE);
-  if (symtab->dump_file)
-    {
-      fprintf (symtab->dump_file, "Before merging:\n");
-      symtab->dump (symtab->dump_file);
-    }
   if (!flag_ltrans)
     {
+      /* Finally merge the cgraph according to the decl merging decisions.  */
+      timevar_push (TV_IPA_LTO_CGRAPH_MERGE);
+
+      gcc_assert (!dump_file);
+      dump_file = dump_begin (lto_link_dump_id, NULL);
+
+      if (dump_file)
+	{
+	  fprintf (dump_file, "Before merging:\n");
+	  symtab->dump (dump_file);
+	}
       lto_symtab_merge_symbols ();
       /* Removal of unreachable symbols is needed to make verify_symtab to pass;
 	 we are still having duplicated comdat groups containing local statics.
 	 We could also just remove them while merging.  */
       symtab->remove_unreachable_nodes (dump_file);
+      ggc_collect ();
+
+      if (dump_file)
+        dump_end (lto_link_dump_id, dump_file);
+      dump_file = NULL;
+      timevar_pop (TV_IPA_LTO_CGRAPH_MERGE);
     }
-  ggc_collect ();
   symtab->state = IPA_SSA;
-  /* FIXME: Technically all node removals happening here are useless, because
-     WPA should not stream them.  */
+  /* All node removals happening here are useless, because
+     WPA should not stream them.  Still always perform remove_unreachable_nodes
+     because we may reshape clone tree, get rid of dead masters of inline
+     clones and remove symbol entries for read-only variables we keep around
+     only to be able to constant fold them.  */
   if (flag_ltrans)
-    symtab->remove_unreachable_nodes (dump_file);
-
-  timevar_pop (TV_IPA_LTO_CGRAPH_MERGE);
+    {
+      if (symtab->dump_file)
+	 symtab->dump (symtab->dump_file);
+      symtab->remove_unreachable_nodes (symtab->dump_file);
+    }
 
   /* Indicate that the cgraph is built and ready.  */
   symtab->function_flags_ready = true;
@@ -3108,19 +3191,19 @@
   if (seen_error ())
     return;
 
-  if (symtab->dump_file)
-    {
-      fprintf (symtab->dump_file, "Optimized ");
-      symtab->dump (symtab->dump_file);
-    }
-
-  symtab_node::checking_verify_symtab_nodes ();
-  bitmap_obstack_release (NULL);
-
   /* We are about to launch the final LTRANS phase, stop the WPA timer.  */
   timevar_pop (TV_WHOPR_WPA);
 
   timevar_push (TV_WHOPR_PARTITIONING);
+
+  gcc_assert (!dump_file);
+  dump_file = dump_begin (partition_dump_id, NULL);
+
+  if (dump_file)
+    symtab->dump (dump_file);
+
+  symtab_node::checking_verify_symtab_nodes ();
+  bitmap_obstack_release (NULL);
   if (flag_lto_partition == LTO_PARTITION_1TO1)
     lto_1_to_1_map ();
   else if (flag_lto_partition == LTO_PARTITION_MAX)
@@ -3148,6 +3231,9 @@
      to globals with hidden visibility because they are accessed from multiple
      partitions.  */
   lto_promote_cross_file_statics ();
+  if (dump_file)
+     dump_end (partition_dump_id, dump_file);
+  dump_file = NULL;
   timevar_pop (TV_WHOPR_PARTITIONING);
 
   timevar_stop (TV_PHASE_OPT_GEN);
@@ -3209,7 +3295,8 @@
 lto_process_name (void)
 {
   if (flag_lto)
-    setproctitle ("lto1-lto");
+    setproctitle (flag_incremental_link == INCREMENTAL_LINK_LTO
+		  ? "lto1-inclink" : "lto1-lto");
   if (flag_wpa)
     setproctitle ("lto1-wpa");
   if (flag_ltrans)
@@ -3333,7 +3420,9 @@
 	    lto_promote_statics_nonwpa ();
 
 	  /* Annotate the CU DIE and mark the early debug phase as finished.  */
+	  debuginfo_early_start ();
 	  debug_hooks->early_finish ("<artificial>");
+	  debuginfo_early_stop ();
 
 	  /* Let the middle end know that we have read and merged all of
 	     the input files.  */