Skip to content

Commit d5956fb

Browse files
authored
[BOLT][AArch64] Add support for short LLD thunks/veneers (#118422)
When a callee function is closer than 256MB from its call site, LLD linker can strategically create a short thunk for the function with a single branch instruction (that covers +/-128MB). Detect and convert such thunks into direct calls in BOLT.
1 parent b5b15c1 commit d5956fb

File tree

2 files changed

+47
-23
lines changed

2 files changed

+47
-23
lines changed

bolt/lib/Passes/VeneerElimination.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,17 @@ Error VeneerElimination::runOnFunctions(BinaryContext &BC) {
4646
if (BF.isIgnored())
4747
continue;
4848

49+
MCInst &FirstInstruction = *(BF.begin()->begin());
4950
const MCSymbol *VeneerTargetSymbol = 0;
5051
uint64_t TargetAddress;
51-
if (BC.MIB->matchAbsLongVeneer(BF, TargetAddress)) {
52+
if (BC.MIB->isTailCall(FirstInstruction)) {
53+
VeneerTargetSymbol = BC.MIB->getTargetSymbol(FirstInstruction);
54+
} else if (BC.MIB->matchAbsLongVeneer(BF, TargetAddress)) {
5255
if (BinaryFunction *TargetBF =
5356
BC.getBinaryFunctionAtAddress(TargetAddress))
5457
VeneerTargetSymbol = TargetBF->getSymbol();
55-
} else {
56-
MCInst &FirstInstruction = *(BF.begin()->begin());
57-
if (BC.MIB->hasAnnotation(FirstInstruction, "AArch64Veneer"))
58-
VeneerTargetSymbol = BC.MIB->getTargetSymbol(FirstInstruction, 1);
58+
} else if (BC.MIB->hasAnnotation(FirstInstruction, "AArch64Veneer")) {
59+
VeneerTargetSymbol = BC.MIB->getTargetSymbol(FirstInstruction, 1);
5960
}
6061

6162
if (!VeneerTargetSymbol)

bolt/test/AArch64/veneer-lld-abs.s

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
## Check that llvm-bolt correctly recognizes long absolute thunks generated
2-
## by LLD.
1+
## Check that llvm-bolt correctly recognizes veneers/thunks for absolute code
2+
## generated by LLD.
33

44
# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
55
# RUN: %clang %cflags -fno-PIC -no-pie %t.o -o %t.exe -nostdlib \
@@ -12,40 +12,63 @@
1212

1313
.text
1414
.balign 4
15-
.global foo
16-
.type foo, %function
17-
foo:
18-
adrp x1, foo
15+
.global far_function
16+
.type far_function, %function
17+
far_function:
1918
ret
20-
.size foo, .-foo
19+
.size far_function, .-far_function
20+
21+
.global near_function
22+
.type near_function, %function
23+
near_function:
24+
ret
25+
.size near_function, .-near_function
26+
27+
## Force relocations against .text.
28+
.reloc 0, R_AARCH64_NONE
2129

2230
.section ".mytext", "ax"
2331
.balign 4
2432

25-
.global __AArch64AbsLongThunk_foo
26-
.type __AArch64AbsLongThunk_foo, %function
27-
__AArch64AbsLongThunk_foo:
33+
## This version of a thunk is always generated by LLD for function calls
34+
## spanning more than 256MB.
35+
.global __AArch64AbsLongThunk_far_function
36+
.type __AArch64AbsLongThunk_far_function, %function
37+
__AArch64AbsLongThunk_far_function:
2838
ldr x16, .L1
2939
br x16
30-
# CHECK-INPUT-LABEL: <__AArch64AbsLongThunk_foo>:
40+
# CHECK-INPUT-LABEL: <__AArch64AbsLongThunk_far_function>:
3141
# CHECK-INPUT-NEXT: ldr
3242
# CHECK-INPUT-NEXT: br
3343
.L1:
34-
.quad foo
35-
.size __AArch64AbsLongThunk_foo, .-__AArch64AbsLongThunk_foo
44+
.quad far_function
45+
.size __AArch64AbsLongThunk_far_function, .-__AArch64AbsLongThunk_far_function
46+
47+
## If a callee is closer than 256MB away, LLD may generate a thunk with a direct
48+
## jump to the callee. Note, that the name might still include "AbsLong".
49+
.global __AArch64AbsLongThunk_near_function
50+
.type __AArch64AbsLongThunk_near_function, %function
51+
__AArch64AbsLongThunk_near_function:
52+
b near_function
53+
# CHECK-INPUT-LABEL: <__AArch64AbsLongThunk_near_function>:
54+
# CHECK-INPUT-NEXT: b {{.*}} <near_function>
55+
.size __AArch64AbsLongThunk_near_function, .-__AArch64AbsLongThunk_near_function
3656

37-
## Check that the thunk was removed from .text and _start() calls foo()
57+
## Check that thunks were removed from .text, and _start calls functions
3858
## directly.
3959

40-
# CHECK-OUTPUT-NOT: __AArch64AbsLongThunk_foo
60+
# CHECK-OUTPUT-NOT: __AArch64AbsLongThunk_{{.*}}
4161

4262
.global _start
4363
.type _start, %function
4464
_start:
4565
# CHECK-INPUT-LABEL: <_start>:
4666
# CHECK-OUTPUT-LABEL: <_start>:
47-
bl __AArch64AbsLongThunk_foo
48-
# CHECK-INPUT-NEXT: bl {{.*}} <__AArch64AbsLongThunk_foo>
49-
# CHECK-OUTPUT-NEXT: bl {{.*}} <foo>
67+
bl __AArch64AbsLongThunk_far_function
68+
bl __AArch64AbsLongThunk_near_function
69+
# CHECK-INPUT-NEXT: bl {{.*}} <__AArch64AbsLongThunk_far_function>
70+
# CHECK-INPUT-NEXT: bl {{.*}} <__AArch64AbsLongThunk_near_function>
71+
# CHECK-OUTPUT-NEXT: bl {{.*}} <far_function>
72+
# CHECK-OUTPUT-NEXT: bl {{.*}} <near_function>
5073
ret
5174
.size _start, .-_start

0 commit comments

Comments
 (0)