Write relocation sections contiguously.
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 17 Apr 2015 08:11:38 +0000 (08:11 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 17 Apr 2015 08:11:38 +0000 (08:11 +0000)
Linkers normally read all the relocations upfront to compute the references
between sections. Putting them together is a bit more cache friendly.

I benchmarked linking a Release+Asserts clang with gold on a vm. I tried all
4 combinations of --gc-sections/no --gc-section hot and cold cache.

I cleared the cache with

echo 3 > /proc/sys/vm/drop_caches

and warmed it up by running the link once before timing the subsequent ones.

With cold cache and --gc-sections the time goes from

1.86130781665 +- 0.01713126697463843 seconds
to
1.82370735105 +- 0.014127522318814516 seconds

With cold cache and no --gc-sections the time goes from

1.6087245435500002 +- 0.012999066825178644 seconds
to
1.5687122041500001 +- 0.013145850126026619 seconds

With hot cache and no --gc-sections the time goes from

0.926200939 ( +-  0.33% ) seconds
to
0.907200079 ( +-  0.31% ) seconds

With hot cache and gc sections the time goes from

1.183038049 ( +-  0.34% ) seconds
to
1.147355862 ( +-  0.39% ) seconds

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235165 91177308-0d34-0410-b5e6-96231b3b80d8

lib/MC/ELFObjectWriter.cpp
test/MC/ARM/eh-directive-section-comdat.s
test/MC/ARM/eh-directive-section.s
test/MC/ARM/eh-link.s
test/MC/ELF/comdat-reloc.s

index 8cb01c43edd61e82c991a72b29167fc06927f092..b293afc56a0d4ca27c6f9ac82ef78594c88621b1 100644 (file)
@@ -943,6 +943,8 @@ void ELFObjectWriter::computeIndexMap(MCAssembler &Asm,
     SectionIndexMap[&Section] = Index++;
   }
 
+  std::vector<const MCSectionELF *> RelSections;
+
   for (MCAssembler::iterator it = Asm.begin(),
          ie = Asm.end(); it != ie; ++it) {
     const MCSectionData &SD = *it;
@@ -956,9 +958,14 @@ void ELFObjectWriter::computeIndexMap(MCAssembler &Asm,
     if (MCSectionData *RelSD = createRelocationSection(Asm, SD)) {
       const MCSectionELF *RelSection =
           static_cast<const MCSectionELF *>(&RelSD->getSection());
-      SectionIndexMap[RelSection] = Index++;
+      RelSections.push_back(RelSection);
     }
   }
+
+  // Put relocation sections close together. The linker reads them
+  // first, so this improves cache locality.
+  for (const MCSectionELF * Sec: RelSections)
+    SectionIndexMap[Sec] = Index++;
 }
 
 void ELFObjectWriter::computeSymbolTable(
index 296718f096ca22cdd5daf12890be37fc240cd27f..fb2a83b47e41224f3c2ab0262a26f865103f55f1 100644 (file)
@@ -52,7 +52,7 @@ func1:
 @ The second, third, and fourth word should correspond to the section index
 @ of .TEST1, .ARM.extab.TEST1, and .ARM.exidx.TEST1.
 @-------------------------------------------------------------------------------
-@ CHECK:       0000: 01000000 05000000 06000000 08000000  |................|
+@ CHECK:       0000: 01000000 05000000 06000000 07000000  |................|
 @ CHECK:     )
 @ CHECK:   }
 
@@ -96,7 +96,7 @@ func1:
 @ Check the .ARM.exidx.TEST1 section
 @-------------------------------------------------------------------------------
 @ CHECK:   Section {
-@ CHECK:     Index: 8
+@ CHECK:     Index: 7
 @ CHECK:     Name: .ARM.exidx.TEST1
 @ CHECK:     Type: SHT_ARM_EXIDX (0x70000001)
 @-------------------------------------------------------------------------------
index 671d10679d1b22d72d5994ab0fa6f79992a62aa0..53ac48e848b565accfb0d339d121adb345bc309b 100644 (file)
@@ -109,7 +109,7 @@ func2:
 @ Check the TEST2 section (without the dot in the beginning)
 @-------------------------------------------------------------------------------
 @ CHECK:   Section {
-@ CHECK:     Index: 9
+@ CHECK:     Index: 7
 @ CHECK:     Name: TEST2
 @ CHECK:     SectionData (
 @ CHECK:       0000: 1EFF2FE1                             |../.|
@@ -143,7 +143,7 @@ func2:
 @-------------------------------------------------------------------------------
 @ This section should linked with TEST2 section.
 @-------------------------------------------------------------------------------
-@ CHECK:     Link: 9
+@ CHECK:     Link: 7
 
 @-------------------------------------------------------------------------------
 @ The first word should be relocated to the code address in TEST2 section.
@@ -175,6 +175,6 @@ func2:
 @ CHECK:   }
 @ CHECK:   Symbol {
 @ CHECK:     Name: func2
-@ CHECK:     Section: TEST2 (0x9)
+@ CHECK:     Section: TEST2 (0x7)
 @ CHECK:   }
 @ CHECK: ]
index 0c44c0e2c06d911822572aabe6086a9f9b362b3f..296f9072e0e074283405076d1717ad45e4a58208 100644 (file)
@@ -43,7 +43,7 @@
 @ CHECK-NEXT: }
 
 @ CHECK:      Section {
-@ CHECK:        Index: 9
+@ CHECK:        Index: 8
 @ CHECK-NEXT:   Name: .text
 @ CHECK-NEXT:   Type: SHT_PROGBITS
 @ CHECK-NEXT:   Flags [
@@ -60,7 +60,7 @@
 @ CHECK-NEXT:   EntrySize: 0
 @ CHECK-NEXT: }
 @ CHECK-NEXT: Section {
-@ CHECK-NEXT:   Index: 10
+@ CHECK-NEXT:   Index: 9
 @ CHECK-NEXT:   Name: .ARM.exidx
 @ CHECK-NEXT:   Type: SHT_ARM_EXIDX
 @ CHECK-NEXT:   Flags [
@@ -71,7 +71,7 @@
 @ CHECK-NEXT:   Address: 0x0
 @ CHECK-NEXT:   Offset:
 @ CHECK-NEXT:   Size: 8
-@ CHECK-NEXT:   Link: 9
+@ CHECK-NEXT:   Link: 8
 @ CHECK-NEXT:   Info: 0
 @ CHECK-NEXT:   AddressAlignment: 4
 @ CHECK-NEXT:   EntrySize: 0
index d893a7b149ef5364821f9feba67329d29a50839f..e7aa3d93738e0cee52b3a7c1b09e89433c1ba014 100644 (file)
@@ -16,9 +16,9 @@ world:
 // CHECK:  Name: .group
 // CHECK-NOT: SectionData
 // CHECK: SectionData
-// CHECK-NEXT: 0000: 01000000 06000000 07000000
+// CHECK-NEXT: 0000: 01000000 05000000 07000000
 
-// CHECK: Index: 6
+// CHECK: Index: 5
 // CHECK-NEXT: Name: .text.world
 // CHECK-NOT: Section {
 // CHECK: SHF_GROUP