xref: /aosp_15_r20/external/llvm/test/CodeGen/ARM/fold-stack-adjust.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; Disable shrink-wrapping on the first test otherwise we wouldn't
2*9880d681SAndroid Build Coastguard Worker; exerce the path for PR18136.
3*9880d681SAndroid Build Coastguard Worker; RUN: llc -mtriple=thumbv7-apple-none-macho < %s -enable-shrink-wrap=false | FileCheck %s
4*9880d681SAndroid Build Coastguard Worker; RUN: llc -mtriple=thumbv6m-apple-none-macho -disable-fp-elim < %s | FileCheck %s --check-prefix=CHECK-T1
5*9880d681SAndroid Build Coastguard Worker; RUN: llc -mtriple=thumbv7-apple-darwin-ios -disable-fp-elim < %s | FileCheck %s --check-prefix=CHECK-IOS
6*9880d681SAndroid Build Coastguard Worker; RUN: llc -mtriple=thumbv7--linux-gnueabi -disable-fp-elim < %s | FileCheck %s --check-prefix=CHECK-LINUX
7*9880d681SAndroid Build Coastguard Worker
8*9880d681SAndroid Build Coastguard Worker
9*9880d681SAndroid Build Coastguard Workerdeclare void @bar(i8*)
10*9880d681SAndroid Build Coastguard Worker
11*9880d681SAndroid Build Coastguard Worker%bigVec = type [2 x double]
12*9880d681SAndroid Build Coastguard Worker
13*9880d681SAndroid Build Coastguard Worker@var = global %bigVec zeroinitializer
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Workerdefine void @check_simple() minsize {
16*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: check_simple:
17*9880d681SAndroid Build Coastguard Worker; CHECK: push {r3, r4, r5, r6, r7, lr}
18*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: sub sp, sp,
19*9880d681SAndroid Build Coastguard Worker; ...
20*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: add sp, sp,
21*9880d681SAndroid Build Coastguard Worker; CHECK: pop {r0, r1, r2, r3, r7, pc}
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker; CHECK-T1-LABEL: check_simple:
24*9880d681SAndroid Build Coastguard Worker; CHECK-T1: push {r3, r4, r5, r6, r7, lr}
25*9880d681SAndroid Build Coastguard Worker; CHECK-T1: add r7, sp, #16
26*9880d681SAndroid Build Coastguard Worker; CHECK-T1-NOT: sub sp, sp,
27*9880d681SAndroid Build Coastguard Worker; ...
28*9880d681SAndroid Build Coastguard Worker; CHECK-T1-NOT: add sp, sp,
29*9880d681SAndroid Build Coastguard Worker; CHECK-T1: pop {r0, r1, r2, r3, r7, pc}
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker  ; iOS always has a frame pointer and messing with the push affects
32*9880d681SAndroid Build Coastguard Worker  ; how it's set in the prologue. Make sure we get that right.
33*9880d681SAndroid Build Coastguard Worker; CHECK-IOS-LABEL: check_simple:
34*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: push {r3, r4, r5, r6, r7, lr}
35*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: sub sp,
36*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: add r7, sp, #16
37*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: sub sp,
38*9880d681SAndroid Build Coastguard Worker; ...
39*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: add sp,
40*9880d681SAndroid Build Coastguard Worker; CHEC: pop {r3, r4, r5, r6, r7, pc}
41*9880d681SAndroid Build Coastguard Worker
42*9880d681SAndroid Build Coastguard Worker  %var = alloca i8, i32 16
43*9880d681SAndroid Build Coastguard Worker  call void @bar(i8* %var)
44*9880d681SAndroid Build Coastguard Worker  ret void
45*9880d681SAndroid Build Coastguard Worker}
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Workerdefine void @check_simple_too_big() minsize {
48*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: check_simple_too_big:
49*9880d681SAndroid Build Coastguard Worker; CHECK: push {r7, lr}
50*9880d681SAndroid Build Coastguard Worker; CHECK: sub sp,
51*9880d681SAndroid Build Coastguard Worker; ...
52*9880d681SAndroid Build Coastguard Worker; CHECK: add sp,
53*9880d681SAndroid Build Coastguard Worker; CHECK: pop {r7, pc}
54*9880d681SAndroid Build Coastguard Worker  %var = alloca i8, i32 64
55*9880d681SAndroid Build Coastguard Worker  call void @bar(i8* %var)
56*9880d681SAndroid Build Coastguard Worker  ret void
57*9880d681SAndroid Build Coastguard Worker}
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Workerdefine void @check_vfp_fold() minsize {
60*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: check_vfp_fold:
61*9880d681SAndroid Build Coastguard Worker; CHECK: push {r[[GLOBREG:[0-9]+]], lr}
62*9880d681SAndroid Build Coastguard Worker; CHECK: vpush {d6, d7, d8, d9}
63*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: sub sp,
64*9880d681SAndroid Build Coastguard Worker; ...
65*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: add sp,
66*9880d681SAndroid Build Coastguard Worker; CHECK: vpop {d6, d7, d8, d9}
67*9880d681SAndroid Build Coastguard Worker; CHECK: pop {r[[GLOBREG]], pc}
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker  ; iOS uses aligned NEON stores here, which is convenient since we
70*9880d681SAndroid Build Coastguard Worker  ; want to make sure that works too.
71*9880d681SAndroid Build Coastguard Worker; CHECK-IOS-LABEL: check_vfp_fold:
72*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: push {r4, r7, lr}
73*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: sub.w r4, sp, #16
74*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: bfc r4, #0, #4
75*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: mov sp, r4
76*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: vst1.64 {d8, d9}, [r4:128]
77*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: sub sp, #16
78*9880d681SAndroid Build Coastguard Worker; ...
79*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: add r4, sp, #16
80*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: vld1.64 {d8, d9}, [r4:128]
81*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: mov sp, r4
82*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: pop {r4, r7, pc}
83*9880d681SAndroid Build Coastguard Worker
84*9880d681SAndroid Build Coastguard Worker  %var = alloca i8, i32 16
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker  call void asm "", "r,~{d8},~{d9}"(i8* %var)
87*9880d681SAndroid Build Coastguard Worker  call void @bar(i8* %var)
88*9880d681SAndroid Build Coastguard Worker
89*9880d681SAndroid Build Coastguard Worker  ret void
90*9880d681SAndroid Build Coastguard Worker}
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker; This function should use just enough space that the "add sp, sp, ..." could be
93*9880d681SAndroid Build Coastguard Worker; folded in except that doing so would clobber the value being returned.
94*9880d681SAndroid Build Coastguard Workerdefine i64 @check_no_return_clobber() minsize {
95*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: check_no_return_clobber:
96*9880d681SAndroid Build Coastguard Worker; CHECK: push {r1, r2, r3, r4, r5, r6, r7, lr}
97*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: sub sp,
98*9880d681SAndroid Build Coastguard Worker; ...
99*9880d681SAndroid Build Coastguard Worker; CHECK: add sp, #24
100*9880d681SAndroid Build Coastguard Worker; CHECK: pop {r7, pc}
101*9880d681SAndroid Build Coastguard Worker
102*9880d681SAndroid Build Coastguard Worker  ; Just to keep iOS FileCheck within previous function:
103*9880d681SAndroid Build Coastguard Worker; CHECK-IOS-LABEL: check_no_return_clobber:
104*9880d681SAndroid Build Coastguard Worker
105*9880d681SAndroid Build Coastguard Worker  %var = alloca i8, i32 20
106*9880d681SAndroid Build Coastguard Worker  call void @bar(i8* %var)
107*9880d681SAndroid Build Coastguard Worker  ret i64 0
108*9880d681SAndroid Build Coastguard Worker}
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Workerdefine arm_aapcs_vfpcc double @check_vfp_no_return_clobber() minsize {
111*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: check_vfp_no_return_clobber:
112*9880d681SAndroid Build Coastguard Worker; CHECK: push {r[[GLOBREG:[0-9]+]], lr}
113*9880d681SAndroid Build Coastguard Worker; CHECK: vpush {d0, d1, d2, d3, d4, d5, d6, d7, d8, d9}
114*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: sub sp,
115*9880d681SAndroid Build Coastguard Worker; ...
116*9880d681SAndroid Build Coastguard Worker; CHECK: add sp, #64
117*9880d681SAndroid Build Coastguard Worker; CHECK: vpop {d8, d9}
118*9880d681SAndroid Build Coastguard Worker; CHECK: pop {r[[GLOBREG]], pc}
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker  %var = alloca i8, i32 64
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker  %tmp = load %bigVec, %bigVec* @var
123*9880d681SAndroid Build Coastguard Worker  call void @bar(i8* %var)
124*9880d681SAndroid Build Coastguard Worker  store %bigVec %tmp, %bigVec* @var
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Worker  ret double 1.0
127*9880d681SAndroid Build Coastguard Worker}
128*9880d681SAndroid Build Coastguard Worker
129*9880d681SAndroid Build Coastguard Worker@dbl = global double 0.0
130*9880d681SAndroid Build Coastguard Worker
131*9880d681SAndroid Build Coastguard Worker; PR18136: there was a bug determining where the first eligible pop in a
132*9880d681SAndroid Build Coastguard Worker; basic-block was when the entire block was epilogue code.
133*9880d681SAndroid Build Coastguard Workerdefine void @test_fold_point(i1 %tst) minsize {
134*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_fold_point:
135*9880d681SAndroid Build Coastguard Worker
136*9880d681SAndroid Build Coastguard Worker  ; Important to check for beginning of basic block, because if it gets
137*9880d681SAndroid Build Coastguard Worker  ; if-converted the test is probably no longer checking what it should.
138*9880d681SAndroid Build Coastguard Worker; CHECK: {{LBB[0-9]+_2}}:
139*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: vpop {d7, d8}
140*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: pop {r4, pc}
141*9880d681SAndroid Build Coastguard Worker
142*9880d681SAndroid Build Coastguard Worker  ; With a guaranteed frame-pointer, we want to make sure that its offset in the
143*9880d681SAndroid Build Coastguard Worker  ; push block is correct, even if a few registers have been tacked onto a later
144*9880d681SAndroid Build Coastguard Worker  ; vpush (PR18160).
145*9880d681SAndroid Build Coastguard Worker; CHECK-IOS-LABEL: test_fold_point:
146*9880d681SAndroid Build Coastguard Worker; CHECK-IOS: push {r4, r7, lr}
147*9880d681SAndroid Build Coastguard Worker; CHECK-IOS-NEXT: add r7, sp, #4
148*9880d681SAndroid Build Coastguard Worker; CHECK-IOS-NEXT: vpush {d7, d8}
149*9880d681SAndroid Build Coastguard Worker
150*9880d681SAndroid Build Coastguard Worker  ; We want some memory so there's a stack adjustment to fold...
151*9880d681SAndroid Build Coastguard Worker  %var = alloca i8, i32 8
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker  ; We want a long-lived floating register so that a callee-saved dN is used and
154*9880d681SAndroid Build Coastguard Worker  ; there's both a vpop and a pop.
155*9880d681SAndroid Build Coastguard Worker  %live_val = load double, double* @dbl
156*9880d681SAndroid Build Coastguard Worker  br i1 %tst, label %true, label %end
157*9880d681SAndroid Build Coastguard Workertrue:
158*9880d681SAndroid Build Coastguard Worker  call void @bar(i8* %var)
159*9880d681SAndroid Build Coastguard Worker  store double %live_val, double* @dbl
160*9880d681SAndroid Build Coastguard Worker  br label %end
161*9880d681SAndroid Build Coastguard Workerend:
162*9880d681SAndroid Build Coastguard Worker  ; We want the epilogue to be the only thing in a basic block so that we hit
163*9880d681SAndroid Build Coastguard Worker  ; the correct edge-case (first inst in block is correct one to adjust).
164*9880d681SAndroid Build Coastguard Worker  ret void
165*9880d681SAndroid Build Coastguard Worker}
166*9880d681SAndroid Build Coastguard Worker
167*9880d681SAndroid Build Coastguard Workerdefine void @test_varsize(...) minsize {
168*9880d681SAndroid Build Coastguard Worker; CHECK-T1-LABEL: test_varsize:
169*9880d681SAndroid Build Coastguard Worker; CHECK-T1: sub	sp, #16
170*9880d681SAndroid Build Coastguard Worker; CHECK-T1: push	{r5, r6, r7, lr}
171*9880d681SAndroid Build Coastguard Worker; ...
172*9880d681SAndroid Build Coastguard Worker; CHECK-T1: pop	{r2, r3, r7}
173*9880d681SAndroid Build Coastguard Worker; CHECK-T1: pop {[[POP_REG:r[0-3]]]}
174*9880d681SAndroid Build Coastguard Worker; CHECK-T1: add	sp, #16
175*9880d681SAndroid Build Coastguard Worker; CHECK-T1: bx	[[POP_REG]]
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_varsize:
178*9880d681SAndroid Build Coastguard Worker; CHECK: sub	sp, #16
179*9880d681SAndroid Build Coastguard Worker; CHECK: push	{r5, r6, r7, lr}
180*9880d681SAndroid Build Coastguard Worker; ...
181*9880d681SAndroid Build Coastguard Worker; CHECK: pop.w	{r2, r3, r7, lr}
182*9880d681SAndroid Build Coastguard Worker; CHECK: add	sp, #16
183*9880d681SAndroid Build Coastguard Worker; CHECK: bx	lr
184*9880d681SAndroid Build Coastguard Worker
185*9880d681SAndroid Build Coastguard Worker  %var = alloca i8, i32 8
186*9880d681SAndroid Build Coastguard Worker  call void @llvm.va_start(i8* %var)
187*9880d681SAndroid Build Coastguard Worker  call void @bar(i8* %var)
188*9880d681SAndroid Build Coastguard Worker  ret void
189*9880d681SAndroid Build Coastguard Worker}
190*9880d681SAndroid Build Coastguard Worker
191*9880d681SAndroid Build Coastguard Worker%"MyClass" = type { i8*, i32, i32, float, float, float, [2 x i8], i32, i32* }
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Workerdeclare float @foo()
194*9880d681SAndroid Build Coastguard Worker
195*9880d681SAndroid Build Coastguard Workerdeclare void @bar3()
196*9880d681SAndroid Build Coastguard Worker
197*9880d681SAndroid Build Coastguard Workerdeclare %"MyClass"* @bar2(%"MyClass"* returned, i16*, i32, float, float, i32, i32, i1 zeroext, i1 zeroext, i32)
198*9880d681SAndroid Build Coastguard Worker
199*9880d681SAndroid Build Coastguard Workerdefine fastcc float @check_vfp_no_return_clobber2(i16* %r, i16* %chars, i32 %length, i1 zeroext %flag) minsize {
200*9880d681SAndroid Build Coastguard Workerentry:
201*9880d681SAndroid Build Coastguard Worker; CHECK-LINUX-LABEL: check_vfp_no_return_clobber2
202*9880d681SAndroid Build Coastguard Worker; CHECK-LINUX: vpush	{d0, d1, d2, d3, d4, d5, d6, d7, d8}
203*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: sub sp,
204*9880d681SAndroid Build Coastguard Worker; ...
205*9880d681SAndroid Build Coastguard Worker; CHECK-LINUX: add sp
206*9880d681SAndroid Build Coastguard Worker; CHECK-LINUX: vpop {d8}
207*9880d681SAndroid Build Coastguard Worker  %run = alloca %"MyClass", align 4
208*9880d681SAndroid Build Coastguard Worker  %call = call %"MyClass"* @bar2(%"MyClass"* %run, i16* %chars, i32 %length, float 0.000000e+00, float 0.000000e+00, i32 1, i32 1, i1 zeroext false, i1 zeroext true, i32 3)
209*9880d681SAndroid Build Coastguard Worker  %call1 = call float @foo()
210*9880d681SAndroid Build Coastguard Worker  %cmp = icmp eq %"MyClass"* %run, null
211*9880d681SAndroid Build Coastguard Worker  br i1 %cmp, label %exit, label %if.then
212*9880d681SAndroid Build Coastguard Worker
213*9880d681SAndroid Build Coastguard Workerif.then:                                          ; preds = %entry
214*9880d681SAndroid Build Coastguard Worker  call void @bar3()
215*9880d681SAndroid Build Coastguard Worker  br label %exit
216*9880d681SAndroid Build Coastguard Worker
217*9880d681SAndroid Build Coastguard Workerexit:                                             ; preds = %if.then, %entry
218*9880d681SAndroid Build Coastguard Worker  ret float %call1
219*9880d681SAndroid Build Coastguard Worker}
220*9880d681SAndroid Build Coastguard Worker
221*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.va_start(i8*) nounwind
222