This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][LTO] "Kill" ltrans-driver(?)


This replaces invocation of ltrans-driver from wpa with manually
invoking COLLECT_GCC from within the wpa lto1.  This makes it easier
to debug issues with wpa as -v -save-temps work as expected - you
get all lto1 lines printed, all temporary files are retained (and
end up in the current working directory, not in /tmp or some directory
beyond it).

I can either retain the old behavior or rip it out completely - IMHO
for 4.5 we'll have WPA mainly for developing IPA passes, not for
production use (yet).

The toplev.c hunk avoids the single unreclaimed asm temporary file
you get with each -fwhopr compile.

Bootstrapping and testing in progress.

Diego - any preference on the -fltrans-driver functionality?  I could
preserve the old behavior if -fltrans-driver=ltrans-driver is specified
and make the new behavior the default.  Or turn on the new behavior
on explicit -fltrans-driver= only (or -fno-ltrans-driver?).  Bug 39276
notes existing portability issues with the ltrans-driver script.

I expect that for the testsuite the new behavior will be a tad bit faster.

Thanks,
Richard.

2009-09-16  Richard Guenther  <rguenther@suse.de>

	PR lto/39276
	* toplev.c (lang_dependent_init): Do not write to asm_out_file
	in WPA mode.
	(compile_file): Likewise.

	lto/
	* lto.c (lto_execute_ltrans): Perform ltrans phase manually.

Index: gcc/lto/lto.c
===================================================================
*** gcc/lto/lto.c	(revision 151741)
--- gcc/lto/lto.c	(working copy)
*************** static void
*** 954,975 ****
  lto_execute_ltrans (char *const *files)
  {
    struct pex_obj *pex;
!   const char *env_val;
!   const char *extra_cflags = " -fno-wpa -fltrans -xlto";
    struct obstack env_obstack;
    const char **argv;
    const char **argv_ptr;
    const char *errmsg;
!   size_t i;
    int err;
    int status;
    FILE *ltrans_output_list_stream = NULL;
  
    timevar_push (TV_WHOPR_WPA_LTRANS_EXEC);
  
    /* Initalize the arguments for the LTRANS driver.  */
!   for (i = 0; files[i]; ++i);
!   argv = XNEWVEC (const char *, i + 2);
  
    /* Open the LTRANS output list.  */
    if (ltrans_output_list)
--- 954,1008 ----
  lto_execute_ltrans (char *const *files)
  {
    struct pex_obj *pex;
!   const char *collect_gcc_options, *collect_gcc;
    struct obstack env_obstack;
    const char **argv;
    const char **argv_ptr;
    const char *errmsg;
!   size_t i, j;
    int err;
    int status;
    FILE *ltrans_output_list_stream = NULL;
  
    timevar_push (TV_WHOPR_WPA_LTRANS_EXEC);
  
+   /* Get the driver and options.  */
+   collect_gcc = getenv ("COLLECT_GCC");
+   if (!collect_gcc)
+     fatal_error ("environment variable COLLECT_GCC must be set");
+ 
+   /* Set the CFLAGS environment variable.  */
+   collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
+   if (!collect_gcc_options)
+     fatal_error ("environment variable COLLECT_GCC_OPTIONS must be set");
+ 
+   /* Count arguments.  */
+   i = 0;
+   for (j = 0; collect_gcc_options[j] != '\0'; ++j)
+     if (collect_gcc_options[j] == '\'')
+       ++i;
+   if (i % 2 != 0)
+     fatal_error ("malformed COLLECT_GCC_OPTIONS");
+ 
    /* Initalize the arguments for the LTRANS driver.  */
!   argv = XNEWVEC (const char *, 8 + i/2);
!   argv_ptr = argv;
!   *argv_ptr++ = collect_gcc;
!   *argv_ptr++ = "-xlto";
!   for (j = 0; collect_gcc_options[j] != '\0'; ++j)
!     if (collect_gcc_options[j] == '\'')
!       {
! 	++j;
! 	i = j;
! 	while (collect_gcc_options[j] != '\'')
! 	  ++j;
! 	obstack_init (&env_obstack);
! 	obstack_grow (&env_obstack, &collect_gcc_options[i], j - i);
! 	obstack_1grow (&env_obstack, 0);
! 	*argv_ptr++ = XOBFINISH (&env_obstack, char *);
!       }
!   *argv_ptr++ = "-fno-wpa";
!   *argv_ptr++ = "-fltrans";
  
    /* Open the LTRANS output list.  */
    if (ltrans_output_list)
*************** lto_execute_ltrans (char *const *files)
*** 979,986 ****
  	error ("opening LTRANS output list %s: %m", ltrans_output_list);
      }
  
-   argv_ptr = argv;
-   *argv_ptr++ = ltrans_driver;
    for (i = 0; files[i]; ++i)
      {
        size_t len;
--- 1012,1017 ----
*************** lto_execute_ltrans (char *const *files)
*** 1001,1083 ****
  	}
        else
  	{
  	  /* Otherwise, add FILES[I] to ltrans-driver's command line
  	     and add the resulting file to LTRANS output list.  */
- 	  *argv_ptr++ = files[i];
  
  	  /* Replace the .o suffix with a .ltrans.o suffix and write
  	     the resulting name to the LTRANS output list.  */
  	  if (ltrans_output_list_stream)
  	    {
! 	      len = strlen (files[i]) - 2;
  
! 	      if (fwrite (files[i], 1, len, ltrans_output_list_stream) < len
! 		  || fwrite (".ltrans.o\n", 1, 10, ltrans_output_list_stream)
! 		     < 10)
  		error ("writing to LTRANS output list %s: %m",
  		       ltrans_output_list);
  	    }
- 	}
-     }
  
