If a function needs a frame pointer, but r11 (aka fp) has not been used,
[oota-llvm.git] / test / CodeGen / ARM / ehabi.ll
1 ; ARM EHABI integrated test
2
3 ; This test case checks whether the ARM unwind directives are properly
4 ; generated or not.
5
6 ; The purpose of the test:
7 ; (1) .fnstart and .fnend directives should wrap the function.
8 ; (2) .setfp directive should be available if frame pointer is not eliminated.
9 ; (3) .save directive should come with push instruction.
10 ; (4) .vsave directive should come with vpush instruction.
11 ; (5) .pad directive should come with stack pointer adjustment.
12 ; (6) .cantunwind directive should be available if the function is marked with
13 ;     nounwind function attribute.
14
15 ; We have to check several cases:
16 ; (1) arm with -disable-fp-elim
17 ; (2) arm without -disable-fp-elim
18 ; (3) armv7 with -disable-fp-elim
19 ; (4) armv7 without -disable-fp-elim
20
21 ; RUN: llc -mtriple arm-unknown-linux-gnueabi \
22 ; RUN:     -disable-fp-elim -filetype=asm -o - %s \
23 ; RUN:   | FileCheck %s --check-prefix=CHECK-FP
24
25 ; RUN: llc -mtriple arm-unknown-linux-gnueabi \
26 ; RUN:     -filetype=asm -o - %s \
27 ; RUN:   | FileCheck %s --check-prefix=CHECK-FP-ELIM
28
29 ; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
30 ; RUN:     -disable-fp-elim -filetype=asm -o - %s \
31 ; RUN:   | FileCheck %s --check-prefix=CHECK-V7-FP
32
33 ; RUN: llc -mtriple armv7-unknown-linux-gnueabi \
34 ; RUN:     -filetype=asm -o - %s \
35 ; RUN:   | FileCheck %s --check-prefix=CHECK-V7-FP-ELIM
36
37 ; RUN: llc -mtriple arm-unknown-linux-androideabi \
38 ; RUN:     -disable-fp-elim -filetype=asm -o - %s \
39 ; RUN:   | FileCheck %s --check-prefix=CHECK-FP
40
41 ; RUN: llc -mtriple arm-unknown-linux-androideabi \
42 ; RUN:     -filetype=asm -o - %s \
43 ; RUN:   | FileCheck %s --check-prefix=CHECK-FP-ELIM
44
45 ; RUN: llc -mtriple armv7-unknown-linux-androideabi \
46 ; RUN:     -disable-fp-elim -filetype=asm -o - %s \
47 ; RUN:   | FileCheck %s --check-prefix=CHECK-V7-FP
48
49 ; RUN: llc -mtriple armv7-unknown-linux-androideabi \
50 ; RUN:     -filetype=asm -o - %s \
51 ; RUN:   | FileCheck %s --check-prefix=CHECK-V7-FP-ELIM
52
53 ;-------------------------------------------------------------------------------
54 ; Test 1
55 ;-------------------------------------------------------------------------------
56 ; This is the LLVM assembly generated from following C++ code:
57 ;
58 ;   extern void print(int, int, int, int, int);
59 ;   extern void print(double, double, double, double, double);
60 ;
61 ;   void test(int a, int b, int c, int d, int e,
62 ;             double m, double n, double p, double q, double r) {
63 ;     try {
64 ;       print(a, b, c, d, e);
65 ;     } catch (...) {
66 ;       print(m, n, p, q, r);
67 ;     }
68 ;   }
69
70 declare void @_Z5printiiiii(i32, i32, i32, i32, i32)
71
72 declare void @_Z5printddddd(double, double, double, double, double)
73
74 define void @_Z4testiiiiiddddd(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e,
75                                double %m, double %n, double %p,
76                                double %q, double %r) {
77 entry:
78   invoke void @_Z5printiiiii(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e)
79           to label %try.cont unwind label %lpad
80
81 lpad:
82   %0 = landingpad { i8*, i32 }
83           personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
84           catch i8* null
85   %1 = extractvalue { i8*, i32 } %0, 0
86   %2 = tail call i8* @__cxa_begin_catch(i8* %1)
87   invoke void @_Z5printddddd(double %m, double %n, double %p,
88                              double %q, double %r)
89           to label %invoke.cont2 unwind label %lpad1
90
91 invoke.cont2:
92   tail call void @__cxa_end_catch()
93   br label %try.cont
94
95 try.cont:
96   ret void
97
98 lpad1:
99   %3 = landingpad { i8*, i32 }
100           personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
101           cleanup
102   invoke void @__cxa_end_catch()
103           to label %eh.resume unwind label %terminate.lpad
104
105 eh.resume:
106   resume { i8*, i32 } %3
107
108 terminate.lpad:
109   %4 = landingpad { i8*, i32 }
110           personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
111           catch i8* null
112   %5 = extractvalue { i8*, i32 } %4, 0
113   tail call void @__clang_call_terminate(i8* %5)
114   unreachable
115 }
116
117 declare void @__clang_call_terminate(i8*)
118
119 declare i32 @__gxx_personality_v0(...)
120
121 declare i8* @__cxa_begin_catch(i8*)
122
123 declare void @__cxa_end_catch()
124
125 declare void @_ZSt9terminatev()
126
127 ; CHECK-FP-LABEL: _Z4testiiiiiddddd:
128 ; CHECK-FP:   .fnstart
129 ; CHECK-FP:   .save  {r4, r5, r6, r7, r8, r9, r10, r11, lr}
130 ; CHECK-FP:   push   {r4, r5, r6, r7, r8, r9, r10, r11, lr}
131 ; CHECK-FP:   .setfp r11, sp, #28
132 ; CHECK-FP:   add    r11, sp, #28
133 ; CHECK-FP:   .pad   #28
134 ; CHECK-FP:   sub    sp, sp, #28
135 ; CHECK-FP:   .personality __gxx_personality_v0
136 ; CHECK-FP:   .handlerdata
137 ; CHECK-FP:   .fnend
138
139 ; CHECK-FP-ELIM-LABEL: _Z4testiiiiiddddd:
140 ; CHECK-FP-ELIM:   .fnstart
141 ; CHECK-FP-ELIM:   .save {r4, r5, r6, r7, r8, r9, r10, r11, lr}
142 ; CHECK-FP-ELIM:   push  {r4, r5, r6, r7, r8, r9, r10, r11, lr}
143 ; CHECK-FP-ELIM:   .pad  #28
144 ; CHECK-FP-ELIM:   sub   sp, sp, #28
145 ; CHECK-FP-ELIM:   .personality __gxx_personality_v0
146 ; CHECK-FP-ELIM:   .handlerdata
147 ; CHECK-FP-ELIM:   .fnend
148
149 ; CHECK-V7-FP-LABEL: _Z4testiiiiiddddd:
150 ; CHECK-V7-FP:   .fnstart
151 ; CHECK-V7-FP:   .save  {r4, r10, r11, lr}
152 ; CHECK-V7-FP:   push   {r4, r10, r11, lr}
153 ; CHECK-V7-FP:   .setfp r11, sp, #8
154 ; CHECK-V7-FP:   add    r11, sp, #8
155 ; CHECK-V7-FP:   .vsave {d8, d9, d10, d11, d12}
156 ; CHECK-V7-FP:   vpush  {d8, d9, d10, d11, d12}
157 ; CHECK-V7-FP:   .pad   #24
158 ; CHECK-V7-FP:   sub    sp, sp, #24
159 ; CHECK-V7-FP:   .personality __gxx_personality_v0
160 ; CHECK-V7-FP:   .handlerdata
161 ; CHECK-V7-FP:   .fnend
162
163 ; CHECK-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd:
164 ; CHECK-V7-FP-ELIM:   .fnstart
165 ; CHECK-V7-FP-ELIM:   .save  {r4, lr}
166 ; CHECK-V7-FP-ELIM:   push   {r4, lr}
167 ; CHECK-V7-FP-ELIM:   .vsave {d8, d9, d10, d11, d12}
168 ; CHECK-V7-FP-ELIM:   vpush  {d8, d9, d10, d11, d12}
169 ; CHECK-V7-FP-ELIM:   .pad   #24
170 ; CHECK-V7-FP-ELIM:   sub    sp, sp, #24
171 ; CHECK-V7-FP-ELIM:   .personality __gxx_personality_v0
172 ; CHECK-V7-FP-ELIM:   .handlerdata
173 ; CHECK-V7-FP-ELIM:   .fnend
174
175
176 ;-------------------------------------------------------------------------------
177 ; Test 2
178 ;-------------------------------------------------------------------------------
179
180 declare void @throw_exception_2()
181
182 define void @test2() {
183 entry:
184   call void @throw_exception_2()
185   ret void
186 }
187
188 ; CHECK-FP-LABEL: test2:
189 ; CHECK-FP:   .fnstart
190 ; CHECK-FP:   .save  {r11, lr}
191 ; CHECK-FP:   push   {r11, lr}
192 ; CHECK-FP:   .setfp r11, sp
193 ; CHECK-FP:   mov    r11, sp
194 ; CHECK-FP:   pop    {r11, lr}
195 ; CHECK-FP:   mov    pc, lr
196 ; CHECK-FP:   .fnend
197
198 ; CHECK-FP-ELIM-LABEL: test2:
199 ; CHECK-FP-ELIM:   .fnstart
200 ; CHECK-FP-ELIM:   .save {r11, lr}
201 ; CHECK-FP-ELIM:   push  {r11, lr}
202 ; CHECK-FP-ELIM:   pop   {r11, lr}
203 ; CHECK-FP-ELIM:   mov   pc, lr
204 ; CHECK-FP-ELIM:   .fnend
205
206 ; CHECK-V7-FP-LABEL: test2:
207 ; CHECK-V7-FP:   .fnstart
208 ; CHECK-V7-FP:   .save  {r11, lr}
209 ; CHECK-V7-FP:   push   {r11, lr}
210 ; CHECK-V7-FP:   .setfp r11, sp
211 ; CHECK-V7-FP:   mov    r11, sp
212 ; CHECK-V7-FP:   pop    {r11, pc}
213 ; CHECK-V7-FP:   .fnend
214
215 ; CHECK-V7-FP-ELIM-LABEL: test2:
216 ; CHECK-V7-FP-ELIM:   .fnstart
217 ; CHECK-V7-FP-ELIM:   .save {r11, lr}
218 ; CHECK-V7-FP-ELIM:   push  {r11, lr}
219 ; CHECK-V7-FP-ELIM:   pop   {r11, pc}
220 ; CHECK-V7-FP-ELIM:   .fnend
221
222
223 ;-------------------------------------------------------------------------------
224 ; Test 3
225 ;-------------------------------------------------------------------------------
226
227 declare void @throw_exception_3(i32)
228
229 define i32 @test3(i32 %a, i32 %b, i32 %c, i32 %d,
230                   i32 %e, i32 %f, i32 %g, i32 %h) {
231 entry:
232   %add = add nsw i32 %b, %a
233   %add1 = add nsw i32 %add, %c
234   %add2 = add nsw i32 %add1, %d
235   tail call void @throw_exception_3(i32 %add2)
236   %add3 = add nsw i32 %f, %e
237   %add4 = add nsw i32 %add3, %g
238   %add5 = add nsw i32 %add4, %h
239   tail call void @throw_exception_3(i32 %add5)
240   %add6 = add nsw i32 %add5, %add2
241   ret i32 %add6
242 }
243
244 ; CHECK-FP-LABEL: test3:
245 ; CHECK-FP:   .fnstart
246 ; CHECK-FP:   .save  {r4, r5, r11, lr}
247 ; CHECK-FP:   push   {r4, r5, r11, lr}
248 ; CHECK-FP:   .setfp r11, sp, #8
249 ; CHECK-FP:   add    r11, sp, #8
250 ; CHECK-FP:   pop    {r4, r5, r11, lr}
251 ; CHECK-FP:   mov    pc, lr
252 ; CHECK-FP:   .fnend
253
254 ; CHECK-FP-ELIM-LABEL: test3:
255 ; CHECK-FP-ELIM:   .fnstart
256 ; CHECK-FP-ELIM:   .save {r4, r5, r11, lr}
257 ; CHECK-FP-ELIM:   push  {r4, r5, r11, lr}
258 ; CHECK-FP-ELIM:   pop   {r4, r5, r11, lr}
259 ; CHECK-FP-ELIM:   mov   pc, lr
260 ; CHECK-FP-ELIM:   .fnend
261
262 ; CHECK-V7-FP-LABEL: test3:
263 ; CHECK-V7-FP:   .fnstart
264 ; CHECK-V7-FP:   .save  {r4, r5, r11, lr}
265 ; CHECK-V7-FP:   push   {r4, r5, r11, lr}
266 ; CHECK-V7-FP:   .setfp r11, sp, #8
267 ; CHECK-V7-FP:   add    r11, sp, #8
268 ; CHECK-V7-FP:   pop    {r4, r5, r11, pc}
269 ; CHECK-V7-FP:   .fnend
270
271 ; CHECK-V7-FP-ELIM-LABEL: test3:
272 ; CHECK-V7-FP-ELIM:   .fnstart
273 ; CHECK-V7-FP-ELIM:   .save {r4, r5, r11, lr}
274 ; CHECK-V7-FP-ELIM:   push  {r4, r5, r11, lr}
275 ; CHECK-V7-FP-ELIM:   pop   {r4, r5, r11, pc}
276 ; CHECK-V7-FP-ELIM:   .fnend
277
278
279 ;-------------------------------------------------------------------------------
280 ; Test 4
281 ;-------------------------------------------------------------------------------
282
283 define void @test4() nounwind {
284 entry:
285   ret void
286 }
287
288 ; CHECK-FP-LABEL: test4:
289 ; CHECK-FP:   .fnstart
290 ; CHECK-FP:   mov pc, lr
291 ; CHECK-FP:   .cantunwind
292 ; CHECK-FP:   .fnend
293
294 ; CHECK-FP-ELIM-LABEL: test4:
295 ; CHECK-FP-ELIM:   .fnstart
296 ; CHECK-FP-ELIM:   mov pc, lr
297 ; CHECK-FP-ELIM:   .cantunwind
298 ; CHECK-FP-ELIM:   .fnend
299
300 ; CHECK-V7-FP-LABEL: test4:
301 ; CHECK-V7-FP:   .fnstart
302 ; CHECK-V7-FP:   bx lr
303 ; CHECK-V7-FP:   .cantunwind
304 ; CHECK-V7-FP:   .fnend
305
306 ; CHECK-V7-FP-ELIM-LABEL: test4:
307 ; CHECK-V7-FP-ELIM:   .fnstart
308 ; CHECK-V7-FP-ELIM:   bx lr
309 ; CHECK-V7-FP-ELIM:   .cantunwind
310 ; CHECK-V7-FP-ELIM:   .fnend