• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -mattr=+multivalue,+tail-call | FileCheck %s
2; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+multivalue,+tail-call | FileCheck %s --check-prefix REGS
3; RUN: llc < %s --filetype=obj -mattr=+multivalue,+tail-call | obj2yaml | FileCheck %s --check-prefix OBJ
4
5; Test that the multivalue calls, returns, function types, and block
6; types work as expected.
7
8target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
9target triple = "wasm32-unknown-unknown"
10
11%pair = type { i32, i64 }
12%rpair = type { i64, i32 }
13
14declare void @use_i32(i32)
15declare void @use_i64(i64)
16
17; CHECK-LABEL: pair_const:
18; CHECK-NEXT: .functype pair_const () -> (i32, i64)
19; CHECK-NEXT: i32.const 42{{$}}
20; CHECK-NEXT: i64.const 42{{$}}
21; CHECK-NEXT: end_function{{$}}
22define %pair @pair_const() {
23  ret %pair { i32 42, i64 42 }
24}
25
26; CHECK-LABEL: pair_ident:
27; CHECK-NEXT: .functype pair_ident (i32, i64) -> (i32, i64)
28; CHECK-NEXT: local.get 0{{$}}
29; CHECK-NEXT: local.get 1{{$}}
30; CHECK-NEXT: end_function{{$}}
31define %pair @pair_ident(%pair %p) {
32  ret %pair %p
33}
34
35; CHECK-LABEL: pair_call:
36; CHECK-NEXT: .functype pair_call () -> ()
37; CHECK-NEXT: call pair_const{{$}}
38; CHECK-NEXT: drop{{$}}
39; CHECK-NEXT: drop{{$}}
40; CHECK-NEXT: end_function{{$}}
41; REGS: call $drop=, $drop=, pair_const{{$}}
42define void @pair_call() {
43  %p = call %pair @pair_const()
44  ret void
45}
46
47; CHECK-LABEL: pair_call_return:
48; CHECK-NEXT: .functype pair_call_return () -> (i32, i64)
49; CHECK-NEXT: call pair_const{{$}}
50; CHECK-NEXT: end_function{{$}}
51; REGS: call $push{{[0-9]+}}=, $push{{[0-9]+}}=, pair_const{{$}}
52define %pair @pair_call_return() {
53  %p = call %pair @pair_const()
54  ret %pair %p
55}
56
57; CHECK-LABEL: pair_call_indirect:
58; CHECK-NEXT: .functype pair_call_indirect (i32) -> (i32, i64)
59; CHECK-NEXT: local.get 0{{$}}
60; CHECK-NEXT: call_indirect () -> (i32, i64){{$}}
61; CHECK-NEXT: end_function{{$}}
62; REGS: call_indirect $push{{[0-9]+}}=, $push{{[0-9]+}}=, $0{{$}}
63define %pair @pair_call_indirect(%pair()* %f) {
64  %p = call %pair %f()
65  ret %pair %p
66}
67
68; CHECK-LABEL: pair_tail_call:
69; CHECK-NEXT: .functype pair_tail_call () -> (i32, i64)
70; CHECK-NEXT: return_call pair_const{{$}}
71; CHECK-NEXT: end_function{{$}}
72; REGS: return_call pair_const{{$}}
73define %pair @pair_tail_call() {
74  %p = musttail call %pair @pair_const()
75  ret %pair %p
76}
77
78; CHECK-LABEL: pair_call_return_first:
79; CHECK-NEXT: .functype pair_call_return_first () -> (i32)
80; CHECK-NEXT: call pair_const{{$}}
81; CHECK-NEXT: drop{{$}}
82; CHECK-NEXT: end_function{{$}}
83; REGS: call $push{{[0-9]+}}=, $drop=, pair_const{{$}}
84define i32 @pair_call_return_first() {
85  %p = call %pair @pair_const()
86  %v = extractvalue %pair %p, 0
87  ret i32 %v
88}
89
90; CHECK-LABEL: pair_call_return_second:
91; CHECK-NEXT: .functype pair_call_return_second () -> (i64)
92; CHECK-NEXT: .local i64{{$}}
93; CHECK-NEXT: call pair_const{{$}}
94; CHECK-NEXT: local.set 0{{$}}
95; CHECK-NEXT: drop{{$}}
96; CHECK-NEXT: local.get 0{{$}}
97; CHECK-NEXT: end_function{{$}}
98; REGS: call $drop=, $0=, pair_const{{$}}
99define i64 @pair_call_return_second() {
100  %p = call %pair @pair_const()
101  %v = extractvalue %pair %p, 1
102  ret i64 %v
103}
104
105; CHECK-LABEL: pair_call_use_first:
106; CHECK-NEXT: .functype pair_call_use_first () -> ()
107; CHECK-NEXT: call pair_const{{$}}
108; CHECK-NEXT: drop{{$}}
109; CHECK-NEXT: call use_i32{{$}}
110; CHECK-NEXT: end_function{{$}}
111; REGS: call $push{{[0-9]+}}=, $drop=, pair_const{{$}}
112define void @pair_call_use_first() {
113  %p = call %pair @pair_const()
114  %v = extractvalue %pair %p, 0
115  call void @use_i32(i32 %v)
116  ret void
117}
118
119; CHECK-LABEL: pair_call_use_second:
120; CHECK-NEXT: .functype pair_call_use_second () -> ()
121; CHECK-NEXT: .local i64
122; CHECK-NEXT: call pair_const{{$}}
123; CHECK-NEXT: local.set 0{{$}}
124; CHECK-NEXT: drop{{$}}
125; CHECK-NEXT: local.get 0{{$}}
126; CHECK-NEXT: call use_i64{{$}}
127; CHECK-NEXT: end_function{{$}}
128; REGS: call $drop=, $0=, pair_const{{$}}
129define void @pair_call_use_second() {
130  %p = call %pair @pair_const()
131  %v = extractvalue %pair %p, 1
132  call void @use_i64(i64 %v)
133  ret void
134}
135
136; CHECK-LABEL: pair_call_use_first_return_second:
137; CHECK-NEXT: .functype pair_call_use_first_return_second () -> (i64)
138; CHECK-NEXT: .local i64{{$}}
139; CHECK-NEXT: call pair_const{{$}}
140; CHECK-NEXT: local.set 0{{$}}
141; CHECK-NEXT: call use_i32{{$}}
142; CHECK-NEXT: local.get 0{{$}}
143; CHECK-NEXT: end_function{{$}}
144; REGS: call $push{{[0-9]+}}=, $0=, pair_const{{$}}
145define i64 @pair_call_use_first_return_second() {
146  %p = call %pair @pair_const()
147  %v = extractvalue %pair %p, 0
148  call void @use_i32(i32 %v)
149  %r = extractvalue %pair %p, 1
150  ret i64 %r
151}
152
153; CHECK-LABEL: pair_call_use_second_return_first:
154; CHECK-NEXT: .functype pair_call_use_second_return_first () -> (i32)
155; CHECK-NEXT: .local i32, i64{{$}}
156; CHECK-NEXT: call pair_const{{$}}
157; CHECK-NEXT: local.set 1{{$}}
158; CHECK-NEXT: local.set 0{{$}}
159; CHECK-NEXT: local.get 1{{$}}
160; CHECK-NEXT: call use_i64{{$}}
161; CHECK-NEXT: local.get 0{{$}}
162; CHECK-NEXT: end_function{{$}}
163; REGS: call $0=, $1=, pair_const{{$}}
164define i32 @pair_call_use_second_return_first() {
165  %p = call %pair @pair_const()
166  %v = extractvalue %pair %p, 1
167  call void @use_i64(i64 %v)
168  %r = extractvalue %pair %p, 0
169  ret i32 %r
170}
171
172; CHECK-LABEL: pair_pass_through:
173; CHECK-NEXT: .functype pair_pass_through (i32, i64) -> (i32, i64)
174; CHECK-NEXT: local.get 0
175; CHECK-NEXT: local.get 1
176; CHECK-NEXT: call pair_ident{{$}}
177; CHECK-NEXT: end_function{{$}}
178; REGS: call $push{{[0-9]+}}=, $push{{[0-9]+}}=, pair_ident, $0, $1{{$}}
179define %pair @pair_pass_through(%pair %p) {
180  %r = call %pair @pair_ident(%pair %p)
181  ret %pair %r
182}
183
184; CHECK-LABEL: pair_swap:
185; CHECK-NEXT: .functype pair_swap (i32, i64) -> (i64, i32)
186; CHECK-NEXT: local.get 1{{$}}
187; CHECK-NEXT: local.get 0{{$}}
188; CHECK-NEXT: end_function{{$}}
189define %rpair @pair_swap(%pair %p) {
190  %first = extractvalue %pair %p, 0
191  %second = extractvalue %pair %p, 1
192  %r1 = insertvalue %rpair undef, i32 %first, 1
193  %r2 = insertvalue %rpair %r1, i64 %second, 0
194  ret %rpair %r2
195}
196
197; CHECK-LABEL: pair_call_swap:
198; CHECK-NEXT: .functype pair_call_swap () -> (i64, i32)
199; CHECK-NEXT: .local i32, i64{{$}}
200; CHECK-NEXT: call pair_const{{$}}
201; CHECK-NEXT: local.set 1{{$}}
202; CHECK-NEXT: local.set 0{{$}}
203; CHECK-NEXT: local.get 1{{$}}
204; CHECK-NEXT: local.get 0{{$}}
205; CHECK-NEXT: end_function{{$}}
206; REGS: call $0=, $1=, pair_const{{$}}
207define %rpair @pair_call_swap() {
208  %p = call %pair @pair_const()
209  %first = extractvalue %pair %p, 0
210  %second = extractvalue %pair %p, 1
211  %r1 = insertvalue %rpair undef, i32 %first, 1
212  %r2 = insertvalue %rpair %r1, i64 %second, 0
213  ret %rpair %r2
214}
215
216; CHECK-LABEL: pair_pass_through_swap:
217; CHECK-NEXT: .functype pair_pass_through_swap (i32, i64) -> (i64, i32)
218; CHECK-NEXT: local.get 0{{$}}
219; CHECK-NEXT: local.get 1{{$}}
220; CHECK-NEXT: call pair_ident{{$}}
221; CHECK-NEXT: local.set 1{{$}}
222; CHECK-NEXT: local.set 0{{$}}
223; CHECK-NEXT: local.get 1{{$}}
224; CHECK-NEXT: local.get 0{{$}}
225; CHECK-NEXT: end_function{{$}}
226; REGS: call $0=, $1=, pair_ident, $0, $1{{$}}
227define %rpair @pair_pass_through_swap(%pair %p) {
228  %p1 = call %pair @pair_ident(%pair %p)
229  %first = extractvalue %pair %p1, 0
230  %second = extractvalue %pair %p1, 1
231  %r1 = insertvalue %rpair undef, i32 %first, 1
232  %r2 = insertvalue %rpair %r1, i64 %second, 0
233  ret %rpair %r2
234}
235
236; CHECK-LABEL: minimal_loop:
237; CHECK-NEXT: .functype minimal_loop (i32) -> (i32, i64)
238; CHECK-NEXT: .LBB{{[0-9]+}}_1:
239; CHECK-NEXT: loop () -> (i32, i64)
240; CHECK-NEXT: br 0{{$}}
241; CHECK-NEXT: .LBB{{[0-9]+}}_2:
242; CHECK-NEXT: end_loop{{$}}
243; CHECK-NEXT: end_function{{$}}
244define %pair @minimal_loop(i32* %p) {
245entry:
246  br label %loop
247loop:
248  br label %loop
249}
250
251; CHECK-LABEL: .section .custom_section.target_features
252; CHECK-NEXT: .int8 2
253; CHECK-NEXT: .int8 43
254; CHECK-NEXT: .int8 10
255; CHECK-NEXT: .ascii "multivalue"
256; CHECK-NEXT: .int8 43
257; CHECK-NEXT: .int8 9
258; CHECK-NEXT: .ascii "tail-call"
259
260; OBJ-LABEL:  - Type:            TYPE
261; OBJ-NEXT:     Signatures:
262; OBJ-NEXT:       - Index:           0
263; OBJ-NEXT:         ParamTypes:      []
264; OBJ-NEXT:         ReturnTypes:
265; OBJ-NEXT:           - I32
266; OBJ-NEXT:           - I64
267; OBJ-NEXT:       - Index:           1
268; OBJ-NEXT:         ParamTypes:
269; OBJ-NEXT:           - I32
270; OBJ-NEXT:           - I64
271; OBJ-NEXT:         ReturnTypes:
272; OBJ-NEXT:           - I32
273; OBJ-NEXT:           - I64
274; OBJ-NEXT:       - Index:           2
275; OBJ-NEXT:         ParamTypes:      []
276; OBJ-NEXT:         ReturnTypes:     []
277; OBJ-NEXT:       - Index:           3
278; OBJ-NEXT:         ParamTypes:
279; OBJ-NEXT:           - I32
280; OBJ-NEXT:         ReturnTypes:
281; OBJ-NEXT:           - I32
282; OBJ-NEXT:           - I64
283; OBJ-NEXT:       - Index:           4
284; OBJ-NEXT:         ParamTypes:      []
285; OBJ-NEXT:         ReturnTypes:
286; OBJ-NEXT:           - I32
287; OBJ-NEXT:       - Index:           5
288; OBJ-NEXT:         ParamTypes:      []
289; OBJ-NEXT:         ReturnTypes:
290; OBJ-NEXT:           - I64
291; OBJ-NEXT:       - Index:           6
292; OBJ-NEXT:         ParamTypes:
293; OBJ-NEXT:           - I32
294; OBJ-NEXT:         ReturnTypes:     []
295; OBJ-NEXT:       - Index:           7
296; OBJ-NEXT:         ParamTypes:
297; OBJ-NEXT:           - I64
298; OBJ-NEXT:         ReturnTypes:     []
299; OBJ-NEXT:       - Index:           8
300; OBJ-NEXT:         ParamTypes:
301; OBJ-NEXT:           - I32
302; OBJ-NEXT:           - I64
303; OBJ-NEXT:         ReturnTypes:
304; OBJ-NEXT:           - I64
305; OBJ-NEXT:           - I32
306; OBJ-NEXT:       - Index:           9
307; OBJ-NEXT:         ParamTypes:      []
308; OBJ-NEXT:         ReturnTypes:
309; OBJ-NEXT:           - I64
310; OBJ-NEXT:           - I32
311