]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Store estimated distances 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 21:06:10 +0000 (13:06 -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 distances 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.

Backport from master

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

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

index 7f09156ac1ba774b1d5cb5dd5b449fe62d26ffb2..1704438c2296fcc301be0d85079201a69b15872d 100644 (file)
@@ -1,3 +1,12 @@
+2016-02-02  H.J. Lu  <hongjiu.lu@intel.com>
+
+       Backport from master
+       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
+       distances in the compressed_size field of the output section.
+
 2016-02-01  John David Anglin  <danglin@gcc.gnu.org>
 
        PR ld/19526
index 63957bbd1c34db4dda4ae021c6cb29d37f114da0..156734b7ab733b1d376cfed294aef7e74cf4055d 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 distances 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;
        }