[BOLT] Align constant islands to 8 bytes

AArch64 requires CI to be aligned to 8 bytes due to access instructions
restrictions. E.g. the ldr with imm, where imm must be aligned to 8 bytes.

Differential Revision: https://reviews.llvm.org/D122065
This commit is contained in:
Vladislav Khmelevsky 2022-03-19 13:26:38 +03:00
parent 8b245ab41d
commit af9bdcfc46
5 changed files with 63 additions and 4 deletions

View file

@ -172,6 +172,9 @@ public:
mutable MCSymbol *FunctionConstantIslandLabel{nullptr};
mutable MCSymbol *FunctionColdConstantIslandLabel{nullptr};
// Returns constant island alignment
uint16_t getAlignment() const { return sizeof(uint64_t); }
};
static constexpr uint64_t COUNT_NO_PROFILE =
@ -2047,6 +2050,10 @@ public:
return *std::prev(CodeIter) <= *DataIter;
}
uint16_t getConstantIslandAlignment() const {
return Islands ? Islands->getAlignment() : 1;
}
uint64_t
estimateConstantIslandSize(const BinaryFunction *OnBehalfOf = nullptr) const {
if (!Islands)
@ -2074,9 +2081,13 @@ public:
Size += NextMarker - *DataIter;
}
if (!OnBehalfOf)
for (BinaryFunction *ExternalFunc : Islands->Dependency)
if (!OnBehalfOf) {
for (BinaryFunction *ExternalFunc : Islands->Dependency) {
Size = alignTo(Size, ExternalFunc->getConstantIslandAlignment());
Size += ExternalFunc->estimateConstantIslandSize(this);
}
}
return Size;
}

View file

@ -500,6 +500,13 @@ void BinaryEmitter::emitConstantIslands(BinaryFunction &BF, bool EmitColdPart,
if (Islands.DataOffsets.empty() && Islands.Dependency.empty())
return;
// AArch64 requires CI to be aligned to 8 bytes due to access instructions
// restrictions. E.g. the ldr with imm, where imm must be aligned to 8 bytes.
const uint16_t Alignment = OnBehalfOf
? OnBehalfOf->getConstantIslandAlignment()
: BF.getConstantIslandAlignment();
Streamer.emitCodeAlignment(Alignment, &*BC.STI);
if (!OnBehalfOf) {
if (!EmitColdPart)
Streamer.emitLabel(BF.getFunctionConstantIslandLabel());

View file

@ -308,6 +308,7 @@ uint64_t LongJmpPass::tentativeLayoutRelocColdPart(
LLVM_DEBUG(dbgs() << Func->getPrintName() << " cold tentative: "
<< Twine::utohexstr(DotAddress) << "\n");
DotAddress += Func->estimateColdSize();
DotAddress = alignTo(DotAddress, Func->getConstantIslandAlignment());
DotAddress += Func->estimateConstantIslandSize();
}
return DotAddress;
@ -364,6 +365,8 @@ uint64_t LongJmpPass::tentativeLayoutRelocMode(
DotAddress += Func->estimateSize();
else
DotAddress += Func->estimateHotSize();
DotAddress = alignTo(DotAddress, Func->getConstantIslandAlignment());
DotAddress += Func->estimateConstantIslandSize();
++CurrentIndex;
}

View file

@ -0,0 +1,38 @@
// This test checks that the constant island is aligned after BOLT tool.
// In case the nop before .Lci will be removed the pointer to exit function
// won't be alinged and the test will fail.
# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \
# RUN: %s -o %t.o
# RUN: %clang %cflags -fPIC -pie %t.o -o %t.exe -Wl,-q \
# RUN: -nostartfiles -nodefaultlibs -lc
# RUN: llvm-bolt %t.exe -o %t.bolt -use-old-text=0 -lite=0 -trap-old-code
# RUN: llvm-objdump -d --disassemble-symbols='$d' %t.bolt | FileCheck %s
.text
.align 4
.global
.type dummy, %function
dummy:
add x0, x0, #1
ret
.global
.type exitOk, %function
exitOk:
mov x0, #0
bl exit
.global _start
.type _start, %function
_start:
adrp x0, .Lci
ldr x0, [x0, #:lo12:.Lci]
blr x0
mov x1, #1
bl exit
nop
# CHECK: {{0|8}} <$d>:
.Lci:
.xword exitOk
.xword 0

View file

@ -41,9 +41,9 @@ br:
.word 0xff
# CHECK: <main>:
# CHECK-NEXT: adr x0, #28
# CHECK-NEXT: adr x0, #{{[0-9][0-9]*}}
# CHECK-NEXT: adrp x1, 0x{{[1-8a-f][0-9a-f]*}}
# CHECK-NEXT: add x1, x1, #{{[1-8a-f][0-9a-f]*}}
# CHECK-NEXT: adrp x2, 0x{{[1-8a-f][0-9a-f]*}}
# CHECK-NEXT: add x2, x2, #{{[1-8a-f][0-9a-f]*}}
# CHECK-NEXT: adr x3, #4
# CHECK-NEXT: adr x3, #{{[0-9][0-9]*}}