Patchwork Allow more WHOPR partitions than souce files

login
register
mail settings
Submitter Jan Hubicka
Date Sept. 9, 2010, 12:23 a.m.
Message ID <20100909002348.GD17338@atrey.karlin.mff.cuni.cz>
Download mbox | patch
Permalink /patch/64247/
State New
Headers show

Comments

Jan Hubicka - Sept. 9, 2010, 12:23 a.m.
Hi,
there is updated patch...

Bootstrapped/regested x86_64-linux, OK?

Honza
	* collect2.c (maybe_run_lto_and_relink): Rewrite code producing ld
	command line to allow more partitions than input files.
Richard Guenther - Sept. 9, 2010, 8:41 a.m.
On Thu, 9 Sep 2010, Jan Hubicka wrote:

> Hi,
> there is updated patch...
> 
> Bootstrapped/regested x86_64-linux, OK?

Ok.

Thanks,
Richard.

> Honza
> 	* collect2.c (maybe_run_lto_and_relink): Rewrite code producing ld
> 	command line to allow more partitions than input files.
> Index: collect2.c
> ===================================================================
> --- collect2.c	(revision 164002)
> +++ collect2.c	(working copy)
> @@ -942,12 +942,16 @@ maybe_run_lto_and_relink (char **lto_ld_
>      {
>        char **lto_c_argv;
>        const char **lto_c_ptr;
> -      const char **p, **q, **r;
> -      const char **lto_o_ptr;
> +      char **p;
> +      char **lto_o_ptr;
>        struct lto_object *list;
>        char *lto_wrapper = getenv ("COLLECT_LTO_WRAPPER");
>        struct pex_obj *pex;
>        const char *prog = "lto-wrapper";
> +      int lto_ld_argv_size = 0;
> +      char **out_lto_ld_argv;
> +      int out_lto_ld_argv_size;
> +      size_t num_files;
>  
>        if (!lto_wrapper)
>  	fatal ("COLLECT_LTO_WRAPPER must be set.");
> @@ -955,7 +959,11 @@ maybe_run_lto_and_relink (char **lto_ld_
>        num_lto_c_args++;
>  
>        /* There is at least one object file containing LTO info,
> -         so we need to run the LTO back end and relink.  */
> +         so we need to run the LTO back end and relink.
> +
> +	 To do so we build updated ld arguments with first
> +	 LTO object replaced by all partitions and other LTO
> +	 objects removed.  */
>  
>        lto_c_argv = (char **) xcalloc (sizeof (char *), num_lto_c_args);
>        lto_c_ptr = CONST_CAST2 (const char **, char **, lto_c_argv);
> @@ -973,7 +981,7 @@ maybe_run_lto_and_relink (char **lto_ld_
>        {
>  	int c;
>  	FILE *stream;
> -	size_t i, num_files;
> +	size_t i;
>  	char *start, *end;
>  
>  	stream = pex_read_output (pex, 0);
> @@ -1007,55 +1015,50 @@ maybe_run_lto_and_relink (char **lto_ld_
>        do_wait (prog, pex);
>        pex = NULL;
>  
> +      /* Compute memory needed for new LD arguments.  At most number of original arguemtns
> +	 plus number of partitions.  */
> +      for (lto_ld_argv_size = 0; lto_ld_argv[lto_ld_argv_size]; lto_ld_argv_size++)
> +	;
> +      out_lto_ld_argv = XCNEWVEC(char *, num_files + lto_ld_argv_size + 1);
> +      out_lto_ld_argv_size = 0;
> +
>        /* After running the LTO back end, we will relink, substituting
>  	 the LTO output for the object files that we submitted to the
>  	 LTO. Here, we modify the linker command line for the relink.  */
> -      p = CONST_CAST2 (const char **, char **, lto_ld_argv);
> -      lto_o_ptr = CONST_CAST2 (const char **, char **, lto_o_files);
>  
> +      /* Copy all arguments until we find first LTO file.  */
> +      p = lto_ld_argv;
>        while (*p != NULL)
>          {
>            for (list = lto_objects.first; list; list = list->next)
> -            {
> -              if (*p == list->name) /* Note test for pointer equality!  */
> -                {
> -                  /* Excise argument from linker command line.  */
> -                  if (*lto_o_ptr)
> -                    {
> -                      /* Replace first argument with LTO output file.  */
> -                      *p++ = *lto_o_ptr++;
> -                    }
> -                  else
> -                    {
> -                      /* Move following arguments one position earlier,
> -                         overwriting the current argument.  */
> -                      q = p;
> -                      r = p + 1;
> -                      while (*r != NULL)
> -                        *q++ = *r++;
> -                      *q = NULL;
> -                    }
> -
> -                  /* No need to continue searching the LTO object list.  */
> -                  break;
> -                }
> -            }
> -
> -          /* If we didn't find a match, move on to the next argument.
> -             Otherwise, P has been set to the correct argument position
> -             at which to continue.  */
> -          if (!list) ++p;
> +            if (*p == list->name) /* Note test for pointer equality!  */
> +	      break;
> +	  if (list)
> +	    break;
> +	  out_lto_ld_argv[out_lto_ld_argv_size++] = *p++;
>          }
>  
> -      /* The code above assumes we will never have more lto output files than
> -	 input files.  Otherwise, we need to resize lto_ld_argv.  Check this
> -	 assumption.  */
> -      if (*lto_o_ptr)
> -	fatal ("too many lto output files");
> +      /* Now insert all LTO partitions.  */
> +      lto_o_ptr = lto_o_files;
> +      while (*lto_o_ptr)
> +	out_lto_ld_argv[out_lto_ld_argv_size++] = *lto_o_ptr++;
> +
> +      /* ... and copy the rest.  */
> +      while (*p != NULL)
> +        {
> +          for (list = lto_objects.first; list; list = list->next)
> +            if (*p == list->name) /* Note test for pointer equality!  */
> +	      break;
> +	  if (!list)
> +	    out_lto_ld_argv[out_lto_ld_argv_size++] = *p;
> +	  p++;
> +        }
> +      out_lto_ld_argv[out_lto_ld_argv_size++] = 0;
>  
>        /* Run the linker again, this time replacing the object files
>           optimized by the LTO with the temporary file generated by the LTO.  */
> -      fork_execute ("ld", lto_ld_argv);
> +      fork_execute ("ld", out_lto_ld_argv);
> +      free (lto_ld_argv);
>  
>        maybe_unlink_list (lto_o_files);
>      }
> 
>

Patch

Index: collect2.c
===================================================================
--- collect2.c	(revision 164002)
+++ collect2.c	(working copy)
@@ -942,12 +942,16 @@  maybe_run_lto_and_relink (char **lto_ld_
     {
       char **lto_c_argv;
       const char **lto_c_ptr;
-      const char **p, **q, **r;
-      const char **lto_o_ptr;
+      char **p;
+      char **lto_o_ptr;
       struct lto_object *list;
       char *lto_wrapper = getenv ("COLLECT_LTO_WRAPPER");
       struct pex_obj *pex;
       const char *prog = "lto-wrapper";
+      int lto_ld_argv_size = 0;
+      char **out_lto_ld_argv;
+      int out_lto_ld_argv_size;
+      size_t num_files;
 
       if (!lto_wrapper)
 	fatal ("COLLECT_LTO_WRAPPER must be set.");
@@ -955,7 +959,11 @@  maybe_run_lto_and_relink (char **lto_ld_
       num_lto_c_args++;
 
       /* There is at least one object file containing LTO info,
-         so we need to run the LTO back end and relink.  */
+         so we need to run the LTO back end and relink.
+
+	 To do so we build updated ld arguments with first
+	 LTO object replaced by all partitions and other LTO
+	 objects removed.  */
 
       lto_c_argv = (char **) xcalloc (sizeof (char *), num_lto_c_args);
       lto_c_ptr = CONST_CAST2 (const char **, char **, lto_c_argv);
@@ -973,7 +981,7 @@  maybe_run_lto_and_relink (char **lto_ld_
       {
 	int c;
 	FILE *stream;
-	size_t i, num_files;
+	size_t i;
 	char *start, *end;
 
 	stream = pex_read_output (pex, 0);
@@ -1007,55 +1015,50 @@  maybe_run_lto_and_relink (char **lto_ld_
       do_wait (prog, pex);
       pex = NULL;
 
+      /* Compute memory needed for new LD arguments.  At most number of original arguemtns
+	 plus number of partitions.  */
+      for (lto_ld_argv_size = 0; lto_ld_argv[lto_ld_argv_size]; lto_ld_argv_size++)
+	;
+      out_lto_ld_argv = XCNEWVEC(char *, num_files + lto_ld_argv_size + 1);
+      out_lto_ld_argv_size = 0;
+
       /* After running the LTO back end, we will relink, substituting
 	 the LTO output for the object files that we submitted to the
 	 LTO. Here, we modify the linker command line for the relink.  */
-      p = CONST_CAST2 (const char **, char **, lto_ld_argv);
-      lto_o_ptr = CONST_CAST2 (const char **, char **, lto_o_files);
 
+      /* Copy all arguments until we find first LTO file.  */
+      p = lto_ld_argv;
       while (*p != NULL)
         {
           for (list = lto_objects.first; list; list = list->next)
-            {
-              if (*p == list->name) /* Note test for pointer equality!  */
-                {
-                  /* Excise argument from linker command line.  */
-                  if (*lto_o_ptr)
-                    {
-                      /* Replace first argument with LTO output file.  */
-                      *p++ = *lto_o_ptr++;
-                    }
-                  else
-                    {
-                      /* Move following arguments one position earlier,
-                         overwriting the current argument.  */
-                      q = p;
-                      r = p + 1;
-                      while (*r != NULL)
-                        *q++ = *r++;
-                      *q = NULL;
-                    }
-
-                  /* No need to continue searching the LTO object list.  */
-                  break;
-                }
-            }
-
-          /* If we didn't find a match, move on to the next argument.
-             Otherwise, P has been set to the correct argument position
-             at which to continue.  */
-          if (!list) ++p;
+            if (*p == list->name) /* Note test for pointer equality!  */
+	      break;
+	  if (list)
+	    break;
+	  out_lto_ld_argv[out_lto_ld_argv_size++] = *p++;
         }
 
-      /* The code above assumes we will never have more lto output files than
-	 input files.  Otherwise, we need to resize lto_ld_argv.  Check this
-	 assumption.  */
-      if (*lto_o_ptr)
-	fatal ("too many lto output files");
+      /* Now insert all LTO partitions.  */
+      lto_o_ptr = lto_o_files;
+      while (*lto_o_ptr)
+	out_lto_ld_argv[out_lto_ld_argv_size++] = *lto_o_ptr++;
+
+      /* ... and copy the rest.  */
+      while (*p != NULL)
+        {
+          for (list = lto_objects.first; list; list = list->next)
+            if (*p == list->name) /* Note test for pointer equality!  */
+	      break;
+	  if (!list)
+	    out_lto_ld_argv[out_lto_ld_argv_size++] = *p;
+	  p++;
+        }
+      out_lto_ld_argv[out_lto_ld_argv_size++] = 0;
 
       /* Run the linker again, this time replacing the object files
          optimized by the LTO with the temporary file generated by the LTO.  */
-      fork_execute ("ld", lto_ld_argv);
+      fork_execute ("ld", out_lto_ld_argv);
+      free (lto_ld_argv);
 
       maybe_unlink_list (lto_o_files);
     }