[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / WebAssembly / tailcall.ll
blobd0f39e6416ba836c3e37cfc6752fa9ce998852bb
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
5 ; Test that the tail calls lower correctly
7 target triple = "wasm32-unknown-unknown"
9 %fn = type <{i32 (%fn, i32, i32)*}>
10 declare i1 @foo(i1)
11 declare i1 @bar(i1)
13 ; CHECK-LABEL: recursive_notail_nullary:
14 ; CHECK: {{^}} call recursive_notail_nullary{{$}}
15 ; CHECK-NEXT: return
16 define void @recursive_notail_nullary() {
17   notail call void @recursive_notail_nullary()
18   ret void
21 ; CHECK-LABEL: recursive_musttail_nullary:
22 ; CHECK: return_call recursive_musttail_nullary{{$}}
23 define void @recursive_musttail_nullary() {
24   musttail call void @recursive_musttail_nullary()
25   ret void
28 ; CHECK-LABEL: recursive_tail_nullary:
29 ; SLOW: return_call recursive_tail_nullary{{$}}
30 ; FAST: {{^}} call recursive_tail_nullary{{$}}
31 ; FAST-NEXT: return{{$}}
32 define void @recursive_tail_nullary() {
33   tail call void @recursive_tail_nullary()
34   ret void
37 ; CHECK-LABEL: recursive_notail:
38 ; CHECK: call $push[[L:[0-9]+]]=, recursive_notail, $0, $1{{$}}
39 ; CHECK-NEXT: return $pop[[L]]{{$}}
40 define i32 @recursive_notail(i32 %x, i32 %y) {
41   %v = notail call i32 @recursive_notail(i32 %x, i32 %y)
42   ret i32 %v
45 ; CHECK-LABEL: recursive_musttail:
46 ; CHECK: return_call recursive_musttail, $0, $1{{$}}
47 define i32 @recursive_musttail(i32 %x, i32 %y) {
48   %v = musttail call i32 @recursive_musttail(i32 %x, i32 %y)
49   ret i32 %v
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]]{{$}}
56 define i32 @recursive_tail(i32 %x, i32 %y) {
57   %v = tail call i32 @recursive_tail(i32 %x, i32 %y)
58   ret i32 %v
61 ; CHECK-LABEL: indirect_notail:
62 ; CHECK: call_indirect $push[[L:[0-9]+]]=, $0, $1, $2, $0{{$}}
63 ; CHECK-NEXT: return $pop[[L]]{{$}}
64 define 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
70 ; CHECK-LABEL: indirect_musttail:
71 ; CHECK: return_call_indirect , $0, $1, $2, $0{{$}}
72 define 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
78 ; CHECK-LABEL: indirect_tail:
79 ; CHECK: return_call_indirect , $0, $1, $2, $0{{$}}
80 define 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
86 ; CHECK-LABEL: choice_notail:
87 ; CHECK: call_indirect $push[[L:[0-9]+]]=, $0, $pop{{[0-9]+}}{{$}}
88 ; CHECK-NEXT: return $pop[[L]]{{$}}
89 define 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
95 ; CHECK-LABEL: choice_musttail:
96 ; CHECK: return_call_indirect , $0, $pop{{[0-9]+}}{{$}}
97 define 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
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]]{{$}}
107 define 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
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'.
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]]{{$}}
121 declare i32 @baz(i32, i32, i32)
122 define i32 @mismatched_prototypes() {
123   %v = tail call i32 @baz(i32 0, i32 42, i32 6)
124   ret i32 %v
127 ; CHECK-LABEL: mismatched_return_void:
128 ; CHECK: call $drop=, baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
129 ; CHECK: return{{$}}
130 define void @mismatched_return_void() {
131   %v = tail call i32 @baz(i32 0, i32 42, i32 6)
132   ret void
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]]{{$}}
139 define 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
145 ; CHECK-LABEL: mismatched_indirect_void:
146 ; CHECK: call_indirect $drop=, $0, $1, $2, $0{{$}}
147 ; CHECK: return{{$}}
148 define 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
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]]{{$}}
158 define 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
165 ; CHECK-LABEL: mismatched_byval:
166 ; CHECK: i32.store
167 ; CHECK: return_call quux, $pop{{[0-9]+}}{{$}}
168 declare i32 @quux(i32* byval(i32))
169 define i32 @mismatched_byval(i32* %x) {
170   %v = tail call i32 @quux(i32* byval(i32) %x)
171   ret i32 %v
174 ; CHECK-LABEL: varargs:
175 ; CHECK: i32.store
176 ; CHECK: call $0=, var, $1{{$}}
177 ; CHECK: return $0{{$}}
178 declare i32 @var(...)
179 define i32 @varargs(i32 %x) {
180   %v = tail call i32 (...) @var(i32 %x)
181   ret i32 %v
184 ; Type transformations inhibit tail calls, even when they are nops
186 ; CHECK-LABEL: mismatched_return_zext:
187 ; CHECK: call
188 define i32 @mismatched_return_zext() {
189   %v = tail call i1 @foo(i1 1)
190   %u = zext i1 %v to i32
191   ret i32 %u
194 ; CHECK-LABEL: mismatched_return_sext:
195 ; CHECK: call
196 define i32 @mismatched_return_sext() {
197   %v = tail call i1 @foo(i1 1)
198   %u = sext i1 %v to i32
199   ret i32 %u
202 ; CHECK-LABEL: mismatched_return_trunc:
203 ; CHECK: call
204 declare i32 @int()
205 define i1 @mismatched_return_trunc() {
206   %v = tail call i32 @int()
207   %u = trunc i32 %v to i1
208   ret i1 %u
211 ; Stack-allocated arguments inhibit tail calls
213 ; CHECK-LABEL: stack_arg:
214 ; CHECK: call
215 define i32 @stack_arg(i32* %x) {
216   %a = alloca i32
217   %v = tail call i32 @stack_arg(i32* %a)
218   ret i32 %v
221 ; CHECK-LABEL: stack_arg_gep:
222 ; CHECK: call
223 define 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
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]+}}
236 define 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
243 ; Check that the signatures generated for external indirectly
244 ; return-called functions include the proper return types
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
254 define 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
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"