Store estimated istrances in compressed_size
authorH.J. Lu <hjl.tools@gmail.com>
Tue, 2 Feb 2016 16:14:43 +0000 (08:14 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Tue, 2 Feb 2016 16:20:37 +0000 (08:20 -0800)
elf_x86_64_convert_load is very time consuming since it is called on
each input section and has a loop over input text sections to estimate
the branch distrance.  We can store the estimated distrances in the
compressed_size field of the output section, which is only used to
decompress the compressed input section.

Before the patch, linking clang 3.9 takes 52 seconds.  After the patch,
it only takes 2.5 seconds.

PR ld/19542
* elf64-x86-64.c (elf_x86_64_convert_load): Store the estimated
distrances in the compressed_size field of the output section.

bfd/ChangeLog
bfd/elf64-x86-64.c

index 81e751c4ea009459f926d4143cde5e5f9bf63064..e862c3c4b43610c84ab97389e9af7a8e8d0cbb7f 100644 (file)
@@ -1,3 +1,9 @@
+2016-02-02  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/19542
+       * elf64-x86-64.c (elf_x86_64_convert_load): Store the estimated
+       distrances in the compressed_size field of the output section.
+
 2016-02-02  Alan Modra  <amodra@gmail.com>
 
        * elf64-ppc.c (ppc64_elf_relocate_section): Further restrict
index 88ed00e2d16ff0d2c002dad0489efc4f438f8751..8118c1dec7e8167a836ba8326cead46fad4e7ded 100644 (file)
@@ -3190,35 +3190,43 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec,
        }
       else
        {
-         asection *asect;
-         bfd_size_type size;
+         bfd_signed_vma distance;
 
          /* At this point, we don't know the load addresses of TSEC
             section nor SEC section.  We estimate the distrance between
-            SEC and TSEC.  */
-         size = 0;
-         for (asect = sec->output_section;
-              asect != NULL && asect != tsec->output_section;
-              asect = asect->next)
+            SEC and TSEC.  We store the estimated distrances in the
+            compressed_size field of the output section, which is only
+            used to decompress the compressed input section.  */
+         if (sec->output_section->compressed_size == 0)
            {
-             asection *i;
-             for (i = asect->output_section->map_head.s;
-                  i != NULL;
-                  i = i->map_head.s)
+             asection *asect;
+             bfd_size_type size = 0;
+             for (asect = link_info->output_bfd->sections;
+                  asect != NULL;
+                  asect = asect->next)
                {
-                 size = align_power (size, i->alignment_power);
-                 size += i->size;
+                 asection *i;
+                 for (i = asect->map_head.s;
+                      i != NULL;
+                      i = i->map_head.s)
+                   {
+                     size = align_power (size, i->alignment_power);
+                     size += i->size;
+                   }
+                 asect->compressed_size = size;
                }
            }
 
          /* Don't convert GOTPCREL relocations if TSEC isn't placed
             after SEC.  */
-         if (asect == NULL)
+         distance = (tsec->output_section->compressed_size
+                     - sec->output_section->compressed_size);
+         if (distance < 0)
            continue;
 
          /* Take PT_GNU_RELRO segment into account by adding
             maxpagesize.  */
-         if ((toff + size + maxpagesize - roff + 0x80000000)
+         if ((toff + distance + maxpagesize - roff + 0x80000000)
              > 0xffffffff)
            continue;
        }