Skip to content

Commit e2cee2c

Browse files
authored
[BOLT][AArch64] Fixes assertion errors occurred when perf2bolt was executed (#83394)
BOLT only checks for the most common indirect branch pattern during the branch analyzation. Extended the logic with two other indirect patterns which slightly differ from the expected one. Those patterns may be hit when statically linking libc (pattern 2 requires 'lld' linker). As a workaround mark them as UNKNOWN branch for now. Fixes: #83114
1 parent ccc0b66 commit e2cee2c

File tree

2 files changed

+110
-2
lines changed

2 files changed

+110
-2
lines changed

bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -702,8 +702,20 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
702702
unsigned ShiftVal = AArch64_AM::getArithShiftValue(OperandExtension);
703703
AArch64_AM::ShiftExtendType ExtendType =
704704
AArch64_AM::getArithExtendType(OperandExtension);
705-
if (ShiftVal != 2)
706-
llvm_unreachable("Failed to match indirect branch! (fragment 2)");
705+
if (ShiftVal != 2) {
706+
// TODO: Handle the patten where ShiftVal != 2.
707+
// The following code sequence below has no shift amount,
708+
// the range could be 0 to 4.
709+
// The pattern comes from libc, it occurs when the binary is static.
710+
// adr x6, 0x219fb0 <sigall_set+0x88>
711+
// add x6, x6, x14, lsl #2
712+
// ldr w7, [x6]
713+
// add x6, x6, w7, sxtw => no shift amount
714+
// br x6
715+
errs() << "BOLT-WARNING: "
716+
"Failed to match indirect branch: ShiftVAL != 2 \n";
717+
return false;
718+
}
707719

708720
if (ExtendType == AArch64_AM::SXTB)
709721
ScaleValue = 1LL;
@@ -748,6 +760,19 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
748760
return true;
749761
}
750762

763+
if (DefJTBaseAdd->getOpcode() == AArch64::ADR) {
764+
// TODO: Handle the pattern where there is no adrp/add pair.
765+
// It also occurs when the binary is static.
766+
// adr x13, 0x215a18 <_nl_value_type_LC_COLLATE+0x50>
767+
// ldrh w13, [x13, w12, uxtw #1]
768+
// adr x12, 0x247b30 <__gettextparse+0x5b0>
769+
// add x13, x12, w13, sxth #2
770+
// br x13
771+
errs() << "BOLT-WARNING: Failed to match indirect branch: "
772+
"nop/adr instead of adrp/add \n";
773+
return false;
774+
}
775+
751776
assert(DefJTBaseAdd->getOpcode() == AArch64::ADDXri &&
752777
"Failed to match jump table base address pattern! (1)");
753778

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Test how BOLT handles indirect branch sequence of instructions in
2+
// AArch64MCPlus builder.
3+
4+
// clang-format off
5+
6+
// REQUIRES: system-linux
7+
// RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o
8+
// RUN: %clang %cflags --target=aarch64-unknown-linux %t.o -o %t.exe -Wl,-q
9+
// RUN: llvm-bolt %t.exe -o %t.bolt --print-cfg --strict\
10+
// RUN: -v=1 2>&1 | FileCheck %s
11+
12+
// Pattern 1: there is no shift amount after the 'add' instruction.
13+
//
14+
// adr x6, 0x219fb0 <sigall_set+0x88>
15+
// add x6, x6, x14, lsl #2
16+
// ldr w7, [x6]
17+
// add x6, x6, w7, sxtw => no shift amount
18+
// br x6
19+
//
20+
21+
// Pattern 2: nop/adr pair is used in place of adrp/add
22+
//
23+
// nop => nop/adr instead of adrp/add
24+
// adr x13, 0x215a18 <_nl_value_type_LC_COLLATE+0x50>
25+
// ldrh w13, [x13, w12, uxtw #1]
26+
// adr x12, 0x247b30 <__gettextparse+0x5b0>
27+
// add x13, x12, w13, sxth #2
28+
// br x13
29+
30+
.section .text
31+
.align 4
32+
.globl _start
33+
.type _start, %function
34+
_start:
35+
bl test1
36+
bl test2
37+
// mov x0, #4
38+
// mov w8, #93
39+
// svc #0
40+
41+
// Pattern 1
42+
// CHECK: BOLT-WARNING: Failed to match indirect branch: ShiftVAL != 2
43+
.globl test1
44+
.type test1, %function
45+
test1:
46+
mov x1, #0
47+
adr x3, datatable
48+
add x3, x3, x1, lsl #2
49+
ldr w2, [x3]
50+
add x3, x3, w2, sxtw
51+
br x3
52+
test1_0:
53+
ret
54+
test1_1:
55+
ret
56+
test1_2:
57+
ret
58+
59+
// Pattern 2
60+
// CHECK: BOLT-WARNING: Failed to match indirect branch: nop/adr instead of adrp/add
61+
.globl test2
62+
.type test2, %function
63+
test2:
64+
nop
65+
adr x3, jump_table
66+
ldrh w3, [x3, x1, lsl #1]
67+
adr x1, test2_0
68+
add x3, x1, w3, sxth #2
69+
br x3
70+
test2_0:
71+
ret
72+
test2_1:
73+
ret
74+
75+
.section .rodata,"a",@progbits
76+
datatable:
77+
.word test1_0-datatable
78+
.word test1_1-datatable
79+
.word test1_2-datatable
80+
81+
jump_table:
82+
.hword (test2_0-test2_0)>>2
83+
.hword (test2_1-test2_0)>>2

0 commit comments

Comments
 (0)