diff mbox

[RFC] Getting LTO incremental linking work

Message ID 20151125234631.GG20593@kam.mff.cuni.cz
State New
Headers show

Commit Message

Jan Hubicka Nov. 25, 2015, 11:46 p.m. UTC
Hi,
here is the patch that implement incremental LTO linking.  I will wait few days
for feedback.  gcc -r now does LTO IL linking only.  To force codegen, one can
use -Wl,-rnolto which I found no right place to document.  We may want -rnolto
flag uspported by GCC driver, so the testsuite can be updated to use -rnolto
whenever it uses -r currently and it won't fail on unrecognized option with
non-GNU linkers. I got lost in gcc.c and I do not know where -rdynamic is parsed
(I suppose at the same spot I can do -rnolto and turn it into -r -Wl,-rnolto on
plugin enabled setups and -r on others)

There are still few bugs to track. Most notably WPA will produce hidden symbols
with non-obstructated names which may conflict with later static linking.  I will
look into that separately and also try to find more testcases.

	* lto-streamer-out.c: Also copy sections when 
	flag_incremental_link == 2
	* flag-types.h (lto_partition_model): Add LTO_LINKER_OUTPUT_NOLTOREL.
	* common.opt (flag_incremental_link): Update docs.
	* passes.c (ipa_write_summaries): Only renumber statements when
	the body is really in memory.
	* lto-wrapper.c (run_gcc): Parse -flinker-output and turn into
	non-WPA mode at -flinker-output=rel.

	* lang.opt (lto_linker_output): New value noltorel.
	* lto-lang.c (lto_post_options): Handle LTO_LINKER_OUTPUT_REL
	and LTO_LINKER_OUTPUT_NOLTOREL.
	(lto_init): We also generate LTO during incremental_link.

	* toplev.c (compile_file): Cut compilation when doing incremental
	link.
	* cgraphunit.c (ipa_passes): Support incremental link.
	(symbol_table::compile): Likewise.
	* lto-cgraph.c (lto_output_node): Do not propagate resolution info
	when linking incrmentally.

	* lto-plugin.c: Document flags; add new flag -rnolto
	(non_claimed_files, rnolto): New statics.
	(all_symbols_read_handler): Decide on rel model.
	(claim_file_handler): Count non_claimed_files
	(process_option): Process rnolto.
diff mbox

Patch

Index: gcc/lto-streamer-out.c
===================================================================
--- gcc/lto-streamer-out.c	(revision 230915)
+++ gcc/lto-streamer-out.c	(working copy)
@@ -2286,13 +2286,16 @@  lto_output (void)
 		}
 	      decl_state = lto_new_out_decl_state ();
 	      lto_push_out_decl_state (decl_state);
-	      if (gimple_has_body_p (node->decl) || !flag_wpa
+	      if (gimple_has_body_p (node->decl)
 		  /* Thunks have no body but they may be synthetized
 		     at WPA time.  */
 		  || DECL_ARGUMENTS (node->decl))
 		output_function (node);
 	      else
-		copy_function_or_variable (node);
+		{
+		  gcc_checking_assert (flag_wpa || flag_incremental_link == 2);
+		  copy_function_or_variable (node);
+		}
 	      gcc_assert (lto_get_out_decl_state () == decl_state);
 	      lto_pop_out_decl_state ();
 	      lto_record_function_out_decl_state (node->decl, decl_state);
@@ -2318,7 +2321,7 @@  lto_output (void)
 	      decl_state = lto_new_out_decl_state ();
 	      lto_push_out_decl_state (decl_state);
 	      if (DECL_INITIAL (node->decl) != error_mark_node
-		  || !flag_wpa)
+		  || (!flag_wpa && flag_incremental_link != 2))
 		output_constructor (node);
 	      else
 		copy_function_or_variable (node);
