Skip to content

Commit 00ddd1f

Browse files
MaskRaylfeng14
authored andcommitted
[AArch64] Implement -fno-plt for SelectionDAG/GlobalISel
Clang sets the nonlazybind attribute for certain ObjC features. The AArch64 SelectionDAG implementation for non-intrinsic calls (46e36f0) is behind a cl option. GCC implements -fno-plt for a few ELF targets. In Clang, -fno-plt also sets the nonlazybind attribute. For SelectionDAG, make the cl option not affect ELF so that non-intrinsic calls to a dso_preemptable function use GOT. Adjust AArch64TargetLowering::LowerCall to handle intrinsic calls. For FastISel, change `fastLowerCall` to bail out when a call is due to -fno-plt. For GlobalISel, handle non-intrinsic calls in CallLowering::lowerCall and intrinsic calls in AArch64CallLowering::lowerCall (where the target-independent CallLowering::lowerCall is not called). The GlobalISel test in `call-rv-marker.ll` is therefore updated. Note: the current -fno-plt -fpic implementation does not use GOT for a preemptable function. Link: #78275 Pull Request: llvm/llvm-project#78890
1 parent 7652572 commit 00ddd1f

File tree

9 files changed

+347
-45
lines changed

9 files changed

+347
-45
lines changed

llvm/lib/CodeGen/GlobalISel/CallLowering.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,20 @@ bool CallLowering::lowerCall(MachineIRBuilder &MIRBuilder, const CallBase &CB,
142142
// Try looking through a bitcast from one function type to another.
143143
// Commonly happens with calls to objc_msgSend().
144144
const Value *CalleeV = CB.getCalledOperand()->stripPointerCasts();
145-
if (const Function *F = dyn_cast<Function>(CalleeV))
146-
Info.Callee = MachineOperand::CreateGA(F, 0);
147-
else
145+
if (const Function *F = dyn_cast<Function>(CalleeV)) {
146+
if (F->hasFnAttribute(Attribute::NonLazyBind)) {
147+
LLT Ty = getLLTForType(*F->getType(), DL);
148+
Register Reg = MIRBuilder.buildGlobalValue(Ty, F).getReg(0);
149+
Info.Callee = MachineOperand::CreateReg(Reg, false);
150+
} else {
151+
Info.Callee = MachineOperand::CreateGA(F, 0);
152+
}
153+
} else if (isa<GlobalIFunc>(CalleeV) || isa<GlobalAlias>(CalleeV)) {
154+
// IR IFuncs and Aliases can't be forward declared (only defined), so the
155+
// callee must be in the same TU and therefore we can direct-call it without
156+
// worrying about it being out of range.
157+
Info.Callee = MachineOperand::CreateGA(cast<GlobalValue>(CalleeV), 0);
158+
} else
148159
Info.Callee = MachineOperand::CreateReg(GetCalleeReg(), false);
149160

150161
Register ReturnHintAlignReg;

llvm/lib/Target/AArch64/AArch64FastISel.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3179,6 +3179,11 @@ bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
31793179
if (CM == CodeModel::Large && !Subtarget->isTargetMachO())
31803180
return false;
31813181

3182+
// ELF -fno-plt compiled intrinsic calls do not have the nonlazybind
3183+
// attribute. Check "RtLibUseGOT" instead.
3184+
if (MF->getFunction().getParent()->getRtLibUseGOT())
3185+
return false;
3186+
31823187
// Let SDISel handle vararg functions.
31833188
if (IsVarArg)
31843189
return false;

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7580,13 +7580,14 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,
75807580
Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, 0);
75817581
}
75827582
} else if (auto *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
7583-
if (getTargetMachine().getCodeModel() == CodeModel::Large &&
7584-
Subtarget->isTargetMachO()) {
7585-
const char *Sym = S->getSymbol();
7583+
bool UseGot = (getTargetMachine().getCodeModel() == CodeModel::Large &&
7584+
Subtarget->isTargetMachO()) ||
7585+
MF.getFunction().getParent()->getRtLibUseGOT();
7586+
const char *Sym = S->getSymbol();
7587+
if (UseGot) {
75867588
Callee = DAG.getTargetExternalSymbol(Sym, PtrVT, AArch64II::MO_GOT);
75877589
Callee = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, Callee);
75887590
} else {
7589-
const char *Sym = S->getSymbol();
75907591
Callee = DAG.getTargetExternalSymbol(Sym, PtrVT, 0);
75917592
}
75927593
}

