[binutils-gdb/binutils-2_26-branch] Store estimated distances in compressed_size

H.J.Lu hjl@sourceware.org
Tue Feb 2 21:09:00 GMT 2016


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cc2d819b58fd5d60dfef34007662535f9e142c16

commit cc2d819b58fd5d60dfef34007662535f9e142c16
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue Feb 2 08:14:43 2016 -0800

    Store estimated distances in compressed_size
    
    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.

Diff:
---
 bfd/ChangeLog      |  9 +++++++++
 bfd/elf64-x86-64.c | 38 +++++++++++++++++++++++---------------
 2 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7f09156..1704438 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 63957bb..156734b 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -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;
 	}



More information about the Binutils-cvs mailing list