• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5define void @t1(i32 %x) nounwind ssp {
6entry:
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
19declare void @foo()
20
21define void @t2() nounwind ssp {
22entry:
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
35declare i32 @foo2()
36
37define void @t3() nounwind ssp {
38entry:
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
51declare i32 @foo3()
52
53define void @t4(void (i32)* nocapture %x) nounwind ssp {
54entry:
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
70define void @t5(void ()* nocapture %x) nounwind ssp {
71entry:
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
90define i32 @t6(i32 %x) nounwind ssp {
91entry:
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
106bb:
107  %1 = add nsw i32 %x, -1
108  %2 = tail call i32 @t6(i32 %1) nounwind ssp
109  ret i32 %2
110
111bb1:
112  %3 = tail call i32 @bar(i32 %x) nounwind
113  ret i32 %3
114}
115
116declare i32 @bar(i32)
117
118define i32 @t7(i32 %a, i32 %b, i32 %c) nounwind ssp {
119entry:
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
132declare i32 @bar2(i32, i32, i32)
133
134define signext i16 @t8() nounwind ssp {
135entry:
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
148declare signext i16 @bar3()
149
150define signext i16 @t9(i32 (i32)* nocapture %x) nounwind ssp {
151entry:
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
165define void @t10() nounwind ssp {
166entry:
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
179declare i32 @foo4()
180
181define 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
201entry:
202  %0 = icmp eq i32 %x, 0
203  br i1 %0, label %bb6, label %bb
204
205bb:
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
209bb6:
210  ret i32 0
211}
212
213declare i32 @foo5(i32, i32, i32, i32, i32)
214
215%struct.t = type { i32, i32, i32, i32, i32 }
216
217define 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
232entry:
233  %0 = icmp eq i32 %x, 0
234  br i1 %0, label %bb2, label %bb
235
236bb:
237  %1 = tail call i32 @foo6(i32 %x, i32 %y, %struct.t* byval align 4 %z) nounwind
238  ret i32 %1
239
240bb2:
241  ret i32 0
242}
243
244declare 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
250define %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
265entry:
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).
272declare 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
279define void @t14(%struct.__block_literal_2* nocapture %.block_descriptor) nounwind ssp {
280entry:
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
304define 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
320declare void @f(%struct.foo* noalias sret) nounwind
321
322define void @t16() nounwind ssp {
323entry:
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
337declare double @bar4()
338
339; rdar://6283267
340define void @t17() nounwind ssp {
341entry:
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
356declare void @bar5(...)
357
358; rdar://7774847
359define void @t18() nounwind ssp {
360entry:
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
376declare double @bar6(...)
377
378define void @t19() alignstack(32) nounwind {
379entry:
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
395define double @t20(double %x) nounwind {
396entry:
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
410declare fastcc double @foo20(double) nounwind
411