• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -mtriple=x86_64-apple-macosx -mcpu=core2 < %s | FileCheck %s
3
4declare i64 @testi()
5
6define i64 @test_trivial() {
7; CHECK-LABEL: test_trivial:
8; CHECK:       ## %bb.0: ## %entry
9; CHECK-NEXT:    jmp _testi ## TAILCALL
10entry:
11 %A = tail call i64 @testi()
12 ret i64 %A
13}
14
15define i64 @test_noop_bitcast() {
16; CHECK-LABEL: test_noop_bitcast:
17; CHECK:       ## %bb.0: ## %entry
18; CHECK-NEXT:    jmp _testi ## TAILCALL
19entry:
20 %A = tail call i64 @testi()
21 %B = bitcast i64 %A to i64
22 ret i64 %B
23}
24
25; Tail call shouldn't be blocked by no-op inttoptr.
26define i8* @test_inttoptr() {
27; CHECK-LABEL: test_inttoptr:
28; CHECK:       ## %bb.0: ## %entry
29; CHECK-NEXT:    jmp _testi ## TAILCALL
30entry:
31  %A = tail call i64 @testi()
32  %B = inttoptr i64 %A to i8*
33  ret i8* %B
34}
35
36declare <4 x float> @testv()
37
38define <4 x i32> @test_vectorbitcast() {
39; CHECK-LABEL: test_vectorbitcast:
40; CHECK:       ## %bb.0: ## %entry
41; CHECK-NEXT:    jmp _testv ## TAILCALL
42entry:
43  %A = tail call <4 x float> @testv()
44  %B = bitcast <4 x float> %A to <4 x i32>
45  ret <4 x i32> %B
46}
47
48declare { i64, i64 } @testp()
49
50define {i64, i64} @test_pair_trivial() {
51; CHECK-LABEL: test_pair_trivial:
52; CHECK:       ## %bb.0: ## %entry
53; CHECK-NEXT:    jmp _testp ## TAILCALL
54entry:
55  %A = tail call { i64, i64} @testp()
56  ret { i64, i64} %A
57}
58
59define {i64, i64} @test_pair_notail() {
60; CHECK-LABEL: test_pair_notail:
61; CHECK:       ## %bb.0: ## %entry
62; CHECK-NEXT:    pushq %rax
63; CHECK-NEXT:    .cfi_def_cfa_offset 16
64; CHECK-NEXT:    callq _testi
65; CHECK-NEXT:    movq %rax, %rdx
66; CHECK-NEXT:    popq %rcx
67; CHECK-NEXT:    retq
68entry:
69  %A = tail call i64 @testi()
70
71  %b = insertvalue {i64, i64} undef, i64 %A, 0
72  %c = insertvalue {i64, i64} %b, i64 %A, 1
73
74  ret { i64, i64} %c
75}
76
77define {i64, i64} @test_pair_extract_trivial() {
78; CHECK-LABEL: test_pair_extract_trivial:
79; CHECK:       ## %bb.0: ## %entry
80; CHECK-NEXT:    jmp _testp ## TAILCALL
81entry:
82  %A = tail call { i64, i64} @testp()
83  %x = extractvalue { i64, i64} %A, 0
84  %y = extractvalue { i64, i64} %A, 1
85
86  %b = insertvalue {i64, i64} undef, i64 %x, 0
87  %c = insertvalue {i64, i64} %b, i64 %y, 1
88
89  ret { i64, i64} %c
90}
91
92define {i64, i64} @test_pair_extract_notail() {
93; CHECK-LABEL: test_pair_extract_notail:
94; CHECK:       ## %bb.0: ## %entry
95; CHECK-NEXT:    pushq %rax
96; CHECK-NEXT:    .cfi_def_cfa_offset 16
97; CHECK-NEXT:    callq _testp
98; CHECK-NEXT:    movq %rax, %rcx
99; CHECK-NEXT:    movq %rdx, %rax
100; CHECK-NEXT:    movq %rcx, %rdx
101; CHECK-NEXT:    popq %rcx
102; CHECK-NEXT:    retq
103entry:
104  %A = tail call { i64, i64} @testp()
105  %x = extractvalue { i64, i64} %A, 0
106  %y = extractvalue { i64, i64} %A, 1
107
108  %b = insertvalue {i64, i64} undef, i64 %y, 0
109  %c = insertvalue {i64, i64} %b, i64 %x, 1
110
111  ret { i64, i64} %c
112}
113
114define {i8*, i64} @test_pair_extract_conv() {
115; CHECK-LABEL: test_pair_extract_conv:
116; CHECK:       ## %bb.0: ## %entry
117; CHECK-NEXT:    jmp _testp ## TAILCALL
118entry:
119  %A = tail call { i64, i64} @testp()
120  %x = extractvalue { i64, i64} %A, 0
121  %y = extractvalue { i64, i64} %A, 1
122
123  %x1 = inttoptr i64 %x to i8*
124
125  %b = insertvalue {i8*, i64} undef, i8* %x1, 0
126  %c = insertvalue {i8*, i64} %b, i64 %y, 1
127
128  ret { i8*, i64} %c
129}
130
131define {i64, i64} @test_pair_extract_multiple() {
132; CHECK-LABEL: test_pair_extract_multiple:
133; CHECK:       ## %bb.0: ## %entry
134; CHECK-NEXT:    jmp _testp ## TAILCALL
135entry:
136  %A = tail call { i64, i64} @testp()
137  %x = extractvalue { i64, i64} %A, 0
138  %y = extractvalue { i64, i64} %A, 1
139
140  %b = insertvalue {i64, i64} undef, i64 %x, 0
141  %c = insertvalue {i64, i64} %b, i64 %y, 1
142
143  %x1 = extractvalue { i64, i64} %b, 0
144  %y1 = extractvalue { i64, i64} %c, 1
145
146  %d = insertvalue {i64, i64} undef, i64 %x1, 0
147  %e = insertvalue {i64, i64} %b, i64 %y1, 1
148
149  ret { i64, i64} %e
150}
151
152define {i64, i64} @test_pair_extract_undef() {
153; CHECK-LABEL: test_pair_extract_undef:
154; CHECK:       ## %bb.0: ## %entry
155; CHECK-NEXT:    jmp _testp ## TAILCALL
156entry:
157  %A = tail call { i64, i64} @testp()
158  %x = extractvalue { i64, i64} %A, 0
159
160  %b = insertvalue {i64, i64} undef, i64 %x, 0
161
162  ret { i64, i64} %b
163}
164
165declare { i64, { i32, i32 } } @testn()
166
167define {i64, {i32, i32}} @test_nest() {
168; CHECK-LABEL: test_nest:
169; CHECK:       ## %bb.0: ## %entry
170; CHECK-NEXT:    jmp _testn ## TAILCALL
171entry:
172  %A = tail call { i64, { i32, i32 } } @testn()
173  %x = extractvalue { i64, { i32, i32}} %A, 0
174  %y = extractvalue { i64, { i32, i32}} %A, 1
175  %y1 = extractvalue { i32, i32} %y, 0
176  %y2 = extractvalue { i32, i32} %y, 1
177
178  %b = insertvalue {i64, {i32, i32}} undef, i64 %x, 0
179  %c1 = insertvalue {i32, i32} undef, i32 %y1, 0
180  %c2 = insertvalue {i32, i32} %c1, i32 %y2, 1
181  %c = insertvalue {i64, {i32, i32}} %b, {i32, i32} %c2, 1
182
183  ret { i64, { i32, i32}} %c
184}
185
186%struct.A = type { i32 }
187%struct.B = type { %struct.A, i32 }
188
189declare %struct.B* @testu()
190
191define %struct.A* @test_upcast() {
192; CHECK-LABEL: test_upcast:
193; CHECK:       ## %bb.0: ## %entry
194; CHECK-NEXT:    jmp _testu ## TAILCALL
195entry:
196  %A = tail call %struct.B* @testu()
197  %x = getelementptr inbounds %struct.B, %struct.B* %A, i32 0, i32 0
198  ret %struct.A* %x
199}
200
201; PR13006
202define { i64, i64 } @crash(i8* %this) {
203; CHECK-LABEL: crash:
204; CHECK:       ## %bb.0: ## %entry
205; CHECK-NEXT:    jmp _testp ## TAILCALL
206entry:
207  %c = tail call { i64, i64 } @testp()
208  %mrv7 = insertvalue { i64, i64 } %c, i64 undef, 1
209  ret { i64, i64 } %mrv7
210}
211
212%struct.funcs = type { i32 (i8*, i32*, i32)*, i32 (i8*)*, i32 (i8*)*, i32 (i8*, i32)*, i32 }
213
214@func_table = external global [0 x %struct.funcs]
215
216; Check that we can fold an indexed load into a tail call instruction.
217define void @fold_indexed_load(i8* %mbstr, i64 %idxprom) nounwind uwtable ssp {
218; CHECK-LABEL: fold_indexed_load:
219; CHECK:       ## %bb.0: ## %entry
220; CHECK-NEXT:    leaq (%rsi,%rsi,4), %rax
221; CHECK-NEXT:    movq _func_table@{{.*}}(%rip), %rcx
222; CHECK-NEXT:    jmpq *16(%rcx,%rax,8) ## TAILCALL
223entry:
224  %dsplen = getelementptr inbounds [0 x %struct.funcs], [0 x %struct.funcs]* @func_table, i64 0, i64 %idxprom, i32 2
225  %x1 = load i32 (i8*)*, i32 (i8*)** %dsplen, align 8
226  %call = tail call i32 %x1(i8* %mbstr) nounwind
227  ret void
228}
229
230@funcs = external constant [0 x i32 (i8*, ...)*]
231
232; <rdar://problem/12282281> Fold an indexed load into the tail call instruction.
233; Calling a varargs function with 6 arguments requires 7 registers (%al is the
234; vector count for varargs functions). This leaves %r11 as the only available
235; scratch register.
236;
237; It is not possible to fold an indexed load into TCRETURNmi64 in that case.
238;
239; typedef int (*funcptr)(void*, ...);
240; extern const funcptr funcs[];
241; int f(int n) {
242;   return funcs[n](0, 0, 0, 0, 0, 0);
243; }
244define i32 @rdar12282281(i32 %n) nounwind uwtable ssp {
245; CHECK-LABEL: rdar12282281:
246; CHECK:       ## %bb.0: ## %entry
247; CHECK-NEXT:    movslq %edi, %rax
248; CHECK-NEXT:    movq _funcs@{{.*}}(%rip), %rcx
249; CHECK-NEXT:    movq (%rcx,%rax,8), %r11
250; CHECK-NEXT:    xorl %edi, %edi
251; CHECK-NEXT:    xorl %esi, %esi
252; CHECK-NEXT:    xorl %edx, %edx
253; CHECK-NEXT:    xorl %ecx, %ecx
254; CHECK-NEXT:    xorl %r8d, %r8d
255; CHECK-NEXT:    xorl %r9d, %r9d
256; CHECK-NEXT:    xorl %eax, %eax
257; CHECK-NEXT:    jmpq *%r11 ## TAILCALL
258entry:
259  %idxprom = sext i32 %n to i64
260  %arrayidx = getelementptr inbounds [0 x i32 (i8*, ...)*], [0 x i32 (i8*, ...)*]* @funcs, i64 0, i64 %idxprom
261  %0 = load i32 (i8*, ...)*, i32 (i8*, ...)** %arrayidx, align 8
262  %call = tail call i32 (i8*, ...) %0(i8* null, i32 0, i32 0, i32 0, i32 0, i32 0) nounwind
263  ret i32 %call
264}
265
266declare x86_fp80 @fp80_callee(x86_fp80)
267
268define x86_fp80 @fp80_call(x86_fp80 %x) nounwind  {
269; CHECK-LABEL: fp80_call:
270; CHECK:       ## %bb.0: ## %entry
271; CHECK-NEXT:    jmp _fp80_callee ## TAILCALL
272entry:
273  %call = tail call x86_fp80 @fp80_callee(x86_fp80 %x) nounwind
274  ret x86_fp80 %call
275}
276
277declare double @trunc(double) nounwind readnone
278
279; rdar://12229511 - Don't tail call trunc here.
280define x86_fp80 @trunc_fp80(x86_fp80 %x) nounwind  {
281; CHECK-LABEL: trunc_fp80:
282; CHECK:       ## %bb.0: ## %entry
283; CHECK-NEXT:    subq $24, %rsp
284; CHECK-NEXT:    fldt {{[0-9]+}}(%rsp)
285; CHECK-NEXT:    fstpl {{[0-9]+}}(%rsp)
286; CHECK-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
287; CHECK-NEXT:    callq _trunc
288; CHECK-NEXT:    movsd %xmm0, {{[0-9]+}}(%rsp)
289; CHECK-NEXT:    fldl {{[0-9]+}}(%rsp)
290; CHECK-NEXT:    addq $24, %rsp
291; CHECK-NEXT:    retq
292entry:
293  %conv = fptrunc x86_fp80 %x to double
294  %call = tail call double @trunc(double %conv) nounwind readnone
295  %conv1 = fpext double %call to x86_fp80
296  ret x86_fp80 %conv1
297}
298