Index: lld/trunk/ELF/Relocations.cpp =================================================================== --- lld/trunk/ELF/Relocations.cpp +++ lld/trunk/ELF/Relocations.cpp @@ -1218,17 +1218,30 @@ // // We follow a simple but conservative heuristic to place ThunkSections at // offsets that are multiples of a Target specific branch range. -// For an InputSectionRange that is smaller than the range, a single +// For an InputSectionDescription that is smaller than the range, a single // ThunkSection at the end of the range will do. +// +// For an InputSectionDescription that is more than twice the size of the range, +// we place the last ThunkSection at range bytes from the end of the +// InputSectionDescription in order to increase the likelihood that the +// distance from a thunk to its target will be sufficiently small to +// allow for the creation of a short thunk. void ThunkCreator::createInitialThunkSections( ArrayRef OutputSections) { forEachInputSectionDescription( OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) { if (ISD->Sections.empty()) return; + uint32_t ISDBegin = ISD->Sections.front()->OutSecOff; + uint32_t ISDEnd = + ISD->Sections.back()->OutSecOff + ISD->Sections.back()->getSize(); + uint32_t LastThunkLowerBound = -1; + if (ISDEnd - ISDBegin > Target->ThunkSectionSpacing * 2) + LastThunkLowerBound = ISDEnd - Target->ThunkSectionSpacing; + uint32_t ISLimit; - uint32_t PrevISLimit = ISD->Sections.front()->OutSecOff; - uint32_t ThunkUpperBound = PrevISLimit + Target->ThunkSectionSpacing; + uint32_t PrevISLimit = ISDBegin; + uint32_t ThunkUpperBound = ISDBegin + Target->ThunkSectionSpacing; for (const InputSection *IS : ISD->Sections) { ISLimit = IS->OutSecOff + IS->getSize(); @@ -1236,6 +1249,8 @@ addThunkSection(OS, ISD, PrevISLimit); ThunkUpperBound = PrevISLimit + Target->ThunkSectionSpacing; } + if (ISLimit > LastThunkLowerBound) + break; PrevISLimit = ISLimit; } addThunkSection(OS, ISD, ISLimit); Index: lld/trunk/test/ELF/arm-thumb-mix-range-thunk-os.s =================================================================== --- lld/trunk/test/ELF/arm-thumb-mix-range-thunk-os.s +++ lld/trunk/test/ELF/arm-thumb-mix-range-thunk-os.s @@ -11,7 +11,7 @@ // RUN: llvm-objdump -d %t2 -start-address=35651584 -stop-address=35651590 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK6 %s // RUN: llvm-objdump -d %t2 -start-address=36700160 -stop-address=36700168 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s // RUN: llvm-objdump -d %t2 -start-address=48234500 -stop-address=48234512 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK8 %s -// RUN: llvm-objdump -d %t2 -start-address=63963140 -stop-address=63963160 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK9 %s +// RUN: llvm-objdump -d %t2 -start-address=53477380 -stop-address=53477392 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK9 %s // RUN: llvm-objdump -d %t2 -start-address=68157440 -stop-address=68157452 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK10 %s // RUN: llvm-objdump -d %t2 -start-address=69206016 -stop-address=69206024 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK11 %s @@ -155,6 +155,13 @@ ARMFUNCTION 48 THUMBFUNCTION 49 ARMFUNCTION 50 +// Expect precreated Thunk Section here +// CHECK9: __Thumbv7ABSLongThunk_afunc34: +// CHECK9-NEXT: 3300004: 40 f2 00 0c movw r12, #0 +// CHECK9-NEXT: 3300008: c0 f2 30 2c movt r12, #560 +// CHECK9-NEXT: 330000c: 60 47 bx r12 +// CHECK9: __Thumbv7ABSLongThunk_tfunc35: +// CHECK9-NEXT: 330000e: ff f4 f7 97 b.w #-15728658 THUMBFUNCTION 51 ARMFUNCTION 52 THUMBFUNCTION 53 @@ -165,15 +172,6 @@ ARMFUNCTION 58 THUMBFUNCTION 59 ARMFUNCTION 60 -// Expect precreated Thunk Section here -// CHECK9: __Thumbv7ABSLongThunk_afunc34: -// CHECK9-NEXT: 3d00004: 40 f2 00 0c movw r12, #0 -// CHECK9-NEXT: 3d00008: c0 f2 30 2c movt r12, #560 -// CHECK9-NEXT: 3d0000c: 60 47 bx r12 -// CHECK9: __Thumbv7ABSLongThunk_tfunc35: -// CHECK9-NEXT: 3d0000e: 40 f2 01 0c movw r12, #1 -// CHECK9-NEXT: 3d00012: c0 f2 40 2c movt r12, #576 -// CHECK9-NEXT: 3d00016: 60 47 bx r12 THUMBFUNCTION 61 ARMFUNCTION 62 THUMBFUNCTION 63 @@ -191,5 +189,5 @@ bl tfunc35 // CHECK11: tfunc65: // CHECK11: 4200000: 70 47 bx lr -// CHECK11-NEXT: 4200002: ff f6 ff f7 bl #-5242882 -// CHECK11-NEXT: 4200006: 00 f7 02 f0 bl #-5242876 +// CHECK11-NEXT: 4200002: ff f4 ff d7 bl #-15728642 +// CHECK11-NEXT: 4200006: 00 f5 02 d0 bl #-15728636 Index: lld/trunk/test/ELF/arm-thumb-range-thunk-os.s =================================================================== --- lld/trunk/test/ELF/arm-thumb-range-thunk-os.s +++ lld/trunk/test/ELF/arm-thumb-range-thunk-os.s @@ -9,8 +9,8 @@ // RUN: llvm-objdump -d %t2 -start-address=4194304 -stop-address=4194310 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s // RUN: llvm-objdump -d %t2 -start-address=16777216 -stop-address=16777270 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK5 %s // RUN: llvm-objdump -d %t2 -start-address=17825792 -stop-address=17825808 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK6 %s -// RUN: llvm-objdump -d %t2 -start-address=31457280 -stop-address=31457286 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s -// RUN: llvm-objdump -d %t2 -start-address=32505860 -stop-address=32505880 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK8 %s +// RUN: llvm-objdump -d %t2 -start-address=20971524 -stop-address=20971532 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s +// RUN: llvm-objdump -d %t2 -start-address=31457280 -stop-address=31457286 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK8 %s // RUN: llvm-objdump -d %t2 -start-address=35651584 -stop-address=35651594 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK9 %s // RUN: llvm-objdump -d %t2 -start-address=36700160 -stop-address=36700170 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK10 %s @@ -105,6 +105,11 @@ FUNCTION 16 FUNCTION 17 FUNCTION 18 +// Expect another precreated thunk section here +// CHECK7: __Thumbv7ABSLongThunk_tfunc15: +// CHECK7-NEXT: 1400004: ff f4 fc bf b.w #-3145736 +// CHECK7: __Thumbv7ABSLongThunk_tfunc16: +// CHECK7-NEXT: 1400008: ff f5 fa bf b.w #-2097164 FUNCTION 19 FUNCTION 20 FUNCTION 21 @@ -117,17 +122,12 @@ FUNCTION 28 // tfunc02 is > 16Mb away, expect range extension thunks in precreated thunk // section -// CHECK7: tfunc28: -// CHECK7-NEXT: 1e00000: 70 47 bx lr -// CHECK7-NEXT: 1e00002: 00 f6 0d 90 b.w #-14680038 <__Thumbv7ABSLongThunk_tfunc02> +// CHECK8: tfunc28: +// CHECK8-NEXT: 1e00000: 70 47 bx lr +// CHECK8-NEXT: 1e00002: 00 f6 0d 90 b.w #-14680038 <__Thumbv7ABSLongThunk_tfunc02> b.w tfunc02 FUNCTION 29 -// Expect another precreated thunk section here -// CHECK8: __Thumbv7ABSLongThunk_tfunc15: -// CHECK8-NEXT: 1f00004: ff f5 fc 97 b.w #-14680072 -// CHECK8: __Thumbv7ABSLongThunk_tfunc16: -// CHECK8-NEXT: 1f00008: ff f6 fa 97 b.w #-13631500 FUNCTION 30 FUNCTION 31 FUNCTION 32 @@ -137,13 +137,13 @@ bl tfunc16 // CHECK9: tfunc32: // CHECK9: 2200000: 70 47 bx lr -// CHECK9-NEXT: 2200002: ff f4 ff ff bl #-3145730 -// CHECK9-NEXT: 2200006: ff f4 ff ff bl #-3145730 +// CHECK9-NEXT: 2200002: ff f5 ff d7 bl #-14680066 +// CHECK9-NEXT: 2200006: ff f5 ff d7 bl #-14680066 FUNCTION 33 bl tfunc15 bl tfunc16 // CHECK10: tfunc33: // CHECK10: 2300000: 70 47 bx lr -// CHECK10-NEXT: 2300002: ff f7 ff f7 bl #-4194306 -// CHECK10-NEXT: 2300006: ff f7 ff f7 bl #-4194306 +// CHECK10-NEXT: 2300002: ff f4 ff d7 bl #-15728642 +// CHECK10-NEXT: 2300006: ff f4 ff d7 bl #-15728642