Skip to content

Commit fb24b4d

Browse files
authored
[BOLT] Push code to higher addresses under options (#146180)
When --hot-functions-at-end is used in combination with --use-old-text, allocate code at the highest possible addresses withing old .text. This feature is mostly useful for HHVM, where it is beneficial to have hot static code placed as close as possible to jitted code.
1 parent f90025e commit fb24b4d

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3918,15 +3918,40 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
39183918
return Address;
39193919
};
39203920

3921+
// Try to allocate sections before the \p Address and return an address for
3922+
// the allocation of the first section, or 0 if [0, Address) range is not
3923+
// big enough to fit all sections.
3924+
auto allocateBefore = [&](uint64_t Address) -> uint64_t {
3925+
for (BinarySection *Section : llvm::reverse(CodeSections)) {
3926+
if (Section->getOutputSize() > Address)
3927+
return 0;
3928+
Address -= Section->getOutputSize();
3929+
Address = alignDown(Address, Section->getAlignment());
3930+
Section->setOutputAddress(Address);
3931+
}
3932+
return Address;
3933+
};
3934+
39213935
// Check if we can fit code in the original .text
39223936
bool AllocationDone = false;
39233937
if (opts::UseOldText) {
3924-
const uint64_t CodeSize =
3925-
allocateAt(BC->OldTextSectionAddress) - BC->OldTextSectionAddress;
3938+
uint64_t StartAddress;
3939+
uint64_t EndAddress;
3940+
if (opts::HotFunctionsAtEnd) {
3941+
EndAddress = BC->OldTextSectionAddress + BC->OldTextSectionSize;
3942+
StartAddress = allocateBefore(EndAddress);
3943+
} else {
3944+
StartAddress = BC->OldTextSectionAddress;
3945+
EndAddress = allocateAt(BC->OldTextSectionAddress);
3946+
}
39263947

3948+
const uint64_t CodeSize = EndAddress - StartAddress;
39273949
if (CodeSize <= BC->OldTextSectionSize) {
39283950
BC->outs() << "BOLT-INFO: using original .text for new code with 0x"
3929-
<< Twine::utohexstr(opts::AlignText) << " alignment\n";
3951+
<< Twine::utohexstr(opts::AlignText) << " alignment";
3952+
if (StartAddress != BC->OldTextSectionAddress)
3953+
BC->outs() << " at 0x" << Twine::utohexstr(StartAddress);
3954+
BC->outs() << '\n';
39303955
AllocationDone = true;
39313956
} else {
39323957
BC->errs()

bolt/test/code-at-high-address.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Check that llvm-bolt pushes code to higher addresses under
2+
// --hot-functions-at-end when rewriting code in-place.
3+
4+
// REQUIRES: system-linux
5+
6+
// RUN: %clang %cflags -O0 %s -o %t -no-pie -Wl,-q -falign-functions=64 \
7+
// RUN: -nostartfiles -nostdlib -ffreestanding
8+
// RUN: llvm-bolt %t -o %t.bolt --use-old-text --align-functions=1 \
9+
// RUN: --no-huge-pages --align-text=1 --use-gnu-stack --hot-functions-at-end \
10+
// RUN: | FileCheck %s --check-prefix=CHECK-BOLT
11+
// RUN: llvm-readelf --sections %t.bolt | FileCheck %s
12+
13+
// CHECK-BOLT: using original .text for new code with 0x1 alignment at {{.*}}
14+
15+
// As .text is pushed higher, preceding .bolt.org.text should have non-zero
16+
// size.
17+
// CHECK: .bolt.org.text PROGBITS
18+
// CHECK-NOT: {{ 000000 }}
19+
// CHECK-SAME: AX
20+
// CHECK-NEXT: .text PROGBITS
21+
22+
int foo() { return 0; }
23+
24+
int main() { return foo(); }

0 commit comments

Comments
 (0)