Skip to content

Commit 48d7e62

Browse files
committed
Allow outlining ADRP pair as a whole
1 parent b4216f1 commit 48d7e62

File tree

2 files changed

+47
-57
lines changed

2 files changed

+47
-57
lines changed

llvm/lib/Target/AArch64/AArch64InstrInfo.cpp

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9547,6 +9547,21 @@ AArch64InstrInfo::getOutliningCandidateInfo(
95479547

95489548
unsigned NumBytesToCreateFrame = 0;
95499549

9550+
// Avoid splitting ADRP-ADD/LDR pair into outlined functions.
9551+
MachineInstr &LastMI = RepeatedSequenceLocs[0].back();
9552+
MachineInstr &FirstMI = RepeatedSequenceLocs[0].front();
9553+
if (LastMI.getOpcode() == AArch64::ADRP &&
9554+
(LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_PAGE) != 0 &&
9555+
(LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_GOT) != 0) {
9556+
return std::nullopt;
9557+
}
9558+
9559+
if ((FirstMI.getOpcode() == AArch64::ADDXri || FirstMI.getOpcode() == AArch64::LDRXui) &&
9560+
(FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_PAGEOFF) != 0 &&
9561+
(FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) != 0) {
9562+
return std::nullopt;
9563+
}
9564+
95509565
// We only allow outlining for functions having exactly matching return
95519566
// address signing attributes, i.e., all share the same value for the
95529567
// attribute "sign-return-address" and all share the same type of key they
@@ -10179,34 +10194,6 @@ AArch64InstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
1017910194
return outliner::InstrType::Illegal;
1018010195
}
1018110196

10182-
// An ADRP instruction referencing a GOT should not be outlined.
10183-
// This is to avoid splitting ADRP/(LDR/ADD/etc.) pair into different
10184-
// functions which can lead to linker ICF merging sections incorrectly.
10185-
if (MI.getOpcode() == AArch64::ADRP) {
10186-
bool IsPage = (MI.getOperand(1).getTargetFlags() & AArch64II::MO_PAGE) != 0;
10187-
bool IsGot = (MI.getOperand(1).getTargetFlags() & AArch64II::MO_GOT) != 0;
10188-
if (IsPage && IsGot)
10189-
return outliner::InstrType::Illegal;
10190-
10191-
// Special cases for instructions that can always be outlined, but will fail
10192-
// the later tests. e.g, ADRPs, which are PC-relative use LR, but can always
10193-
// be outlined because they don't require a *specific* value to be in LR.
10194-
return outliner::InstrType::Legal;
10195-
}
10196-
10197-
// Similarly, any user of ADRP instruction referencing a GOT should not be
10198-
// outlined. It's hard/costly to check exact users of ADRP. So we use check
10199-
// all operands and reject any that's a page offset and references a GOT.
10200-
const auto &F = MI.getMF()->getFunction();
10201-
for (const auto &MO : MI.operands()) {
10202-
bool IsPageOff = (MO.getTargetFlags() & AArch64II::MO_PAGEOFF) != 0;
10203-
bool IsGot = (MO.getTargetFlags() & AArch64II::MO_GOT) != 0;
10204-
if (IsPageOff && IsGot &&
10205-
(MI.getMF()->getTarget().getFunctionSections() || F.hasComdat() ||
10206-
F.hasSection() || F.getSectionPrefix()))
10207-
return outliner::InstrType::Illegal;
10208-
}
10209-
1021010197
// If MI is a call we might be able to outline it. We don't want to outline
1021110198
// any calls that rely on the position of items on the stack. When we outline
1021210199
// something containing a call, we have to emit a save and restore of LR in

llvm/test/CodeGen/AArch64/machine-outliner-adrp-got-split.mir

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,16 @@
1111
ret i32 0
1212
}
1313