!   *argv_ptr++ = NULL;
  
!   /* Close the LTRANS output list.  */
!   if (ltrans_output_list_stream && fclose (ltrans_output_list_stream))
!     error ("closing LTRANS output list %s: %m", ltrans_output_list);
  
!   /* If there are any files to compile, execute the LTRANS driver.  */
!   if (argv[1] != NULL)
!     {
!       /* Set the CC environment variable.  */
!       env_val = getenv ("COLLECT_GCC");
!       if (!env_val)
! 	fatal_error ("environment variable COLLECT_GCC must be set");
! 
!       obstack_init (&env_obstack);
!       obstack_grow (&env_obstack, "CC=", sizeof ("CC=") - 1);
!       obstack_grow (&env_obstack, env_val, strlen (env_val) + 1);
!       putenv (XOBFINISH (&env_obstack, char *));
! 
!       /* Set the CFLAGS environment variable.  */
!       env_val = getenv ("COLLECT_GCC_OPTIONS");
!       if (!env_val)
! 	fatal_error ("environment variable COLLECT_GCC_OPTIONS must be set");
! 
!       obstack_init (&env_obstack);
!       obstack_grow (&env_obstack, "CFLAGS=", sizeof ("CFLAGS=") - 1);
!       obstack_grow (&env_obstack, env_val, strlen (env_val));
!       obstack_grow (&env_obstack, extra_cflags, strlen (extra_cflags) + 1);
!       putenv (XOBFINISH (&env_obstack, char *));
! 
!       pex = pex_init (0, "lto1", NULL);
!       if (pex == NULL)
! 	fatal_error ("pex_init failed: %s", xstrerror (errno));
! 
!       errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0],
! 			CONST_CAST (char **, argv), NULL, NULL, &err);
!       if (errmsg)
! 	fatal_error ("%s: %s", errmsg, xstrerror (err));
! 
!       if (!pex_get_status (pex, 1, &status))
! 	fatal_error ("can't get program status: %s", xstrerror (errno));
! 
!       if (status)
! 	{
! 	  if (WIFSIGNALED (status))
  	    {
! 	      int sig = WTERMSIG (status);
! 	      fatal_error ("%s terminated with signal %d [%s]%s",
! 			   argv[0], sig, strsignal (sig),
! 			   WCOREDUMP (status) ? ", core dumped" : "");
  	    }
- 	  else
- 	    fatal_error ("%s terminated with status %d", argv[0], status);
- 	}
  
!       pex_free (pex);
      }
  
    timevar_pop (TV_WHOPR_WPA_LTRANS_EXEC);
  }
  