llvm/lib/Target/AArch64/AArch64Subtarget.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ static cl::opt<bool>
4343
UseAddressTopByteIgnored("aarch64-use-tbi", cl::desc("Assume that top byte of "
4444
"an address is ignored"), cl::init(false), cl::Hidden);
4545

46-
static cl::opt<bool>
47-
UseNonLazyBind("aarch64-enable-nonlazybind",
48-
cl::desc("Call nonlazybind functions via direct GOT load"),
49-
cl::init(false), cl::Hidden);
46+
static cl::opt<bool> MachOUseNonLazyBind(
47+
"aarch64-macho-enable-nonlazybind",
48+
cl::desc("Call nonlazybind functions via direct GOT load for Mach-O"),
49+
cl::Hidden);
5050

5151
static cl::opt<bool> UseAA("aarch64-use-aa", cl::init(true),
5252
cl::desc("Enable the use of AA during codegen."));
@@ -433,7 +433,8 @@ unsigned AArch64Subtarget::classifyGlobalFunctionReference(
433433

434434
// NonLazyBind goes via GOT unless we know it's available locally.
435435
auto *F = dyn_cast<Function>(GV);
436-
if (UseNonLazyBind && F && F->hasFnAttribute(Attribute::NonLazyBind) &&
436+
if ((!isTargetMachO() || MachOUseNonLazyBind) && F &&
437+
F->hasFnAttribute(Attribute::NonLazyBind) &&
437438
!TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
438439
return AArch64II::MO_GOT;
439440

llvm/lib/Target/AArch64/GISel/AArch64CallLowering.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1270,8 +1270,17 @@ bool AArch64CallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
12701270
!Subtarget.noBTIAtReturnTwice() &&
12711271
MF.getInfo<AArch64FunctionInfo>()->branchTargetEnforcement())
12721272
Opc = AArch64::BLR_BTI;
1273-
else
1273+
else {
1274+
// For an intrinsic call (e.g. memset), use GOT if "RtLibUseGOT" (-fno-plt)
1275+
// is set.
1276+
if (Info.Callee.isSymbol() && F.getParent()->getRtLibUseGOT()) {
1277+
auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_GLOBAL_VALUE);
1278+
DstOp(getLLTForType(*F.getType(), DL)).addDefToMIB(MRI, MIB);
1279+
MIB.addExternalSymbol(Info.Callee.getSymbolName(), AArch64II::MO_GOT);
1280+
Info.Callee = MachineOperand::CreateReg(MIB.getReg(0), false);
1281+
}
12741282
Opc = getCallOpcode(MF, Info.Callee.isReg(), false);
1283+
}
12751284

12761285
auto MIB = MIRBuilder.buildInstrNoInsert(Opc);
12771286
unsigned CalleeOpNo = 0;

llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,11 +2802,19 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
28022802
}
28032803

