Skip to content

Commit c69dbcc

Browse files
committed
[ARM] Fix llvm.returnaddress for Thumb1 with R11 frame-pointer
When using R11 as the frame pointer for a Thumb1 target, we need to use LR as a temporary in the prologue when setting up the frame record, like this: push {lr} mov lr, r11 push {r11} mov r11, sp This means that the value in LR is clobbered by the prologue, so we can't use it as a live-in value to the function to implement the llvm.returnaddress intrinsic. I don't think there's any way to avoid this use if LR without making the prologue code even more complicated. Instead, we can load the return address from the frame record, as we do when the intrinsic is used with a non-zero depth.
1 parent f9dca5b commit c69dbcc

File tree

3 files changed

+324
-4
lines changed

3 files changed

+324
-4
lines changed

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6196,18 +6196,28 @@ SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
61966196
return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi);
61976197
}
61986198

6199-
SDValue ARMTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const{
6199+
SDValue
6200+
ARMTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
6201+
const ARMSubtarget *Subtarget) const {
62006202
MachineFunction &MF = DAG.getMachineFunction();
62016203
MachineFrameInfo &MFI = MF.getFrameInfo();
6204+
const ARMBaseRegisterInfo &ARI =
6205+
*static_cast<const ARMBaseRegisterInfo*>(RegInfo);
62026206
MFI.setReturnAddressIsTaken(true);
62036207

62046208
if (verifyReturnAddressArgumentIsConstant(Op, DAG))
62056209
return SDValue();
62066210

6211+
// When the frame register is R11 for a Thumb1-only target, we need to use LR
6212+
// as a temporary while setting up the frame record, so it can not be used as
6213+
// a live-in to the function.
6214+
bool LRAvailable =
6215+
!(Subtarget->isThumb1Only() && ARI.getFrameRegister(MF) == ARM::R11);
6216+
62076217
EVT VT = Op.getValueType();
62086218
SDLoc dl(Op);
62096219
unsigned Depth = Op.getConstantOperandVal(0);
6210-
if (Depth) {
6220+
if (Depth || !LRAvailable) {
62116221
SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
62126222
SDValue Offset = DAG.getConstant(4, dl, MVT::i32);
62136223
return DAG.getLoad(VT, dl, DAG.getEntryNode(),
@@ -10667,7 +10677,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
1066710677
case ISD::FP_TO_SINT_SAT:
1066810678
case ISD::FP_TO_UINT_SAT: return LowerFP_TO_INT_SAT(Op, DAG, Subtarget);
1066910679
case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
10670-
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
10680+
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG, Subtarget);
1067110681
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
1067210682
case ISD::EH_SJLJ_SETJMP: return LowerEH_SJLJ_SETJMP(Op, DAG);
1067310683
case ISD::EH_SJLJ_LONGJMP: return LowerEH_SJLJ_LONGJMP(Op, DAG);

llvm/lib/Target/ARM/ARMISelLowering.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -854,7 +854,8 @@ class VectorType;
854854
SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const;
855855
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
856856
SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
857-
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
857+
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
858+
const ARMSubtarget *Subtarget) const;
858859
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
859860
SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG) const;
860861
SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc < %s -mtriple=thumbv6m-none-eabi -frame-pointer=none -verify-machineinstrs | FileCheck %s --check-prefix=FP-NONE
3+
; RUN: llc < %s -mtriple=thumbv6m-none-eabi -frame-pointer=all -verify-machineinstrs | FileCheck %s --check-prefix=FP-ALL
4+
; RUN: llc < %s -mtriple=thumbv6m-none-eabi -frame-pointer=all -mattr=+aapcs-frame-chain -verify-machineinstrs | FileCheck %s --check-prefix=FP-AAPCS
5+
6+
define void @ra_call() {
7+
; FP-NONE-LABEL: ra_call:
8+
; FP-NONE: @ %bb.0: @ %entry
9+
; FP-NONE-NEXT: .save {r7, lr}
10+
; FP-NONE-NEXT: push {r7, lr}
11+
; FP-NONE-NEXT: mov r0, lr
12+
; FP-NONE-NEXT: bl sink_ptr
13+
; FP-NONE-NEXT: pop {r7, pc}
14+
;
15+
; FP-ALL-LABEL: ra_call:
16+
; FP-ALL: @ %bb.0: @ %entry
17+
; FP-ALL-NEXT: .save {r7, lr}
18+
; FP-ALL-NEXT: push {r7, lr}
19+
; FP-ALL-NEXT: .setfp r7, sp
20+
; FP-ALL-NEXT: add r7, sp, #0
21+
; FP-ALL-NEXT: mov r0, lr
22+
; FP-ALL-NEXT: bl sink_ptr
23+
; FP-ALL-NEXT: pop {r7, pc}
24+
;
25+
; FP-AAPCS-LABEL: ra_call:
26+
; FP-AAPCS: @ %bb.0: @ %entry
27+
; FP-AAPCS-NEXT: .save {lr}
28+
; FP-AAPCS-NEXT: push {lr}
29+
; FP-AAPCS-NEXT: mov lr, r11
30+
; FP-AAPCS-NEXT: .save {r11}
31+
; FP-AAPCS-NEXT: push {lr}
32+
; FP-AAPCS-NEXT: .setfp r11, sp
33+
; FP-AAPCS-NEXT: mov r11, sp
34+
; FP-AAPCS-NEXT: mov r0, r11
35+
; FP-AAPCS-NEXT: ldr r0, [r0, #4]
36+
; FP-AAPCS-NEXT: bl sink_ptr
37+
; FP-AAPCS-NEXT: pop {r0}
38+
; FP-AAPCS-NEXT: mov r11, r0
39+
; FP-AAPCS-NEXT: pop {pc}
40+
entry:
41+
%r = tail call ptr @llvm.returnaddress(i32 0)
42+
tail call void @sink_ptr(ptr %r)
43+
ret void
44+
}
45+
46+
define ptr @ra_return() {
47+
; FP-NONE-LABEL: ra_return:
48+
; FP-NONE: @ %bb.0: @ %entry
49+
; FP-NONE-NEXT: mov r0, lr
50+
; FP-NONE-NEXT: bx lr
51+
;
52+
; FP-ALL-LABEL: ra_return:
53+
; FP-ALL: @ %bb.0: @ %entry
54+
; FP-ALL-NEXT: .save {r7, lr}
55+
; FP-ALL-NEXT: push {r7, lr}
56+
; FP-ALL-NEXT: .setfp r7, sp
57+
; FP-ALL-NEXT: add r7, sp, #0
58+
; FP-ALL-NEXT: mov r0, lr
59+
; FP-ALL-NEXT: pop {r7, pc}
60+
;
61+
; FP-AAPCS-LABEL: ra_return:
62+
; FP-AAPCS: @ %bb.0: @ %entry
63+
; FP-AAPCS-NEXT: .save {lr}
64+
; FP-AAPCS-NEXT: push {lr}
65+
; FP-AAPCS-NEXT: mov lr, r11
66+
; FP-AAPCS-NEXT: .save {r11}
67+
; FP-AAPCS-NEXT: push {lr}
68+
; FP-AAPCS-NEXT: .setfp r11, sp
69+
; FP-AAPCS-NEXT: mov r11, sp
70+
; FP-AAPCS-NEXT: mov r0, r11
71+
; FP-AAPCS-NEXT: ldr r0, [r0, #4]
72+
; FP-AAPCS-NEXT: pop {r1}
73+
; FP-AAPCS-NEXT: mov r11, r1
74+
; FP-AAPCS-NEXT: pop {pc}
75+
entry:
76+
%r = tail call ptr @llvm.returnaddress(i32 0)
77+
ret ptr %r
78+
}
79+
80+
define ptr @callee_saved_low() {
81+
; FP-NONE-LABEL: callee_saved_low:
82+
; FP-NONE: @ %bb.0: @ %entry
83+
; FP-NONE-NEXT: .save {r4, r5, r7, lr}
84+
; FP-NONE-NEXT: push {r4, r5, r7, lr}
85+
; FP-NONE-NEXT: mov r0, lr
86+
; FP-NONE-NEXT: @APP
87+
; FP-NONE-NEXT: @NO_APP
88+
; FP-NONE-NEXT: pop {r4, r5, r7, pc}
89+
;
90+
; FP-ALL-LABEL: callee_saved_low:
91+
; FP-ALL: @ %bb.0: @ %entry
92+
; FP-ALL-NEXT: .save {r4, r5, r7, lr}
93+
; FP-ALL-NEXT: push {r4, r5, r7, lr}
94+
; FP-ALL-NEXT: .setfp r7, sp, #8
95+
; FP-ALL-NEXT: add r7, sp, #8
96+
; FP-ALL-NEXT: mov r0, lr
97+
; FP-ALL-NEXT: @APP
98+
; FP-ALL-NEXT: @NO_APP
99+
; FP-ALL-NEXT: pop {r4, r5, r7, pc}
100+
;
101+
; FP-AAPCS-LABEL: callee_saved_low:
102+
; FP-AAPCS: @ %bb.0: @ %entry
103+
; FP-AAPCS-NEXT: .save {lr}
104+
; FP-AAPCS-NEXT: push {lr}
105+
; FP-AAPCS-NEXT: mov lr, r11
106+
; FP-AAPCS-NEXT: .save {r11}
107+
; FP-AAPCS-NEXT: push {lr}
108+
; FP-AAPCS-NEXT: .setfp r11, sp
109+
; FP-AAPCS-NEXT: mov r11, sp
110+
; FP-AAPCS-NEXT: .save {r4, r5}
111+
; FP-AAPCS-NEXT: push {r4, r5}
112+
; FP-AAPCS-NEXT: mov r0, r11
113+
; FP-AAPCS-NEXT: ldr r0, [r0, #4]
114+
; FP-AAPCS-NEXT: @APP
115+
; FP-AAPCS-NEXT: @NO_APP
116+
; FP-AAPCS-NEXT: pop {r4, r5}
117+
; FP-AAPCS-NEXT: pop {r1}
118+
; FP-AAPCS-NEXT: mov r11, r1
119+
; FP-AAPCS-NEXT: pop {pc}
120+
entry:
121+
call void asm sideeffect "", "~{r4},~{r5}"()
122+
%r = tail call ptr @llvm.returnaddress(i32 0)
123+
ret ptr %r
124+
}
125+
126+
define ptr @callee_saved_high() {
127+
; FP-NONE-LABEL: callee_saved_high:
128+
; FP-NONE: @ %bb.0: @ %entry
129+
; FP-NONE-NEXT: mov r3, r9
130+
; FP-NONE-NEXT: mov r2, r8
131+
; FP-NONE-NEXT: .save {r8, r9}
132+
; FP-NONE-NEXT: push {r2, r3}
133+
; FP-NONE-NEXT: mov r0, lr
134+
; FP-NONE-NEXT: @APP
135+
; FP-NONE-NEXT: @NO_APP
136+
; FP-NONE-NEXT: pop {r1, r2}
137+
; FP-NONE-NEXT: mov r8, r1
138+
; FP-NONE-NEXT: mov r9, r2
139+
; FP-NONE-NEXT: bx lr
140+
;
141+
; FP-ALL-LABEL: callee_saved_high:
142+
; FP-ALL: @ %bb.0: @ %entry
143+
; FP-ALL-NEXT: .save {r7, lr}
144+
; FP-ALL-NEXT: push {r7, lr}
145+
; FP-ALL-NEXT: .setfp r7, sp
146+
; FP-ALL-NEXT: add r7, sp, #0
147+
; FP-ALL-NEXT: mov r3, r9
148+
; FP-ALL-NEXT: mov r2, r8
149+
; FP-ALL-NEXT: .save {r8, r9}
150+
; FP-ALL-NEXT: push {r2, r3}
151+
; FP-ALL-NEXT: mov r0, lr
152+
; FP-ALL-NEXT: @APP
153+
; FP-ALL-NEXT: @NO_APP
154+
; FP-ALL-NEXT: pop {r1, r2}
155+
; FP-ALL-NEXT: mov r8, r1
156+
; FP-ALL-NEXT: mov r9, r2
157+
; FP-ALL-NEXT: pop {r7, pc}
158+
;
159+
; FP-AAPCS-LABEL: callee_saved_high:
160+
; FP-AAPCS: @ %bb.0: @ %entry
161+
; FP-AAPCS-NEXT: .save {lr}
162+
; FP-AAPCS-NEXT: push {lr}
163+
; FP-AAPCS-NEXT: mov lr, r11
164+
; FP-AAPCS-NEXT: .save {r11}
165+
; FP-AAPCS-NEXT: push {lr}
166+
; FP-AAPCS-NEXT: .setfp r11, sp
167+
; FP-AAPCS-NEXT: mov r11, sp
168+
; FP-AAPCS-NEXT: mov r3, r9
169+
; FP-AAPCS-NEXT: mov r2, r8
170+
; FP-AAPCS-NEXT: .save {r8, r9}
171+
; FP-AAPCS-NEXT: push {r2, r3}
172+
; FP-AAPCS-NEXT: mov r0, r11
173+
; FP-AAPCS-NEXT: ldr r0, [r0, #4]
174+
; FP-AAPCS-NEXT: @APP
175+
; FP-AAPCS-NEXT: @NO_APP
176+
; FP-AAPCS-NEXT: pop {r1, r2}
177+
; FP-AAPCS-NEXT: mov r8, r1
178+
; FP-AAPCS-NEXT: mov r9, r2
179+
; FP-AAPCS-NEXT: pop {r1}
180+
; FP-AAPCS-NEXT: mov r11, r1
181+
; FP-AAPCS-NEXT: pop {pc}
182+
entry:
183+
call void asm sideeffect "", "~{r8},~{r9}"()
184+
%r = tail call ptr @llvm.returnaddress(i32 0)
185+
ret ptr %r
186+
}
187+
188+
define ptr @large_alloca() {
189+
; FP-NONE-LABEL: large_alloca:
190+
; FP-NONE: @ %bb.0: @ %entry
191+
; FP-NONE-NEXT: .save {r4, r5, r6, lr}
192+
; FP-NONE-NEXT: push {r4, r5, r6, lr}
193+
; FP-NONE-NEXT: ldr r6, .LCPI4_0
194+
; FP-NONE-NEXT: .pad #2000
195+
; FP-NONE-NEXT: add sp, r6
196+
; FP-NONE-NEXT: mov r4, lr
197+
; FP-NONE-NEXT: mov r0, sp
198+
; FP-NONE-NEXT: bl sink_ptr
199+
; FP-NONE-NEXT: mov r0, r4
200+
; FP-NONE-NEXT: ldr r6, .LCPI4_1
201+
; FP-NONE-NEXT: add sp, r6
202+
; FP-NONE-NEXT: pop {r4, r5, r6, pc}
203+
; FP-NONE-NEXT: .p2align 2
204+
; FP-NONE-NEXT: @ %bb.1:
205+
; FP-NONE-NEXT: .LCPI4_0:
206+
; FP-NONE-NEXT: .long 4294965296 @ 0xfffff830
207+
; FP-NONE-NEXT: .LCPI4_1:
208+
; FP-NONE-NEXT: .long 2000 @ 0x7d0
209+
;
210+
; FP-ALL-LABEL: large_alloca:
211+
; FP-ALL: @ %bb.0: @ %entry
212+
; FP-ALL-NEXT: .save {r4, r6, r7, lr}
213+
; FP-ALL-NEXT: push {r4, r6, r7, lr}
214+
; FP-ALL-NEXT: .setfp r7, sp, #8
215+
; FP-ALL-NEXT: add r7, sp, #8
216+
; FP-ALL-NEXT: ldr r6, .LCPI4_0
217+
; FP-ALL-NEXT: .pad #2000
218+
; FP-ALL-NEXT: add sp, r6
219+
; FP-ALL-NEXT: mov r4, lr
220+
; FP-ALL-NEXT: mov r0, sp
221+
; FP-ALL-NEXT: bl sink_ptr
222+
; FP-ALL-NEXT: mov r0, r4
223+
; FP-ALL-NEXT: subs r6, r7, #7
224+
; FP-ALL-NEXT: subs r6, #1
225+
; FP-ALL-NEXT: mov sp, r6
226+
; FP-ALL-NEXT: pop {r4, r6, r7, pc}
227+
; FP-ALL-NEXT: .p2align 2
228+
; FP-ALL-NEXT: @ %bb.1:
229+
; FP-ALL-NEXT: .LCPI4_0:
230+
; FP-ALL-NEXT: .long 4294965296 @ 0xfffff830
231+
;
232+
; FP-AAPCS-LABEL: large_alloca:
233+
; FP-AAPCS: @ %bb.0: @ %entry
234+
; FP-AAPCS-NEXT: .save {lr}
235+
; FP-AAPCS-NEXT: push {lr}
236+
; FP-AAPCS-NEXT: mov lr, r11
237+
; FP-AAPCS-NEXT: .save {r11}
238+
; FP-AAPCS-NEXT: push {lr}
239+
; FP-AAPCS-NEXT: .setfp r11, sp
240+
; FP-AAPCS-NEXT: mov r11, sp
241+
; FP-AAPCS-NEXT: .save {r4, r7}
242+
; FP-AAPCS-NEXT: push {r4, r7}
243+
; FP-AAPCS-NEXT: ldr r7, .LCPI4_0
244+
; FP-AAPCS-NEXT: .pad #2000
245+
; FP-AAPCS-NEXT: add sp, r7
246+
; FP-AAPCS-NEXT: mov r0, sp
247+
; FP-AAPCS-NEXT: bl sink_ptr
248+
; FP-AAPCS-NEXT: mov r0, r11
249+
; FP-AAPCS-NEXT: ldr r0, [r0, #4]
250+
; FP-AAPCS-NEXT: mov r7, r11
251+
; FP-AAPCS-NEXT: subs r7, #8
252+
; FP-AAPCS-NEXT: mov sp, r7
253+
; FP-AAPCS-NEXT: pop {r4, r7}
254+
; FP-AAPCS-NEXT: pop {r1}
255+
; FP-AAPCS-NEXT: mov r11, r1
256+
; FP-AAPCS-NEXT: pop {pc}
257+
; FP-AAPCS-NEXT: .p2align 2
258+
; FP-AAPCS-NEXT: @ %bb.1:
259+
; FP-AAPCS-NEXT: .LCPI4_0:
260+
; FP-AAPCS-NEXT: .long 4294965296 @ 0xfffff830
261+
entry:
262+
%big = alloca i8, i32 2000
263+
tail call void @sink_ptr(ptr %big)
264+
%r = tail call ptr @llvm.returnaddress(i32 0)
265+
ret ptr %r
266+
}
267+
268+
define ptr @ra_depth_1() {
269+
; FP-NONE-LABEL: ra_depth_1:
270+
; FP-NONE: @ %bb.0: @ %entry
271+
; FP-NONE-NEXT: .save {r7, lr}
272+
; FP-NONE-NEXT: push {r7, lr}
273+
; FP-NONE-NEXT: .setfp r7, sp
274+
; FP-NONE-NEXT: add r7, sp, #0
275+
; FP-NONE-NEXT: ldr r0, [r7]
276+
; FP-NONE-NEXT: ldr r0, [r0, #4]
277+
; FP-NONE-NEXT: pop {r7, pc}
278+
;
279+
; FP-ALL-LABEL: ra_depth_1:
280+
; FP-ALL: @ %bb.0: @ %entry
281+
; FP-ALL-NEXT: .save {r7, lr}
282+
; FP-ALL-NEXT: push {r7, lr}
283+
; FP-ALL-NEXT: .setfp r7, sp
284+
; FP-ALL-NEXT: add r7, sp, #0
285+
; FP-ALL-NEXT: ldr r0, [r7]
286+
; FP-ALL-NEXT: ldr r0, [r0, #4]
287+
; FP-ALL-NEXT: pop {r7, pc}
288+
;
289+
; FP-AAPCS-LABEL: ra_depth_1:
290+
; FP-AAPCS: @ %bb.0: @ %entry
291+
; FP-AAPCS-NEXT: .save {lr}
292+
; FP-AAPCS-NEXT: push {lr}
293+
; FP-AAPCS-NEXT: mov lr, r11
294+
; FP-AAPCS-NEXT: .save {r11}
295+
; FP-AAPCS-NEXT: push {lr}
296+
; FP-AAPCS-NEXT: .setfp r11, sp
297+
; FP-AAPCS-NEXT: mov r11, sp
298+
; FP-AAPCS-NEXT: mov r0, r11
299+
; FP-AAPCS-NEXT: ldr r0, [r0]
300+
; FP-AAPCS-NEXT: ldr r0, [r0, #4]
301+
; FP-AAPCS-NEXT: pop {r1}
302+
; FP-AAPCS-NEXT: mov r11, r1
303+
; FP-AAPCS-NEXT: pop {pc}
304+
entry:
305+
%r = tail call ptr @llvm.returnaddress(i32 1)
306+
ret ptr %r
307+
}
308+
309+
declare void @sink_ptr(ptr)

0 commit comments

Comments
 (0)