Skip to content

Commit 1e302e9

Browse files
authored
[BOLT] Add heuristics to determine constant island's alignment (#159486)
Constant island embedded in text section doesn't have its alignment information from input binary and we currently set its alignment as 8 bytes. Constant island might be given a much larger alignment due to performance or other reasons, so this change adds some heuristics to determine its alignment based on its size, original address from input binary and its owning section's alignment.
1 parent 9e6fa39 commit 1e302e9

File tree

3 files changed

+109
-12
lines changed

3 files changed

+109
-12
lines changed

bolt/include/bolt/Core/BinaryFunction.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,6 @@ class BinaryFunction {
192192

193193
mutable MCSymbol *FunctionConstantIslandLabel{nullptr};
194194
mutable MCSymbol *FunctionColdConstantIslandLabel{nullptr};
195-
196-
// Returns constant island alignment
197-
uint16_t getAlignment() const { return sizeof(uint64_t); }
198195
};
199196

200197
static constexpr uint64_t COUNT_NO_PROFILE =
@@ -2114,9 +2111,7 @@ class BinaryFunction {
21142111
return *std::prev(CodeIter) <= *DataIter;
21152112
}
21162113

2117-
uint16_t getConstantIslandAlignment() const {
2118-
return Islands ? Islands->getAlignment() : 1;
2119-
}
2114+
uint16_t getConstantIslandAlignment() const;
21202115

21212116
/// If there is a constant island in the range [StartOffset, EndOffset),
21222117
/// return its address.
@@ -2168,6 +2163,11 @@ class BinaryFunction {
21682163
return Islands && !Islands->DataOffsets.empty();
21692164
}
21702165

2166+
/// Return true if the whole function is a constant island.
2167+
bool isDataObject() const {
2168+
return Islands && Islands->CodeOffsets.size() == 0;
2169+
}
2170+
21712171
bool isStartOfConstantIsland(uint64_t Offset) const {
21722172
return hasConstantIsland() && Islands->DataOffsets.count(Offset);
21732173
}

bolt/lib/Core/BinaryFunction.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,33 @@ BinaryFunction::getBasicBlockContainingOffset(uint64_t Offset) {
284284
return (Offset < BB->getOffset() + BB->getOriginalSize()) ? BB : nullptr;
285285
}
286286

287+
uint16_t BinaryFunction::getConstantIslandAlignment() const {
288+
if (Islands == nullptr)
289+
return 1;
290+
291+
// For constant island inside a function, the default 8-byte alignment is
292+
// probably good enough.
293+
const uint16_t DefaultAlignment = sizeof(uint64_t);
294+
if (!isDataObject())
295+
return DefaultAlignment;
296+
297+
// If the constant island itself is a binary function, get its alignment
298+
// based on its size, original address, and its owning section's alignment.
299+
const uint64_t MaxAlignment =
300+
std::min(uint64_t(1) << llvm::countr_zero(getAddress()),
301+
OriginSection->getAlignment());
302+
const uint64_t MinAlignment =
303+
std::max((uint64_t)DefaultAlignment,
304+
uint64_t(1) << (63 - llvm::countl_zero(getSize())));
305+
uint64_t Alignment = std::min(MinAlignment, MaxAlignment);
306+
if (Alignment >> 16) {
307+
BC.errs() << "BOLT-ERROR: the constant island's alignment is too big: 0x"
308+
<< Twine::utohexstr(Alignment) << "\n";
309+
exit(1);
310+
}
311+
return (uint16_t)Alignment;
312+
}
313+
287314
void BinaryFunction::markUnreachableBlocks() {
288315
std::stack<BinaryBasicBlock *> Stack;
289316

bolt/test/AArch64/constant-island-alignment.s

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,36 @@
11
// This test checks that the constant island is aligned after BOLT tool.
2-
// In case the nop before .Lci will be removed the pointer to exit function
3-
// won't be alinged and the test will fail.
2+
3+
# RUN: split-file %s %t
4+
5+
// For the first test case, in case the nop before .Lci will be removed
6+
// the pointer to exit function won't be alinged and the test will fail.
47

58
# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \
6-
# RUN: %s -o %t.o
7-
# RUN: %clang %cflags -fPIC -pie %t.o -o %t.exe -Wl,-q \
9+
# RUN: %t/xword_align.s -o %t_xa.o
10+
# RUN: %clang %cflags -fPIC -pie %t_xa.o -o %t_xa.exe -Wl,-q \
811
# RUN: -nostartfiles -nodefaultlibs -Wl,-z,notext
9-
# RUN: llvm-bolt %t.exe -o %t.bolt --use-old-text=0 --lite=0 --trap-old-code
10-
# RUN: llvm-objdump -d --disassemble-symbols='$d' %t.bolt | FileCheck %s
12+
# RUN: llvm-bolt %t_xa.exe -o %t_xa.bolt --use-old-text=0 --lite=0 \
13+
# RUN: --trap-old-code
14+
# RUN: llvm-objdump -d --disassemble-symbols='$d' %t_xa.bolt | FileCheck %s
15+
16+
// For the second and third test cases, we want to set an alignment based
17+
// on various heuristics.
18+
19+
# RUN: %clang %cflags -pie %t/page_align.s -o %t_pa.exe -Wl,-q \
20+
# RUN: -Wl,--init=_foo -Wl,--fini=_foo
21+
# RUN: llvm-bolt %t_pa.exe -o %t_pa.bolt
22+
# RUN: llvm-objdump -t %t_pa.exe | grep _const_island
23+
# RUN: llvm-objdump -t %t_pa.bolt | grep _const_island | FileCheck %s \
24+
# RUN: --check-prefix=PAGE
25+
26+
# RUN: %clang %cflags -pie %t/64B_align.s -o %t_64B.exe -Wl,-q \
27+
# RUN: -Wl,--init=_foo -Wl,--fini=_foo
28+
# RUN: llvm-bolt %t_64B.exe -o %t_64B.bolt
29+
# RUN: llvm-objdump -t %t_64B.exe | grep _const_island
30+
# RUN: llvm-objdump -t %t_64B.bolt | grep _const_island | FileCheck %s \
31+
# RUN: --check-prefix=64BYTE
1132

33+
;--- xword_align.s
1234
.text
1335
.align 4
1436
.global
@@ -36,3 +58,51 @@ _start:
3658
.Lci:
3759
.xword exitOk
3860
.xword 0
61+
62+
;--- page_align.s
63+
.text
64+
.global _foo
65+
.type _foo, %function
66+
_foo:
67+
ret
68+
69+
.text
70+
.global _const_island
71+
.align 12
72+
# PAGE: {{[0-9a-f]*}}000 g
73+
_const_island:
74+
.rept 0x25100
75+
.byte 0xbb
76+
.endr
77+
78+
.global _start
79+
.type _start, %function
80+
_start:
81+
ret
82+
83+
# Dummy relocation to force relocation mode
84+
.reloc 0, R_AARCH64_NONE
85+
86+
;--- 64B_align.s
87+
.text
88+
.global _foo
89+
.type _foo, %function
90+
_foo:
91+
ret
92+
93+
.text
94+
.global _const_island
95+
.align 6
96+
# 64BYTE: {{[0-9a-f]*}}{{0|4|8|c}}0 g
97+
_const_island:
98+
.rept 0x2048
99+
.byte 0xbb
100+
.endr
101+
102+
.global _start
103+
.type _start, %function
104+
_start:
105+
ret
106+
107+
# Dummy relocation to force relocation mode
108+
.reloc 0, R_AARCH64_NONE

0 commit comments

Comments
 (0)