14-
define void @bar(i32 %a) #0 {
15-
ret void
16-
}
17-
1814
attributes #0 = { noinline noredzone }
1915
...
2016
---
21-
# This test ensures that we do not outline ADRP / ADD pair when it's referencing
22-
# a GOT entry.
17+
# Check that main function body doesn't split ADRP pair
2318
#
2419
# CHECK-LABEL: name: adrp_add
2520
# CHECK-DAG: bb.0:
26-
# CHECK: $x9 = ADRP target-flags(aarch64-page, aarch64-got) @x
27-
# CHECK: $x12 = ADDXri $x9, target-flags(aarch64-pageoff, aarch64-got) @x, 0
28-
29-
# CHECK-DAG: bb.1
30-
# CHECK: $x9 = ADRP target-flags(aarch64-page, aarch64-got) @x
31-
# CHECK: $x12 = ADDXri $x9, target-flags(aarch64-pageoff, aarch64-got) @x, 0
32-
33-
# CHECK-DAG: bb.2
34-
# CHECK: $x9 = ADRP target-flags(aarch64-page, aarch64-got) @x
35-
# CHECK: $x12 = ADDXri $x9, target-flags(aarch64-pageoff, aarch64-got) @x, 0
21+
# CHECK: BL @OUTLINED_FUNCTION_[[F0:[0-9]+]]
22+
# CHECK-NEXT: BL @OUTLINED_FUNCTION_[[F2:[0-9]+]]
23+
# CHECK-NEXT: $lr = ORRXri $xzr, 1
3624
name: adrp_add
3725
tracksRegLiveness: true
3826
body: |
@@ -74,21 +62,13 @@ body: |
7462
RET undef $lr
7563
...
7664
---
77-
# This test ensures that we do not outline ADRP / LDR pair when it's referencing
78-
# a GOT entry.
65+
# Check that main function body doesn't split ADRP pair
7966
#
8067
# CHECK-LABEL: name: adrp_ldr
8168
# CHECK-DAG: bb.0:
82-
# CHECK: $x9 = ADRP target-flags(aarch64-page, aarch64-got) @x
83-
# CHECK: $x12 = LDRXui $x9, target-flags(aarch64-pageoff, aarch64-got) @x
84-
85-
# CHECK-DAG: bb.1
86-
# CHECK: $x9 = ADRP target-flags(aarch64-page, aarch64-got) @x
87-
# CHECK: $x12 = LDRXui $x9, target-flags(aarch64-pageoff, aarch64-got) @x
88-
89-
# CHECK-DAG: bb.2
90-
# CHECK: $x9 = ADRP target-flags(aarch64-page, aarch64-got) @x
91-
# CHECK: $x12 = LDRXui $x9, target-flags(aarch64-pageoff, aarch64-got) @x
69+
# CHECK: BL @OUTLINED_FUNCTION_[[F0]]
70+
# CHECK-NEXT: BL @OUTLINED_FUNCTION_[[F1:[0-9]+]]
71+
# CHECK-NEXT: $lr = ORRXri $xzr, 1
9272
name: adrp_ldr
9373
tracksRegLiveness: true
9474
body: |
@@ -127,4 +107,27 @@ body: |
127107
$lr = ORRXri $xzr, 1
128108
bb.3:
129109
liveins: $lr
130-
RET undef $lr
110+
RET undef $lr
111+
112+
# Check that no outlined function split the ADRP pair apart
113+
#
114+
# CHECK: OUTLINED_FUNCTION_[[F0]]
115+
# CHECK-DAG: bb.0
116+
# CHECK: $w12 = ORRWri $wzr, 1
117+
# CHECK-NEXT: $w12 = ORRWri $wzr, 1
118+
# CHECK-NEXT: $w12 = ORRWri $wzr, 1
119+
# CHECK-NEXT: $w12 = ORRWri $wzr, 1
120+
# CHECK-NEXT: $w12 = ORRWri $wzr, 1
121+
# CHECK-NEXT: RET $lr
122+
123+
# CHECK: OUTLINED_FUNCTION_[[F1]]
124+
# CHECK-DAG: bb.0
125+
# CHECK: $w12 = ORRWri $wzr, 1
126+
# CHECK-NEXT: $x9 = ADRP target-flags(aarch64-page, aarch64-got) @x
127+
# CHECK-NEXT: $x12 = LDRXui $x9, target-flags(aarch64-pageoff, aarch64-got) @x
128+
129+
# CHECK: name: OUTLINED_FUNCTION_[[F2]]
130+
# CHECK-DAG: bb.0
131+
# CHECK: $w12 = ORRWri $wzr, 1
132+
# CHECK-NEXT: $x9 = ADRP target-flags(aarch64-page, aarch64-got) @x
133+
# CHECK-NEXT: $x12 = ADDXri $x9, target-flags(aarch64-pageoff, aarch64-got) @x, 0

0 commit comments

Comments
 (0)