[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.
This commit is contained in:
@@ -3918,15 +3918,40 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {
|
||||
return Address;
|
||||
};
|
||||
|
||||
// Try to allocate sections before the \p Address and return an address for
|
||||
// the allocation of the first section, or 0 if [0, Address) range is not
|
||||
// big enough to fit all sections.
|
||||
auto allocateBefore = [&](uint64_t Address) -> uint64_t {
|
||||
for (BinarySection *Section : llvm::reverse(CodeSections)) {
|
||||
if (Section->getOutputSize() > Address)
|
||||
return 0;
|
||||
Address -= Section->getOutputSize();
|
||||
Address = alignDown(Address, Section->getAlignment());
|
||||
Section->setOutputAddress(Address);
|
||||
}
|
||||
return Address;
|
||||
};
|
||||
|
||||
// Check if we can fit code in the original .text
|
||||
bool AllocationDone = false;
|
||||
if (opts::UseOldText) {
|
||||
const uint64_t CodeSize =
|
||||
allocateAt(BC->OldTextSectionAddress) - BC->OldTextSectionAddress;
|
||||
uint64_t StartAddress;
|
||||
uint64_t EndAddress;
|
||||
if (opts::HotFunctionsAtEnd) {
|
||||
EndAddress = BC->OldTextSectionAddress + BC->OldTextSectionSize;
|
||||
StartAddress = allocateBefore(EndAddress);
|
||||
} else {
|
||||
StartAddress = BC->OldTextSectionAddress;
|
||||
EndAddress = allocateAt(BC->OldTextSectionAddress);
|
||||
}
|
||||
|
||||
const uint64_t CodeSize = EndAddress - StartAddress;
|
||||
if (CodeSize <= BC->OldTextSectionSize) {
|
||||
BC->outs() << "BOLT-INFO: using original .text for new code with 0x"
|
||||
<< Twine::utohexstr(opts::AlignText) << " alignment\n";
|
||||
<< Twine::utohexstr(opts::AlignText) << " alignment";
|
||||
if (StartAddress != BC->OldTextSectionAddress)
|
||||
BC->outs() << " at 0x" << Twine::utohexstr(StartAddress);
|
||||
BC->outs() << '\n';
|
||||
AllocationDone = true;
|
||||
} else {
|
||||
BC->errs()
|
||||
|
||||
24
bolt/test/code-at-high-address.c
Normal file
24
bolt/test/code-at-high-address.c
Normal file
@@ -0,0 +1,24 @@
|
||||
// Check that llvm-bolt pushes code to higher addresses under
|
||||
// --hot-functions-at-end when rewriting code in-place.
|
||||
|
||||
// REQUIRES: system-linux
|
||||
|
||||
// RUN: %clang %cflags -O0 %s -o %t -no-pie -Wl,-q -falign-functions=64 \
|
||||
// RUN: -nostartfiles -nostdlib -ffreestanding
|
||||
// RUN: llvm-bolt %t -o %t.bolt --use-old-text --align-functions=1 \
|
||||
// RUN: --no-huge-pages --align-text=1 --use-gnu-stack --hot-functions-at-end \
|
||||
// RUN: | FileCheck %s --check-prefix=CHECK-BOLT
|
||||
// RUN: llvm-readelf --sections %t.bolt | FileCheck %s
|
||||
|
||||
// CHECK-BOLT: using original .text for new code with 0x1 alignment at {{.*}}
|
||||
|
||||
// As .text is pushed higher, preceding .bolt.org.text should have non-zero
|
||||
// size.
|
||||
// CHECK: .bolt.org.text PROGBITS
|
||||
// CHECK-NOT: {{ 000000 }}
|
||||
// CHECK-SAME: AX
|
||||
// CHECK-NEXT: .text PROGBITS
|
||||
|
||||
int foo() { return 0; }
|
||||
|
||||
int main() { return foo(); }
|
||||
Reference in New Issue
Block a user