Skip to content

Commit 7db9c91

Browse files
committed
[BOLT] Push code to higher addresses under options
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 570b952 commit 7db9c91

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3918,15 +3918,42 @@ 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 (auto SI = CodeSections.rbegin(), SE = CodeSections.rend(); SI != SE;
3926+
++SI) {
3927+
BinarySection *Section = *SI;
3928+
if (Section->getOutputSize() > Address)
3929+
return 0;
3930+
Address -= Section->getOutputSize();
3931+
Address = alignDown(Address, Section->getAlignment());
3932+
Section->setOutputAddress(Address);
3933+
}
3934+
return Address;
3935+
};
3936+
39213937
// Check if we can fit code in the original .text
39223938
bool AllocationDone = false;
39233939
if (opts::UseOldText) {
3924-
const uint64_t CodeSize =
3925-
allocateAt(BC->OldTextSectionAddress) - BC->OldTextSectionAddress;
3940+
uint64_t StartAddress;
3941+
uint64_t EndAddress;
3942+
if (opts::HotFunctionsAtEnd) {
3943+
EndAddress = BC->OldTextSectionAddress + BC->OldTextSectionSize;
3944+
StartAddress = allocateBefore(EndAddress);
3945+
} else {
3946+
StartAddress = BC->OldTextSectionAddress;
3947+
EndAddress = allocateAt(BC->OldTextSectionAddress);
3948+
}
39263949

3950+
const uint64_t CodeSize = EndAddress - StartAddress;
39273951
if (CodeSize <= BC->OldTextSectionSize) {
39283952
BC->outs() << "BOLT-INFO: using original .text for new code with 0x"
3929-
<< Twine::utohexstr(opts::AlignText) << " alignment\n";
3953+
<< Twine::utohexstr(opts::AlignText) << " alignment";
3954+
if (StartAddress != BC->OldTextSectionAddress)
3955+
BC->outs() << " at 0x" << Twine::utohexstr(StartAddress);
3956+
BC->outs() << '\n';
39303957
AllocationDone = true;
39313958
} else {
39323959
BC->errs()

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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 %p/Inputs/hello.c -o %t -no-pie -Wl,-q
7+
RUN: llvm-bolt %t -o %t.bolt --use-old-text --align-functions=1 \
8+
RUN: --no-huge-pages --align-text=1 --use-gnu-stack --hot-functions-at-end \
9+
RUN: | FileCheck %s --check-prefix=CHECK-BOLT
10+
RUN: llvm-readelf --sections %t.bolt | FileCheck %s
11+
12+
CHECK-BOLT: using original .text for new code with 0x1 alignment at {{.*}}
13+
14+
## As .text is pushed higher, preceding .bolt.org.text should have non-zero
15+
## size.
16+
CHECK: .bolt.org.text PROGBITS
17+
CHECK-NOT: {{ 000000 }}
18+
CHECK-SAME: AX
19+
CHECK-NEXT: .text PROGBITS

0 commit comments

Comments
 (0)