28042804
case TargetOpcode::G_GLOBAL_VALUE: {
2805-
auto GV = I.getOperand(1).getGlobal();
2806-
if (GV->isThreadLocal())
2807-
return selectTLSGlobalValue(I, MRI);
2805+
const GlobalValue *GV = nullptr;
2806+
unsigned OpFlags;
2807+
if (I.getOperand(1).isSymbol()) {
2808+
OpFlags = I.getOperand(1).getTargetFlags();
2809+
// Currently only used by "RtLibUseGOT".
2810+
assert(OpFlags == AArch64II::MO_GOT);
2811+
} else {
2812+
GV = I.getOperand(1).getGlobal();
2813+
if (GV->isThreadLocal())
2814+
return selectTLSGlobalValue(I, MRI);
2815+
OpFlags = STI.ClassifyGlobalReference(GV, TM);
2816+
}
28082817

2809-
unsigned OpFlags = STI.ClassifyGlobalReference(GV, TM);
28102818
if (OpFlags & AArch64II::MO_GOT) {
28112819
I.setDesc(TII.get(AArch64::LOADgot));
28122820
I.getOperand(1).setTargetFlags(OpFlags);

llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,9 @@ bool AArch64LegalizerInfo::legalizeSmallCMGlobalValue(
10701070
// By splitting this here, we can optimize accesses in the small code model by
10711071
// folding in the G_ADD_LOW into the load/store offset.
10721072
auto &GlobalOp = MI.getOperand(1);
1073+
// Don't modify an intrinsic call.
1074+
if (GlobalOp.isSymbol())
1075+
return true;
10731076
const auto* GV = GlobalOp.getGlobal();
10741077
if (GV->isThreadLocal())
10751078
return true; // Don't want to modify TLS vars.

llvm/test/CodeGen/AArch64/call-rv-marker.ll

Lines changed: 196 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,73 @@ define dso_local void @rv_marker_3() personality ptr @__gxx_personality_v0 {
7070
; CHECK-NEXT: mov x29, x29
7171
; CHECK-NEXT: bl _objc_retainAutoreleasedReturnValue
7272
;
73+
; GISEL-LABEL: rv_marker_3:
74+
; GISEL: Lfunc_begin0:
75+
; GISEL-NEXT: .cfi_startproc
76+
; GISEL-NEXT: .cfi_personality 155, ___gxx_personality_v0
77+
; GISEL-NEXT: .cfi_lsda 16, Lexception0
78+
; GISEL-NEXT: ; %bb.0: ; %entry
79+
; GISEL-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
80+
; GISEL-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill
81+
; GISEL-NEXT: .cfi_def_cfa_offset 32
82+
; GISEL-NEXT: .cfi_offset w30, -8
83+
; GISEL-NEXT: .cfi_offset w29, -16
84+
; GISEL-NEXT: .cfi_offset w19, -24
85+
; GISEL-NEXT: .cfi_offset w20, -32
86+
; GISEL-NEXT: bl _foo1
87+
; GISEL-NEXT: mov x29, x29
88+
; GISEL-NEXT: bl _objc_retainAutoreleasedReturnValue
89+
; GISEL-NEXT: mov x19, x0
90+
; GISEL-NEXT: Ltmp0:
91+
; GISEL-NEXT: bl _objc_object
92+
; GISEL-NEXT: Ltmp1:
93+
; GISEL-NEXT: ; %bb.1: ; %invoke.cont
94+
; GISEL-NEXT: Lloh0:
95+
; GISEL-NEXT: adrp x1, _objc_release@GOTPAGE
96+
; GISEL-NEXT: mov x0, x19
97+
; GISEL-NEXT: Lloh1:
98+
; GISEL-NEXT: ldr x1, [x1, _objc_release@GOTPAGEOFF]
99+
; GISEL-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
100+
; GISEL-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
101+
; GISEL-NEXT: br x1
102+
; GISEL-NEXT: LBB3_2: ; %lpad
103+
; GISEL-NEXT: Ltmp2:
104+
; GISEL-NEXT: Lloh2:
105+
; GISEL-NEXT: adrp x8, _objc_release@GOTPAGE
106+
; GISEL-NEXT: mov x20, x0
107+
; GISEL-NEXT: mov x0, x19
108+
; GISEL-NEXT: Lloh3:
109+
; GISEL-NEXT: ldr x8, [x8, _objc_release@GOTPAGEOFF]
110+
; GISEL-NEXT: blr x8
111+
; GISEL-NEXT: mov x0, x20
112+
; GISEL-NEXT: bl __Unwind_Resume
113+
; GISEL-NEXT: .loh AdrpLdrGot Lloh0, Lloh1
114+
; GISEL-NEXT: .loh AdrpLdrGot Lloh2, Lloh3
115+
; GISEL-NEXT: Lfunc_end0:
116+
; GISEL-NEXT: .cfi_endproc
117+
; GISEL-NEXT: .section __TEXT,__gcc_except_tab
118+
; GISEL-NEXT: .p2align 2, 0x0
119+
; GISEL-NEXT: GCC_except_table3:
120+
; GISEL-NEXT: Lexception0:
121+
; GISEL-NEXT: .byte 255 ; @LPStart Encoding = omit
122+
; GISEL-NEXT: .byte 255 ; @TType Encoding = omit
123+
; GISEL-NEXT: .byte 1 ; Call site Encoding = uleb128
124+
; GISEL-NEXT: .uleb128 Lcst_end0-Lcst_begin0
125+
; GISEL-NEXT: Lcst_begin0:
126+
; GISEL-NEXT: .uleb128 Lfunc_begin0-Lfunc_begin0 ; >> Call Site 1 <<
127+
; GISEL-NEXT: .uleb128 Ltmp0-Lfunc_begin0 ; Call between Lfunc_begin0 and Ltmp0
128+
; GISEL-NEXT: .byte 0 ; has no landing pad
129+
; GISEL-NEXT: .byte 0 ; On action: cleanup
130+
; GISEL-NEXT: .uleb128 Ltmp0-Lfunc_begin0 ; >> Call Site 2 <<
131+
; GISEL-NEXT: .uleb128 Ltmp1-Ltmp0 ; Call between Ltmp0 and Ltmp1
132+
; GISEL-NEXT: .uleb128 Ltmp2-Lfunc_begin0 ; jumps to Ltmp2
133+
; GISEL-NEXT: .byte 0 ; On action: cleanup
134+
; GISEL-NEXT: .uleb128 Ltmp1-Lfunc_begin0 ; >> Call Site 3 <<
135+
; GISEL-NEXT: .uleb128 Lfunc_end0-Ltmp1 ; Call between Ltmp1 and Lfunc_end0
136+
; GISEL-NEXT: .byte 0 ; has no landing pad
137+
; GISEL-NEXT: .byte 0 ; On action: cleanup
138+
; GISEL-NEXT: Lcst_end0:
139+
; GISEL-NEXT: .p2align 2, 0x0
73140
entry:
74141
%call = call ptr @foo1() [ "clang.arc.attachedcall"(ptr @objc_retainAutoreleasedReturnValue) ]
75142
invoke void @objc_object(ptr %call) #5
@@ -94,6 +161,88 @@ define dso_local void @rv_marker_4() personality ptr @__gxx_personality_v0 {
94161
; CHECK-NEXT: bl _objc_retainAutoreleasedReturnValue
95162
; CHECK-NEXT: Ltmp4:
96163
;
164+
; GISEL-LABEL: rv_marker_4:
165+
; GISEL: Lfunc_begin1:
166+
; GISEL-NEXT: .cfi_startproc
167+
; GISEL-NEXT: .cfi_personality 155, ___gxx_personality_v0
168+
; GISEL-NEXT: .cfi_lsda 16, Lexception1
169+
; GISEL-NEXT: ; %bb.0: ; %entry
170+
; GISEL-NEXT: sub sp, sp, #48
171+
; GISEL-NEXT: stp x20, x19, [sp, #16] ; 16-byte Folded Spill
172+
; GISEL-NEXT: stp x29, x30, [sp, #32] ; 16-byte Folded Spill
173+
; GISEL-NEXT: .cfi_def_cfa_offset 48
174+
; GISEL-NEXT: .cfi_offset w30, -8
175+
; GISEL-NEXT: .cfi_offset w29, -16
176+
; GISEL-NEXT: .cfi_offset w19, -24
177+
; GISEL-NEXT: .cfi_offset w20, -32
178+
; GISEL-NEXT: Ltmp3:
179+
; GISEL-NEXT: bl _foo1
180+
; GISEL-NEXT: mov x29, x29
181+
; GISEL-NEXT: bl _objc_retainAutoreleasedReturnValue
182+
; GISEL-NEXT: Ltmp4:
183+
; GISEL-NEXT: ; %bb.1: ; %invoke.cont
184+
; GISEL-NEXT: Ltmp6:
185+
; GISEL-NEXT: mov x19, x0
186+
; GISEL-NEXT: bl _objc_object
187+
; GISEL-NEXT: Ltmp7:
188+
; GISEL-NEXT: ; %bb.2: ; %invoke.cont2
189+
; GISEL-NEXT: Lloh4:
190+
; GISEL-NEXT: adrp x8, _objc_release@GOTPAGE
191+
; GISEL-NEXT: mov x0, x19
192+
; GISEL-NEXT: Lloh5:
193+
; GISEL-NEXT: ldr x8, [x8, _objc_release@GOTPAGEOFF]
194+
; GISEL-NEXT: blr x8
195+
; GISEL-NEXT: add x0, sp, #15
196+
; GISEL-NEXT: bl __ZN1SD1Ev
197+
; GISEL-NEXT: ldp x29, x30, [sp, #32] ; 16-byte Folded Reload
198+
; GISEL-NEXT: ldp x20, x19, [sp, #16] ; 16-byte Folded Reload
199+
; GISEL-NEXT: add sp, sp, #48
200+
; GISEL-NEXT: ret
201+
; GISEL-NEXT: LBB4_3: ; %lpad1
202+
; GISEL-NEXT: Ltmp8:
203+
; GISEL-NEXT: Lloh6:
204+
; GISEL-NEXT: adrp x8, _objc_release@GOTPAGE
205+
; GISEL-NEXT: mov x20, x0
206+
; GISEL-NEXT: mov x0, x19
207+
; GISEL-NEXT: Lloh7:
208+
; GISEL-NEXT: ldr x8, [x8, _objc_release@GOTPAGEOFF]
209+
; GISEL-NEXT: blr x8
210+
; GISEL-NEXT: b LBB4_5
211+
; GISEL-NEXT: LBB4_4: ; %lpad
212+
; GISEL-NEXT: Ltmp5:
213+
; GISEL-NEXT: mov x20, x0
214+
; GISEL-NEXT: LBB4_5: ; %ehcleanup
215+
; GISEL-NEXT: add x0, sp, #15
216+
; GISEL-NEXT: bl __ZN1SD1Ev
217+
; GISEL-NEXT: mov x0, x20
218+
; GISEL-NEXT: bl __Unwind_Resume
219+
; GISEL-NEXT: .loh AdrpLdrGot Lloh4, Lloh5
220+
; GISEL-NEXT: .loh AdrpLdrGot Lloh6, Lloh7
221+
; GISEL-NEXT: Lfunc_end1:
222+
; GISEL-NEXT: .cfi_endproc
223+
; GISEL-NEXT: .section __TEXT,__gcc_except_tab
224+
; GISEL-NEXT: .p2align 2, 0x0
225+
; GISEL-NEXT: GCC_except_table4:
226+
; GISEL-NEXT: Lexception1:
227+
; GISEL-NEXT: .byte 255 ; @LPStart Encoding = omit
228+
; GISEL-NEXT: .byte 255 ; @TType Encoding = omit
229+
; GISEL-NEXT: .byte 1 ; Call site Encoding = uleb128
230+
; GISEL-NEXT: .uleb128 Lcst_end1-Lcst_begin1
231+
; GISEL-NEXT: Lcst_begin1:
232+
; GISEL-NEXT: .uleb128 Ltmp3-Lfunc_begin1 ; >> Call Site 1 <<
233+
; GISEL-NEXT: .uleb128 Ltmp4-Ltmp3 ; Call between Ltmp3 and Ltmp4
234+
; GISEL-NEXT: .uleb128 Ltmp5-Lfunc_begin1 ; jumps to Ltmp5
235+
; GISEL-NEXT: .byte 0 ; On action: cleanup
236+
; GISEL-NEXT: .uleb128 Ltmp6-Lfunc_begin1 ; >> Call Site 2 <<
237+
; GISEL-NEXT: .uleb128 Ltmp7-Ltmp6 ; Call between Ltmp6 and Ltmp7
238+
; GISEL-NEXT: .uleb128 Ltmp8-Lfunc_begin1 ; jumps to Ltmp8
239+
; GISEL-NEXT: .byte 0 ; On action: cleanup
240+
; GISEL-NEXT: .uleb128 Ltmp7-Lfunc_begin1 ; >> Call Site 3 <<
241+
; GISEL-NEXT: .uleb128 Lfunc_end1-Ltmp7 ; Call between Ltmp7 and Lfunc_end1
242+
; GISEL-NEXT: .byte 0 ; has no landing pad
243+
; GISEL-NEXT: .byte 0 ; On action: cleanup
244+
; GISEL-NEXT: Lcst_end1:
245+
; GISEL-NEXT: .p2align 2, 0x0
97246
entry:
98247
%s = alloca %struct.S, align 1
99248
call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %s) #2
@@ -129,11 +278,53 @@ ehcleanup: ; preds = %lpad1, %lpad
129278
}
130279

131280
define dso_local ptr @rv_marker_5_indirect_call() {
132-
; CHECK-LABEL: _rv_marker_5_indirect_call:
133-
; CHECK: ldr [[ADDR:x[0-9]+]], [
134-
; CHECK-NEXT: blr [[ADDR]]
135-
; CHECK-NEXT: mov x29, x29
136-
; CHECK-NEXT: bl _objc_retainAutoreleasedReturnValue
281+
; SELDAG-LABEL: rv_marker_5_indirect_call:
282+
; SELDAG: ; %bb.0: ; %entry
283+
; SELDAG-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
284+
; SELDAG-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill
285+
; SELDAG-NEXT: .cfi_def_cfa_offset 32
286+
; SELDAG-NEXT: .cfi_offset w30, -8
287+
; SELDAG-NEXT: .cfi_offset w29, -16
288+
; SELDAG-NEXT: .cfi_offset w19, -24
289+
; SELDAG-NEXT: .cfi_offset w20, -32
290+
; SELDAG-NEXT: Lloh0:
291+
; SELDAG-NEXT: adrp x8, _fptr@PAGE
292+
; SELDAG-NEXT: Lloh1:
293+
; SELDAG-NEXT: ldr x8, [x8, _fptr@PAGEOFF]
294+
; SELDAG-NEXT: blr x8
295+
; SELDAG-NEXT: mov x29, x29
296+
; SELDAG-NEXT: bl _objc_retainAutoreleasedReturnValue
297+
; SELDAG-NEXT: mov x19, x0
298+
; SELDAG-NEXT: bl _foo2
299+
; SELDAG-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
300+
; SELDAG-NEXT: mov x0, x19
301+
; SELDAG-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
302+
; SELDAG-NEXT: ret
303+
; SELDAG-NEXT: .loh AdrpLdr Lloh0, Lloh1
304+
;
305+
; GISEL-LABEL: rv_marker_5_indirect_call:
306+
; GISEL: ; %bb.0: ; %entry
307+
; GISEL-NEXT: stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
308+
; GISEL-NEXT: stp x29, x30, [sp, #16] ; 16-byte Folded Spill
309+
; GISEL-NEXT: .cfi_def_cfa_offset 32
310+
; GISEL-NEXT: .cfi_offset w30, -8
311+
; GISEL-NEXT: .cfi_offset w29, -16
312+
; GISEL-NEXT: .cfi_offset w19, -24
313+
; GISEL-NEXT: .cfi_offset w20, -32
314+
; GISEL-NEXT: Lloh8:
315+
; GISEL-NEXT: adrp x8, _fptr@PAGE
316+
; GISEL-NEXT: Lloh9:
317+
; GISEL-NEXT: ldr x8, [x8, _fptr@PAGEOFF]
318+
; GISEL-NEXT: blr x8
319+
; GISEL-NEXT: mov x29, x29
320+
; GISEL-NEXT: bl _objc_retainAutoreleasedReturnValue
321+
; GISEL-NEXT: mov x19, x0
322+
; GISEL-NEXT: bl _foo2
323+
; GISEL-NEXT: ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
324+
; GISEL-NEXT: mov x0, x19
325+
; GISEL-NEXT: ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
326+
; GISEL-NEXT: ret
327+
; GISEL-NEXT: .loh AdrpLdr Lloh8, Lloh9
137328
entry:
138329
%0 = load ptr, ptr @fptr, align 8
139330
%call = call ptr %0() [ "clang.arc.attachedcall"(ptr @objc_retainAutoreleasedReturnValue) ]

0 commit comments

Comments
 (0)