1; RUN: llc -mtriple=thumbv4t-none--eabi < %s | FileCheck %s --check-prefix=CHECK-V4T
2; RUN: llc -mtriple=thumbv5t-none--eabi < %s | FileCheck %s --check-prefix=CHECK-V5T
3
4; CHECK-V4T-LABEL: clobberframe
5; CHECK-V5T-LABEL: clobberframe
6define <4 x i32> @clobberframe() #0 {
7entry:
8; Prologue
9; --------
10; CHECK-V4T:    push {[[SAVED:(r[4567](, )?)+]], lr}
11; CHECK-V4T:    sub sp,
12; CHECK-V5T:    push {[[SAVED:(r[4567](, )?)+]], lr}
13
14  %b = alloca <4 x i32>, align 16
15  %a = alloca <4 x i32>, align 16
16  store <4 x i32> <i32 42, i32 42, i32 42, i32 42>, <4 x i32>* %b, align 16
17  store <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32>* %a, align 16
18  %0 = load <4 x i32>* %a, align 16
19  ret <4 x i32> %0
20
21; Epilogue
22; --------
23; CHECK-V4T:         add sp,
24; CHECK-V4T-NEXT:    pop {[[SAVED]]}
25; CHECK-V4T-NEXT:    mov r12, r3
26; CHECK-V4T-NEXT:    pop {r3}
27; CHECK-V4T-NEXT:    mov lr, r3
28; CHECK-V4T-NEXT:    mov r3, r12
29; CHECK-V4T:         bx  lr
30; CHECK-V5T:         pop {[[SAVED]], pc}
31}
32
33; CHECK-V4T-LABEL: clobbervariadicframe
34; CHECK-V5T-LABEL: clobbervariadicframe
35define <4 x i32> @clobbervariadicframe(i32 %i, ...) #0 {
36entry:
37; Prologue
38; --------
39; CHECK-V4T:    sub sp,
40; CHECK-V4T:    push {[[SAVED:(r[4567](, )?)+]], lr}
41; CHECK-V5T:    sub sp,
42; CHECK-V5T:    push {[[SAVED:(r[4567](, )?)+]], lr}
43
44  %b = alloca <4 x i32>, align 16
45  %a = alloca <4 x i32>, align 16
46  store <4 x i32> <i32 42, i32 42, i32 42, i32 42>, <4 x i32>* %b, align 16
47  store <4 x i32> <i32 0, i32 1, i32 2, i32 3>, <4 x i32>* %a, align 16
48  %0 = load <4 x i32>* %a, align 16
49  call void @llvm.va_start(i8* null)
50  ret <4 x i32> %0
51
52; Epilogue
53; --------
54; CHECK-V4T:         pop {[[SAVED]]}
55; CHECK-V4T-NEXT:    mov r12, r3
56; CHECK-V4T-NEXT:    pop {r3}
57; CHECK-V4T-NEXT:    add sp,
58; CHECK-V4T-NEXT:    mov lr, r3
59; CHECK-V4T-NEXT:    mov r3, r12
60; CHECK-V4T:         bx  lr
61; CHECK-V5T:         add sp,
62; CHECK-V5T-NEXT:    pop {[[SAVED]]}
63; CHECK-V5T-NEXT:    mov r12, r3
64; CHECK-V5T-NEXT:    pop {r3}
65; CHECK-V5T-NEXT:    add sp,
66; CHECK-V5T-NEXT:    mov lr, r3
67; CHECK-V5T-NEXT:    mov r3, r12
68; CHECK-V5T-NEXT:    bx lr
69}
70
71; CHECK-V4T-LABEL: simpleframe
72; CHECK-V5T-LABEL: simpleframe
73define i32 @simpleframe() #0 {
74entry:
75; Prologue
76; --------
77; CHECK-V4T:    push    {[[SAVED:(r[4567](, )?)+]], lr}
78; CHECK-V5T:    push    {[[SAVED:(r[4567](, )?)+]], lr}
79
80  %a = alloca i32, align 4
81  %b = alloca i32, align 4
82  %c = alloca i32, align 4
83  %d = alloca i32, align 4
84  store i32 1, i32* %a, align 4
85  store i32 2, i32* %b, align 4
86  store i32 3, i32* %c, align 4
87  store i32 4, i32* %d, align 4
88  %0 = load i32* %a, align 4
89  %inc = add nsw i32 %0, 1
90  store i32 %inc, i32* %a, align 4
91  %1 = load i32* %b, align 4
92  %inc1 = add nsw i32 %1, 1
93  store i32 %inc1, i32* %b, align 4
94  %2 = load i32* %c, align 4
95  %inc2 = add nsw i32 %2, 1
96  store i32 %inc2, i32* %c, align 4
97  %3 = load i32* %d, align 4
98  %inc3 = add nsw i32 %3, 1
99  store i32 %inc3, i32* %d, align 4
100  %4 = load i32* %a, align 4
101  %5 = load i32* %b, align 4
102  %add = add nsw i32 %4, %5
103  %6 = load i32* %c, align 4
104  %add4 = add nsw i32 %add, %6
105  %7 = load i32* %d, align 4
106  %add5 = add nsw i32 %add4, %7
107  ret i32 %add5
108
109; Epilogue
110; --------
111; CHECK-V4T:    pop {[[SAVED]]}
112; CHECK-V4T:    pop {r3}
113; CHECK-V4T:    bx r3
114; CHECK-V5T:    pop {[[SAVED]], pc}
115}
116
117; CHECK-V4T-LABEL: simplevariadicframe
118; CHECK-V5T-LABEL: simplevariadicframe
119define i32 @simplevariadicframe(i32 %i, ...) #0 {
120entry:
121; Prologue
122; --------
123; CHECK-V4T:    sub sp,
124; CHECK-V4T:    push {[[SAVED:(r[4567](, )?)+]], lr}
125; CHECK-V4T:    sub sp,
126; CHECK-V5T:    sub sp,
127; CHECK-V5T:    push {[[SAVED:(r[4567](, )?)+]], lr}
128; CHECK-V5T:    sub sp,
129
130  %a = alloca i32, align 4
131  %b = alloca i32, align 4
132  %c = alloca i32, align 4
133  %d = alloca i32, align 4
134  store i32 1, i32* %a, align 4
135  store i32 2, i32* %b, align 4
136  store i32 3, i32* %c, align 4
137  store i32 4, i32* %d, align 4
138  %0 = load i32* %a, align 4
139  %inc = add nsw i32 %0, 1
140  store i32 %inc, i32* %a, align 4
141  %1 = load i32* %b, align 4
142  %inc1 = add nsw i32 %1, 1
143  store i32 %inc1, i32* %b, align 4
144  %2 = load i32* %c, align 4
145  %inc2 = add nsw i32 %2, 1
146  store i32 %inc2, i32* %c, align 4
147  %3 = load i32* %d, align 4
148  %inc3 = add nsw i32 %3, 1
149  store i32 %inc3, i32* %d, align 4
150  %4 = load i32* %a, align 4
151  %5 = load i32* %b, align 4
152  %add = add nsw i32 %4, %5
153  %6 = load i32* %c, align 4
154  %add4 = add nsw i32 %add, %6
155  %7 = load i32* %d, align 4
156  %add5 = add nsw i32 %add4, %7
157  %add6 = add nsw i32 %add5, %i
158  call void @llvm.va_start(i8* null)
159  ret i32 %add6
160
161; Epilogue
162; --------
163; CHECK-V4T:         add sp,
164; CHECK-V4T-NEXT:    pop {[[SAVED]]}
165; CHECK-V4T-NEXT:    pop {r3}
166; CHECK-V4T-NEXT:    add sp,
167; CHECK-V4T-NEXT:    bx r3
168; CHECK-V5T:         add sp,
169; CHECK-V5T-NEXT:    pop {[[SAVED]]}
170; CHECK-V5T-NEXT:    pop {r3}
171; CHECK-V5T-NEXT:    add sp,
172; CHECK-V5T-NEXT:    bx r3
173}
174
175; CHECK-V4T-LABEL: noframe
176; CHECK-V5T-LABEL: noframe
177define i32 @noframe() #0 {
178entry:
179; Prologue
180; --------
181; CHECK-V4T-NOT: push
182; CHECK-V5T-NOT: push
183    ret i32 0;
184; Epilogue
185; --------
186; CHECK-V4T-NOT: pop
187; CHECK-V5T-NOT: pop
188; CHECK-V4T:    bx  lr
189; CHECK-V5T:    bx  lr
190}
191
192; CHECK-V4T-LABEL: novariadicframe
193; CHECK-V5T-LABEL: novariadicframe
194define i32 @novariadicframe(i32 %i, ...) #0 {
195entry:
196; Prologue
197; --------
198; CHECK-V4T:    sub sp,
199; CHECK-V4T:    push {[[SAVED:(r[4567](, )?)+]], lr}
200; CHECK-V5T:    sub sp,
201; CHECK-V5T:    push {[[SAVED:(r[4567](, )?)+]], lr}
202
203  call void @llvm.va_start(i8* null)
204  ret i32 %i;
205; Epilogue
206; --------
207; CHECK-V4T:         pop {[[SAVED]]}
208; CHECK-V4T-NEXT:    pop {r3}
209; CHECK-V4T-NEXT:    add sp,
210; CHECK-V4T-NEXT:    bx r3
211; CHECK-V5T:         pop {[[SAVED]]}
212; CHECK-V5T-NEXT:    pop {r3}
213; CHECK-V5T-NEXT:    add sp,
214; CHECK-V5T-NEXT:    bx r3
215}
216
217declare void @llvm.va_start(i8*) nounwind
218