--- 1032,1100 ----
  	}
        else
  	{
+ 	  char *output_name;
+ 
  	  /* Otherwise, add FILES[I] to ltrans-driver's command line
  	     and add the resulting file to LTRANS output list.  */
  
  	  /* Replace the .o suffix with a .ltrans.o suffix and write
  	     the resulting name to the LTRANS output list.  */
+ 	  obstack_init (&env_obstack);
+ 	  obstack_grow (&env_obstack, files[i], strlen (files[i]) - 2);
+ 	  obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
+ 	  output_name = XOBFINISH (&env_obstack, char *);
  	  if (ltrans_output_list_stream)
  	    {
! 	      len = strlen (output_name);
  
! 	      if (fwrite (output_name, 1, len, ltrans_output_list_stream) < len
! 		  || fwrite ("\n", 1, 1, ltrans_output_list_stream) < 1)
  		error ("writing to LTRANS output list %s: %m",
  		       ltrans_output_list);
  	    }
  
! 	  argv_ptr[0] = "-o";
! 	  argv_ptr[1] = output_name;
! 	  argv_ptr[2] = files[i];
! 	  argv_ptr[3] = NULL;
! 
! 	  /* Execute the ltrans driver.  */
! 	  pex = pex_init (0, "lto1", NULL);
! 	  if (pex == NULL)
! 	    fatal_error ("pex_init failed: %s", xstrerror (errno));
! 
! 	  errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0],
! 			    CONST_CAST (char **, argv), NULL, NULL, &err);
! 	  if (errmsg)
! 	    fatal_error ("%s: %s", errmsg, xstrerror (err));
  
! 	  if (!pex_get_status (pex, 1, &status))
! 	    fatal_error ("can't get program status: %s", xstrerror (errno));
  
! 	  if (status)
  	    {
! 	      if (WIFSIGNALED (status))
! 		{
! 		  int sig = WTERMSIG (status);
! 		  fatal_error ("%s terminated with signal %d [%s]%s",
! 			       argv[0], sig, strsignal (sig),
! 			       WCOREDUMP (status) ? ", core dumped" : "");
! 		}
! 	      else
! 		fatal_error ("%s terminated with status %d", argv[0], status);
  	    }
  
! 	  pex_free (pex);
! 	}
      }
  
+   /* Close the LTRANS output list.  */
+   if (ltrans_output_list_stream && fclose (ltrans_output_list_stream))
+     error ("closing LTRANS output list %s: %m", ltrans_output_list);
+ 
+   obstack_free (&env_obstack, NULL);
+   free (argv);
+ 
    timevar_pop (TV_WHOPR_WPA_LTRANS_EXEC);
  }
  
Index: gcc/toplev.c
===================================================================
*** gcc/toplev.c	(revision 151741)
--- gcc/toplev.c	(working copy)
*************** compile_file (void)
*** 1102,1115 ****
       We used to emit an undefined reference here, but this produces
       link errors if an object file with IL is stored into a shared
       library without invoking lto1.  */
!   if (flag_generate_lto)
      fprintf (asm_out_file,"\t.comm\tgnu_lto_v1,1,1\n");
  
    /* Attach a special .ident directive to the end of the file to identify
       the version of GCC which compiled this code.  The format of the .ident
       string is patterned after the ones produced by native SVR4 compilers.  */
  #ifdef IDENT_ASM_OP
!   if (!flag_no_ident)
      {
        const char *pkg_version = "(GNU) ";
  
--- 1102,1117 ----
       We used to emit an undefined reference here, but this produces
       link errors if an object file with IL is stored into a shared
       library without invoking lto1.  */
!   if (flag_generate_lto
!       && !flag_wpa)
      fprintf (asm_out_file,"\t.comm\tgnu_lto_v1,1,1\n");
  
    /* Attach a special .ident directive to the end of the file to identify
       the version of GCC which compiled this code.  The format of the .ident
       string is patterned after the ones produced by native SVR4 compilers.  */
  #ifdef IDENT_ASM_OP
!   if (!flag_no_ident
!       && !flag_wpa)
      {
        const char *pkg_version = "(GNU) ";
  
*************** compile_file (void)
*** 1126,1132 ****
    /* This must be at the end.  Some target ports emit end of file directives
       into the assembly file here, and hence we can not output anything to the
       assembly file after this point.  */
!   targetm.asm_out.file_end ();
  }
  
  /* Parse a -d... command line switch.  */
--- 1128,1135 ----
    /* This must be at the end.  Some target ports emit end of file directives
       into the assembly file here, and hence we can not output anything to the
       assembly file after this point.  */
!   if (!flag_wpa)
!     targetm.asm_out.file_end ();
  }
  
  /* Parse a -d... command line switch.  */
*************** lang_dependent_init (const char *name)
*** 2277,2283 ****
      return 0;
    input_location = save_loc;
  
!   init_asm_output (name);
  
    /* This creates various _DECL nodes, so needs to be called after the
       front end is initialized.  */
--- 2280,2287 ----
      return 0;
    input_location = save_loc;
  
!   if (!flag_wpa)
!     init_asm_output (name);
  
    /* This creates various _DECL nodes, so needs to be called after the
       front end is initialized.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]