Add a triple to switch.ll test.
[oota-llvm.git] / test / CodeGen / X86 / sibcall.ll
1 ; RUN: llc < %s -mtriple=i686-linux   -mcpu=core2 -mattr=+sse2 -asm-verbose=false | FileCheck %s -check-prefix=32
2 ; RUN: llc < %s -mtriple=x86_64-linux -mcpu=core2 -mattr=+sse2 -asm-verbose=false | FileCheck %s -check-prefix=64
3 ; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -mcpu=core2 -mattr=+sse2 -asm-verbose=false | FileCheck %s -check-prefix=X32ABI
4
5 define void @t1(i32 %x) nounwind ssp {
6 entry:
7 ; 32-LABEL: t1:
8 ; 32: jmp {{_?}}foo
9
10 ; 64-LABEL: t1:
11 ; 64: jmp {{_?}}foo
12
13 ; X32ABI-LABEL: t1:
14 ; X32ABI: jmp {{_?}}foo
15   tail call void @foo() nounwind
16   ret void
17 }
18
19 declare void @foo()
20
21 define void @t2() nounwind ssp {
22 entry:
23 ; 32-LABEL: t2:
24 ; 32: jmp {{_?}}foo2
25
26 ; 64-LABEL: t2:
27 ; 64: jmp {{_?}}foo2
28
29 ; X32ABI-LABEL: t2:
30 ; X32ABI: jmp {{_?}}foo2
31   %0 = tail call i32 @foo2() nounwind
32   ret void
33 }
34
35 declare i32 @foo2()
36
37 define void @t3() nounwind ssp {
38 entry:
39 ; 32-LABEL: t3:
40 ; 32: jmp {{_?}}foo3
41
42 ; 64-LABEL: t3:
43 ; 64: jmp {{_?}}foo3
44
45 ; X32ABI-LABEL: t3:
46 ; X32ABI: jmp {{_?}}foo3
47   %0 = tail call i32 @foo3() nounwind
48   ret void
49 }
50
51 declare i32 @foo3()
52
53 define void @t4(void (i32)* nocapture %x) nounwind ssp {
54 entry:
55 ; 32-LABEL: t4:
56 ; 32: calll *
57 ; FIXME: gcc can generate a tailcall for this. But it's tricky.
58
59 ; 64-LABEL: t4:
60 ; 64-NOT: call
61 ; 64: jmpq *
62
63 ; X32ABI-LABEL: t4:
64 ; X32ABI-NOT: call
65 ; X32ABI: jmpq *
66   tail call void %x(i32 0) nounwind
67   ret void
68 }
69
70 define void @t5(void ()* nocapture %x) nounwind ssp {
71 entry:
72 ; 32-LABEL: t5:
73 ; 32-NOT: call
74 ; 32: jmpl *4(%esp)
75
76 ; 64-LABEL: t5:
77 ; 64-NOT: call
78 ; 64: jmpq *%rdi
79
80 ; X32ABI-LABEL: t5:
81 ; X32ABI-NOT: call
82 ; FIXME: This isn't needed since x32 psABI specifies that callers must
83 ;        zero-extend pointers passed in registers.
84 ; X32ABI: movl %edi, %eax
85 ; X32ABI: jmpq *%rax
86   tail call void %x() nounwind
87   ret void
88 }
89
90 define i32 @t6(i32 %x) nounwind ssp {
91 entry:
92 ; 32-LABEL: t6:
93 ; 32: calll {{_?}}t6
94 ; 32: jmp {{_?}}bar
95
96 ; 64-LABEL: t6:
97 ; 64: jmp {{_?}}t6
98 ; 64: jmp {{_?}}bar
99
100 ; X32ABI-LABEL: t6:
101 ; X32ABI: jmp {{_?}}t6
102 ; X32ABI: jmp {{_?}}bar
103   %0 = icmp slt i32 %x, 10
104   br i1 %0, label %bb, label %bb1
105
106 bb:
107   %1 = add nsw i32 %x, -1
108   %2 = tail call i32 @t6(i32 %1) nounwind ssp
109   ret i32 %2
110
111 bb1:
112   %3 = tail call i32 @bar(i32 %x) nounwind
113   ret i32 %3
114 }
115
116 declare i32 @bar(i32)
117
118 define i32 @t7(i32 %a, i32 %b, i32 %c) nounwind ssp {
119 entry:
120 ; 32-LABEL: t7:
121 ; 32: jmp {{_?}}bar2
122
123 ; 64-LABEL: t7:
124 ; 64: jmp {{_?}}bar2
125
126 ; X32ABI-LABEL: t7:
127 ; X32ABI: jmp {{_?}}bar2
128   %0 = tail call i32 @bar2(i32 %a, i32 %b, i32 %c) nounwind
129   ret i32 %0
130 }
131
132 declare i32 @bar2(i32, i32, i32)
133
134 define signext i16 @t8() nounwind ssp {
135 entry:
136 ; 32-LABEL: t8:
137 ; 32: jmp {{_?}}bar3
138
139 ; 64-LABEL: t8:
140 ; 64: jmp {{_?}}bar3
141
142 ; X32ABI-LABEL: t8:
143 ; X32ABI: jmp {{_?}}bar3
144   %0 = tail call signext i16 @bar3() nounwind      ; <i16> [#uses=1]
145   ret i16 %0
146 }
147
148 declare signext i16 @bar3()
149
150 define signext i16 @t9(i32 (i32)* nocapture %x) nounwind ssp {
151 entry:
152 ; 32-LABEL: t9:
153 ; 32: calll *
154
155 ; 64-LABEL: t9:
156 ; 64: jmpq *
157
158 ; X32ABI-LABEL: t9:
159 ; X32ABI: jmpq *
160   %0 = bitcast i32 (i32)* %x to i16 (i32)*
161   %1 = tail call signext i16 %0(i32 0) nounwind
162   ret i16 %1
163 }
164
165 define void @t10() nounwind ssp {
166 entry:
167 ; 32-LABEL: t10:
168 ; 32: calll
169
170 ; 64-LABEL: t10:
171 ; 64: callq
172
173 ; X32ABI-LABEL: t10:
174 ; X32ABI: callq
175   %0 = tail call i32 @foo4() noreturn nounwind
176   unreachable
177 }
178
179 declare i32 @foo4()
180
181 define i32 @t11(i32 %x, i32 %y, i32 %z.0, i32 %z.1, i32 %z.2) nounwind ssp {
182 ; In 32-bit mode, it's emitting a bunch of dead loads that are not being
183 ; eliminated currently.
184
185 ; 32-LABEL: t11:
186 ; 32-NOT: subl ${{[0-9]+}}, %esp
187 ; 32: je
188 ; 32-NOT: movl
189 ; 32-NOT: addl ${{[0-9]+}}, %esp
190 ; 32: jmp {{_?}}foo5
191
192 ; 64-LABEL: t11:
193 ; 64-NOT: subq ${{[0-9]+}}, %rsp
194 ; 64-NOT: addq ${{[0-9]+}}, %rsp
195 ; 64: jmp {{_?}}foo5
196
197 ; X32ABI-LABEL: t11:
198 ; X32ABI-NOT: subl ${{[0-9]+}}, %esp
199 ; X32ABI-NOT: addl ${{[0-9]+}}, %esp
200 ; X32ABI: jmp {{_?}}foo5
201 entry:
202   %0 = icmp eq i32 %x, 0
203   br i1 %0, label %bb6, label %bb
204
205 bb:
206   %1 = tail call i32 @foo5(i32 %x, i32 %y, i32 %z.0, i32 %z.1, i32 %z.2) nounwind
207   ret i32 %1
208
209 bb6:
210   ret i32 0
211 }
212
213 declare i32 @foo5(i32, i32, i32, i32, i32)
214
215 %struct.t = type { i32, i32, i32, i32, i32 }
216
217 define i32 @t12(i32 %x, i32 %y, %struct.t* byval align 4 %z) nounwind ssp {
218 ; 32-LABEL: t12:
219 ; 32-NOT: subl ${{[0-9]+}}, %esp
220 ; 32-NOT: addl ${{[0-9]+}}, %esp
221 ; 32: jmp {{_?}}foo6
222
223 ; 64-LABEL: t12:
224 ; 64-NOT: subq ${{[0-9]+}}, %rsp
225 ; 64-NOT: addq ${{[0-9]+}}, %rsp
226 ; 64: jmp {{_?}}foo6
227
228 ; X32ABI-LABEL: t12:
229 ; X32ABI-NOT: subl ${{[0-9]+}}, %esp
230 ; X32ABI-NOT: addl ${{[0-9]+}}, %esp
231 ; X32ABI: jmp {{_?}}foo6
232 entry:
233   %0 = icmp eq i32 %x, 0
234   br i1 %0, label %bb2, label %bb
235
236 bb:
237   %1 = tail call i32 @foo6(i32 %x, i32 %y, %struct.t* byval align 4 %z) nounwind
238   ret i32 %1
239
240 bb2:
241   ret i32 0
242 }
243
244 declare i32 @foo6(i32, i32, %struct.t* byval align 4)
245
246 ; rdar://r7717598
247 %struct.ns = type { i32, i32 }
248 %struct.cp = type { float, float, float, float, float }
249
250 define %struct.ns* @t13(%struct.cp* %yy) nounwind ssp {
251 ; 32-LABEL: t13:
252 ; 32-NOT: jmp
253 ; 32: calll
254 ; 32: ret
255
256 ; 64-LABEL: t13:
257 ; 64-NOT: jmp
258 ; 64: callq
259 ; 64: ret
260
261 ; X32ABI-LABEL: t13:
262 ; X32ABI-NOT: jmp
263 ; X32ABI: callq
264 ; X32ABI: ret
265 entry:
266   %0 = tail call fastcc %struct.ns* @foo7(%struct.cp* byval align 4 %yy, i8 signext 0) nounwind
267   ret %struct.ns* %0
268 }
269
270 ; rdar://6195379
271 ; llvm can't do sibcall for this in 32-bit mode (yet).
272 declare fastcc %struct.ns* @foo7(%struct.cp* byval align 4, i8 signext) nounwind ssp
273
274 %struct.__block_descriptor = type { i64, i64 }
275 %struct.__block_descriptor_withcopydispose = type { i64, i64, i8*, i8* }
276 %struct.__block_literal_1 = type { i8*, i32, i32, i8*, %struct.__block_descriptor* }
277 %struct.__block_literal_2 = type { i8*, i32, i32, i8*, %struct.__block_descriptor_withcopydispose*, void ()* }
278
279 define void @t14(%struct.__block_literal_2* nocapture %.block_descriptor) nounwind ssp {
280 entry:
281 ; 64-LABEL: t14:
282 ; 64: movq 32(%rdi)
283 ; 64-NOT: movq 16(%rdi)
284 ; 64: jmpq *16({{%rdi|%rax}})
285
286 ; X32ABI-LABEL: t14:
287 ; X32ABI: movl 20(%edi), %edi
288 ; X32ABI-NEXT: movl 12(%edi), %eax
289 ; X32ABI-NEXT: jmpq *%rax
290   %0 = getelementptr inbounds %struct.__block_literal_2, %struct.__block_literal_2* %.block_descriptor, i64 0, i32 5 ; <void ()**> [#uses=1]
291   %1 = load void ()*, void ()** %0, align 8                 ; <void ()*> [#uses=2]
292   %2 = bitcast void ()* %1 to %struct.__block_literal_1* ; <%struct.__block_literal_1*> [#uses=1]
293   %3 = getelementptr inbounds %struct.__block_literal_1, %struct.__block_literal_1* %2, i64 0, i32 3 ; <i8**> [#uses=1]
294   %4 = load i8*, i8** %3, align 8                      ; <i8*> [#uses=1]
295   %5 = bitcast i8* %4 to void (i8*)*              ; <void (i8*)*> [#uses=1]
296   %6 = bitcast void ()* %1 to i8*                 ; <i8*> [#uses=1]
297   tail call void %5(i8* %6) nounwind
298   ret void
299 }
300
301 ; rdar://7726868
302 %struct.foo = type { [4 x i32] }
303
304 define void @t15(%struct.foo* noalias sret %agg.result) nounwind  {
305 ; 32-LABEL: t15:
306 ; 32: calll {{_?}}f
307 ; 32: retl $4
308
309 ; 64-LABEL: t15:
310 ; 64: callq {{_?}}f
311 ; 64: retq
312
313 ; X32ABI-LABEL: t15:
314 ; X32ABI: callq {{_?}}f
315 ; X32ABI: retq
316   tail call fastcc void @f(%struct.foo* noalias sret %agg.result) nounwind
317   ret void
318 }
319
320 declare void @f(%struct.foo* noalias sret) nounwind
321
322 define void @t16() nounwind ssp {
323 entry:
324 ; 32-LABEL: t16:
325 ; 32: calll {{_?}}bar4
326 ; 32: fstp
327
328 ; 64-LABEL: t16:
329 ; 64: jmp {{_?}}bar4
330
331 ; X32ABI-LABEL: t16:
332 ; X32ABI: jmp {{_?}}bar4
333   %0 = tail call double @bar4() nounwind
334   ret void
335 }
336
337 declare double @bar4()
338
339 ; rdar://6283267
340 define void @t17() nounwind ssp {
341 entry:
342 ; 32-LABEL: t17:
343 ; 32: jmp {{_?}}bar5
344
345 ; 64-LABEL: t17:
346 ; 64: xorl %eax, %eax
347 ; 64: jmp {{_?}}bar5
348
349 ; X32ABI-LABEL: t17:
350 ; X32ABI: xorl %eax, %eax
351 ; X32ABI: jmp {{_?}}bar5
352   tail call void (...)* @bar5() nounwind
353   ret void
354 }
355
356 declare void @bar5(...)
357
358 ; rdar://7774847
359 define void @t18() nounwind ssp {
360 entry:
361 ; 32-LABEL: t18:
362 ; 32: calll {{_?}}bar6
363 ; 32: fstp %st(0)
364
365 ; 64-LABEL: t18:
366 ; 64: xorl %eax, %eax
367 ; 64: jmp {{_?}}bar6
368
369 ; X32ABI-LABEL: t18:
370 ; X32ABI: xorl %eax, %eax
371 ; X32ABI: jmp {{_?}}bar6
372   %0 = tail call double (...)* @bar6() nounwind
373   ret void
374 }
375
376 declare double @bar6(...)
377
378 define void @t19() alignstack(32) nounwind {
379 entry:
380 ; CHECK-LABEL: t19:
381 ; CHECK: andl $-32
382 ; CHECK: calll {{_?}}foo
383
384 ; X32ABI-LABEL: t19:
385 ; X32ABI: andl $-32
386 ; X32ABI: callq {{_?}}foo
387   tail call void @foo() nounwind
388   ret void
389 }
390
391 ; If caller / callee calling convention mismatch then check if the return
392 ; values are returned in the same registers.
393 ; rdar://7874780
394
395 define double @t20(double %x) nounwind {
396 entry:
397 ; 32-LABEL: t20:
398 ; 32: calll {{_?}}foo20
399 ; 32: fldl (%esp)
400
401 ; 64-LABEL: t20:
402 ; 64: jmp {{_?}}foo20
403
404 ; X32ABI-LABEL: t20:
405 ; X32ABI: jmp {{_?}}foo20
406   %0 = tail call fastcc double @foo20(double %x) nounwind
407   ret double %0
408 }
409
410 declare fastcc double @foo20(double) nounwind