Skip to content

Commit 750113d

Browse files
committed
[BOLT][AArch64] Add support for short LLD thunks/veneers
When a callee function is closer than 256MB away 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 5f881b7 commit 750113d

File tree

2 files changed

+44
-23
lines changed

2 files changed

+44
-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: 38 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,60 @@
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
2126

2227
.section ".mytext", "ax"
2328
.balign 4
2429

25-
.global __AArch64AbsLongThunk_foo
26-
.type __AArch64AbsLongThunk_foo, %function
27-
__AArch64AbsLongThunk_foo:
30+
## This version of a thunk is always generated by LLD for function calls
31+
## spanning more than 256MB.
32+
.global __AArch64AbsLongThunk_far_function
33+
.type __AArch64AbsLongThunk_far_function, %function
34+
__AArch64AbsLongThunk_far_function:
2835
ldr x16, .L1
2936
br x16
30-
# CHECK-INPUT-LABEL: <__AArch64AbsLongThunk_foo>:
37+
# CHECK-INPUT-LABEL: <__AArch64AbsLongThunk_far_function>:
3138
# CHECK-INPUT-NEXT: ldr
3239
# CHECK-INPUT-NEXT: br
3340
.L1:
34-
.quad foo
35-
.size __AArch64AbsLongThunk_foo, .-__AArch64AbsLongThunk_foo
41+
.quad far_function
42+
.size __AArch64AbsLongThunk_far_function, .-__AArch64AbsLongThunk_far_function
43+
44+
## If a callee is closer than 256MB away, LLD may generate a thunk with a direct
45+
## jump to the callee. Note, that the name might still include "AbSLong".
46+
.global __AArch64AbsLongThunk_near_function
47+
.type __AArch64AbsLongThunk_near_function, %function
48+
__AArch64AbsLongThunk_near_function:
49+
b near_function
50+
# CHECK-INPUT-LABEL: <__AArch64AbsLongThunk_near_function>:
51+
# CHECK-INPUT-NEXT: b {{.*}} <near_function>
52+
.size __AArch64AbsLongThunk_near_function, .-__AArch64AbsLongThunk_near_function
3653

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

40-
# CHECK-OUTPUT-NOT: __AArch64AbsLongThunk_foo
57+
# CHECK-OUTPUT-NOT: __AArch64AbsLongThunk_{{.*}}
4158

4259
.global _start
4360
.type _start, %function
4461
_start:
4562
# CHECK-INPUT-LABEL: <_start>:
4663
# CHECK-OUTPUT-LABEL: <_start>:
47-
bl __AArch64AbsLongThunk_foo
48-
# CHECK-INPUT-NEXT: bl {{.*}} <__AArch64AbsLongThunk_foo>
49-
# CHECK-OUTPUT-NEXT: bl {{.*}} <foo>
64+
bl __AArch64AbsLongThunk_far_function
65+
bl __AArch64AbsLongThunk_near_function
66+
# CHECK-INPUT-NEXT: bl {{.*}} <__AArch64AbsLongThunk_far_function>
67+
# CHECK-INPUT-NEXT: bl {{.*}} <__AArch64AbsLongThunk_near_function>
68+
# CHECK-OUTPUT-NEXT: bl {{.*}} <far_function>
69+
# CHECK-OUTPUT-NEXT: bl {{.*}} <near_function>
5070
ret
5171
.size _start, .-_start

0 commit comments

Comments
 (0)