1; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+tail-call | FileCheck --check-prefixes=CHECK,SLOW %s
2; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -fast-isel -mattr=+tail-call | FileCheck --check-prefixes=CHECK,FAST %s
3; RUN: llc < %s --filetype=obj -mattr=+tail-call | obj2yaml | FileCheck --check-prefix=YAML %s
4
5; Test that the tail calls lower correctly
6
7target triple = "wasm32-unknown-unknown"
8
9%fn = type <{i32 (%fn, i32, i32)*}>
10declare i1 @foo(i1)
11declare i1 @bar(i1)
12
13; CHECK-LABEL: recursive_notail_nullary:
14; CHECK: {{^}} call recursive_notail_nullary{{$}}
15; CHECK-NEXT: return
16define void @recursive_notail_nullary() {
17  notail call void @recursive_notail_nullary()
18  ret void
19}
20
21; CHECK-LABEL: recursive_musttail_nullary:
22; CHECK: return_call recursive_musttail_nullary{{$}}
23define void @recursive_musttail_nullary() {
24  musttail call void @recursive_musttail_nullary()
25  ret void
26}
27
28; CHECK-LABEL: recursive_tail_nullary:
29; SLOW: return_call recursive_tail_nullary{{$}}
30; FAST: {{^}} call recursive_tail_nullary{{$}}
31; FAST-NEXT: return{{$}}
32define void @recursive_tail_nullary() {
33  tail call void @recursive_tail_nullary()
34  ret void
35}
36
37; CHECK-LABEL: recursive_notail:
38; CHECK: call $push[[L:[0-9]+]]=, recursive_notail, $0, $1{{$}}
39; CHECK-NEXT: return $pop[[L]]{{$}}
40define i32 @recursive_notail(i32 %x, i32 %y) {
41  %v = notail call i32 @recursive_notail(i32 %x, i32 %y)
42  ret i32 %v
43}
44
45; CHECK-LABEL: recursive_musttail:
46; CHECK: return_call recursive_musttail, $0, $1{{$}}
47define i32 @recursive_musttail(i32 %x, i32 %y) {
48  %v = musttail call i32 @recursive_musttail(i32 %x, i32 %y)
49  ret i32 %v
50}
51
52; CHECK-LABEL: recursive_tail:
53; SLOW: return_call recursive_tail, $0, $1{{$}}
54; FAST: call $push[[L:[0-9]+]]=, recursive_tail, $0, $1{{$}}
55; FAST-NEXT: return $pop[[L]]{{$}}
56define i32 @recursive_tail(i32 %x, i32 %y) {
57  %v = tail call i32 @recursive_tail(i32 %x, i32 %y)
58  ret i32 %v
59}
60
61; CHECK-LABEL: indirect_notail:
62; CHECK: call_indirect $push[[L:[0-9]+]]=, $0, $1, $2, $0{{$}}
63; CHECK-NEXT: return $pop[[L]]{{$}}
64define i32 @indirect_notail(%fn %f, i32 %x, i32 %y) {
65  %p = extractvalue %fn %f, 0
66  %v = notail call i32 %p(%fn %f, i32 %x, i32 %y)
67  ret i32 %v
68}
69
70; CHECK-LABEL: indirect_musttail:
71; CHECK: return_call_indirect , $0, $1, $2, $0{{$}}
72define i32 @indirect_musttail(%fn %f, i32 %x, i32 %y) {
73  %p = extractvalue %fn %f, 0
74  %v = musttail call i32 %p(%fn %f, i32 %x, i32 %y)
75  ret i32 %v
76}
77
78; CHECK-LABEL: indirect_tail:
79; CHECK: return_call_indirect , $0, $1, $2, $0{{$}}
80define i32 @indirect_tail(%fn %f, i32 %x, i32 %y) {
81  %p = extractvalue %fn %f, 0
82  %v = tail call i32 %p(%fn %f, i32 %x, i32 %y)
83  ret i32 %v
84}
85
86; CHECK-LABEL: choice_notail:
87; CHECK: call_indirect $push[[L:[0-9]+]]=, $0, $pop{{[0-9]+}}{{$}}
88; CHECK-NEXT: return $pop[[L]]{{$}}
89define i1 @choice_notail(i1 %x) {
90  %p = select i1 %x, i1 (i1)* @foo, i1 (i1)* @bar
91  %v = notail call i1 %p(i1 %x)
92  ret i1 %v
93}
94
95; CHECK-LABEL: choice_musttail:
96; CHECK: return_call_indirect , $0, $pop{{[0-9]+}}{{$}}
97define i1 @choice_musttail(i1 %x) {
98  %p = select i1 %x, i1 (i1)* @foo, i1 (i1)* @bar
99  %v = musttail call i1 %p(i1 %x)
100  ret i1 %v
101}
102
103; CHECK-LABEL: choice_tail:
104; SLOW: return_call_indirect , $0, $pop{{[0-9]+}}{{$}}
105; FAST: call_indirect $push[[L:[0-9]+]]=, $0, $pop{{[0-9]+}}{{$}}
106; FAST: return $pop[[L]]{{$}}
107define i1 @choice_tail(i1 %x) {
108  %p = select i1 %x, i1 (i1)* @foo, i1 (i1)* @bar
109  %v = tail call i1 %p(i1 %x)
110  ret i1 %v
111}
112
113; It is an LLVM validation error for a 'musttail' callee to have a different
114; prototype than its caller, so the following tests can only be done with
115; 'tail'.
116
117; CHECK-LABEL: mismatched_prototypes:
118; SLOW: return_call baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
119; FAST: call $push[[L:[0-9]+]]=, baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
120; FAST: return $pop[[L]]{{$}}
121declare i32 @baz(i32, i32, i32)
122define i32 @mismatched_prototypes() {
123  %v = tail call i32 @baz(i32 0, i32 42, i32 6)
124  ret i32 %v
125}
126
127; CHECK-LABEL: mismatched_return_void:
128; CHECK: call $drop=, baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
129; CHECK: return{{$}}
130define void @mismatched_return_void() {
131  %v = tail call i32 @baz(i32 0, i32 42, i32 6)
132  ret void
133}
134
135; CHECK-LABEL: mismatched_return_f32:
136; CHECK: call $push[[L:[0-9]+]]=, baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
137; CHECK: f32.reinterpret_i32 $push[[L1:[0-9]+]]=, $pop[[L]]{{$}}
138; CHECK: return $pop[[L1]]{{$}}
139define float @mismatched_return_f32() {
140  %v = tail call i32 @baz(i32 0, i32 42, i32 6)
141  %u = bitcast i32 %v to float
142  ret float %u
143}
144
145; CHECK-LABEL: mismatched_indirect_void:
146; CHECK: call_indirect $drop=, $0, $1, $2, $0{{$}}
147; CHECK: return{{$}}
148define void @mismatched_indirect_void(%fn %f, i32 %x, i32 %y) {
149  %p = extractvalue %fn %f, 0
150  %v = tail call i32 %p(%fn %f, i32 %x, i32 %y)
151  ret void
152}
153
154; CHECK-LABEL: mismatched_indirect_f32:
155; CHECK: call_indirect $push[[L:[0-9]+]]=, $0, $1, $2, $0{{$}}
156; CHECK: f32.reinterpret_i32 $push[[L1:[0-9]+]]=, $pop[[L]]{{$}}
157; CHECK: return $pop[[L1]]{{$}}
158define float @mismatched_indirect_f32(%fn %f, i32 %x, i32 %y) {
159  %p = extractvalue %fn %f, 0
160  %v = tail call i32 %p(%fn %f, i32 %x, i32 %y)
161  %u = bitcast i32 %v to float
162  ret float %u
163}
164
165; CHECK-LABEL: mismatched_byval:
166; CHECK: i32.store
167; CHECK: return_call quux, $pop{{[0-9]+}}{{$}}
168declare i32 @quux(i32* byval(i32))
169define i32 @mismatched_byval(i32* %x) {
170  %v = tail call i32 @quux(i32* byval(i32) %x)
171  ret i32 %v
172}
173
174; CHECK-LABEL: varargs:
175; CHECK: i32.store
176; CHECK: call $0=, var, $1{{$}}
177; CHECK: return $0{{$}}
178declare i32 @var(...)
179define i32 @varargs(i32 %x) {
180  %v = tail call i32 (...) @var(i32 %x)
181  ret i32 %v
182}
183
184; Type transformations inhibit tail calls, even when they are nops
185
186; CHECK-LABEL: mismatched_return_zext:
187; CHECK: call
188define i32 @mismatched_return_zext() {
189  %v = tail call i1 @foo(i1 1)
190  %u = zext i1 %v to i32
191  ret i32 %u
192}
193
194; CHECK-LABEL: mismatched_return_sext:
195; CHECK: call
196define i32 @mismatched_return_sext() {
197  %v = tail call i1 @foo(i1 1)
198  %u = sext i1 %v to i32
199  ret i32 %u
200}
201
202; CHECK-LABEL: mismatched_return_trunc:
203; CHECK: call
204declare i32 @int()
205define i1 @mismatched_return_trunc() {
206  %v = tail call i32 @int()
207  %u = trunc i32 %v to i1
208  ret i1 %u
209}
210
211; Stack-allocated arguments inhibit tail calls
212
213; CHECK-LABEL: stack_arg:
214; CHECK: call
215define i32 @stack_arg(i32* %x) {
216  %a = alloca i32
217  %v = tail call i32 @stack_arg(i32* %a)
218  ret i32 %v
219}
220
221; CHECK-LABEL: stack_arg_gep:
222; CHECK: call
223define i32 @stack_arg_gep(i32* %x) {
224  %a = alloca { i32, i32 }
225  %p = getelementptr { i32, i32 }, { i32, i32 }* %a, i32 0, i32 1
226  %v = tail call i32 @stack_arg_gep(i32* %p)
227  ret i32 %v
228}
229
230; CHECK-LABEL: stack_arg_cast:
231; CHECK: global.get $push{{[0-9]+}}=, __stack_pointer
232; CHECK: global.set __stack_pointer, $pop{{[0-9]+}}
233; FAST: call ${{[0-9]+}}=, stack_arg_cast, $pop{{[0-9]+}}
234; CHECK: global.set __stack_pointer, $pop{{[0-9]+}}
235; SLOW: return_call stack_arg_cast, ${{[0-9]+}}
236define i32 @stack_arg_cast(i32 %x) {
237  %a = alloca [64 x i32]
238  %i = ptrtoint [64 x i32]* %a to i32
239  %v = tail call i32 @stack_arg_cast(i32 %i)
240  ret i32 %v
241}
242
243; Check that the signatures generated for external indirectly
244; return-called functions include the proper return types
245
246; YAML-LABEL: - Index:           8
247; YAML-NEXT:    ParamTypes:
248; YAML-NEXT:      - I32
249; YAML-NEXT:      - F32
250; YAML-NEXT:      - I64
251; YAML-NEXT:      - F64
252; YAML-NEXT:    ReturnTypes:
253; YAML-NEXT:      - I32
254define i32 @unique_caller(i32 (i32, float, i64, double)** %p) {
255  %f = load i32 (i32, float, i64, double)*, i32 (i32, float, i64, double)** %p
256  %v = tail call i32 %f(i32 0, float 0., i64 0, double 0.)
257  ret i32 %v
258}
259
260; CHECK-LABEL: .section .custom_section.target_features
261; CHECK-NEXT: .int8 1
262; CHECK-NEXT: .int8 43
263; CHECK-NEXT: .int8 9
264; CHECK-NEXT: .ascii "tail-call"
265