diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1316,8 +1316,13 @@ SmallVector unorderedSections; SmallVector, 0> orderedSections; uint64_t unorderedSize = 0; + uint64_t totalSize = 0; + uint64_t executableInputSections = 0; for (InputSection *isec : isd->sections) { + totalSize += isec->getSize(); + if (isec->flags & SHF_EXECINSTR) + ++executableInputSections; auto i = order.find(isec); if (i == order.end()) { unorderedSections.push_back(isec); @@ -1355,8 +1360,15 @@ // of the second block of cold code can call the hot code without a thunk. So // we effectively double the amount of code that could potentially call into // the hot code without a thunk. + // + // The above is not necessary when less than two input sections contain + // anything that is executable or when total size of output section is small, + // for which no thunk would be required. Hot code could occupy one less page + // if it can be placed at beginning of the output section. size_t insPt = 0; - if (target->getThunkSectionSpacing() && !orderedSections.empty()) { + if (executableInputSections > 1 && target->getThunkSectionSpacing() && + !orderedSections.empty() && + totalSize >= target->getThunkSectionSpacing()) { uint64_t unorderedPos = 0; for (; insPt != unorderedSections.size(); ++insPt) { unorderedPos += unorderedSections[insPt]->getSize(); diff --git a/lld/test/ELF/arm-symbol-ordering-file.s b/lld/test/ELF/arm-symbol-ordering-file.s --- a/lld/test/ELF/arm-symbol-ordering-file.s +++ b/lld/test/ELF/arm-symbol-ordering-file.s @@ -1,16 +1,31 @@ # REQUIRES: arm -# RUN: llvm-mc -filetype=obj -triple=armv7-unknown-linux %s -o %t.o + +# RUN: split-file %s %t + +# RUN: llvm-mc -filetype=obj -triple=armv7-unknown-linux %t/small.s -o %t.small.o +# RUN: llvm-mc -filetype=obj -triple=armv7-unknown-linux %t/large.s -o %t.large.o # RUN: echo ordered > %t_order.txt -# RUN: ld.lld --symbol-ordering-file %t_order.txt %t.o -o %t2.out -# RUN: llvm-nm -n %t2.out | FileCheck %s -# CHECK: unordered1 -# CHECK-NEXT: unordered2 -# CHECK-NEXT: unordered3 -# CHECK-NEXT: ordered -# CHECK-NEXT: unordered4 +# RUN: ld.lld --symbol-ordering-file %t_order.txt %t.small.o -o %t2.small.out +# RUN: ld.lld --symbol-ordering-file %t_order.txt %t.large.o -o %t2.large.out +# RUN: llvm-nm -n %t2.small.out | FileCheck --check-prefix=SMALL %s +# RUN: llvm-nm -n %t2.large.out | FileCheck --check-prefix=LARGE %s +# RUN: rm -f %t.*.o %t2.*.out + +# SMALL: ordered +# SMALL-NEXT: unordered1 +# SMALL-NEXT: unordered2 +# SMALL-NEXT: unordered3 +# SMALL-NEXT: unordered4 + +# LARGE: unordered1 +# LARGE-NEXT: unordered2 +# LARGE-NEXT: ordered +# LARGE-NEXT: unordered3 +# LARGE-NEXT: unordered4 +#--- small.s .section .foo,"ax",%progbits,unique,1 unordered1: .zero 1 @@ -30,3 +45,24 @@ .section .foo,"ax",%progbits,unique,5 ordered: .zero 1 + +#--- large.s +.section .bar,"ax",%progbits,unique,1 +unordered1: +.zero 0xC00000 + +.section .bar,"ax",%progbits,unique,2 +unordered2: +.zero 0xC00000 + +.section .bar,"ax",%progbits,unique,3 +unordered3: +.zero 0xC00000 + +.section .bar,"ax",%progbits,unique,4 +unordered4: +.zero 0xC00000 + +.section .bar,"ax",%progbits,unique,5 +ordered: +.zero 8