Index: gcc/flag-types.h
===================================================================
--- gcc/flag-types.h	(revision 230915)
+++ gcc/flag-types.h	(working copy)
@@ -269,6 +269,7 @@  enum lto_partition_model {
 enum lto_linker_output {
   LTO_LINKER_OUTPUT_UNKNOWN,
   LTO_LINKER_OUTPUT_REL,
+  LTO_LINKER_OUTPUT_NOLTOREL,
   LTO_LINKER_OUTPUT_DYN,
   LTO_LINKER_OUTPUT_PIE,
   LTO_LINKER_OUTPUT_EXEC
Index: gcc/common.opt
===================================================================
--- gcc/common.opt	(revision 230915)
+++ gcc/common.opt	(working copy)
@@ -48,7 +48,8 @@  bool in_lto_p = false
 
 ; This variable is set to non-0 only by LTO front-end.  1 indicates that
 ; the output produced will be used for incrmeental linking (thus weak symbols
-; can still be bound).
+; can still be bound) and 2 indicates that the IL is going to be linked and
+; and output to LTO object file.
 Variable
 int flag_incremental_link = 0
 
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 230915)
+++ gcc/passes.c	(working copy)
@@ -2530,7 +2530,7 @@  ipa_write_summaries (void)
     {
       struct cgraph_node *node = order[i];
 
-      if (node->has_gimple_body_p ())
+      if (gimple_has_body_p (node->decl))
 	{
 	  /* When streaming out references to statements as part of some IPA
 	     pass summary, the statements need to have uids assigned and the
Index: gcc/lto-wrapper.c
===================================================================
--- gcc/lto-wrapper.c	(revision 230915)
+++ gcc/lto-wrapper.c	(working copy)
@@ -953,9 +953,15 @@  run_gcc (unsigned argc, char *argv[])
 	  file_offset = (off_t) loffset;
 	}
       fd = open (filename, O_RDONLY | O_BINARY);
+      /* Linker plugin passes -fresolution and -flinker-output options.  */
       if (fd == -1)
 	{
 	  lto_argv[lto_argc++] = argv[i];
+	  if (strcmp (argv[i], "-flinker-output=rel") == 0)
+	    {
+	       no_partition = true;
+	       lto_mode = LTO_MODE_LTO;
+	    }
 	  continue;
 	}
 
Index: gcc/lto/lang.opt
===================================================================
--- gcc/lto/lang.opt	(revision 230915)
+++ gcc/lto/lang.opt	(working copy)
@@ -34,6 +34,9 @@  EnumValue
 Enum(lto_linker_output) String(rel) Value(LTO_LINKER_OUTPUT_REL)
 
 EnumValue
+Enum(lto_linker_output) String(noltorel) Value(LTO_LINKER_OUTPUT_NOLTOREL)
+
+EnumValue
 Enum(lto_linker_output) String(dyn) Value(LTO_LINKER_OUTPUT_DYN)
 
 EnumValue
Index: gcc/lto/lto-lang.c
===================================================================
--- gcc/lto/lto-lang.c	(revision 230915)
+++ gcc/lto/lto-lang.c	(working copy)
@@ -823,6 +823,26 @@  lto_post_options (const char **pfilename
   switch (flag_lto_linker_output)
     {
     case LTO_LINKER_OUTPUT_REL: /* .o: incremental link producing LTO IL  */
+      /* Configure compiler same way as normal frontend would do with -flto:
+	 this way we read the trees (declarations & types), symbol table,
+	 optimization summaries and link them. Subsequently we output new LTO
+	 file.  */
+      flag_lto = "";
+      flag_incremental_link = 2;
+      flag_whole_program = 0;
+      flag_wpa = 0;
+      flag_generate_lto = 1;
+      /* It would be cool to produce .o file directly, but our current
+	 simple objects does not contain the lto symbol markers.  Go the slow
+	 way through the asm file.  */
+      lang_hooks.lto.begin_section = lhd_begin_section;
+      lang_hooks.lto.append_data = lhd_append_data;
+      lang_hooks.lto.end_section = lhd_end_section;
+      if (flag_ltrans)
+	error ("-flinker-output=rel and -fltrans are mutually exclussive");
+      break;
+
+    case LTO_LINKER_OUTPUT_NOLTOREL: /* .o: incremental link producing asm  */
       flag_whole_program = 0;
       flag_incremental_link = 1;
       break;
@@ -1243,7 +1263,7 @@  lto_init (void)
   int i;
 
   /* We need to generate LTO if running in WPA mode.  */
-  flag_generate_lto = (flag_wpa != NULL);
+  flag_generate_lto = (flag_incremental_link == 2 || flag_wpa != NULL);
 
   /* Create the basic integer types.  */
   build_common_tree_nodes (flag_signed_char, flag_short_double);
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 230915)
+++ gcc/toplev.c	(working copy)
@@ -504,7 +504,8 @@  compile_file (void)
 
   /* Compilation unit is finalized.  When producing non-fat LTO object, we are
      basically finished.  */
-  if (in_lto_p || !flag_lto || flag_fat_lto_objects)
+  if ((in_lto_p && flag_incremental_link != 2)
+      || !flag_lto || flag_fat_lto_objects)
     {
       /* File-scope initialization for AddressSanitizer.  */
       if (flag_sanitize & SANITIZE_ADDRESS)
Index: gcc/cgraphunit.c
===================================================================
--- gcc/cgraphunit.c	(revision 230915)
+++ gcc/cgraphunit.c	(working copy)
@@ -2270,8 +2270,10 @@  ipa_passes (void)
   if (flag_generate_lto || flag_generate_offload)
     targetm.asm_out.lto_start ();
 
-  if (!in_lto_p)
+  if (!in_lto_p || flag_incremental_link == 2)
     {
+      if (!quiet_flag)
+	fprintf (stderr, "Streaming LTO\n");
       if (g->have_offload)
 	{
 	  section_name_prefix = OFFLOAD_SECTION_NAME_PREFIX;
@@ -2290,7 +2292,9 @@  ipa_passes (void)
   if (flag_generate_lto || flag_generate_offload)
     targetm.asm_out.lto_end ();
 
-  if (!flag_ltrans && (in_lto_p || !flag_lto || flag_fat_lto_objects))
+  if (!flag_ltrans
+      && ((in_lto_p && flag_incremental_link != 2)
+	  || !flag_lto || flag_fat_lto_objects))
     execute_ipa_pass_list (passes->all_regular_ipa_passes);
   invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
 
@@ -2381,7 +2385,8 @@  symbol_table::compile (void)
 
   /* Do nothing else if any IPA pass found errors or if we are just streaming LTO.  */
   if (seen_error ()
-      || (!in_lto_p && flag_lto && !flag_fat_lto_objects))
+      || ((!in_lto_p || flag_incremental_link == 2)
+	  && flag_lto && !flag_fat_lto_objects))
     {
       timevar_pop (TV_CGRAPHOPT);
       return;
Index: gcc/lto-cgraph.c
===================================================================
--- gcc/lto-cgraph.c	(revision 230915)
+++ gcc/lto-cgraph.c	(working copy)
@@ -534,7 +534,10 @@  lto_output_node (struct lto_simple_outpu
   bp_pack_value (&bp, node->thunk.thunk_p, 1);
   bp_pack_value (&bp, node->parallelized_function, 1);
   bp_pack_enum (&bp, ld_plugin_symbol_resolution,
-	        LDPR_NUM_KNOWN, node->resolution);
+	        LDPR_NUM_KNOWN,
+		/* When doing incremental link, we will get new resolution
+		   info next time we process the file.  */
+		flag_incremental_link ? LDPR_UNKNOWN : node->resolution);
   bp_pack_value (&bp, node->instrumentation_clone, 1);
   bp_pack_value (&bp, node->split_part, 1);
   streamer_write_bitpack (&bp);
Index: lto-plugin/lto-plugin.c
===================================================================
--- lto-plugin/lto-plugin.c	(revision 230915)
+++ lto-plugin/lto-plugin.c	(working copy)
@@ -27,10 +27,13 @@  along with this program; see the file CO
    More information at http://gcc.gnu.org/wiki/whopr/driver.
 
    This plugin should be passed the lto-wrapper options and will forward them.
-   It also has 2 options of its own:
+   It also has options at his own:
    -debug: Print the command line used to run lto-wrapper.
    -nop: Instead of running lto-wrapper, pass the original to the plugin. This
-   only works if the input files are hybrid.  */
+   only works if the input files are hybrid. 
+   -rnolto: When doing incremental linking, turn the result into actual binary
+   -sym-style={none,win32,underscore|uscore}
+   -pass-through  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -151,6 +154,7 @@  static ld_plugin_add_symbols add_symbols
 
 static struct plugin_file_info *claimed_files = NULL;
 static unsigned int num_claimed_files = 0;
+static unsigned int non_claimed_files = 0;
 
 static struct plugin_file_info *offload_files = NULL;
 static unsigned int num_offload_files = 0;
@@ -169,6 +173,7 @@  static char nop;
 static char *resolution_file = NULL;
 static enum ld_plugin_output_file_type linker_output;
 static int linker_output_set;
+static int rnolto;
 
 /* The version of gold being used, or -1 if not gold.  The number is
    MAJOR * 100 + MINOR.  */
@@ -655,7 +660,17 @@  all_symbols_read_handler (void)
   switch (linker_output)
     {
     case LDPO_REL:
-      linker_output_str = "-flinker-output=rel";
+      if (non_claimed_files)
+	{
+	  rnolto = 1;
+	  message (LDPL_WARNING, "incremental linking of LTO and non-LTO "
+		   "objects will produce final assembly for LTO objects and "
+		   "bypass whole program optimization");
+	}
+      if (rnolto)
+	linker_output_str = "-flinker-output=nonltorel";
+      else
+        linker_output_str = "-flinker-output=rel";
       break;
     case LDPO_DYN:
       linker_output_str = "-flinker-output=dyn";
@@ -1008,6 +1023,8 @@  claim_file_handler (const struct ld_plug
 		  num_claimed_files * sizeof (struct plugin_file_info));
       claimed_files[num_claimed_files - 1] = lto_file;
     }
+  else
+    non_claimed_files++;
 
   if (obj.found == 0 && obj.offload == 1)
     {
@@ -1037,6 +1054,8 @@  claim_file_handler (const struct ld_plug
 static void
 process_option (const char *option)
 {
+  if (strcmp (option, "-rnolto") == 0)
+    rnolto = 1;
   if (strcmp (option, "-debug") == 0)
     debug = 1;
   else if (strcmp (option, "-nop") == 0)